]> The Tcpdump Group git mirrors - libpcap/blobdiff - gencode.c
The value pointed to by "gen_pf_ifname()"'s argument isn't modified, so
[libpcap] / gencode.c
index 47eba1b9dbde1c767b469cd7ad77c48f711f2763..f8765fb5dcb96ccb32582ff6c49010c3b7e81880 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -21,7 +21,7 @@
  */
 #ifndef lint
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.182 2002-12-06 00:01:33 hannes Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.191 2003-05-02 08:37:43 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -70,6 +70,7 @@ static const char rcsid[] =
 #include "ppp.h"
 #include "sll.h"
 #include "arcnet.h"
+#include "pf.h"
 #ifdef INET6
 #ifndef WIN32
 #include <netdb.h>     /* for "struct addrinfo" */
@@ -225,6 +226,8 @@ newchunk(n)
                        bpf_error("out of memory");
                size = CHUNK0SIZE << k;
                cp->m = (void *)malloc(size);
+               if (cp->m == NULL)
+                       bpf_error("out of memory");
                memset((char *)cp->m, 0, size);
                cp->n_left = size;
                if (n > size)
@@ -695,10 +698,16 @@ init_linktype(type)
 
        case DLT_ARCNET:
                off_linktype = 2;
-               off_nl = 6;     /* XXX in reality, variable! */
+               off_nl = 6;             /* XXX in reality, variable! */
                off_nl_nosnap = 6;      /* no 802.2 LLC */
                return;
 
+       case DLT_ARCNET_LINUX:
+               off_linktype = 4;
+               off_nl = 8;             /* XXX in reality, variable! */
+               off_nl_nosnap = 8;      /* no 802.2 LLC */
+               return;
+
        case DLT_EN10MB:
                off_linktype = 12;
                off_nl = 14;            /* Ethernet II */
@@ -730,6 +739,18 @@ init_linktype(type)
                off_nl_nosnap = 4;      /* no 802.2 LLC */
                return;
 
+       case DLT_ENC:
+               off_linktype = 0;
+               off_nl = 12;
+               off_nl_nosnap = 12;     /* no 802.2 LLC */
+               return;
+
+       case DLT_PFLOG:
+               off_linktype = 0;
+               off_nl = 28;
+               off_nl_nosnap = 28;     /* no 802.2 LLC */
+               return;
+
        case DLT_PPP:
        case DLT_C_HDLC:                /* BSD/OS Cisco HDLC */
        case DLT_PPP_SERIAL:            /* NetBSD sync/async serial PPP */
@@ -838,11 +859,26 @@ init_linktype(type)
                off_nl_nosnap = 144+27; /* Prism+802.11+802.2 */
                return;
 
-       case DLT_ATM_RFC1483:
-               off_linktype = 0;
-               off_nl = 4;             /* FIXME SNAP */
+       case DLT_IEEE802_11_RADIO:
+               /*
+                * Same as 802.11, but with an additional header before
+                * the 802.11 header, containing a bunch of additional
+                * information including radio-level information.
+                *
+                * The header is 64 bytes long.
+                *
+                * XXX - same variable-length header problem, only
+                * 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.
+                */
+               off_linktype = 64+24;
+               off_nl = 64+32;         /* Radio+802.11+802.2+SNAP */
+               off_nl_nosnap = 64+27;  /* Radio+802.11+802.2 */
                return;
 
+       case DLT_ATM_RFC1483:
        case DLT_ATM_CLIP:      /* Linux ATM defines this */
                /*
                 * assume routed, non-ISO PDUs
@@ -968,6 +1004,9 @@ gen_ether_linktype(proto)
        case LLCSAP_ISONS:
                /*
                 * OSI protocols always use 802.2 encapsulation.
+                * XXX - should we check both the DSAP and the
+                * SSAP, like this, or should we check just the
+                * DSAP?
                 */
                b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
                gen_not(b0);
