X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/bd4881668c87901ee50a4bf648a4bcc2b38ad5c0..2f23c057fc71caaea4e57a151d23c0d0fc6c2552:/gencode.c diff --git a/gencode.c b/gencode.c index 47eba1b9..535f4a64 100644 --- a/gencode.c +++ b/gencode.c @@ -20,8 +20,8 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint -static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.182 2002-12-06 00:01:33 hannes Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.216 2005-01-12 09:02:55 hannes Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -33,7 +33,6 @@ static const char rcsid[] = #else /* WIN32 */ #include #include -#include #endif /* WIN32 */ /* @@ -59,6 +58,10 @@ static const char rcsid[] = #include #include +#ifdef MSDOS +#include "pcap-dos.h" +#endif + #include "pcap-int.h" #include "ethertype.h" @@ -70,6 +73,10 @@ static const char rcsid[] = #include "ppp.h" #include "sll.h" #include "arcnet.h" +#include "pf.h" +#ifndef offsetof +#define offsetof(s, e) ((size_t)&((s *)0)->e) +#endif #ifdef INET6 #ifndef WIN32 #include /* for "struct addrinfo" */ @@ -93,14 +100,12 @@ static const char rcsid[] = 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; +/* Hack for updating VLAN, MPLS offsets. */ +static u_int orig_linktype = -1U, orig_nl = -1U, orig_nl_nosnap = -1U; /* XXX */ #ifdef PCAP_FDDIPAD -int pcap_fddipad = PCAP_FDDIPAD; -#else -int pcap_fddipad; +static int pcap_fddipad; #endif /* VARARGS */ @@ -119,7 +124,7 @@ bpf_error(const char *fmt, ...) /* NOTREACHED */ } -static void init_linktype(int); +static void init_linktype(pcap_t *); static int alloc_reg(void); static void free_reg(int); @@ -129,8 +134,10 @@ static struct block *root; /* * We divy out chunks of memory rather than call malloc each time so * we don't have to worry about leaking memory. It's probably - * not a big deal if all this memory was wasted but it this ever + * not a big deal if all this memory was wasted but if this ever * goes into a library that would probably not be a good idea. + * + * XXX - this *is* in a library.... */ #define NCHUNKS 16 #define CHUNK0SIZE 1024 @@ -161,6 +168,7 @@ static struct block *gen_uncond(int); static inline struct block *gen_true(void); static inline struct block *gen_false(void); static struct block *gen_ether_linktype(int); +static struct block *gen_linux_sll_linktype(int); static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); static struct block *gen_llc(int); @@ -208,7 +216,8 @@ newchunk(n) u_int n; { struct chunk *cp; - int k, size; + int k; + size_t size; #ifndef __NetBSD__ /* XXX Round up to nearest long. */ @@ -225,6 +234,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) @@ -333,7 +344,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program, } lex_init(buf ? buf : ""); - init_linktype(pcap_datalink(p)); + init_linktype(p); (void)pcap_parse(); if (n_errors) @@ -570,15 +581,15 @@ gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse) { struct slist *s; struct block *b; - + s = new_stmt(BPF_LD|datasize|BPF_ABS); s->s.k = offset; - + if (mask != 0xffffffff) { s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K); s->next->s.k = mask; } - + b = new_block(JMP(jtype)); b->stmts = s; b->s.k = jvalue; @@ -671,10 +682,13 @@ static u_int off_nl_nosnap; static int linktype; static void -init_linktype(type) - int type; +init_linktype(p) + pcap_t *p; { - linktype = type; + linktype = pcap_datalink(p); +#ifdef PCAP_FDDIPAD + pcap_fddipad = p->fddipad; +#endif /* * Assume it's not raw ATM with a pseudo-header, for now. @@ -691,14 +705,20 @@ init_linktype(type) orig_nl = -1; orig_nl_nosnap = -1; - switch (type) { + switch (linktype) { 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,7 +750,14 @@ 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_PPP: + case DLT_PPP_WITHDIRECTION: case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; @@ -815,7 +842,9 @@ init_linktype(type) * * XXX - the header is actually variable-length. We * assume a 24-byte link-layer header, as appears in - * data frames in networks with no bridges. + * data frames in networks with no bridges. If the + * fromds and tods 802.11 header bits are both set, + * it's actually supposed to be 30 bytes. */ off_linktype = 24; off_nl = 32; /* 802.11+802.2+SNAP */ @@ -838,11 +867,50 @@ 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_AVS: + /* + * 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, at least in its + * current incarnation. + * + * 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_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. + * + * XXX - same variable-length header problem, only + * even *more* so; this header is also variable-length, + * with the length being the 16-bit number at an offset + * of 2 from the beginning of the radio header, and it's + * device-dependent (different devices might supply + * different amounts of information), so we can't even + * assume a fixed length for the current version of the + * header. + * + * Therefore, currently, only raw "link[N:M]" filtering is + * supported. + */ + off_linktype = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_ATM_RFC1483: case DLT_ATM_CLIP: /* Linux ATM defines this */ /* * assume routed, non-ISO PDUs @@ -862,7 +930,7 @@ init_linktype(type) off_vpi = SUNATM_VPI_POS; off_vci = SUNATM_VCI_POS; off_proto = PROTO_POS; - off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */ + off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */ off_payload = SUNATM_PKT_BEGIN_POS; off_linktype = off_payload; off_nl = off_payload+8; /* 802.2+SNAP */ @@ -917,6 +985,69 @@ init_linktype(type) off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ return; + + case DLT_APPLE_IP_OVER_IEEE1394: + off_linktype = 16; + off_nl = 18; + off_nl_nosnap = 0; /* no 802.2 LLC */ + return; + + case DLT_LINUX_IRDA: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_DOCSIS: + /* + * Currently, only raw "link[N:M]" filtering is supported. + */ + off_linktype = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + + case DLT_SYMANTEC_FIREWALL: + off_linktype = 6; + off_nl = 44; /* Ethernet II */ + off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */ + return; + + case DLT_PFLOG: + off_linktype = 0; + /* XXX read from header? */ + off_nl = PFLOG_HDRLEN; + off_nl_nosnap = PFLOG_HDRLEN; + return; + + case DLT_JUNIPER_MLPPP: + off_linktype = 4; + off_nl = 4; + off_nl_nosnap = -1; + break; + + case DLT_JUNIPER_ATM1: + off_linktype = 4; /* in reality variable between 4-8 */ + off_nl = 4; + off_nl_nosnap = 14; + return; + + case DLT_JUNIPER_ATM2: + off_linktype = 8; /* in reality variable between 8-12 */ + off_nl = 8; + off_nl_nosnap = 18; + return; + +#ifdef DLT_PFSYNC + case DLT_PFSYNC: + off_linktype = -1; + off_nl = 4; + off_nl_nosnap = 4; + return; +#endif } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ @@ -968,6 +1099,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 +1121,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); @@ -1135,6 +1272,172 @@ gen_ether_linktype(proto) } } +static struct block * +gen_linux_sll_linktype(proto) + register int proto; +{ + struct block *b0, *b1; + + switch (proto) { + + case LLCSAP_IP: + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_IP << 8) | LLCSAP_IP)); + gen_and(b0, b1); + return b1; + + 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(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + gen_and(b0, b1); + return b1; + + case LLCSAP_NETBEUI: + /* + * NetBEUI always uses 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) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + gen_and(b0, b1); + return b1; + + case LLCSAP_IPX: + /* + * Ethernet_II frames, which are Ethernet + * frames with a frame type of ETHERTYPE_IPX; + * + * Ethernet_802.3 frames, which have a frame + * type of LINUX_SLL_P_802_3; + * + * Ethernet_802.2 frames, which are 802.3 + * frames with an 802.2 LLC header (i.e, have + * a frame type of LINUX_SLL_P_802_2) and + * with the IPX LSAP as the DSAP in the LLC + * header; + * + * Ethernet_SNAP frames, which are 802.3 + * frames with an LLC header and a SNAP + * header and with an OUI of 0x000000 + * (encapsulated Ethernet) and a protocol + * ID of ETHERTYPE_IPX in the SNAP header. + * + * First, do the checks on LINUX_SLL_P_802_2 + * frames; generate the check for either + * Ethernet_802.2 or Ethernet_SNAP frames, and + * then put a check for LINUX_SLL_P_802_2 frames + * before it. + */ + b0 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)LLCSAP_IPX); + b1 = gen_snap(0x000000, ETHERTYPE_IPX, + off_linktype + 2); + gen_or(b0, b1); + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + gen_and(b0, b1); + + /* + * Now check for 802.3 frames and OR that with + * the previous test. + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3); + gen_or(b0, b1); + + /* + * Now add the check for Ethernet_II frames, and + * do that before checking for the other frame + * types. + */ + b0 = gen_cmp(off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_IPX); + gen_or(b0, b1); + return b1; + + case ETHERTYPE_ATALK: + case ETHERTYPE_AARP: + /* + * EtherTalk (AppleTalk protocols on Ethernet link + * layer) may use 802.2 encapsulation. + */ + + /* + * Check for 802.2 encapsulation (EtherTalk phase 2?); + * we check for the 802.2 protocol type in the + * "Ethernet type" field. + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + + /* + * 802.2-encapsulated ETHERTYPE_ATALK packets are + * SNAP packets with an organization code of + * 0x080007 (Apple, for Appletalk) and a protocol + * type of ETHERTYPE_ATALK (Appletalk). + * + * 802.2-encapsulated ETHERTYPE_AARP packets are + * SNAP packets with an organization code of + * 0x000000 (encapsulated Ethernet) and a protocol + * type of ETHERTYPE_AARP (Appletalk ARP). + */ + if (proto == ETHERTYPE_ATALK) + b1 = gen_snap(0x080007, ETHERTYPE_ATALK, + off_linktype + 2); + else /* proto == ETHERTYPE_AARP */ + b1 = gen_snap(0x000000, ETHERTYPE_AARP, + off_linktype + 2); + gen_and(b0, b1); + + /* + * Check for Ethernet encapsulation (Ethertalk + * phase 1?); we just check for the Ethernet + * protocol type. + */ + b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + + gen_or(b0, b1); + return b1; + + default: + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so the frames + * that match would be 802.2 frames. + * Check for the 802.2 protocol type + * in the "Ethernet type" field, and + * then check the DSAP. + */ + b0 = gen_cmp(off_linktype, BPF_H, + LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)proto); + gen_and(b0, b1); + return b1; + } else { + /* + * This is an Ethernet type, so compare + * the length/type field with it (if + * the frame is an 802.2 frame, the length + * field will be <= ETHERMTU, and, as + * "proto" is > ETHERMTU, this test + * will fail and the frame won't match, + * which is what we want). + */ + return gen_cmp(off_linktype, BPF_H, + (bpf_int32)proto); + } + } +} + static struct block * gen_linktype(proto) register int proto; @@ -1145,25 +1448,33 @@ gen_linktype(proto) case DLT_EN10MB: return gen_ether_linktype(proto); + /*NOTREACHED*/ + 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); + /*NOTREACHED*/ + break; + } 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_IEEE802_11: case DLT_PRISM_HEADER: + case DLT_IEEE802_11_RADIO: case DLT_FDDI: case DLT_IEEE802: case DLT_ATM_RFC1483: case DLT_ATM_CLIP: case DLT_IP_OVER_FC: return gen_llc(proto); + /*NOTREACHED*/ break; case DLT_SUNATM: @@ -1201,161 +1512,8 @@ gen_linktype(proto) } case DLT_LINUX_SLL: - switch (proto) { - - case LLCSAP_IP: - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_IP << 8) | LLCSAP_IP)); - gen_and(b0, b1); - return b1; - - case LLCSAP_ISONS: - /* - * OSI protocols always use 802.2 encapsulation. - */ - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); - gen_and(b0, b1); - return b1; - - case LLCSAP_NETBEUI: - /* - * NetBEUI always uses 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) - ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); - gen_and(b0, b1); - return b1; - - case LLCSAP_IPX: - /* - * Ethernet_II frames, which are Ethernet - * frames with a frame type of ETHERTYPE_IPX; - * - * Ethernet_802.3 frames, which have a frame - * type of LINUX_SLL_P_802_3; - * - * Ethernet_802.2 frames, which are 802.3 - * frames with an 802.2 LLC header (i.e, have - * a frame type of LINUX_SLL_P_802_2) and - * with the IPX LSAP as the DSAP in the LLC - * header; - * - * Ethernet_SNAP frames, which are 802.3 - * frames with an LLC header and a SNAP - * header and with an OUI of 0x000000 - * (encapsulated Ethernet) and a protocol - * ID of ETHERTYPE_IPX in the SNAP header. - * - * First, do the checks on LINUX_SLL_P_802_2 - * frames; generate the check for either - * Ethernet_802.2 or Ethernet_SNAP frames, and - * then put a check for LINUX_SLL_P_802_2 frames - * before it. - */ - b0 = gen_cmp(off_linktype + 2, BPF_B, - (bpf_int32)LLCSAP_IPX); - b1 = gen_snap(0x000000, ETHERTYPE_IPX, - off_linktype + 2); - gen_or(b0, b1); - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); - gen_and(b0, b1); - - /* - * Now check for 802.3 frames and OR that with - * the previous test. - */ - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3); - gen_or(b0, b1); - - /* - * Now add the check for Ethernet_II frames, and - * do that before checking for the other frame - * types. - */ - b0 = gen_cmp(off_linktype, BPF_H, - (bpf_int32)ETHERTYPE_IPX); - gen_or(b0, b1); - return b1; - - case ETHERTYPE_ATALK: - case ETHERTYPE_AARP: - /* - * EtherTalk (AppleTalk protocols on Ethernet link - * layer) may use 802.2 encapsulation. - */ - - /* - * Check for 802.2 encapsulation (EtherTalk phase 2?); - * we check for the 802.2 protocol type in the - * "Ethernet type" field. - */ - b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); - - /* - * 802.2-encapsulated ETHERTYPE_ATALK packets are - * SNAP packets with an organization code of - * 0x080007 (Apple, for Appletalk) and a protocol - * type of ETHERTYPE_ATALK (Appletalk). - * - * 802.2-encapsulated ETHERTYPE_AARP packets are - * SNAP packets with an organization code of - * 0x000000 (encapsulated Ethernet) and a protocol - * type of ETHERTYPE_AARP (Appletalk ARP). - */ - if (proto == ETHERTYPE_ATALK) - b1 = gen_snap(0x080007, ETHERTYPE_ATALK, - off_linktype + 2); - else /* proto == ETHERTYPE_AARP */ - b1 = gen_snap(0x000000, ETHERTYPE_AARP, - off_linktype + 2); - gen_and(b0, b1); - - /* - * Check for Ethernet encapsulation (Ethertalk - * phase 1?); we just check for the Ethernet - * protocol type. - */ - b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); - - gen_or(b0, b1); - return b1; - - default: - if (proto <= ETHERMTU) { - /* - * This is an LLC SAP value, so the frames - * that match would be 802.2 frames. - * Check for the 802.2 protocol type - * in the "Ethernet type" field, and - * then check the DSAP. - */ - b0 = gen_cmp(off_linktype, BPF_H, - LINUX_SLL_P_802_2); - b1 = gen_cmp(off_linktype + 2, BPF_B, - (bpf_int32)proto); - gen_and(b0, b1); - return b1; - } else { - /* - * This is an Ethernet type, so compare - * the length/type field with it (if - * the frame is an 802.2 frame, the length - * field will be <= ETHERMTU, and, as - * "proto" is > ETHERMTU, this test - * will fail and the frame won't match, - * which is what we want). - */ - return gen_cmp(off_linktype, BPF_H, - (bpf_int32)proto); - } - } + return gen_linux_sll_linktype(proto); + /*NOTREACHED*/ break; case DLT_SLIP: @@ -1379,9 +1537,11 @@ gen_linktype(proto) default: return gen_false(); /* always false */ } + /*NOTREACHED*/ break; case DLT_PPP: + case DLT_PPP_WITHDIRECTION: case DLT_PPP_SERIAL: case DLT_PPP_ETHER: /* @@ -1486,9 +1646,13 @@ gen_linktype(proto) case DLT_NULL: case DLT_LOOP: + case DLT_ENC: /* * 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 @@ -1526,7 +1690,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 @@ -1546,38 +1710,66 @@ gen_linktype(proto) } return (gen_cmp(0, BPF_W, (bpf_int32)proto)); + case DLT_PFLOG: + /* + * af field is host byte order in contrast to the rest of + * the packet. + */ + if (proto == ETHERTYPE_IP) + return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B, + (bpf_int32)AF_INET)); +#ifdef INET6 + else if (proto == ETHERTYPE_IPV6) + return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B, + (bpf_int32)AF_INET6)); +#endif /* INET6 */ + else + return gen_false(); + /*NOTREACHED*/ + break; + 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)); } + /*NOTREACHED*/ break; case DLT_LTALK: @@ -1587,6 +1779,7 @@ gen_linktype(proto) default: return gen_false(); } + /*NOTREACHED*/ break; case DLT_FRELAY: @@ -1632,7 +1825,26 @@ gen_linktype(proto) default: return gen_false(); } + /*NOTREACHED*/ break; + + case DLT_JUNIPER_MLPPP: + case DLT_JUNIPER_ATM1: + case DLT_JUNIPER_ATM2: + /* just lets verify the magic number for now - + * we may have up to 6 different encapsulations on the wire + * and need a lot of heuristics to figure out that the payload + * might be; + * + * FIXME encapsulation specific BPF_ filters + */ + return gen_mcmp(0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ + + case DLT_LINUX_IRDA: + bpf_error("IrDA link-layer type filtering not implemented"); + + case DLT_DOCSIS: + bpf_error("DOCSIS link-layer type filtering not implemented"); } /* @@ -1645,7 +1857,7 @@ gen_linktype(proto) * * Therefore, if "off_linktype" is -1, there's an error. */ - if (off_linktype == -1) + if (off_linktype == (u_int)-1) abort(); /* @@ -1698,10 +1910,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)); @@ -2367,7 +2579,7 @@ gen_dnhostop(addr, dir, base_off) return b1; case Q_ISO: - bpf_error("ISO host filtering not implemented"); + bpf_error("ISO host filtering not implemented"); default: abort(); @@ -2415,7 +2627,7 @@ gen_host(addr, mask, proto, dir) case Q_DEFAULT: b0 = gen_host(addr, mask, Q_IP, dir); - if (off_linktype != -1) { + if (off_linktype != (u_int)-1) { b1 = gen_host(addr, mask, Q_ARP, dir); gen_or(b0, b1); b0 = gen_host(addr, mask, Q_RARP, dir); @@ -2695,7 +2907,7 @@ gen_proto_abbrev(proto) int proto; { struct block *b0; - struct block *b1; + struct block *b1; switch (proto) { @@ -2841,91 +3053,91 @@ gen_proto_abbrev(proto) break; case Q_ISO: - b1 = gen_linktype(LLCSAP_ISONS); + b1 = gen_linktype(LLCSAP_ISONS); break; case Q_ESIS: - b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT); + b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS: - b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); + b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); break; case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */ - b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ + b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); - b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */ - b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ + b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */ gen_or(b0, b1); - b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */ - b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT); + 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); - b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); - gen_or(b0, b1); break; - case Q_ISIS_LSP: - b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); + case Q_ISIS_LSP: + b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_SNP: - b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); - b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_CSNP: - b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_ISIS_PSNP: - b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); - b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); + b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT); + b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT); gen_or(b0, b1); break; case Q_CLNP: - b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); + b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); break; case Q_STP: - b1 = gen_linktype(LLCSAP_8021D); + b1 = gen_linktype(LLCSAP_8021D); break; case Q_IPX: - b1 = gen_linktype(LLCSAP_IPX); + b1 = gen_linktype(LLCSAP_IPX); break; case Q_NETBEUI: - b1 = gen_linktype(LLCSAP_NETBEUI); + b1 = gen_linktype(LLCSAP_NETBEUI); break; default: @@ -3031,19 +3243,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 +3724,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 @@ -3551,15 +3771,20 @@ gen_proto(v, proto, dir) * XXX - what about SNAP-encapsulated frames? */ return gen_cmp(2, BPF_H, (0x03<<8) | v); + /*NOTREACHED*/ 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 +3792,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"); @@ -3801,7 +4029,7 @@ gen_scode(name, q) if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); tproto = proto; - if (off_linktype == -1 && tproto == Q_DEFAULT) + if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT) tproto = Q_IP; b = gen_host(**alist++, 0xffffffff, tproto, dir); while (*alist) { @@ -3984,6 +4212,7 @@ gen_mcode(s1, s2, masklen, q) bpf_error("Mask syntax for networks only"); /* NOTREACHED */ } + /* NOTREACHED */ } struct block * @@ -4576,7 +4805,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 +4815,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 +4846,8 @@ 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"); + /* NOTREACHED */ } /* @@ -4649,7 +4881,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 +5025,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 +5063,8 @@ 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"); + /* NOTREACHED */ } /* @@ -4845,7 +5083,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 +5110,37 @@ gen_inbound(dir) } break; + case DLT_PFLOG: + b0 = gen_cmp(offsetof(struct pfloghdr, dir), BPF_B, + (bpf_int32)((dir == 0) ? PF_IN : PF_OUT)); + break; + + case DLT_PPP_WITHDIRECTION: + if (dir) { + /* match outgoing packets */ + b0 = gen_cmp(0, BPF_B, PPP_WITHDIRECTION_OUT); + } else { + /* match incoming packets */ + b0 = gen_cmp(0, BPF_B, PPP_WITHDIRECTION_IN); + } + break; + + case DLT_JUNIPER_MLPPP: + case DLT_JUNIPER_ATM1: + case DLT_JUNIPER_ATM2: + /* juniper flags (including direction) are stored + * the byte after the 3-byte magic number */ + if (dir) { + /* match outgoing packets */ + b0 = gen_mcmp(3, BPF_B, 0, 0x01); + } else { + /* match incoming packets */ + b0 = gen_mcmp(3, BPF_B, 1, 0x01); + } + 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 +5148,123 @@ gen_inbound(dir) return (b0); } +/* PF firewall log matched interface */ +struct block * +gen_pf_ifname(const char *ifname) +{ + struct block *b0; + u_int len, off; + + if (linktype == DLT_PFLOG) { + len = sizeof(((struct pfloghdr *)0)->ifname); + off = offsetof(struct pfloghdr, ifname); + } else { + bpf_error("ifname not supported on linktype 0x%x", linktype); + /* NOTREACHED */ + } + if (strlen(ifname) >= len) { + bpf_error("ifname interface names can only be %d characters", + len-1); + /* NOTREACHED */ + } + b0 = gen_bcmp(off, strlen(ifname), (const u_char *)ifname); + return (b0); +} + +/* PF firewall log matched interface */ +struct block * +gen_pf_ruleset(char *ruleset) +{ + struct block *b0; + + if (linktype != DLT_PFLOG) { + bpf_error("ruleset not supported on linktype 0x%x", linktype); + /* NOTREACHED */ + } + if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) { + bpf_error("ruleset names can only be %ld characters", + (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1)); + /* NOTREACHED */ + } + b0 = gen_bcmp(offsetof(struct pfloghdr, ruleset), + strlen(ruleset), (const u_char *)ruleset); + return (b0); +} + +/* PF firewall log rule number */ +struct block * +gen_pf_rnr(int rnr) +{ + struct block *b0; + + if (linktype == DLT_PFLOG) { + b0 = gen_cmp(offsetof(struct pfloghdr, rulenr), BPF_W, + (bpf_int32)rnr); + } else { + bpf_error("rnr not supported on linktype 0x%x", linktype); + /* NOTREACHED */ + } + + return (b0); +} + +/* PF firewall log sub-rule number */ +struct block * +gen_pf_srnr(int srnr) +{ + struct block *b0; + + if (linktype != DLT_PFLOG) { + bpf_error("srnr not supported on linktype 0x%x", linktype); + /* NOTREACHED */ + } + + b0 = gen_cmp(offsetof(struct pfloghdr, subrulenr), BPF_W, + (bpf_int32)srnr); + return (b0); +} + +/* PF firewall log reason code */ +struct block * +gen_pf_reason(int reason) +{ + struct block *b0; + + if (linktype == DLT_PFLOG) { + b0 = gen_cmp(offsetof(struct pfloghdr, reason), BPF_B, + (bpf_int32)reason); + } else { + bpf_error("reason not supported on linktype 0x%x", linktype); + /* NOTREACHED */ + } + + return (b0); +} + +/* PF firewall log action */ +struct block * +gen_pf_action(int action) +{ + struct block *b0; + + if (linktype == DLT_PFLOG) { + b0 = gen_cmp(offsetof(struct pfloghdr, action), BPF_B, + (bpf_int32)action); + } else { + bpf_error("action not supported on linktype 0x%x", linktype); + /* NOTREACHED */ + } + + return (b0); +} + 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"); @@ -4967,7 +5343,78 @@ gen_vlan(vlan_num) if (vlan_num >= 0) { struct block *b1; - b1 = gen_cmp(orig_nl, BPF_H, (bpf_int32)vlan_num); + b1 = gen_mcmp(orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff); + gen_and(b0, b1); + b0 = b1; + } + + return (b0); +} + +/* + * support for MPLS + */ +struct block * +gen_mpls(label_num) + int label_num; +{ + struct block *b0; + + /* + * Change the offsets to point to the type and data fields within + * the MPLS packet. This is somewhat of a kludge. + */ + 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; + + b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS); + break; + + case DLT_PPP: + off_linktype = 6; + off_nl_nosnap = 8; + off_nl = 8; + + b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)PPP_MPLS_UCAST); + break; + + case DLT_C_HDLC: + off_linktype = 6; + off_nl_nosnap = 8; + off_nl = 8; + + b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS); + break; + + /* FIXME add other DLT_s ... + * for Frame-Relay/and ATM this may get messy due to SNAP headers + * leave it for now */ + + default: + bpf_error("no MPLS support for data link type %d", + linktype); + /*NOTREACHED*/ + } + } else { + bpf_error("'mpls' can't be combined with 'vlan' or another 'mpls'"); + /*NOTREACHED*/ + } + + /* If a specific MPLS label is requested, check it */ + if (label_num >= 0) { + struct block *b1; + + label_num = label_num << 12; /* label is shifted 12 bits on the wire */ + b1 = gen_mcmp(orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ gen_and(b0, b1); b0 = b1; } @@ -4989,7 +5436,7 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) case A_VPI: if (!is_atm) bpf_error("'vpi' supported only on raw ATM"); - if (off_vpi == -1) + if (off_vpi == (u_int)-1) abort(); b0 = gen_ncmp(BPF_B, off_vpi, 0xffffffff, (u_int)jtype, (u_int)jvalue, reverse); @@ -4998,21 +5445,21 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) case A_VCI: if (!is_atm) bpf_error("'vci' supported only on raw ATM"); - if (off_vci == -1) + if (off_vci == (u_int)-1) abort(); b0 = gen_ncmp(BPF_H, off_vci, 0xffffffff, (u_int)jtype, (u_int)jvalue, reverse); break; case A_PROTOTYPE: - if (off_proto == -1) + if (off_proto == (u_int)-1) abort(); /* XXX - this isn't on FreeBSD */ b0 = gen_ncmp(BPF_B, off_proto, 0x0f, (u_int)jtype, (u_int)jvalue, reverse); break; case A_MSGTYPE: - if (off_payload == -1) + if (off_payload == (u_int)-1) abort(); b0 = gen_ncmp(BPF_B, off_payload + MSG_TYPE_POS, 0xffffffff, (u_int)jtype, (u_int)jvalue, reverse); @@ -5021,7 +5468,7 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) case A_CALLREFTYPE: if (!is_atm) bpf_error("'callref' supported only on raw ATM"); - if (off_proto == -1) + if (off_proto == (u_int)-1) abort(); b0 = gen_ncmp(BPF_B, off_proto, 0xffffffff, (u_int)jtype, (u_int)jvalue, reverse); @@ -5152,15 +5599,15 @@ gen_msg_abbrev(type) break; case A_CALLPROCEED: - b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0); break; case A_CONNECT: b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0); - break; + break; case A_CONNECTACK: - b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0); break; case A_RELEASE: @@ -5168,7 +5615,7 @@ gen_msg_abbrev(type) break; case A_RELEASE_DONE: - b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0); break; default: @@ -5195,9 +5642,9 @@ gen_atmmulti_abbrev(type) if (!is_atm) bpf_error("'oamf4' supported only on raw ATM"); /* OAM F4 type */ - b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); + b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); - gen_or(b0, b1); + gen_or(b0, b1); b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); gen_and(b0, b1); break;