]> The Tcpdump Group git mirrors - libpcap/blobdiff - gencode.c
Fix a typo; this fixes bug 1854436.
[libpcap] / gencode.c
index 3f864fdba1b6655007e5ef84b708bf4fd941bf6c..177ff925c36071a199735acab0cd9d08db796d49 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -21,7 +21,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.42 2006-09-13 07:04:07 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.54 2007-10-26 00:47:36 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -73,7 +73,12 @@ static const char rcsid[] _U_ =
 #include "ppp.h"
 #include "sll.h"
 #include "arcnet.h"
-#include "pf.h"
+#ifdef HAVE_NET_PFVAR_H
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/pfvar.h>
+#include <net/if_pflog.h>
+#endif
 #ifndef offsetof
 #define offsetof(s, e) ((size_t)&((s *)0)->e)
 #endif
@@ -100,8 +105,12 @@ static const char rcsid[] _U_ =
 static jmp_buf top_ctx;
 static pcap_t *bpf_pcap;
 
+#ifdef WIN32
 /* Hack for updating VLAN, MPLS, and PPPoE offsets. */
+static u_int   orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1;
+#else
 static u_int   orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
+#endif
 
 /* XXX */
 #ifdef PCAP_FDDIPAD
@@ -125,6 +134,7 @@ bpf_error(const char *fmt, ...)
 
 static void init_linktype(pcap_t *);
 
+static void init_regs(void);
 static int alloc_reg(void);
 static void free_reg(int);
 
@@ -189,6 +199,7 @@ static inline struct block *gen_false(void);
 static struct block *gen_ether_linktype(int);
 static struct block *gen_linux_sll_linktype(int);
 static void insert_radiotap_load_llprefixlen(struct block *);
+static void insert_ppi_load_llprefixlen(struct block *);
 static void insert_load_llprefixlen(struct block *);
 static struct slist *gen_llprefixlen(void);
 static struct block *gen_linktype(int);
@@ -238,6 +249,7 @@ static struct slist *xfer_to_a(struct arth *);
 static struct block *gen_mac_multicast(int);
 static struct block *gen_len(int, int);
 
+static struct block *gen_ppi_dlt_check(void);
 static struct block *gen_msg_abbrev(int type);
 
 static void *
@@ -348,15 +360,17 @@ int no_optimize;
 
 int
 pcap_compile(pcap_t *p, struct bpf_program *program,
-            char *buf, int optimize, bpf_u_int32 mask)
+            const char *buf, int optimize, bpf_u_int32 mask)
 {
        extern int n_errors;
+       const char * volatile xbuf = buf;
        int len;
 
        no_optimize = 0;
        n_errors = 0;
        root = NULL;
        bpf_pcap = p;
+       init_regs();
        if (setjmp(top_ctx)) {
                lex_cleanup();
                freechunks();
@@ -372,7 +386,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
                return -1;
        }
 
-       lex_init(buf ? buf : "");
+       lex_init(xbuf ? xbuf : "");
        init_linktype(p);
        (void)pcap_parse();
 
@@ -403,7 +417,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
 int
 pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
                    struct bpf_program *program,
-            char *buf, int optimize, bpf_u_int32 mask)
+            const char *buf, int optimize, bpf_u_int32 mask)
 {
        pcap_t *p;
        int ret;
@@ -472,10 +486,20 @@ merge(b0, b1)
        *p = b1;
 }
 
+
 void
 finish_parse(p)
        struct block *p;
 {
+       struct block *ppi_dlt_check;
+       
+       ppi_dlt_check = gen_ppi_dlt_check();
+
+       if (ppi_dlt_check != NULL)
+       {
+               gen_and(ppi_dlt_check, p);
+       }
+
        backpatch(p, gen_retblk(snaplen));
        p->sense = !p->sense;
        backpatch(p, gen_retblk(0));
@@ -496,6 +520,7 @@ finish_parse(p)
         * require the length of that header, doing more for that
         * header length isn't really worth the effort.
         */
+
        insert_load_llprefixlen(root);
 }
 
@@ -724,6 +749,11 @@ static u_int off_vpi;
 static u_int off_vci;
 static u_int off_proto;
 
+/*
+ * These are offsets for the MTP2 fields.
+ */
+static u_int off_li;
+
 /*
  * These are offsets for the MTP3 fields.
  */
@@ -790,6 +820,7 @@ init_linktype(p)
        /*
         * And assume we're not doing SS7.
         */
+       off_li = -1;
        off_sio = -1;
        off_opc = -1;
        off_dpc = -1;