@@ -987,6 +1026,9 @@ gen_ether_linktype(proto)
        case LLCSAP_NETBEUI:
                /*
                 * NetBEUI always uses 802.2 encapsulation.
+                * XXX - should we check both the DSAP and the
+                * SSAP, like this, or should we check just the
+                * DSAP?
                 */
                b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU);
                gen_not(b0);
@@ -1147,17 +1189,22 @@ gen_linktype(proto)
                return gen_ether_linktype(proto);
                break;
 
-        case DLT_C_HDLC:
-            switch (proto) {
-            case LLCSAP_ISONS:
-                proto = (proto << 8 | LLCSAP_ISONS);
-                /* fall through */
-            default:
-                return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
-                break;
-            }
+       case DLT_C_HDLC:
+               switch (proto) {
+
+               case LLCSAP_ISONS:
+                       proto = (proto << 8 | LLCSAP_ISONS);
+                       /* fall through */
+
+               default:
+                       return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
+                       break;
+               }
+               break;
+
        case DLT_IEEE802_11:
        case DLT_PRISM_HEADER:
+       case DLT_IEEE802_11_RADIO:
        case DLT_FDDI:
        case DLT_IEEE802:
        case DLT_ATM_RFC1483:
@@ -1213,6 +1260,9 @@ gen_linktype(proto)
                case LLCSAP_ISONS:
                        /*
                         * OSI protocols always use 802.2 encapsulation.
+                        * XXX - should we check both the DSAP and the
+                        * LSAP, like this, or should we check just the
+                        * DSAP?
                         */
                        b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
                        b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
@@ -1486,9 +1536,14 @@ gen_linktype(proto)
 
        case DLT_NULL:
        case DLT_LOOP:
+       case DLT_ENC:
+       case DLT_PFLOG:
                /*
                 * For DLT_NULL, the link-layer header is a 32-bit
-                * word containing an AF_ value in *host* byte order.
+                * word containing an AF_ value in *host* byte order,
+                * and for DLT_ENC, the link-layer header begins
+                * with a 32-bit work containing an AF_ value in
+                * host byte order.
                 *
                 * In addition, if we're reading a saved capture file,
                 * the host byte order in the capture may not be the
@@ -1504,6 +1559,8 @@ gen_linktype(proto)
                 * This means that, when reading a capture file, just
                 * checking for our AF_INET6 value won't work if the
                 * capture file came from another OS.
+                *
+                * XXX - what's the byte order for DLT_PFLOG?
                 */
                switch (proto) {
 
@@ -1526,7 +1583,7 @@ gen_linktype(proto)
                        return gen_false();
                }
 
