]> The Tcpdump Group git mirrors - libpcap/blobdiff - gencode.c
Get ready for libpcap 0.7.2
[libpcap] / gencode.c
index e567de14fcada6331a38d4356a94cc3c3ad8283a..f18bad5c01a3287bca8349041d4eafe05d31ceb8 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.154 2001-06-10 01:11:40 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.160.2.4 2002-06-01 23:23:20 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -35,8 +35,8 @@ static const char rcsid[] =
 #include <sys/param.h>
 #endif
 
-struct mbuf;
-struct rtentry;
+struct mbuf;           /* Squelch compiler warnings on some platforms for */
+struct rtentry;                /* declarations in <net/if.h> */
 #include <net/if.h>
 
 #include <netinet/in.h>
@@ -56,11 +56,10 @@ struct rtentry;
 #include "ppp.h"
 #include "sll.h"
 #include "arcnet.h"
-#include <pcap-namedb.h>
 #ifdef INET6
-#include <netdb.h>
-#include <sys/socket.h>
+#include <netdb.h>     /* for "struct addrinfo" */
 #endif /*INET6*/
+#include <pcap-namedb.h>
 
 #define ETHERMTU       1500
 
@@ -78,6 +77,9 @@ struct rtentry;
 static jmp_buf top_ctx;
 static pcap_t *bpf_pcap;
 
+/* Hack for updating VLAN offsets. */
+static u_int   orig_linktype = -1, orig_nl = -1, orig_nl_nosnap = -1;
+
 /* XXX */
 #ifdef PCAP_FDDIPAD
 int    pcap_fddipad = PCAP_FDDIPAD;
@@ -538,11 +540,55 @@ gen_bcmp(offset, size, v)
 
 /*
  * Various code constructs need to know the layout of the data link
- * layer.  These variables give the necessary offsets.  off_linktype
- * is set to -1 for no encapsulation, in which case, IP is assumed.
+ * layer.  These variables give the necessary offsets.
+ */
+
+/*
+ * "off_linktype" is the offset to information in the link-layer header
+ * giving the packet type.
+ *
+ * For Ethernet, it's the offset of the Ethernet type field.
+ *
+ * For link-layer types that always use 802.2 headers, it's the
+ * offset of the LLC header.
+ *
+ * For PPP, it's the offset of the PPP type field.
+ *
+ * For Cisco HDLC, it's the offset of the CHDLC type field.
+ *
+ * For BSD loopback, it's the offset of the AF_ value.
+ *
+ * For Linux cooked sockets, it's the offset of the type field.
+ *
+ * It's set to -1 for no encapsulation, in which case, IP is assumed.
  */
 static u_int off_linktype;
+
+/*
+ * These are offsets to the beginning of the network-layer header.
+ *
+ * If the link layer never uses 802.2 LLC:
+ *
+ *     "off_nl" and "off_nl_nosnap" are the same.
+ *
+ * If the link layer always uses 802.2 LLC:
+ *
+ *     "off_nl" is the offset if there's a SNAP header following
+ *     the 802.2 header;
+ *
+ *     "off_nl_nosnap" is the offset if there's no SNAP header.
+ *
+ * If the link layer is Ethernet:
+ *
+ *     "off_nl" is the offset if the packet is an Ethernet II packet
+ *     (we assume no 802.3+802.2+SNAP);
+ *
+ *     "off_nl_nosnap" is the offset if the packet is an 802.3 packet
+ *     with an 802.2 header following it.
+ */
 static u_int off_nl;
+static u_int off_nl_nosnap;
+
 static int linktype;
 
 static void