@@ -1001,6 +1032,16 @@ init_linktype(p)
                off_nl_nosnap = 27;     /* Radio+802.11+802.2 */
                return;
 
+               
+               /* 
+                * At the moment we treat PPI as normal Radiotap encoded
+                * packets. The difference is in the function that generates
+                * the code at the beginning to compute the header length.
+                * Since this code generator of PPI supports bare 802.11
+                * encapsulation only (i.e. the encapsulated DLT should be
+                * DLT_IEEE802_11) we generate code to check for this too.
+                */
+       case DLT_PPI:
        case DLT_IEEE802_11_RADIO:
                /*
                 * Same as 802.11, but with an additional header before
@@ -1141,12 +1182,13 @@ init_linktype(p)
                off_nl_nosnap = 44;     /* XXX - what does it do with 802.3 packets? */
                return;
 
+#ifdef HAVE_NET_PFVAR_H
        case DLT_PFLOG:
                off_linktype = 0;
-               /* XXX read this from pf.h? */
                off_nl = PFLOG_HDRLEN;
                off_nl_nosnap = PFLOG_HDRLEN;   /* no 802.2 LLC */
                return;
+#endif
 
         case DLT_JUNIPER_MFR:
         case DLT_JUNIPER_MLFR:
@@ -1210,7 +1252,14 @@ init_linktype(p)
                off_nl_nosnap = -1;     /* no 802.2 LLC */
                return;
 
+       case DLT_JUNIPER_VP:
+               off_linktype = 18;
+               off_nl = -1;
+               off_nl_nosnap = -1;
+               return;
+
        case DLT_MTP2:
+               off_li = 2;
                off_sio = 3;
                off_opc = 4;
                off_dpc = 4;
@@ -1220,6 +1269,17 @@ init_linktype(p)
                off_nl_nosnap = -1;
                return;
 
+       case DLT_MTP2_WITH_PHDR:
+               off_li = 6;
+               off_sio = 7;
+               off_opc = 8;
+               off_dpc = 8;
+               off_sls = 11;
+               off_linktype = -1;
+               off_nl = -1;
+               off_nl_nosnap = -1;
+               return;
+
 #ifdef DLT_PFSYNC
        case DLT_PFSYNC:
                off_linktype = -1;
@@ -1236,6 +1296,24 @@ init_linktype(p)
                off_nl = -1;
                off_nl_nosnap = -1;
                return;
+
+       case DLT_USB:
+               /*
+                * Currently, only raw "link[N:M]" filtering is supported.
+                */
+               off_linktype = -1;
+               off_nl = -1;
+               off_nl_nosnap = -1;
+               return;
+
+       case DLT_BLUETOOTH_HCI_H4:
+               /*
+                * Currently, only raw "link[N:M]" filtering is supported.
+                */
+               off_linktype = -1;
+               off_nl = -1;
+               off_nl_nosnap = -1;
+               return;
        }
        bpf_error("unknown data link type %d", linktype);
        /* NOTREACHED */
@@ -1264,16 +1342,29 @@ gen_load_llrel(offset, size)
         * header is "off_ll".
         */
        if (s != NULL) {
+               /*
+                * There's a variable-length prefix preceding the
+                * link-layer header.  "s" points to a list of statements
+                * that put the length of that prefix into the X register.
+                * do an indirect load, to use the X register as an offset.
+                */
                s2 = new_stmt(BPF_LD|BPF_IND|size);
                s2->s.k = offset;
                sappend(s, s2);
        } else {
+               /*
+                * There is no variable-length header preceding the
+                * link-layer header; add in off_ll, which, if there's
+                * a fixed-length header preceding the link-layer header,
+                * is the length of that header.
+                */
                s = new_stmt(BPF_LD|BPF_ABS|size);
                s->s.k = offset + off_ll;
        }
        return s;
 }
 
+
 /*
  * Load a value relative to the beginning of the specified header.
  */
@@ -1305,17 +1396,24 @@ gen_load_a(offrel, offset, size)
 
        case OR_TRAN_IPV4:
                /*
-                * Load the X register with the length of the IPv4 header,
-                * in bytes.
+                * Load the X register with the length of the IPv4 header
+                * (plus the offset of the link-layer header, if it's
+                * preceded by a variable-length header such as a radio
+                * header), in bytes.
                 */
                s = gen_loadx_iphdrlen();
 
                /*
-                * Load the item at {length of the link-layer header} +
-                * {length of the IPv4 header} + {specified offset}.
+                * Load the item at {offset of the link-layer header} +
+                * {offset, relative to the start of the link-layer
+                * header, of the IPv4 header} + {length of the IPv4 header} +
+                * {specified offset}.
+                *
+                * (If the link-layer is variable-length, it's included
+                * in the value in the X register, and off_ll is 0.)
                 */
                s2 = new_stmt(BPF_LD|BPF_IND|size);
