]> The Tcpdump Group git mirrors - libpcap/blobdiff - gencode.c
Fix a typo; this fixes bug 1854436.
[libpcap] / gencode.c
index b9f75ccb558793f65271f0e52353e9c7dd4e0314..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.35 2005-11-17 04:50:13 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);
 }
 
@@ -668,20 +693,26 @@ gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
 static int reg_ll_size;
 
 /*
- * This is the offset of the beginning of the link-layer header.
+ * This is the offset of the beginning of the link-layer header from
+ * the beginning of the raw packet data.
+ *
  * It's usually 0, except for 802.11 with a fixed-length radio header.
+ * (For 802.11 with a variable-length radio header, we have to generate
+ * code to compute that offset; off_ll is 0 in that case.)
  */
 static u_int off_ll;
 
 /*
  * This is the offset of the beginning of the MAC-layer header.
- * It's usually 0, except for ATM LANE.
+ * It's usually 0, except for ATM LANE, where it's the offset, relative
+ * to the beginning of the raw packet data, of the Ethernet header.
  */
 static u_int off_mac;
 
 /*
  * "off_linktype" is the offset to information in the link-layer header
- * giving the packet type.
+ * giving the packet type.  This offset is relative to the beginning
+ * of the link-layer header (i.e., it doesn't include off_ll).
  *
  * For Ethernet, it's the offset of the Ethernet type field.
  *
@@ -718,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.
  */
@@ -734,6 +770,8 @@ static u_int off_payload;
 
 /*
  * These are offsets to the beginning of the network-layer header.
+ * They are relative to the beginning of the link-layer header (i.e.,
+ * they don't include off_ll).
  *
  * If the link layer never uses 802.2 LLC:
  *
@@ -782,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;
@@ -956,9 +995,9 @@ init_linktype(p)
                 * the Prism header is fixed-length.
                 */
                off_ll = 144;
-               off_linktype = 144+24;
-               off_nl = 144+32;        /* Prism+802.11+802.2+SNAP */
-               off_nl_nosnap = 144+27; /* Prism+802.11+802.2 */
+               off_linktype = 24;
+               off_nl = 32;    /* Prism+802.11+802.2+SNAP */
+               off_nl_nosnap = 27;     /* Prism+802.11+802.2 */
                return;
 
        case DLT_IEEE802_11_RADIO_AVS:
@@ -974,14 +1013,35 @@ init_linktype(p)
                 * more so; this header is also variable-length,
                 * with the length being the 32-bit big-endian
                 * number at an offset of 4 from the beginning
-                * of the radio header.
+                * of the radio header.  We should handle that the
+                * same way we handle the length at the beginning
+                * of the radiotap header.
+                *
+                * XXX - in Linux, do any drivers that supply an AVS
+                * header supply a link-layer type other than
+                * ARPHRD_IEEE80211_PRISM?  If so, we should map that
+                * to DLT_IEEE802_11_RADIO_AVS; if not, or if there are
+                * any drivers that supply an AVS header but supply
+                * an ARPHRD value of ARPHRD_IEEE80211_PRISM, we'll
+                * have to check the header in the generated code to
+                * determine whether it's Prism or AVS.
                 */
                off_ll = 64;
-               off_linktype = 64+24;
-               off_nl = 64+32;         /* Radio+802.11+802.2+SNAP */
-               off_nl_nosnap = 64+27;  /* Radio+802.11+802.2 */
+               off_linktype = 24;
+               off_nl = 32;            /* Radio+802.11+802.2+SNAP */
+               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
@@ -1081,6 +1141,17 @@ init_linktype(p)
                off_nl_nosnap = 0;      /* no 802.2 LLC */
                return;
 
+                /*
+                 * the only BPF-interesting FRF.16 frames are non-control frames;
+                 * Frame Relay has a variable length link-layer
+                 * so lets start with offset 4 for now and increments later on (FIXME);
+                 */
+       case DLT_MFR:
+               off_linktype = -1;
+               off_nl = 4;
+               off_nl_nosnap = 0;      /* XXX - for now -> no 802.2 LLC */
+               return;
+
        case DLT_APPLE_IP_OVER_IEEE1394:
                off_linktype = 16;
                off_nl = 18;