@@ -551,16 +597,22 @@ init_linktype(type)
 {
        linktype = type;
 
+       orig_linktype = -1;
+       orig_nl = -1;
+       orig_nl_nosnap = -1;
+
        switch (type) {
 
        case DLT_ARCNET:
                off_linktype = 2;
                off_nl = 6;     /* XXX in reality, variable! */
+               off_nl_nosnap = 6;      /* no 802.2 LLC */
                return;
 
        case DLT_EN10MB:
                off_linktype = 12;
-               off_nl = 14;
+               off_nl = 14;            /* Ethernet II */
+               off_nl_nosnap = 17;     /* 802.3+802.2 */
                return;
 
        case DLT_SLIP:
@@ -570,6 +622,7 @@ init_linktype(type)
                 */
                off_linktype = -1;
                off_nl = 16;
+               off_nl_nosnap = 16;     /* no 802.2 LLC */
                return;
 
        case DLT_SLIP_BSDOS:
@@ -577,12 +630,14 @@ init_linktype(type)
                off_linktype = -1;
                /* XXX end */
                off_nl = 24;
+               off_nl_nosnap = 24;     /* no 802.2 LLC */
                return;
 
        case DLT_NULL:
        case DLT_LOOP:
                off_linktype = 0;
                off_nl = 4;
+               off_nl_nosnap = 4;      /* no 802.2 LLC */
                return;
 
        case DLT_PPP:
@@ -590,21 +645,23 @@ init_linktype(type)
        case DLT_PPP_SERIAL:            /* NetBSD sync/async serial PPP */
                off_linktype = 2;
                off_nl = 4;
+               off_nl_nosnap = 4;      /* no 802.2 LLC */
                return;
 
-       case DLT_PPP_ETHER:             /* NetBSD PPP over Ethernet */
+       case DLT_PPP_ETHER:
                /*
-                * This includes the Ethernet header (since we need
-                * the ethertype to dispatch Session vs. Discovery)
-                * and the PPPoE (RFC 2516) header.
+                * This does no include the Ethernet header, and
+                * only covers session state.
                 */
-               off_linktype = 20;
-               off_nl = 22;
+               off_linktype = 6;
+               off_nl = 8;
+               off_nl_nosnap = 8;      /* no 802.2 LLC */
                return;
 
        case DLT_PPP_BSDOS:
                off_linktype = 5;
                off_nl = 24;
+               off_nl_nosnap = 24;     /* no 802.2 LLC */
                return;
 
        case DLT_FDDI:
@@ -620,9 +677,11 @@ init_linktype(type)
 #ifdef PCAP_FDDIPAD
                off_linktype += pcap_fddipad;
 #endif
-               off_nl = 21;
+               off_nl = 21;            /* FDDI+802.2+SNAP */
+               off_nl_nosnap = 16;     /* FDDI+802.2 */
 #ifdef PCAP_FDDIPAD
                off_nl += pcap_fddipad;
+               off_nl_nosnap += pcap_fddipad;
 #endif
                return;
 
@@ -651,7 +710,8 @@ init_linktype(type)
                 * 8 - figure out which byte that is).
                 */
                off_linktype = 14;
-               off_nl = 22;
+               off_nl = 22;            /* Token Ring+802.2+SNAP */
+               off_nl_nosnap = 17;     /* Token Ring+802.2 */
                return;
 
        case DLT_IEEE802_11:
@@ -668,31 +728,58 @@ init_linktype(type)
                 * data frames in networks with no bridges.
                 */
                off_linktype = 24;
-               off_nl = 30;
+               off_nl = 32;            /* 802.11+802.2+SNAP */
+               off_nl_nosnap = 27;     /* 802.22+802.2 */
+               return;
+
+       case DLT_PRISM_HEADER:
+               /*
+                * 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 144 bytes long.
+                *
+                * XXX - same variable-length header problem; at least
+                * the Prism header is fixed-length.
+                */
+               off_linktype = 144+24;
+               off_nl = 144+32;        /* Prism+802.11+802.2+SNAP */
+               off_nl_nosnap = 144+27; /* Prism+802.11+802.2 */
                return;
 
        case DLT_ATM_RFC1483:
+       case DLT_ATM_CLIP:      /* Linux ATM defines this */
                /*
                 * assume routed, non-ISO PDUs
                 * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
                 */
-               off_linktype = 6;
-               off_nl = 8;
+               off_linktype = 0;
+               off_nl = 8;             /* 802.2+SNAP */
+               off_nl_nosnap = 3;      /* 802.2 */
                return;
 
        case DLT_RAW:
                off_linktype = -1;
                off_nl = 0;
-               return;
-
-       case DLT_ATM_CLIP:      /* Linux ATM defines this */
-               off_linktype = 6;
-               off_nl = 8;
+               off_nl_nosnap = 0;      /* no 802.2 LLC */
                return;
 
        case DLT_LINUX_SLL:     /* fake header for Linux cooked socket */
                off_linktype = 14;
                off_nl = 16;
+               off_nl_nosnap = 16;     /* no 802.2 LLC */
+               return;
+
+       case DLT_LTALK:
+               /*
+                * LocalTalk does have a 1-byte type field in the LLAP header,
+                * but really it just indicates whether there is a "short" or
+                * "long" DDP packet following.
+                */
+               off_linktype = -1;
+               off_nl = 0;
+               off_nl_nosnap = 0;      /* no 802.2 LLC */
                return;
        }
        bpf_error("unknown data link type %d", linktype);