-               s2->s.k = off_nl + offset;
+               s2->s.k = off_ll + off_nl + offset;
                sappend(s, s2);
                break;
 
@@ -1373,12 +1471,12 @@ gen_loadx_iphdrlen()
        } else {
                /*
                 * There is no variable-length header preceding the
-                * link-layer header; if there's a fixed-length
-                * header preceding it, its length is included in
-                * the off_ variables, so it doesn't need to be added.
+                * link-layer header; add in off_ll, which, if there's
+                * a fixed-length header preceding the link-layer header,
+                * is the length of that header.
                 */
                s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
-               s->s.k = off_nl;
+               s->s.k = off_ll + off_nl;
        }
        return s;
 }
@@ -1828,6 +1926,104 @@ insert_radiotap_load_llprefixlen(b)
        }
 }
 
+/* 
+ * At the moment we treat PPI as normal Radiotap encoded
+ * packets. The difference is in the function that generates
+ * the code at the beginning to compute the header length.
+ * Since this code generator of PPI supports bare 802.11
+ * encapsulation only (i.e. the encapsulated DLT should be
+ * DLT_IEEE802_11) we generate code to check for this too.
+ */
+static void
+insert_ppi_load_llprefixlen(b)
+       struct block *b;
+{
+       struct slist *s1, *s2;
+       
+       /*
+        * Prepend to the statements in this block code to load the
+        * length of the radiotap header into the register assigned
+        * to hold that length, if one has been assigned.
+        */
+       if (reg_ll_size != -1) {
+           /*
+                * The 2 bytes at offsets of 2 and 3 from the beginning
+                * of the radiotap header are the length of the radiotap
+                * header; unfortunately, it's little-endian, so we have
+                * to load it a byte at a time and construct the value.
+                */
+
+               /*
+                * Load the high-order byte, at an offset of 3, shift it
+                * left a byte, and put the result in the X register.
+                */
+               s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+               s1->s.k = 3;
+               s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
+               sappend(s1, s2);
+               s2->s.k = 8;
+               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               sappend(s1, s2);
+
+               /*
+                * Load the next byte, at an offset of 2, and OR the
+                * value from the X register into it.
+                */
+               s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
+               sappend(s1, s2);
+               s2->s.k = 2;
+               s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
+               sappend(s1, s2);
+
+               /*
+                * Now allocate a register to hold that value and store
+                * it.
+                */
+               s2 = new_stmt(BPF_ST);
+               s2->s.k = reg_ll_size;
+               sappend(s1, s2);
+
+               /*
+                * Now move it into the X register.
+                */
+               s2 = new_stmt(BPF_MISC|BPF_TAX);
+               sappend(s1, s2);
+
+               /*
+                * Now append all the existing statements in this
+                * block to these statements.
+                */
+               sappend(s1, b->stmts);
+               b->stmts = s1;
+
+       }
+}
+       
+static struct block *
+gen_ppi_dlt_check(void)
+{
+       struct slist *s_load_dlt;
+       struct block *b;
+
+       if (linktype == DLT_PPI)
+       {
+               /* Create the statements that check for the DLT
+                */
+               s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+               s_load_dlt->s.k = 4;
+
+               b = new_block(JMP(BPF_JEQ));
+
+               b->stmts = s_load_dlt;
+               b->s.k = SWAPLONG(DLT_IEEE802_11);
+       }
+       else
+       {
+               b = NULL;
+       }
+
+       return b;
+}
 
 static void
 insert_load_llprefixlen(b)
@@ -1835,8 +2031,21 @@ insert_load_llprefixlen(b)
 {
        switch (linktype) {
 
+       /* 
+        * At the moment we treat PPI as normal Radiotap encoded
+        * packets. The difference is in the function that generates
+        * the code at the beginning to compute the header length.
+        * Since this code generator of PPI supports bare 802.11
+        * encapsulation only (i.e. the encapsulated DLT should be
+        * DLT_IEEE802_11) we generate code to check for this too.
+        */
+       case DLT_PPI:
+               insert_ppi_load_llprefixlen(b);
+               break;
+
        case DLT_IEEE802_11_RADIO:
                insert_radiotap_load_llprefixlen(b);
+               break;
        }
 }
 
@@ -1863,6 +2072,38 @@ gen_radiotap_llprefixlen(void)
        return s;
 }
 