@@ -1111,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:
@@ -1180,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;
@@ -1190,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;
@@ -1206,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 */
@@ -1229,18 +1337,34 @@ gen_load_llrel(offset, size)
         * If "s" is non-null, it has code to arrange that the X register
         * contains the length of the prefix preceding the link-layer
         * header.
+        *
+        * Otherwise, the length of the prefix preceding the link-layer
+        * 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;
+               s->s.k = offset + off_ll;
        }
        return s;
 }
 
+
 /*
  * Load a value relative to the beginning of the specified header.
  */
@@ -1254,11 +1378,12 @@ gen_load_a(offrel, offset, size)
        switch (offrel) {
 
        case OR_PACKET:
-               s = gen_load_llrel(offset, size);
+                s = new_stmt(BPF_LD|BPF_ABS|size);
+                s->s.k = offset;
                break;
 
        case OR_LINK:
-               s = gen_load_llrel(off_ll + offset, size);
+               s = gen_load_llrel(offset, size);
                break;
 
        case OR_NET:
@@ -1271,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;
 
@@ -1339,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;
 }
@@ -1794,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)
@@ -1801,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;
        }
 }
 
@@ -1829,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
@@ -1840,6 +2115,10 @@ gen_llprefixlen(void)
 {
        switch (linktype) {
 
+       case DLT_PPI:
+               return gen_ppi_llprefixlen();
+
+       
        case DLT_IEEE802_11_RADIO:
                return gen_radiotap_llprefixlen();
 
@@ -1902,6 +2181,7 @@ gen_linktype(proto)
                }
                break;
 
+       case DLT_PPI:
        case DLT_FDDI:
        case DLT_IEEE802:
        case DLT_IEEE802_11:
@@ -1962,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?
@@ -1970,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 */
@@ -2151,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
@@ -2168,6 +2452,7 @@ gen_linktype(proto)
                        return gen_false();
                /*NOTREACHED*/
                break;
+#endif /* HAVE_NET_PFVAR_H */
 
        case DLT_ARCNET:
        case DLT_ARCNET_LINUX:
@@ -2284,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
@@ -3044,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);
 
@@ -3368,18 +3654,25 @@ gen_gateway(eaddr, alist, proto, dir)
        case Q_IP:
        case Q_ARP:
        case Q_RARP:
-               if (linktype == DLT_EN10MB)
-                       b0 = gen_ehostop(eaddr, Q_OR);
-               else if (linktype == DLT_FDDI)
-                       b0 = gen_fhostop(eaddr, Q_OR);
-               else if (linktype == DLT_IEEE802)
-                       b0 = gen_thostop(eaddr, Q_OR);
-               else if (linktype == DLT_IEEE802_11 ||
-                   linktype == DLT_IEEE802_11_RADIO_AVS ||
-                   linktype == DLT_IEEE802_11_RADIO ||
-                   linktype == DLT_PRISM_HEADER)
-                       b0 = gen_wlanhostop(eaddr, Q_OR);
-               else if (linktype == DLT_SUNATM && is_lane) {
+                switch (linktype) {
+                case DLT_EN10MB:
+                    b0 = gen_ehostop(eaddr, Q_OR);
+                    break;
+                case DLT_FDDI:
+                    b0 = gen_fhostop(eaddr, Q_OR);
+                    break;
+               case DLT_IEEE802:
+                    b0 = gen_thostop(eaddr, Q_OR);
+                    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);
+                    break;
+                case DLT_SUNATM:
+                    if (is_lane) {
                        /*
                         * Check that the packet doesn't begin with an
                         * LE Control marker.  (We've already generated
@@ -3394,12 +3687,15 @@ gen_gateway(eaddr, alist, proto, dir)
                         */
                        b0 = gen_ehostop(eaddr, Q_OR);
                        gen_and(b1, b0);
-               } else if (linktype == DLT_IP_OVER_FC)
-                       b0 = gen_ipfchostop(eaddr, Q_OR);
-               else
-                       bpf_error(
+                    }
+                    break;
+               case DLT_IP_OVER_FC:
+                    b0 = gen_ipfchostop(eaddr, Q_OR);
+                    break;
+                default:
+                    bpf_error(
                            "'gateway' supported only on ethernet/FDDI/token ring/802.11/Fibre Channel");
-
+                }
                b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
                while (*alist) {
                        tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
@@ -4176,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 */
 
        /*
@@ -4193,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
@@ -4206,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);
@@ -4286,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);
@@ -4304,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);
@@ -4363,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);
@@ -4381,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);
@@ -4435,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
@@ -4481,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);
@@ -4666,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;
@@ -4725,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(
@@ -4806,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:
@@ -4876,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:
@@ -4920,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:
@@ -4991,7 +5285,14 @@ gen_mcode(s1, s2, masklen, q)
                /* Convert mask len to mask */
                if (masklen > 32)
                        bpf_error("mask length must be <= 32");
-               m = 0xffffffff << (32 - masklen);
+               if (masklen == 0) {
+                       /*
+                        * X << 32 is not guaranteed by C to be 0; it's
+                        * undefined.
+                        */
+                       m = 0;
+               } else
+                       m = 0xffffffff << (32 - masklen);
                if ((n & ~m) != 0)
                        bpf_error("non-network bits set in \"%s/%d\"",
                            s1, masklen);
@@ -5007,6 +5308,7 @@ gen_mcode(s1, s2, masklen, q)
                /* NOTREACHED */
        }
        /* NOTREACHED */