@@ -919,6 +1006,7 @@ gen_linktype(proto)
                break;
 
        case DLT_IEEE802_11:
+       case DLT_PRISM_HEADER:
        case DLT_FDDI:
        case DLT_IEEE802:
        case DLT_ATM_RFC1483:
@@ -1178,6 +1266,7 @@ gen_linktype(proto)
 
        case DLT_PPP:
        case DLT_PPP_SERIAL:
+       case DLT_PPP_ETHER:
                /*
                 * We use Ethernet protocol types inside libpcap;
                 * map them to the corresponding PPP protocol types.
@@ -1373,6 +1462,15 @@ gen_linktype(proto)
                                        (bpf_int32)htonl(ARCTYPE_ATALK)));
                }
                break;
+
+       case DLT_LTALK:
+               switch (proto) {
+               case ETHERTYPE_ATALK:
+                       return gen_true();
+               default:
+                       return gen_false();
+               }
+               break;
        }
 
        /*
@@ -2749,7 +2847,7 @@ gen_proto(v, proto, dir)
 
        case Q_ISO:
                b0 = gen_linktype(LLCSAP_ISONS);
-               b1 = gen_cmp(off_nl + 3, BPF_B, (long)v);
+               b1 = gen_cmp(off_nl_nosnap, BPF_B, (long)v);
                gen_and(b0, b1);
                return b1;
 
@@ -2903,21 +3001,27 @@ gen_scode(name, q)
                                if (eaddr == NULL)
                                        bpf_error(
                                            "unknown ether host '%s'", name);
-                               return gen_ehostop(eaddr, dir);
+                               b = gen_ehostop(eaddr, dir);
+                               free(eaddr);
+                               return b;
 
                        case DLT_FDDI:
                                eaddr = pcap_ether_hostton(name);
                                if (eaddr == NULL)
                                        bpf_error(
                                            "unknown FDDI host '%s'", name);
-                               return gen_fhostop(eaddr, dir);
+                               b = gen_fhostop(eaddr, dir);
+                               free(eaddr);
+                               return b;
 
                        case DLT_IEEE802:
                                eaddr = pcap_ether_hostton(name);
                                if (eaddr == NULL)
                                        bpf_error(
                                            "unknown token ring host '%s'", name);
-                               return gen_thostop(eaddr, dir);
+                               b = gen_thostop(eaddr, dir);
+                               free(eaddr);
+                               return b;
 
                        default:
                                bpf_error(
@@ -3051,7 +3155,9 @@ gen_scode(name, q)
                alist = pcap_nametoaddr(name);
                if (alist == NULL || *alist == NULL)
                        bpf_error("unknown host '%s'", name);
-               return gen_gateway(eaddr, alist, proto, dir);
+               b = gen_gateway(eaddr, alist, proto, dir);
+               free(eaddr);
+               return b;
 #else
                bpf_error("'gateway' not supported in this configuration");
 #endif /*INET6*/
@@ -3232,6 +3338,7 @@ gen_mcode6(s1, s2, masklen, q)
 
        if (sizeof(mask) * 8 < masklen)
                bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
+       memset(&mask, 0, sizeof(mask));
        memset(&mask, 0xff, masklen / 8);
        if (masklen % 8) {
                mask.s6_addr[masklen / 8] =
@@ -3846,7 +3953,6 @@ struct block *
 gen_vlan(vlan_num)
        int vlan_num;
 {
-       static u_int    orig_linktype = -1, orig_nl = -1;
        struct  block   *b0;
 
        /*
@@ -3856,11 +3962,13 @@ gen_vlan(vlan_num)
        if (orig_nl == (u_int)-1) {
                orig_linktype = off_linktype;   /* save original values */
                orig_nl = off_nl;
+               orig_nl_nosnap = off_nl_nosnap;
 
                switch (linktype) {
 
                case DLT_EN10MB:
                        off_linktype = 16;
+                       off_nl_nosnap = 18;
                        off_nl = 18;
                        break;