+/* 
+ * At the moment we treat PPI as normal Radiotap encoded
+ * packets. The difference is in the function that generates
+ * the code at the beginning to compute the header length.
+ * Since this code generator of PPI supports bare 802.11
+ * encapsulation only (i.e. the encapsulated DLT should be
+ * DLT_IEEE802_11) we generate code to check for this too.
+ */
+static struct slist *
+gen_ppi_llprefixlen(void)
+{
+       struct slist *s;
+
+       if (reg_ll_size == -1) {
+               /*
+                * We haven't yet assigned a register for the length
+                * of the radiotap header; allocate one.
+                */
+               reg_ll_size = alloc_reg();
+       }
+
+       /*
+        * Load the register containing the radiotap length
+        * into the X register.
+        */
+       s = new_stmt(BPF_LDX|BPF_MEM);
+       s->s.k = reg_ll_size;
+       return s;
+}
+
+
+
 /*
  * Generate code to compute the link-layer header length, if necessary,
  * putting it into the X register, and to return either a pointer to a
@@ -1874,6 +2115,10 @@ gen_llprefixlen(void)
 {
        switch (linktype) {
 
+       case DLT_PPI:
+               return gen_ppi_llprefixlen();
+
+       
        case DLT_IEEE802_11_RADIO:
                return gen_radiotap_llprefixlen();
 
@@ -1936,6 +2181,7 @@ gen_linktype(proto)
                }
                break;
 
+       case DLT_PPI:
        case DLT_FDDI:
        case DLT_IEEE802:
        case DLT_IEEE802_11:
@@ -1996,7 +2242,7 @@ gen_linktype(proto)
        case DLT_RAW:
                /*
                 * These types don't provide any type field; packets
-                * are always IP.
+                * are always IPv4 or IPv6.
                 *
                 * XXX - for IPv4, check for a version number of 4, and,
                 * for IPv6, check for a version number of 6?
@@ -2004,10 +2250,13 @@ gen_linktype(proto)
                switch (proto) {
 
                case ETHERTYPE_IP:
+                       /* Check for a version number of 4. */
+                       return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
 #ifdef INET6
                case ETHERTYPE_IPV6:
+                       /* Check for a version number of 6. */
+                       return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
 #endif
-                       return gen_true();              /* always true */
 
                default:
                        return gen_false();             /* always false */
@@ -2185,6 +2434,7 @@ gen_linktype(proto)
                }
                return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));
 
+#ifdef HAVE_NET_PFVAR_H
        case DLT_PFLOG:
                /*
                 * af field is host byte order in contrast to the rest of
@@ -2202,6 +2452,7 @@ gen_linktype(proto)
                        return gen_false();
                /*NOTREACHED*/
                break;
+#endif /* HAVE_NET_PFVAR_H */
 
        case DLT_ARCNET:
        case DLT_ARCNET_LINUX:
@@ -2318,6 +2569,7 @@ gen_linktype(proto)
         case DLT_JUNIPER_PPP:
         case DLT_JUNIPER_FRELAY:
         case DLT_JUNIPER_CHDLC:
+        case DLT_JUNIPER_VP:
                /* just lets verify the magic number for now -
                 * on ATM we may have up to 6 different encapsulations on the wire
                 * and need a lot of heuristics to figure out that the payload
@@ -3078,22 +3330,22 @@ gen_dnhostop(addr, dir)
        tmp = gen_mcmp(OR_NET, 2, BPF_H,
            (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
        b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh,
-           BPF_H, (bpf_int32)ntohs(addr));
+           BPF_H, (bpf_int32)ntohs((u_short)addr));
        gen_and(tmp, b1);
        /* Check for pad = 0, long header case */
        tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