+       return NULL;
 }
 
 struct block *
@@ -5175,6 +5477,7 @@ gen_mcode6(s1, s2, masklen, q)
                bpf_error("invalid qualifier against IPv6 address");
                /* NOTREACHED */
        }
+       return NULL;
 }
 #endif /*INET6*/
 
@@ -5186,40 +5489,48 @@ gen_ecode(eaddr, q)
        struct block *b, *tmp;
 
        if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
-               if (linktype == DLT_EN10MB)
-                       return gen_ehostop(eaddr, (int)q.dir);
-               if (linktype == DLT_FDDI)
-                       return gen_fhostop(eaddr, (int)q.dir);
-               if (linktype == DLT_IEEE802)
-                       return gen_thostop(eaddr, (int)q.dir);
-               if (linktype == DLT_IEEE802_11 ||
-                   linktype == DLT_IEEE802_11_RADIO_AVS ||
-                   linktype == DLT_IEEE802_11_RADIO ||
-                   linktype == DLT_PRISM_HEADER)
-                       return gen_wlanhostop(eaddr, (int)q.dir);
-               if (linktype == DLT_SUNATM && 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;
-               }
-               if (linktype == DLT_IP_OVER_FC)
-                       return gen_ipfchostop(eaddr, (int)q.dir);
-               bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+            switch (linktype) {
+            case DLT_EN10MB:
+                return gen_ehostop(eaddr, (int)q.dir);
+            case DLT_FDDI:
+                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:
+                       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");
+                break;
+            }
        }
        bpf_error("ethernet address used in non-ether expression");
        /* NOTREACHED */
+       return NULL;
 }
 
 void
@@ -5265,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:
@@ -5311,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:
@@ -5345,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
@@ -5361,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:
@@ -5394,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:
@@ -5431,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
@@ -5440,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
@@ -5465,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:
@@ -5478,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 *
@@ -5621,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.
  */
@@ -5639,6 +5970,7 @@ alloc_reg()
        }
        bpf_error("too many registers needed to evaluate expression");
        /* NOTREACHED */
