The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netpfil/pf/pf_osfp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
    3  *
    4  * Permission to use, copy, modify, and distribute this software for any
    5  * purpose with or without fee is hereby granted, provided that the above
    6  * copyright notice and this permission notice appear in all copies.
    7  *
    8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   15  *
   16  *      $OpenBSD: pf_osfp.c,v 1.14 2008/06/12 18:17:01 henning Exp $
   17  */
   18 
   19 #include <sys/cdefs.h>
   20 __FBSDID("$FreeBSD: releng/11.0/sys/netpfil/pf/pf_osfp.c 257176 2013-10-26 17:58:36Z glebius $");
   21 
   22 #include <sys/param.h>
   23 #include <sys/kernel.h>
   24 #include <sys/lock.h>
   25 #include <sys/mbuf.h>
   26 #include <sys/rwlock.h>
   27 #include <sys/socket.h>
   28 
   29 #include <netinet/in.h>
   30 #include <netinet/ip.h>
   31 #include <netinet/tcp.h>
   32 
   33 #include <net/if.h>
   34 #include <net/vnet.h>
   35 #include <net/pfvar.h>
   36 
   37 #include <netinet/ip6.h>
   38 
   39 static MALLOC_DEFINE(M_PFOSFP, "pf_osfp", "pf(4) operating system fingerprints");
   40 #define DPFPRINTF(format, x...)         \
   41         if (V_pf_status.debug >= PF_DEBUG_NOISY)        \
   42                 printf(format , ##x)
   43 
   44 SLIST_HEAD(pf_osfp_list, pf_os_fingerprint);
   45 static VNET_DEFINE(struct pf_osfp_list, pf_osfp_list) =
   46         SLIST_HEAD_INITIALIZER();
   47 #define V_pf_osfp_list                  VNET(pf_osfp_list)
   48 
   49 static struct pf_osfp_enlist    *pf_osfp_fingerprint_hdr(const struct ip *,
   50                                     const struct ip6_hdr *,
   51                                     const struct tcphdr *);
   52 static struct pf_os_fingerprint *pf_osfp_find(struct pf_osfp_list *,
   53                                     struct pf_os_fingerprint *, u_int8_t);
   54 static struct pf_os_fingerprint *pf_osfp_find_exact(struct pf_osfp_list *,
   55                                     struct pf_os_fingerprint *);
   56 static void                      pf_osfp_insert(struct pf_osfp_list *,
   57                                     struct pf_os_fingerprint *);
   58 #ifdef PFDEBUG
   59 static struct pf_os_fingerprint *pf_osfp_validate(void);
   60 #endif
   61 
   62 /*
   63  * Passively fingerprint the OS of the host (IPv4 TCP SYN packets only)
   64  * Returns the list of possible OSes.
   65  */
   66 struct pf_osfp_enlist *
   67 pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m, int off,
   68     const struct tcphdr *tcp)
   69 {
   70         struct ip *ip;
   71         struct ip6_hdr *ip6;
   72         char hdr[60];
   73 
   74         if ((pd->af != PF_INET && pd->af != PF_INET6) ||
   75             pd->proto != IPPROTO_TCP || (tcp->th_off << 2) < sizeof(*tcp))
   76                 return (NULL);
   77 
   78         if (pd->af == PF_INET) {
   79                 ip = mtod(m, struct ip *);
   80                 ip6 = (struct ip6_hdr *)NULL;
   81         } else {
   82                 ip = (struct ip *)NULL;
   83                 ip6 = mtod(m, struct ip6_hdr *);
   84         }
   85         if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL,
   86             pd->af)) return (NULL);
   87 
   88         return (pf_osfp_fingerprint_hdr(ip, ip6, (struct tcphdr *)hdr));
   89 }
   90 
   91 static struct pf_osfp_enlist *
   92 pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcp)
   93 {
   94         struct pf_os_fingerprint fp, *fpresult;
   95         int cnt, optlen = 0;
   96         const u_int8_t *optp;
   97         char srcname[128];
   98 
   99         if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN)
  100                 return (NULL);
  101         if (ip) {
  102                 if ((ip->ip_off & htons(IP_OFFMASK)) != 0)
  103                         return (NULL);
  104         }
  105 
  106         memset(&fp, 0, sizeof(fp));
  107 
  108         if (ip) {
  109                 fp.fp_psize = ntohs(ip->ip_len);
  110                 fp.fp_ttl = ip->ip_ttl;
  111                 if (ip->ip_off & htons(IP_DF))
  112                         fp.fp_flags |= PF_OSFP_DF;
  113                 strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname));
  114         }
  115 #ifdef INET6
  116         else if (ip6) {
  117                 /* jumbo payload? */
  118                 fp.fp_psize = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
  119                 fp.fp_ttl = ip6->ip6_hlim;
  120                 fp.fp_flags |= PF_OSFP_DF;
  121                 fp.fp_flags |= PF_OSFP_INET6;
  122                 strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src),
  123                     sizeof(srcname));
  124         }
  125 #endif
  126         else
  127                 return (NULL);
  128         fp.fp_wsize = ntohs(tcp->th_win);
  129 
  130 
  131         cnt = (tcp->th_off << 2) - sizeof(*tcp);
  132         optp = (const u_int8_t *)((const char *)tcp + sizeof(*tcp));
  133         for (; cnt > 0; cnt -= optlen, optp += optlen) {
  134                 if (*optp == TCPOPT_EOL)
  135                         break;
  136 
  137                 fp.fp_optcnt++;
  138                 if (*optp == TCPOPT_NOP) {
  139                         fp.fp_tcpopts = (fp.fp_tcpopts << PF_OSFP_TCPOPT_BITS) |
  140                             PF_OSFP_TCPOPT_NOP;
  141                         optlen = 1;
  142                 } else {
  143                         if (cnt < 2)
  144                                 return (NULL);
  145                         optlen = optp[1];
  146                         if (optlen > cnt || optlen < 2)
  147                                 return (NULL);
  148                         switch (*optp) {
  149                         case TCPOPT_MAXSEG:
  150                                 if (optlen >= TCPOLEN_MAXSEG)
  151                                         memcpy(&fp.fp_mss, &optp[2],
  152                                             sizeof(fp.fp_mss));
  153                                 fp.fp_tcpopts = (fp.fp_tcpopts <<
  154                                     PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_MSS;
  155                                 NTOHS(fp.fp_mss);
  156                                 break;
  157                         case TCPOPT_WINDOW:
  158                                 if (optlen >= TCPOLEN_WINDOW)
  159                                         memcpy(&fp.fp_wscale, &optp[2],
  160                                             sizeof(fp.fp_wscale));
  161                                 NTOHS(fp.fp_wscale);
  162                                 fp.fp_tcpopts = (fp.fp_tcpopts <<
  163                                     PF_OSFP_TCPOPT_BITS) |
  164                                     PF_OSFP_TCPOPT_WSCALE;
  165                                 break;
  166                         case TCPOPT_SACK_PERMITTED:
  167                                 fp.fp_tcpopts = (fp.fp_tcpopts <<
  168                                     PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_SACK;
  169                                 break;
  170                         case TCPOPT_TIMESTAMP:
  171                                 if (optlen >= TCPOLEN_TIMESTAMP) {
  172                                         u_int32_t ts;
  173                                         memcpy(&ts, &optp[2], sizeof(ts));
  174                                         if (ts == 0)
  175                                                 fp.fp_flags |= PF_OSFP_TS0;
  176 
  177                                 }
  178                                 fp.fp_tcpopts = (fp.fp_tcpopts <<
  179                                     PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_TS;
  180                                 break;
  181                         default:
  182                                 return (NULL);
  183                         }
  184                 }
  185                 optlen = MAX(optlen, 1);        /* paranoia */
  186         }
  187 
  188         DPFPRINTF("fingerprinted %s:%d  %d:%d:%d:%d:%llx (%d) "
  189             "(TS=%s,M=%s%d,W=%s%d)\n",
  190             srcname, ntohs(tcp->th_sport),
  191             fp.fp_wsize, fp.fp_ttl, (fp.fp_flags & PF_OSFP_DF) != 0,
  192             fp.fp_psize, (long long int)fp.fp_tcpopts, fp.fp_optcnt,
  193             (fp.fp_flags & PF_OSFP_TS0) ? "" : "",
  194             (fp.fp_flags & PF_OSFP_MSS_MOD) ? "%" :
  195             (fp.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
  196             fp.fp_mss,
  197             (fp.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
  198             (fp.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
  199             fp.fp_wscale);
  200 
  201         if ((fpresult = pf_osfp_find(&V_pf_osfp_list, &fp,
  202             PF_OSFP_MAXTTL_OFFSET)))
  203                 return (&fpresult->fp_oses);
  204         return (NULL);
  205 }
  206 
  207 /* Match a fingerprint ID against a list of OSes */
  208 int
  209 pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)
  210 {
  211         struct pf_osfp_entry *entry;
  212         int os_class, os_version, os_subtype;
  213         int en_class, en_version, en_subtype;
  214 
  215         if (os == PF_OSFP_ANY)
  216                 return (1);
  217         if (list == NULL) {
  218                 DPFPRINTF("osfp no match against %x\n", os);
  219                 return (os == PF_OSFP_UNKNOWN);
  220         }
  221         PF_OSFP_UNPACK(os, os_class, os_version, os_subtype);
  222         SLIST_FOREACH(entry, list, fp_entry) {
  223                 PF_OSFP_UNPACK(entry->fp_os, en_class, en_version, en_subtype);
  224                 if ((os_class == PF_OSFP_ANY || en_class == os_class) &&
  225                     (os_version == PF_OSFP_ANY || en_version == os_version) &&
  226                     (os_subtype == PF_OSFP_ANY || en_subtype == os_subtype)) {
  227                         DPFPRINTF("osfp matched %s %s %s  %x==%x\n",
  228                             entry->fp_class_nm, entry->fp_version_nm,
  229                             entry->fp_subtype_nm, os, entry->fp_os);
  230                         return (1);
  231                 }
  232         }
  233         DPFPRINTF("fingerprint 0x%x didn't match\n", os);
  234         return (0);
  235 }
  236 
  237 /* Flush the fingerprint list */
  238 void
  239 pf_osfp_flush(void)
  240 {
  241         struct pf_os_fingerprint *fp;
  242         struct pf_osfp_entry *entry;
  243 
  244         while ((fp = SLIST_FIRST(&V_pf_osfp_list))) {
  245                 SLIST_REMOVE_HEAD(&V_pf_osfp_list, fp_next);
  246                 while ((entry = SLIST_FIRST(&fp->fp_oses))) {
  247                         SLIST_REMOVE_HEAD(&fp->fp_oses, fp_entry);
  248                         free(entry, M_PFOSFP);
  249                 }
  250                 free(fp, M_PFOSFP);
  251         }
  252 }
  253 
  254 
  255 /* Add a fingerprint */
  256 int
  257 pf_osfp_add(struct pf_osfp_ioctl *fpioc)
  258 {
  259         struct pf_os_fingerprint *fp, fpadd;
  260         struct pf_osfp_entry *entry;
  261 
  262         PF_RULES_WASSERT();
  263 
  264         memset(&fpadd, 0, sizeof(fpadd));
  265         fpadd.fp_tcpopts = fpioc->fp_tcpopts;
  266         fpadd.fp_wsize = fpioc->fp_wsize;
  267         fpadd.fp_psize = fpioc->fp_psize;
  268         fpadd.fp_mss = fpioc->fp_mss;
  269         fpadd.fp_flags = fpioc->fp_flags;
  270         fpadd.fp_optcnt = fpioc->fp_optcnt;
  271         fpadd.fp_wscale = fpioc->fp_wscale;
  272         fpadd.fp_ttl = fpioc->fp_ttl;
  273 
  274 #if 0   /* XXX RYAN wants to fix logging */
  275         DPFPRINTF("adding osfp %s %s %s = %s%d:%d:%d:%s%d:0x%llx %d "
  276             "(TS=%s,M=%s%d,W=%s%d) %x\n",
  277             fpioc->fp_os.fp_class_nm, fpioc->fp_os.fp_version_nm,
  278             fpioc->fp_os.fp_subtype_nm,
  279             (fpadd.fp_flags & PF_OSFP_WSIZE_MOD) ? "%" :
  280             (fpadd.fp_flags & PF_OSFP_WSIZE_MSS) ? "S" :
  281             (fpadd.fp_flags & PF_OSFP_WSIZE_MTU) ? "T" :
  282             (fpadd.fp_flags & PF_OSFP_WSIZE_DC) ? "*" : "",
  283             fpadd.fp_wsize,
  284             fpadd.fp_ttl,
  285             (fpadd.fp_flags & PF_OSFP_DF) ? 1 : 0,
  286             (fpadd.fp_flags & PF_OSFP_PSIZE_MOD) ? "%" :
  287             (fpadd.fp_flags & PF_OSFP_PSIZE_DC) ? "*" : "",
  288             fpadd.fp_psize,
  289             (long long int)fpadd.fp_tcpopts, fpadd.fp_optcnt,
  290             (fpadd.fp_flags & PF_OSFP_TS0) ? "" : "",
  291             (fpadd.fp_flags & PF_OSFP_MSS_MOD) ? "%" :
  292             (fpadd.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
  293             fpadd.fp_mss,
  294             (fpadd.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
  295             (fpadd.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
  296             fpadd.fp_wscale,
  297             fpioc->fp_os.fp_os);
  298 #endif
  299 
  300         if ((fp = pf_osfp_find_exact(&V_pf_osfp_list, &fpadd))) {
  301                  SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
  302                         if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
  303                                 return (EEXIST);
  304                 }
  305                 if ((entry = malloc(sizeof(*entry), M_PFOSFP, M_NOWAIT))
  306                     == NULL)
  307                         return (ENOMEM);
  308         } else {
  309                 if ((fp = malloc(sizeof(*fp), M_PFOSFP, M_ZERO | M_NOWAIT))
  310                     == NULL)
  311                         return (ENOMEM);
  312                 fp->fp_tcpopts = fpioc->fp_tcpopts;
  313                 fp->fp_wsize = fpioc->fp_wsize;
  314                 fp->fp_psize = fpioc->fp_psize;
  315                 fp->fp_mss = fpioc->fp_mss;
  316                 fp->fp_flags = fpioc->fp_flags;
  317                 fp->fp_optcnt = fpioc->fp_optcnt;
  318                 fp->fp_wscale = fpioc->fp_wscale;
  319                 fp->fp_ttl = fpioc->fp_ttl;
  320                 SLIST_INIT(&fp->fp_oses);
  321                 if ((entry = malloc(sizeof(*entry), M_PFOSFP, M_NOWAIT))
  322                     == NULL) {
  323                         free(fp, M_PFOSFP);
  324                         return (ENOMEM);
  325                 }
  326                 pf_osfp_insert(&V_pf_osfp_list, fp);
  327         }
  328         memcpy(entry, &fpioc->fp_os, sizeof(*entry));
  329 
  330         /* Make sure the strings are NUL terminated */
  331         entry->fp_class_nm[sizeof(entry->fp_class_nm)-1] = '\0';
  332         entry->fp_version_nm[sizeof(entry->fp_version_nm)-1] = '\0';
  333         entry->fp_subtype_nm[sizeof(entry->fp_subtype_nm)-1] = '\0';
  334 
  335         SLIST_INSERT_HEAD(&fp->fp_oses, entry, fp_entry);
  336 
  337 #ifdef PFDEBUG
  338         if ((fp = pf_osfp_validate()))
  339                 printf("Invalid fingerprint list\n");
  340 #endif /* PFDEBUG */
  341         return (0);
  342 }
  343 
  344 
  345 /* Find a fingerprint in the list */
  346 static struct pf_os_fingerprint *
  347 pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
  348     u_int8_t ttldiff)
  349 {
  350         struct pf_os_fingerprint *f;
  351 
  352 #define MATCH_INT(_MOD, _DC, _field)                                    \
  353         if ((f->fp_flags & _DC) == 0) {                                 \
  354                 if ((f->fp_flags & _MOD) == 0) {                        \
  355                         if (f->_field != find->_field)                  \
  356                                 continue;                               \
  357                 } else {                                                \
  358                         if (f->_field == 0 || find->_field % f->_field) \
  359                                 continue;                               \
  360                 }                                                       \
  361         }
  362 
  363         SLIST_FOREACH(f, list, fp_next) {
  364                 if (f->fp_tcpopts != find->fp_tcpopts ||
  365                     f->fp_optcnt != find->fp_optcnt ||
  366                     f->fp_ttl < find->fp_ttl ||
  367                     f->fp_ttl - find->fp_ttl > ttldiff ||
  368                     (f->fp_flags & (PF_OSFP_DF|PF_OSFP_TS0)) !=
  369                     (find->fp_flags & (PF_OSFP_DF|PF_OSFP_TS0)))
  370                         continue;
  371 
  372                 MATCH_INT(PF_OSFP_PSIZE_MOD, PF_OSFP_PSIZE_DC, fp_psize)
  373                 MATCH_INT(PF_OSFP_MSS_MOD, PF_OSFP_MSS_DC, fp_mss)
  374                 MATCH_INT(PF_OSFP_WSCALE_MOD, PF_OSFP_WSCALE_DC, fp_wscale)
  375                 if ((f->fp_flags & PF_OSFP_WSIZE_DC) == 0) {
  376                         if (f->fp_flags & PF_OSFP_WSIZE_MSS) {
  377                                 if (find->fp_mss == 0)
  378                                         continue;
  379 
  380 /*
  381  * Some "smart" NAT devices and DSL routers will tweak the MSS size and
  382  * will set it to whatever is suitable for the link type.
  383  */
  384 #define SMART_MSS       1460
  385                                 if ((find->fp_wsize % find->fp_mss ||
  386                                     find->fp_wsize / find->fp_mss !=
  387                                     f->fp_wsize) &&
  388                                     (find->fp_wsize % SMART_MSS ||
  389                                     find->fp_wsize / SMART_MSS !=
  390                                     f->fp_wsize))
  391                                         continue;
  392                         } else if (f->fp_flags & PF_OSFP_WSIZE_MTU) {
  393                                 if (find->fp_mss == 0)
  394                                         continue;
  395 
  396 #define MTUOFF          (sizeof(struct ip) + sizeof(struct tcphdr))
  397 #define SMART_MTU       (SMART_MSS + MTUOFF)
  398                                 if ((find->fp_wsize % (find->fp_mss + MTUOFF) ||
  399                                     find->fp_wsize / (find->fp_mss + MTUOFF) !=
  400                                     f->fp_wsize) &&
  401                                     (find->fp_wsize % SMART_MTU ||
  402                                     find->fp_wsize / SMART_MTU !=
  403                                     f->fp_wsize))
  404                                         continue;
  405                         } else if (f->fp_flags & PF_OSFP_WSIZE_MOD) {
  406                                 if (f->fp_wsize == 0 || find->fp_wsize %
  407                                     f->fp_wsize)
  408                                         continue;
  409                         } else {
  410                                 if (f->fp_wsize != find->fp_wsize)
  411                                         continue;
  412                         }
  413                 }
  414                 return (f);
  415         }
  416 
  417         return (NULL);
  418 }
  419 
  420 /* Find an exact fingerprint in the list */
  421 static struct pf_os_fingerprint *
  422 pf_osfp_find_exact(struct pf_osfp_list *list, struct pf_os_fingerprint *find)
  423 {
  424         struct pf_os_fingerprint *f;
  425 
  426         SLIST_FOREACH(f, list, fp_next) {
  427                 if (f->fp_tcpopts == find->fp_tcpopts &&
  428                     f->fp_wsize == find->fp_wsize &&
  429                     f->fp_psize == find->fp_psize &&
  430                     f->fp_mss == find->fp_mss &&
  431                     f->fp_flags == find->fp_flags &&
  432                     f->fp_optcnt == find->fp_optcnt &&
  433                     f->fp_wscale == find->fp_wscale &&
  434                     f->fp_ttl == find->fp_ttl)
  435                         return (f);
  436         }
  437 
  438         return (NULL);
  439 }
  440 
  441 /* Insert a fingerprint into the list */
  442 static void
  443 pf_osfp_insert(struct pf_osfp_list *list, struct pf_os_fingerprint *ins)
  444 {
  445         struct pf_os_fingerprint *f, *prev = NULL;
  446 
  447         /* XXX need to go semi tree based.  can key on tcp options */
  448 
  449         SLIST_FOREACH(f, list, fp_next)
  450                 prev = f;
  451         if (prev)
  452                 SLIST_INSERT_AFTER(prev, ins, fp_next);
  453         else
  454                 SLIST_INSERT_HEAD(list, ins, fp_next);
  455 }
  456 
  457 /* Fill a fingerprint by its number (from an ioctl) */
  458 int
  459 pf_osfp_get(struct pf_osfp_ioctl *fpioc)
  460 {
  461         struct pf_os_fingerprint *fp;
  462         struct pf_osfp_entry *entry;
  463         int num = fpioc->fp_getnum;
  464         int i = 0;
  465 
  466 
  467         memset(fpioc, 0, sizeof(*fpioc));
  468         SLIST_FOREACH(fp, &V_pf_osfp_list, fp_next) {
  469                 SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
  470                         if (i++ == num) {
  471                                 fpioc->fp_mss = fp->fp_mss;
  472                                 fpioc->fp_wsize = fp->fp_wsize;
  473                                 fpioc->fp_flags = fp->fp_flags;
  474                                 fpioc->fp_psize = fp->fp_psize;
  475                                 fpioc->fp_ttl = fp->fp_ttl;
  476                                 fpioc->fp_wscale = fp->fp_wscale;
  477                                 fpioc->fp_getnum = num;
  478                                 memcpy(&fpioc->fp_os, entry,
  479                                     sizeof(fpioc->fp_os));
  480                                 return (0);
  481                         }
  482                 }
  483         }
  484 
  485         return (EBUSY);
  486 }
  487 
  488 
  489 #ifdef PFDEBUG
  490 /* Validate that each signature is reachable */
  491 static struct pf_os_fingerprint *
  492 pf_osfp_validate(void)
  493 {
  494         struct pf_os_fingerprint *f, *f2, find;
  495 
  496         SLIST_FOREACH(f, &V_pf_osfp_list, fp_next) {
  497                 memcpy(&find, f, sizeof(find));
  498 
  499                 /* We do a few MSS/th_win percolations to make things unique */
  500                 if (find.fp_mss == 0)
  501                         find.fp_mss = 128;
  502                 if (f->fp_flags & PF_OSFP_WSIZE_MSS)
  503                         find.fp_wsize *= find.fp_mss;
  504                 else if (f->fp_flags & PF_OSFP_WSIZE_MTU)
  505                         find.fp_wsize *= (find.fp_mss + 40);
  506                 else if (f->fp_flags & PF_OSFP_WSIZE_MOD)
  507                         find.fp_wsize *= 2;
  508                 if (f != (f2 = pf_osfp_find(&V_pf_osfp_list, &find, 0))) {
  509                         if (f2)
  510                                 printf("Found \"%s %s %s\" instead of "
  511                                     "\"%s %s %s\"\n",
  512                                     SLIST_FIRST(&f2->fp_oses)->fp_class_nm,
  513                                     SLIST_FIRST(&f2->fp_oses)->fp_version_nm,
  514                                     SLIST_FIRST(&f2->fp_oses)->fp_subtype_nm,
  515                                     SLIST_FIRST(&f->fp_oses)->fp_class_nm,
  516                                     SLIST_FIRST(&f->fp_oses)->fp_version_nm,
  517                                     SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
  518                         else
  519                                 printf("Couldn't find \"%s %s %s\"\n",
  520                                     SLIST_FIRST(&f->fp_oses)->fp_class_nm,
  521                                     SLIST_FIRST(&f->fp_oses)->fp_version_nm,
  522                                     SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
  523                         return (f);
  524                 }
  525         }
  526         return (NULL);
  527 }
  528 #endif /* PFDEBUG */

Cache object: f5cd9d1319ebe24875780f68522f34fc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.