-       b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
+       b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
        gen_and(tmp, b2);
        gen_or(b2, b1);
        /* Check for pad = 1, short header case */
        tmp = gen_mcmp(OR_NET, 2, BPF_H,
            (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
-       b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
+       b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
        gen_and(tmp, b2);
        gen_or(b2, b1);
        /* Check for pad = 0, short header case */
        tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
-       b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
+       b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
        gen_and(tmp, b2);
        gen_or(b2, b1);
 
@@ -3414,6 +3666,7 @@ gen_gateway(eaddr, alist, proto, dir)
                     break;
                case DLT_IEEE802_11:
                case DLT_IEEE802_11_RADIO_AVS:
+               case DLT_PPI:
                case DLT_IEEE802_11_RADIO:
                case DLT_PRISM_HEADER:
                     b0 = gen_wlanhostop(eaddr, Q_OR);
@@ -4219,6 +4472,9 @@ gen_protochain(v, proto, dir)
        if (linktype == DLT_IEEE802_11_RADIO)
                bpf_error("'protochain' not supported with radiotap headers");
 
+       if (linktype == DLT_PPI)
+               bpf_error("'protochain' not supported with PPI headers");
+
        no_optimize = 1; /*this code is not compatible with optimzer yet */
 
        /*
@@ -4236,11 +4492,11 @@ gen_protochain(v, proto, dir)
 
                /* A = ip->ip_p */
                s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
-               s[i]->s.k = off_nl + 9;
+               s[i]->s.k = off_ll + off_nl + 9;
                i++;
                /* X = ip->ip_hl << 2 */
                s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
-               s[i]->s.k = off_nl;
+               s[i]->s.k = off_ll + off_nl;
                i++;
                break;
 #ifdef INET6
@@ -4249,7 +4505,7 @@ gen_protochain(v, proto, dir)
 
                /* A = ip6->ip_nxt */
                s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
-               s[i]->s.k = off_nl + 6;
+               s[i]->s.k = off_ll + off_nl + 6;
                i++;
                /* X = sizeof(struct ip6_hdr) */
                s[i] = new_stmt(BPF_LDX|BPF_IMM);
@@ -4329,7 +4585,7 @@ gen_protochain(v, proto, dir)
                i++;
                /* A = P[X + packet head] */
                s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
-               s[i]->s.k = off_nl;
+               s[i]->s.k = off_ll + off_nl;
                i++;
                /* MEM[reg2] = A */
                s[i] = new_stmt(BPF_ST);
@@ -4347,7 +4603,7 @@ gen_protochain(v, proto, dir)
                i++;
                /* A = P[X + packet head]; */
                s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
-               s[i]->s.k = off_nl;
+               s[i]->s.k = off_ll + off_nl;
                i++;
                /* A += 1 */
                s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
@@ -4406,7 +4662,7 @@ gen_protochain(v, proto, dir)
        i++;
        /* A = P[X + packet head]; */
        s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
-       s[i]->s.k = off_nl;
+       s[i]->s.k = off_ll + off_nl;
        i++;
        /* MEM[reg2] = A */
        s[i] = new_stmt(BPF_ST);
@@ -4424,7 +4680,7 @@ gen_protochain(v, proto, dir)
        i++;
        /* A = P[X + packet head] */
        s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
-       s[i]->s.k = off_nl;
+       s[i]->s.k = off_ll + off_nl;
        i++;
        /* A += 2 */
        s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
@@ -4478,6 +4734,7 @@ gen_protochain(v, proto, dir)
 #endif
 }
 
+
 /*
  * Generate code that checks whether the packet is a packet for protocol
  * <proto> and whether the type field in that protocol's header has
@@ -4524,7 +4781,6 @@ gen_proto(v, proto, dir)
                 *
                 * So we always check for ETHERTYPE_IP.
                 */
-
                b0 = gen_linktype(ETHERTYPE_IP);
 #ifndef CHASE_CHAIN
                b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
@@ -4709,7 +4965,7 @@ gen_scode(name, q)
        bpf_u_int32 **alist;
 #else
        int tproto6;
-       struct sockaddr_in *sin;
+       struct sockaddr_in *sin4;
        struct sockaddr_in6 *sin6;
        struct addrinfo *res, *res0;
        struct in6_addr mask128;
@@ -4768,6 +5024,7 @@ gen_scode(name, q)
                        case DLT_IEEE802_11_RADIO_AVS:
                        case DLT_IEEE802_11_RADIO:
                        case DLT_PRISM_HEADER:
+                       case DLT_PPI:
                                eaddr = pcap_ether_hostton(name);
                                if (eaddr == NULL)
                                        bpf_error(
@@ -4849,9 +5106,9 @@ gen_scode(name, q)
                                        if (tproto == Q_IPV6)
                                                continue;
 
-                                       sin = (struct sockaddr_in *)
+                                       sin4 = (struct sockaddr_in *)
                                                res->ai_addr;
-                                       tmp = gen_host(ntohl(sin->sin_addr.s_addr),
+                                       tmp = gen_host(ntohl(sin4->sin_addr.s_addr),
                                                0xffffffff, tproto, dir, q.addr);
                                        break;
                                case AF_INET6:
@@ -4919,12 +5176,9 @@ gen_scode(name, q)
 #ifndef INET6
                return gen_port(port, real_proto, dir);
 #else
-           {
-               struct block *b;
                b = gen_port(port, real_proto, dir);
                gen_or(gen_port6(port, real_proto, dir), b);
                return b;
-           }
 #endif /* INET6 */
 
        case Q_PORTRANGE:
@@ -4963,12 +5217,9 @@ gen_scode(name, q)
 #ifndef INET6
                return gen_portrange(port1, port2, real_proto, dir);
 #else
-           {
-               struct block *b;
                b = gen_portrange(port1, port2, real_proto, dir);
                gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
                return b;
-           }
 #endif /* INET6 */
 
        case Q_GATEWAY:
@@ -5057,6 +5308,7 @@ gen_mcode(s1, s2, masklen, q)
                /* NOTREACHED */
        }
        /* NOTREACHED */
+       return NULL;
 }
 
 struct block *
@@ -5225,6 +5477,7 @@ gen_mcode6(s1, s2, masklen, q)
                bpf_error("invalid qualifier against IPv6 address");
                /* NOTREACHED */
        }