+       return 0;
 }
 
 /*
@@ -5751,22 +6083,26 @@ gen_broadcast(proto)
 
        case Q_DEFAULT:
        case Q_LINK:
-               if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX)
-                       return gen_ahostop(abroadcast, Q_DST);
-               if (linktype == DLT_EN10MB)
-                       return gen_ehostop(ebroadcast, Q_DST);
-               if (linktype == DLT_FDDI)
-                       return gen_fhostop(ebroadcast, Q_DST);
-               if (linktype == DLT_IEEE802)
-                       return gen_thostop(ebroadcast, Q_DST);
-               if (linktype == DLT_IEEE802_11 ||
-                   linktype == DLT_IEEE802_11_RADIO_AVS ||
-                   linktype == DLT_IEEE802_11_RADIO ||
-                   linktype == DLT_PRISM_HEADER)
-                       return gen_wlanhostop(ebroadcast, Q_DST);
-               if (linktype == DLT_IP_OVER_FC)
-                       return gen_ipfchostop(ebroadcast, Q_DST);
-               if (linktype == DLT_SUNATM && is_lane) {
+                switch (linktype) {
+                case DLT_ARCNET:
+                case DLT_ARCNET_LINUX:
+                    return gen_ahostop(abroadcast, Q_DST);
+                case DLT_EN10MB:    
+                    return gen_ehostop(ebroadcast, Q_DST);
+                case DLT_FDDI:
+                    return gen_fhostop(ebroadcast, Q_DST);
+                case DLT_IEEE802:
+                    return gen_thostop(ebroadcast, Q_DST);
+                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:
+                    return gen_ipfchostop(ebroadcast, Q_DST);
+                case DLT_SUNATM:
+                    if (is_lane) {
                        /*
                         * Check that the packet doesn't begin with an
                         * LE Control marker.  (We've already generated
@@ -5782,8 +6118,11 @@ gen_broadcast(proto)
                        b0 = gen_ehostop(ebroadcast, Q_DST);
                        gen_and(b1, b0);
                        return b0;
-               }
-               bpf_error("not a broadcast link");
+                    }
+                    break;
+                default:
+                    bpf_error("not a broadcast link");
+                }
                break;
 
        case Q_IP:
@@ -5798,6 +6137,7 @@ gen_broadcast(proto)
        }
        bpf_error("only link-layer/IP broadcast filters supported");
        /* NOTREACHED */