-               if (linktype == DLT_NULL) {
+               if (linktype == DLT_NULL || linktype == DLT_ENC) {
                        /*
                         * The AF_ value is in host byte order, but
                         * the BPF interpreter will convert it to
@@ -1547,36 +1604,45 @@ gen_linktype(proto)
                return (gen_cmp(0, BPF_W, (bpf_int32)proto));
 
        case DLT_ARCNET:
+       case DLT_ARCNET_LINUX:
                /*
                 * XXX should we check for first fragment if the protocol
                 * uses PHDS?
                 */
-               switch(proto) {
+               switch (proto) {
+
                default:
                        return gen_false();
+
 #ifdef INET6
                case ETHERTYPE_IPV6:
-                       return(gen_cmp(2, BPF_B,
-                                       (bpf_int32)htonl(ARCTYPE_INET6)));
+                       return (gen_cmp(off_linktype, BPF_B,
+                               (bpf_int32)ARCTYPE_INET6));
 #endif /* INET6 */
+
                case ETHERTYPE_IP:
-                       b0 = gen_cmp(2, BPF_B, (bpf_int32)htonl(ARCTYPE_IP));
-                       b1 = gen_cmp(2, BPF_B,
-                                       (bpf_int32)htonl(ARCTYPE_IP_OLD));
+                       b0 = gen_cmp(off_linktype, BPF_B, 
+                                    (bpf_int32)ARCTYPE_IP);
+                       b1 = gen_cmp(off_linktype, BPF_B,
+                                    (bpf_int32)ARCTYPE_IP_OLD);
                        gen_or(b0, b1);
-                       return(b1);
+                       return (b1);
+
                case ETHERTYPE_ARP:
-                       b0 = gen_cmp(2, BPF_B, (bpf_int32)htonl(ARCTYPE_ARP));
-                       b1 = gen_cmp(2, BPF_B,
-                                       (bpf_int32)htonl(ARCTYPE_ARP_OLD));
+                       b0 = gen_cmp(off_linktype, BPF_B,
+                                    (bpf_int32)ARCTYPE_ARP);
+                       b1 = gen_cmp(off_linktype, BPF_B, 
+                                    (bpf_int32)ARCTYPE_ARP_OLD);
                        gen_or(b0, b1);
-                       return(b1);
+                       return (b1);
+
                case ETHERTYPE_REVARP:
-                       return(gen_cmp(2, BPF_B,
-                                       (bpf_int32)htonl(ARCTYPE_REVARP)));
+                       return (gen_cmp(off_linktype, BPF_B,
+                                       (bpf_int32)ARCTYPE_REVARP));
+
                case ETHERTYPE_ATALK:
-                       return(gen_cmp(2, BPF_B,
-                                       (bpf_int32)htonl(ARCTYPE_ATALK)));
+                       return (gen_cmp(off_linktype, BPF_B,
+                                       (bpf_int32)ARCTYPE_ATALK));
                }
                break;
 
@@ -1698,10 +1764,10 @@ gen_llc(proto)
         */
        switch (proto) {
 
-        case LLCSAP_IP:
+       case LLCSAP_IP:
                return gen_cmp(off_linktype, BPF_H, (long)
                             ((LLCSAP_IP << 8) | LLCSAP_IP));
-                
+
        case LLCSAP_ISONS:
                return gen_cmp(off_linktype, BPF_H, (long)
                             ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
@@ -2695,7 +2761,7 @@ gen_proto_abbrev(proto)
        int proto;
 {
        struct block *b0;
-        struct block *b1;
+       struct block *b1;
 
        switch (proto) {
 
@@ -2881,7 +2947,7 @@ gen_proto_abbrev(proto)
                b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
                gen_or(b0, b1);
                b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);                
-                gen_or(b0, b1);
+               gen_or(b0, b1);
                break;
 
        case Q_ISIS_LSP: 
@@ -3031,19 +3097,24 @@ gen_port(port, ip_proto, dir)
 {
        struct block *b0, *b1, *tmp;
 
-        switch (linktype) {
-        case DLT_IEEE802_11:
-        case DLT_PRISM_HEADER:
-        case DLT_FDDI:
-        case DLT_IEEE802:
-        case DLT_ATM_RFC1483:
-        case DLT_ATM_CLIP:
-                b0 = gen_linktype(LLCSAP_IP);
-                break;
-        default:
-                b0 = gen_linktype(ETHERTYPE_IP);
-                break;
-        }
+       /*
+        * ether proto ip
+        *
+        * For FDDI, RFC 1188 says that SNAP encapsulation is used,
+        * not LLC encapsulation with LLCSAP_IP.
+        *
+        * For IEEE 802 networks - which includes 802.5 token ring
+        * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
+        * says that SNAP encapsulation is used, not LLC encapsulation
+        * with LLCSAP_IP.
+        *
+        * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
+        * RFC 2225 say that SNAP encapsulation is used, not LLC
+        * encapsulation with LLCSAP_IP.
+        *
+        * So we always check for ETHERTYPE_IP.
+        */
+       b0 =  gen_linktype(ETHERTYPE_IP);
 
        switch (ip_proto) {
        case IPPROTO_UDP:
@@ -3507,19 +3578,22 @@ gen_proto(v, proto, dir)
                /*FALLTHROUGH*/
 #endif
        case Q_IP:
-                switch (linktype) {
-                case DLT_IEEE802_11:
-                case DLT_PRISM_HEADER:
-                case DLT_FDDI:
-                case DLT_IEEE802:
-                case DLT_ATM_RFC1483:
-                case DLT_ATM_CLIP:
-                       b0 = gen_linktype(LLCSAP_IP);
-                        break;
-                default:
-                        b0 = gen_linktype(ETHERTYPE_IP);
-                        break;
-                }
+               /*
+                * For FDDI, RFC 1188 says that SNAP encapsulation is used,
+                * not LLC encapsulation with LLCSAP_IP.
+                *
+                * For IEEE 802 networks - which includes 802.5 token ring
+                * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
+                * says that SNAP encapsulation is used, not LLC encapsulation
+                * with LLCSAP_IP.
+                *
+                * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
+                * RFC 2225 say that SNAP encapsulation is used, not LLC
+                * encapsulation with LLCSAP_IP.
+                *
+                * So we always check for ETHERTYPE_IP.
+                */
+               b0 = gen_linktype(ETHERTYPE_IP);
 #ifndef CHASE_CHAIN
                b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v);
 #else
@@ -3553,13 +3627,17 @@ gen_proto(v, proto, dir)
                        return gen_cmp(2, BPF_H, (0x03<<8) | v);
                        break;
 
-                case DLT_C_HDLC:
-                        /* Cisco uses an Ethertype lookalike - for OSI its 0xfefe */
-                        b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
-                        /* OSI in C-HDLC is stuffed with a fudge byte */
+               case DLT_C_HDLC:
+                       /*
+                        * Cisco uses an Ethertype lookalike - for OSI,
+                        * it's 0xfefe.
+                        */
+                       b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
+                       /* OSI in C-HDLC is stuffed with a fudge byte */
                        b1 = gen_cmp(off_nl_nosnap+1, BPF_B, (long)v);
                        gen_and(b0, b1);
-                        return b1;
+                       return b1;
+
                default:
                        b0 = gen_linktype(LLCSAP_ISONS);
                        b1 = gen_cmp(off_nl_nosnap, BPF_B, (long)v);
@@ -3567,12 +3645,15 @@ gen_proto(v, proto, dir)
                        return b1;
                }
 
-        case Q_ISIS:
-            b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
-            /* 4 is the offset of the PDU type relative to the IS-IS header */
-            b1 = gen_cmp(off_nl_nosnap+4, BPF_B, (long)v);
-            gen_and(b0, b1);
-            return b1;
+       case Q_ISIS:
+               b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+               /*
+                * 4 is the offset of the PDU type relative to the IS-IS
+                * header.
+                */
+               b1 = gen_cmp(off_nl_nosnap+4, BPF_B, (long)v);
+               gen_and(b0, b1);
+               return b1;
 
        case Q_ARP:
                bpf_error("arp does not encapsulate another protocol");
@@ -4576,7 +4657,7 @@ gen_broadcast(proto)
 
        case Q_DEFAULT:
        case Q_LINK:
-               if (linktype == DLT_ARCNET)
+               if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX)
                        return gen_ahostop(abroadcast, Q_DST);
                if (linktype == DLT_EN10MB)
                        return gen_ehostop(ebroadcast, Q_DST);
@@ -4586,6 +4667,8 @@ gen_broadcast(proto)
                        return gen_thostop(ebroadcast, Q_DST);
                if (linktype == DLT_IEEE802_11)
                        return gen_wlanhostop(ebroadcast, Q_DST);
+               if (linktype == DLT_IP_OVER_FC)
+                       return gen_ipfchostop(ebroadcast, Q_DST);
                if (linktype == DLT_SUNATM && is_lane) {
                        /*
                         * Check that the packet doesn't begin with an
@@ -4615,7 +4698,7 @@ gen_broadcast(proto)
                gen_and(b0, b2);
                return b2;
        }
-       bpf_error("only ether/ip broadcast filters supported");
+       bpf_error("only link-layer/IP broadcast filters supported");
 }
 
 /*
@@ -4649,7 +4732,7 @@ gen_multicast(proto)
 
        case Q_DEFAULT:
        case Q_LINK:
-               if (linktype == DLT_ARCNET)
+               if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX)
                        /* all ARCnet multicasts use the same address */
                        return gen_ahostop(abroadcast, Q_DST);
 
@@ -4793,6 +4876,11 @@ gen_multicast(proto)
                        return b0;
                }
 
+               if (linktype == DLT_IP_OVER_FC) {
+                       b0 = gen_mac_multicast(2);
+                       return b0;
+               }
+
                if (linktype == DLT_SUNATM && is_lane) {
                        /*
                         * Check that the packet doesn't begin with an
@@ -4826,7 +4914,7 @@ gen_multicast(proto)
                return b1;
 #endif /* INET6 */
        }
-       bpf_error("only IP multicast filters supported on ethernet/FDDI");
+       bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
 }
 
 /*
@@ -4845,7 +4933,6 @@ gen_inbound(dir)
         */
        switch (linktype) {
        case DLT_SLIP:
-       case DLT_PPP:
                b0 = gen_relation(BPF_JEQ,
                          gen_load(Q_LINK, gen_loadi(0), 1),
                          gen_loadi(0),
@@ -4873,8 +4960,13 @@ gen_inbound(dir)
                }
                break;
 
+       case DLT_PFLOG:
+               b0 = gen_cmp(26, BPF_H,
+                   (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
+               break;
+
        default:
-               bpf_error("inbound/outbound not supported on linktype %d\n",
+               bpf_error("inbound/outbound not supported on linktype %d",
                    linktype);
                b0 = NULL;
                /* NOTREACHED */
@@ -4882,13 +4974,65 @@ gen_inbound(dir)
        return (b0);
 }
 
+/* PF firewall log matched interface */
+struct block *
+gen_pf_ifname(const char *ifname)
+{
+       if (linktype != DLT_PFLOG) {
+               bpf_error("ifname supported only for DLT_PFLOG");
+               /* NOTREACHED */
+       }
+       if (strlen(ifname) >= 16) {
+               bpf_error("ifname interface names can't be larger than 16 characters");
+               /* NOTREACHED */
+       }
+       return (gen_bcmp(4, strlen(ifname), (const u_char *)ifname));
+}
+
+
+/* PF firewall log rule number */
+struct block *
+gen_pf_rnr(int rnr)
+{
+       if (linktype != DLT_PFLOG) {
+               bpf_error("rnr supported only for DLT_PFLOG");
+               /* NOTREACHED */
+       }
+
+       return (gen_cmp(20, BPF_H, (bpf_int32)rnr));
+}
+
+/* PF firewall log reason code */
+struct block *
+gen_pf_reason(int reason)
+{
+       if (linktype != DLT_PFLOG) {
+               bpf_error("reason supported only for DLT_PFLOG");
+               /* NOTREACHED */
+       }
+
+       return (gen_cmp(22, BPF_H, (bpf_int32)reason));
+}
+
+/* PF firewall log action */
+struct block *
+gen_pf_action(int action)
+{
+       if (linktype != DLT_PFLOG) {
+               bpf_error("action supported only for DLT_PFLOG");
+               /* NOTREACHED */
+       }
+
+       return (gen_cmp(24, BPF_H, (bpf_int32)action));
+}
+
 struct block *
 gen_acode(eaddr, q)
        register const u_char *eaddr;
        struct qual q;
 {
        if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
-               if (linktype == DLT_ARCNET)
+               if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX)
                        return gen_ahostop(eaddr, (int)q.dir);
        }
        bpf_error("ARCnet address used in non-arc expression");