+       return NULL;
 }
 #endif /*INET6*/
 
@@ -5243,39 +5496,41 @@ gen_ecode(eaddr, q)
                 return gen_fhostop(eaddr, (int)q.dir);
             case DLT_IEEE802:
                 return gen_thostop(eaddr, (int)q.dir);
-           case DLT_IEEE802_11:
-           case DLT_IEEE802_11_RADIO_AVS:
-           case DLT_IEEE802_11_RADIO:
-           case DLT_PRISM_HEADER:
-                return gen_wlanhostop(eaddr, (int)q.dir);
-            case DLT_SUNATM:
-               if (is_lane) {
-                       /*
-                        * Check that the packet doesn't begin with an
-                        * LE Control marker.  (We've already generated
-                        * a test for LANE.)
-                        */
-                       tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
-                           0xFF00);
-                       gen_not(tmp);
-
-                       /*
-                        * Now check the MAC address.
-                        */
-                       b = gen_ehostop(eaddr, (int)q.dir);
-                       gen_and(tmp, b);
-                       return b;
-               }
-                break;
-           case DLT_IP_OVER_FC:
+                       case DLT_IEEE802_11:
+                       case DLT_IEEE802_11_RADIO_AVS:
+                       case DLT_IEEE802_11_RADIO:
+                       case DLT_PRISM_HEADER:
+                       case DLT_PPI:
+                               return gen_wlanhostop(eaddr, (int)q.dir);
+                       case DLT_SUNATM:
+                               if (is_lane) {
+                                       /*
+                                        * Check that the packet doesn't begin with an
+                                        * LE Control marker.  (We've already generated
+                                        * a test for LANE.)
+                                        */
+                                       tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
+                                               0xFF00);
+                                       gen_not(tmp);
+
+                                       /*
+                                        * Now check the MAC address.
+                                        */
+                                       b = gen_ehostop(eaddr, (int)q.dir);
+                                       gen_and(tmp, b);
+                                       return b;
+                               }
+                               break;
+                       case DLT_IP_OVER_FC:
                 return gen_ipfchostop(eaddr, (int)q.dir);
             default:
-               bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+                               bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
                 break;
             }
        }
        bpf_error("ethernet address used in non-ether expression");
        /* NOTREACHED */
+       return NULL;
 }
 
 void
@@ -5321,16 +5576,16 @@ xfer_to_a(a)
  * for "index".
  */
 struct arth *
-gen_load(proto, index, size)
+gen_load(proto, inst, size)
        int proto;