+       return NULL;
 }
 
 /*
@@ -5830,154 +6170,147 @@ gen_multicast(proto)
 
        case Q_DEFAULT:
        case Q_LINK:
-               if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX)
-                       /* all ARCnet multicasts use the same address */
-                       return gen_ahostop(abroadcast, Q_DST);
-
-               if (linktype == DLT_EN10MB) {
-                       /* ether[0] & 1 != 0 */
-                       return gen_mac_multicast(0);
-               }
-
-               if (linktype == DLT_FDDI) {
-                       /*
-                        * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
-                        *
-                        * XXX - was that referring to bit-order issues?
-                        */
-                       /* fddi[1] & 1 != 0 */
-                       return gen_mac_multicast(1);
-               }
-
-               if (linktype == DLT_IEEE802) {
-                       /* tr[2] & 1 != 0 */
-                       return gen_mac_multicast(2);
-               }
-
-               if (linktype == DLT_IEEE802_11 ||
-                   linktype == DLT_IEEE802_11_RADIO_AVS ||
-                   linktype == DLT_IEEE802_11_RADIO ||
-                   linktype == DLT_PRISM_HEADER) {
-                       /*
-                        * Oh, yuk.
-                        *
-                        *      For control frames, there is no DA.
-                        *
-                        *      For management frames, DA is at an
-                        *      offset of 4 from the beginning of
-                        *      the packet.
-                        *
-                        *      For data frames, DA is at an offset
-                        *      of 4 from the beginning of the packet
-                        *      if To DS is clear and at an offset of
-                        *      16 from the beginning of the packet
-                        *      if To DS is set.
-                        */
-
-                       /*
-                        * Generate the tests to be done for data frames.
-                        *
-                        * First, check for To DS set, i.e. "link[1] & 0x01".
-                        */
-                       s = gen_load_a(OR_LINK, 1, BPF_B);
-                       b1 = new_block(JMP(BPF_JSET));
-                       b1->s.k = 0x01; /* To DS */
-                       b1->stmts = s;
-
-                       /*
-                        * If To DS is set, the DA is at 16.
-                        */
-                       b0 = gen_mac_multicast(16);
-                       gen_and(b1, b0);
-
-                       /*
-                        * Now, check for To DS not set, i.e. check
-                        * "!(link[1] & 0x01)".
-                        */
-                       s = gen_load_a(OR_LINK, 1, BPF_B);
-                       b2 = new_block(JMP(BPF_JSET));
-                       b2->s.k = 0x01; /* To DS */
-                       b2->stmts = s;
-                       gen_not(b2);
-
-                       /*
-                        * If To DS is not set, the DA is at 4.
-                        */
-                       b1 = gen_mac_multicast(4);
-                       gen_and(b2, b1);
-
-                       /*
-                        * Now OR together the last two checks.  That gives
-                        * the complete set of checks for data frames.
-                        */
-                       gen_or(b1, b0);
-
-                       /*
-                        * Now check for a data frame.
-                        * I.e, check "link[0] & 0x08".
-                        */
-                       s = gen_load_a(OR_LINK, 0, BPF_B);
-                       b1 = new_block(JMP(BPF_JSET));
-                       b1->s.k = 0x08;
-                       b1->stmts = s;
-
-                       /*
-                        * AND that with the checks done for data frames.
-                        */
-                       gen_and(b1, b0);
-
-                       /*
-                        * If the high-order bit of the type value is 0, this
-                        * is a management frame.
-                        * I.e, check "!(link[0] & 0x08)".
-                        */
-                       s = gen_load_a(OR_LINK, 0, BPF_B);
-                       b2 = new_block(JMP(BPF_JSET));
-                       b2->s.k = 0x08;
-                       b2->stmts = s;
-                       gen_not(b2);
-
-                       /*
-                        * For management frames, the DA is at 4.
-                        */
-                       b1 = gen_mac_multicast(4);
-                       gen_and(b2, b1);
-
-                       /*
-                        * OR that with the checks done for data frames.
-                        * That gives the checks done for management and
-                        * data frames.
-                        */
-                       gen_or(b1, b0);
-
-                       /*
-                        * If the low-order bit of the type value is 1,
-                        * this is either a control frame or a frame
-                        * with a reserved type, and thus not a
-                        * frame with an SA.
-                        *
-                        * I.e., check "!(link[0] & 0x04)".
-                        */
-                       s = gen_load_a(OR_LINK, 0, BPF_B);
-                       b1 = new_block(JMP(BPF_JSET));
-                       b1->s.k = 0x04;
-                       b1->stmts = s;
-                       gen_not(b1);
-
-                       /*
-                        * AND that with the checks for data and management
-                        * frames.
-                        */
-                       gen_and(b1, b0);
-                       return b0;
-               }
-
-               if (linktype == DLT_IP_OVER_FC) {
-                       b0 = gen_mac_multicast(2);
-                       return b0;
-               }
-
-               if (linktype == DLT_SUNATM && is_lane) {
+                switch (linktype) {
+                case DLT_ARCNET:
+                case DLT_ARCNET_LINUX:
+                    /* all ARCnet multicasts use the same address */
+                    return gen_ahostop(abroadcast, Q_DST);
+                case  DLT_EN10MB:
+                    /* ether[0] & 1 != 0 */
+                    return gen_mac_multicast(0);
+                case DLT_FDDI:
+                    /*
+                     * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
+                     *
+                     * XXX - was that referring to bit-order issues?
+                     */
+                    /* fddi[1] & 1 != 0 */
+                    return gen_mac_multicast(1);
+                case DLT_IEEE802:
+                    /* tr[2] & 1 != 0 */
+                    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:
+                    /*
+                     * Oh, yuk.
+                     *
+                     * For control frames, there is no DA.
+                     *
+                     * For management frames, DA is at an
+                     * offset of 4 from the beginning of
+                     * the packet.
+                     *
+                     * For data frames, DA is at an offset
+                     * of 4 from the beginning of the packet
+                     * if To DS is clear and at an offset of
+                     * 16 from the beginning of the packet
+                     * if To DS is set.
+                     */
+                    
+                    /*
+                     * Generate the tests to be done for data frames.
+                     *
+                     * First, check for To DS set, i.e. "link[1] & 0x01".
+                     */
+                    s = gen_load_a(OR_LINK, 1, BPF_B);
+                    b1 = new_block(JMP(BPF_JSET));
+                    b1->s.k = 0x01;    /* To DS */
+                    b1->stmts = s;
+                    
+                    /*
+                     * If To DS is set, the DA is at 16.
+                     */
+                    b0 = gen_mac_multicast(16);
+                    gen_and(b1, b0);
+                    
+                    /*
+                     * Now, check for To DS not set, i.e. check
+                     * "!(link[1] & 0x01)".
+                     */
+                    s = gen_load_a(OR_LINK, 1, BPF_B);
+                    b2 = new_block(JMP(BPF_JSET));
+                    b2->s.k = 0x01;    /* To DS */
+                    b2->stmts = s;
+                    gen_not(b2);
+                    
+                    /*
+                     * If To DS is not set, the DA is at 4.
+                     */
+                    b1 = gen_mac_multicast(4);
+                    gen_and(b2, b1);
+                    
+                    /*
+                     * Now OR together the last two checks.  That gives
+                     * the complete set of checks for data frames.
+                     */
+                    gen_or(b1, b0);
+                    
+                    /*
+                     * Now check for a data frame.
+                     * I.e, check "link[0] & 0x08".
+                     */
+                    s = gen_load_a(OR_LINK, 0, BPF_B);
+                    b1 = new_block(JMP(BPF_JSET));
+                    b1->s.k = 0x08;
+                    b1->stmts = s;
+                    
+                    /*
+                     * AND that with the checks done for data frames.
+                     */
+                    gen_and(b1, b0);
+                    
+                    /*
+                     * If the high-order bit of the type value is 0, this
+                     * is a management frame.
+                     * I.e, check "!(link[0] & 0x08)".
+                     */
+                    s = gen_load_a(OR_LINK, 0, BPF_B);
+                    b2 = new_block(JMP(BPF_JSET));
+                    b2->s.k = 0x08;
+                    b2->stmts = s;
+                    gen_not(b2);
+                    
+                    /*
+                     * For management frames, the DA is at 4.
+                     */
+                    b1 = gen_mac_multicast(4);
+                    gen_and(b2, b1);
+                    
+                    /*
+                     * OR that with the checks done for data frames.
+                     * That gives the checks done for management and
+                     * data frames.
+                     */
+                    gen_or(b1, b0);
+                    
+                    /*
+                     * If the low-order bit of the type value is 1,
+                     * this is either a control frame or a frame
+                     * with a reserved type, and thus not a
+                     * frame with an SA.
+                     *
+                     * I.e., check "!(link[0] & 0x04)".
+                     */
+                    s = gen_load_a(OR_LINK, 0, BPF_B);
+                    b1 = new_block(JMP(BPF_JSET));
+                    b1->s.k = 0x04;
+                    b1->stmts = s;
+                    gen_not(b1);
+                    
+                    /*
+                     * AND that with the checks for data and management
+                     * frames.
+                     */
+                    gen_and(b1, b0);
+                    return b0;
+                case DLT_IP_OVER_FC:
+                    b0 = gen_mac_multicast(2);
+                    return b0;
+                case DLT_SUNATM:
+                    if (is_lane) {
                        /*
                         * Check that the packet doesn't begin with an
                         * LE Control marker.  (We've already generated
@@ -5991,10 +6324,13 @@ gen_multicast(proto)
                        b0 = gen_mac_multicast(off_mac);
                        gen_and(b1, b0);
                        return b0;
-               }
-
-               /* Link not known to support multicasts */
-               break;
+                    }
+                    break;
+                default:
+                    break;
+                }
+                /* Link not known to support multicasts */
+                break;
 
        case Q_IP:
                b0 = gen_linktype(ETHERTYPE_IP);
@@ -6012,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;
 }
 
 /*
@@ -6057,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) {
@@ -6087,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) {
@@ -6107,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)
@@ -6216,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)
@@ -6228,6 +6618,7 @@ gen_acode(eaddr, q)
        }
        bpf_error("ARCnet address used in non-arc expression");
        /* NOTREACHED */
+       return NULL;
 }
 
 static struct block *
@@ -6370,13 +6761,11 @@ gen_mpls(label_num)
                 
             case DLT_C_HDLC: /* fall through */
             case DLT_EN10MB:
-                    b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
-                                 (bpf_int32)ETHERTYPE_MPLS);
+                    b0 = gen_linktype(ETHERTYPE_MPLS);
                     break;
                 
             case DLT_PPP:
-                    b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
-                                 (bpf_int32)PPP_MPLS_UCAST);
+                    b0 = gen_linktype(PPP_MPLS_UCAST);
                     break;
                 
                     /* FIXME add other DLT_s ...
@@ -6638,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;