-       struct arth *index;
+       struct arth *inst;
        int size;
 {
        struct slist *s, *tmp;
        struct block *b;
        int regno = alloc_reg();
 
-       free_reg(index->regno);
+       free_reg(inst->regno);
        switch (size) {
 
        default:
@@ -5367,14 +5622,14 @@ gen_load(proto, index, size)
                 * Load into the X register the offset computed into the
                 * register specifed by "index".
                 */
-               s = xfer_to_x(index);
+               s = xfer_to_x(inst);
 
                /*
                 * Load the item at that offset.
                 */
                tmp = new_stmt(BPF_LD|BPF_IND|size);
                sappend(s, tmp);
-               sappend(index->s, s);
+               sappend(inst->s, s);
                break;
 
        case Q_LINK:
@@ -5401,11 +5656,11 @@ gen_load(proto, index, size)
                 * by "index".
                 */
                if (s != NULL) {
-                       sappend(s, xfer_to_a(index));
+                       sappend(s, xfer_to_a(inst));
                        sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
                        sappend(s, new_stmt(BPF_MISC|BPF_TAX));
                } else
-                       s = xfer_to_x(index);
+                       s = xfer_to_x(inst);
 
                /*
                 * Load the item at the sum of the offset we've put in the
@@ -5417,7 +5672,7 @@ gen_load(proto, index, size)
                tmp = new_stmt(BPF_LD|BPF_IND|size);
                tmp->s.k = off_ll;
                sappend(s, tmp);
-               sappend(index->s, s);
+               sappend(inst->s, s);
                break;
 
        case Q_IP:
@@ -5450,30 +5705,33 @@ gen_load(proto, index, size)
                 * by "index".
                 */
                if (s != NULL) {
-                       sappend(s, xfer_to_a(index));
+                       sappend(s, xfer_to_a(inst));
                        sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
                        sappend(s, new_stmt(BPF_MISC|BPF_TAX));
                } else
-                       s = xfer_to_x(index);
+                       s = xfer_to_x(inst);
 
                /*
                 * Load the item at the sum of the offset we've put in the
-                * X register and the offset of the start of the network
-                * layer header.
+                * X register, the offset of the start of the network
+                * layer header, and the offset of the start of the link
+                * layer header (which is 0 if the radio header is
+                * variable-length; that header length is what we put
+                * into the X register and then added to the index).
                 */
                tmp = new_stmt(BPF_LD|BPF_IND|size);
-               tmp->s.k = off_nl;
+               tmp->s.k = off_ll + off_nl;
                sappend(s, tmp);
-               sappend(index->s, s);
+               sappend(inst->s, s);
 
                /*
                 * Do the computation only if the packet contains
                 * the protocol in question.
                 */
                b = gen_proto_abbrev(proto);
-               if (index->b)
-                       gen_and(index->b, b);
-               index->b = b;
+               if (inst->b)
+                       gen_and(inst->b, b);
+               inst->b = b;
                break;
 
        case Q_SCTP:
@@ -5487,6 +5745,11 @@ gen_load(proto, index, size)
                /*
                 * The offset is relative to the beginning of
                 * the transport-layer header.
+                *
+                * Load the X register with the length of the IPv4 header
+                * (plus the offset of the link-layer header, if it's
+                * a variable-length header), in bytes.
+                *
                 * XXX - are there any cases where we want
                 * off_nl_nosnap?
                 * XXX - we should, if we're built with
@@ -5496,23 +5759,25 @@ gen_load(proto, index, size)
                s = gen_loadx_iphdrlen();
 
                /*
-                * The X register now contains the sum of the offset
-                * of the beginning of the link-layer header and
-                * the length of the network-layer header.  Load
-                * into the A register the offset relative to
+                * The X register now contains the sum of the length
+                * of any variable-length header preceding the link-layer
+                * header and the length of the network-layer header.
+                * Load into the A register the offset relative to
                 * the beginning of the transport layer header,
                 * add the X register to that, move that to the
                 * X register, and load with an offset from the
                 * X register equal to the offset of the network
                 * layer header relative to the beginning of
-                * the link-layer header.
+                * the link-layer header plus the length of any
+                * fixed-length header preceding the link-layer
+                * header.
                 */
-               sappend(s, xfer_to_a(index));
+               sappend(s, xfer_to_a(inst));
                sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
                sappend(s, new_stmt(BPF_MISC|BPF_TAX));
                sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
-               tmp->s.k = off_nl;
-               sappend(index->s, s);
+               tmp->s.k = off_ll + off_nl;
+               sappend(inst->s, s);
 
                /*
                 * Do the computation only if the packet contains
@@ -5521,12 +5786,12 @@ gen_load(proto, index, size)
                 * only fragment of that datagram.
                 */
                gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
-               if (index->b)
-                       gen_and(index->b, b);
+               if (inst->b)
+                       gen_and(inst->b, b);
 #ifdef INET6
                gen_and(gen_proto_abbrev(Q_IP), b);
 #endif
-               index->b = b;
+               inst->b = b;
                break;
 #ifdef INET6
        case Q_ICMPV6:
@@ -5534,12 +5799,12 @@ gen_load(proto, index, size)
                /*NOTREACHED*/
 #endif
        }
-       index->regno = regno;
+       inst->regno = regno;
        s = new_stmt(BPF_ST);
        s->s.k = regno;
-       sappend(index->s, s);
+       sappend(inst->s, s);
 
-       return index;
+       return inst;
 }
 
 struct block *
@@ -5677,6 +5942,16 @@ gen_arth(code, a0, a1)
 static int regused[BPF_MEMWORDS];
 static int curreg;
 
+/*
+ * Initialize the table of used registers and the current register.
+ */
+static void
+init_regs()
+{
+       curreg = 0;
+       memset(regused, 0, sizeof regused);
+}
+
 /*
  * Return the next free register.
  */
@@ -5695,6 +5970,7 @@ alloc_reg()
        }
        bpf_error("too many registers needed to evaluate expression");
        /* NOTREACHED */
+       return 0;
 }
 
 /*
@@ -5820,6 +6096,7 @@ gen_broadcast(proto)
                 case DLT_IEEE802_11:
                 case DLT_IEEE802_11_RADIO_AVS:
                 case DLT_IEEE802_11_RADIO:
+                               case DLT_PPI:
                 case DLT_PRISM_HEADER:
                     return gen_wlanhostop(ebroadcast, Q_DST);
                 case DLT_IP_OVER_FC:
@@ -5860,6 +6137,7 @@ gen_broadcast(proto)
        }
        bpf_error("only link-layer/IP broadcast filters supported");
        /* NOTREACHED */
+       return NULL;
 }
 
 /*
@@ -5913,6 +6191,7 @@ gen_multicast(proto)
                     return gen_mac_multicast(2);
                 case DLT_IEEE802_11:
                 case DLT_IEEE802_11_RADIO_AVS:
+                               case DLT_PPI:
                 case DLT_IEEE802_11_RADIO:
                 case DLT_PRISM_HEADER:
                     /*
@@ -6069,6 +6348,7 @@ gen_multicast(proto)
        }
        bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
        /* NOTREACHED */
+       return NULL;
 }
 
 /*
@@ -6114,10 +6394,12 @@ gen_inbound(dir)
                }
                break;
 
+#ifdef HAVE_NET_PFVAR_H
        case DLT_PFLOG:
                b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B,
                    (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
                break;
+#endif
 
        case DLT_PPP_PPPD:
                if (dir) {
@@ -6144,6 +6426,7 @@ gen_inbound(dir)
         case DLT_JUNIPER_PPP:
         case DLT_JUNIPER_FRELAY:
         case DLT_JUNIPER_CHDLC:
+        case DLT_JUNIPER_VP:
                /* juniper flags (including direction) are stored
                 * the byte after the 3-byte magic number */
                if (dir) {
@@ -6164,6 +6447,7 @@ gen_inbound(dir)
        return (b0);
 }
 
+#ifdef HAVE_NET_PFVAR_H
 /* PF firewall log matched interface */
 struct block *
 gen_pf_ifname(const char *ifname)
@@ -6273,6 +6557,55 @@ gen_pf_action(int action)
 
        return (b0);
 }
+#else /* !HAVE_NET_PFVAR_H */
+struct block *
+gen_pf_ifname(const char *ifname)
+{
+       bpf_error("libpcap was compiled without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_ruleset(char *ruleset)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_rnr(int rnr)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_srnr(int srnr)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_reason(int reason)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+
+struct block *
+gen_pf_action(int action)
+{
+       bpf_error("libpcap was compiled on a machine without pf support");
+       /* NOTREACHED */
+       return (NULL);
+}
+#endif /* HAVE_NET_PFVAR_H */
 
 struct block *
 gen_acode(eaddr, q)
@@ -6285,6 +6618,7 @@ gen_acode(eaddr, q)
        }
        bpf_error("ARCnet address used in non-arc expression");
        /* NOTREACHED */
+       return NULL;
 }
 
 static struct block *
@@ -6693,6 +7027,50 @@ gen_atmtype_abbrev(type)
        return b1;
 }
 
+/* 
+ * Filtering for MTP2 messages based on li value
+ * FISU, length is null
+ * LSSU, length is 1 or 2
+ * MSU, length is 3 or more
+ */
+struct block *
+gen_mtp2type_abbrev(type)
+       int type;
+{
+       struct block *b0, *b1;
+
+       switch (type) {
+
+       case M_FISU:
+               if ( (linktype != DLT_MTP2) &&
+                    (linktype != DLT_MTP2_WITH_PHDR) )
+                       bpf_error("'fisu' supported only on MTP2");
+               /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
+               b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
+               break;
+
+       case M_LSSU:
+               if ( (linktype != DLT_MTP2) &&
+                    (linktype != DLT_MTP2_WITH_PHDR) )
+                       bpf_error("'lssu' supported only on MTP2");
+               b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
+               b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
+               gen_and(b1, b0);
+               break;
+
+       case M_MSU:
+               if ( (linktype != DLT_MTP2) &&
+                    (linktype != DLT_MTP2_WITH_PHDR) )
+                       bpf_error("'msu' supported only on MTP2");
+               b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
+               break;
+
+       default:
+               abort();
+       }
+       return b0;
+}
+
 struct block *
 gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
        int mtp3field;