diff options
Diffstat (limited to 'contrib/libpcap/gencode.c')
-rw-r--r-- | contrib/libpcap/gencode.c | 762 |
1 files changed, 727 insertions, 35 deletions
diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c index 1b9cafc..498539d 100644 --- a/contrib/libpcap/gencode.c +++ b/contrib/libpcap/gencode.c @@ -21,7 +21,7 @@ */ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.140.2.1 2001/01/14 06:48:35 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.160 2001/11/30 07:25:48 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -51,20 +51,23 @@ struct rtentry; #include "ethertype.h" #include "nlpid.h" +#include "llc.h" #include "gencode.h" #include "ppp.h" #include "sll.h" +#include "arcnet.h" #include <pcap-namedb.h> #ifdef INET6 #include <netdb.h> #include <sys/socket.h> #endif /*INET6*/ -#define LLC_SNAP_LSAP 0xaa -#define LLC_ISO_LSAP 0xfe - #define ETHERMTU 1500 +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -75,6 +78,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; + /* XXX */ #ifdef PCAP_FDDIPAD int pcap_fddipad = PCAP_FDDIPAD; @@ -143,6 +149,7 @@ static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int #ifdef INET6 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); #endif +static struct block *gen_ahostop(const u_char *, int); static struct block *gen_ehostop(const u_char *, int); static struct block *gen_fhostop(const u_char *, int); static struct block *gen_thostop(const u_char *, int); @@ -547,8 +554,16 @@ init_linktype(type) { linktype = type; + orig_linktype = -1; + orig_nl = -1; + switch (type) { + case DLT_ARCNET: + off_linktype = 2; + off_nl = 6; /* XXX in reality, variable! */ + return; + case DLT_EN10MB: off_linktype = 12; off_nl = 14; @@ -577,12 +592,21 @@ init_linktype(type) return; case DLT_PPP: - case DLT_C_HDLC: - case DLT_PPP_SERIAL: + case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ + case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ off_linktype = 2; off_nl = 4; return; + case DLT_PPP_ETHER: + /* + * This does no include the Ethernet header, and + * only covers session state. + */ + off_linktype = 6; + off_nl = 8; + return; + case DLT_PPP_BSDOS: off_linktype = 5; off_nl = 24; @@ -591,12 +615,13 @@ init_linktype(type) case DLT_FDDI: /* * FDDI doesn't really have a link-level type field. - * We assume that SSAP = SNAP is being used and pick - * out the encapsulated Ethernet type. + * We set "off_linktype" to the offset of the LLC header. * + * To check for Ethernet types, we assume that SSAP = SNAP + * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? */ - off_linktype = 19; + off_linktype = 13; #ifdef PCAP_FDDIPAD off_linktype += pcap_fddipad; #endif @@ -609,9 +634,10 @@ init_linktype(type) case DLT_IEEE802: /* * Token Ring doesn't really have a link-level type field. - * We assume that SSAP = SNAP is being used and pick - * out the encapsulated Ethernet type. + * We set "off_linktype" to the offset of the LLC header. * + * To check for Ethernet types, we assume that SSAP = SNAP + * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? * * XXX - the header is actually variable-length. @@ -629,10 +655,42 @@ init_linktype(type) * the 16-bit value at an offset of 14 (shifted right * 8 - figure out which byte that is). */ - off_linktype = 20; + off_linktype = 14; off_nl = 22; return; + case DLT_IEEE802_11: + /* + * 802.11 doesn't really have a link-level type field. + * We set "off_linktype" to the offset of the LLC header. + * + * To check for Ethernet types, we assume that SSAP = SNAP + * is being used and pick out the encapsulated Ethernet type. + * XXX - should we generate code to check for SNAP? + * + * 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. + */ + off_linktype = 24; + off_nl = 30; + 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+30; + return; + case DLT_ATM_RFC1483: /* * assume routed, non-ISO PDUs @@ -656,6 +714,16 @@ init_linktype(type) off_linktype = 14; off_nl = 16; 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; + return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ @@ -702,30 +770,110 @@ gen_linktype(proto) { struct block *b0, *b1; - /* If we're not using encapsulation, we're done */ - if (off_linktype == -1) - return gen_true(); - switch (linktype) { case DLT_EN10MB: - /* - * XXX - handle other LLC-encapsulated protocols here - * (IPX, OSI)? - */ switch (proto) { - case LLC_ISO_LSAP: + 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); b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) - ((LLC_ISO_LSAP << 8) | LLC_ISO_LSAP)); + ((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 + * SSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + gen_and(b0, b1); + return b1; + + case LLCSAP_IPX: + /* + * Check for; + * + * Ethernet_II frames, which are Ethernet + * frames with a frame type of ETHERTYPE_IPX; + * + * Ethernet_802.3 frames, which are 802.3 + * frames (i.e., the type/length field is + * a length field, <= ETHERMTU, rather than + * a type field) with the first two bytes + * after the Ethernet/802.3 header being + * 0xFFFF; + * + * Ethernet_802.2 frames, which are 802.3 + * frames with an 802.2 LLC header 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. + * + * XXX - should we generate the same code both + * for tests for LLCSAP_IPX and for ETHERTYPE_IPX? + */ + + /* + * This generates code to check both for the + * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3. + */ + b0 = gen_cmp(off_linktype + 2, BPF_B, + (bpf_int32)LLCSAP_IPX); + b1 = gen_cmp(off_linktype + 2, BPF_H, + (bpf_int32)0xFFFF); + gen_or(b0, b1); + + /* + * Now we add code to check for SNAP frames with + * ETHERTYPE_IPX, i.e. Ethernet_SNAP. + */ + b0 = gen_snap(0x000000, ETHERTYPE_IPX, 14); + gen_or(b0, b1); + + /* + * Now we generate code to check for 802.3 + * frames in general. + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + + /* + * Now add the check for 802.3 frames before the + * check for Ethernet_802.2 and Ethernet_802.3, + * as those checks should only be done on 802.3 + * frames, not on Ethernet frames. + */ + gen_and(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: /* @@ -767,14 +915,301 @@ gen_linktype(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 that the frame is an 802.2 frame + * (i.e., that the length/type field is + * a length field, <= ETHERMTU) and + * then check the DSAP. + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + 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); + } + } + break; + + case DLT_IEEE802_11: + case DLT_PRISM_HEADER: + case DLT_FDDI: + case DLT_IEEE802: + case DLT_ATM_RFC1483: + case DLT_ATM_CLIP: + /* + * XXX - handle token-ring variable-length header. + */ + switch (proto) { + + case LLCSAP_ISONS: + return gen_cmp(off_linktype, BPF_H, (long) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + + case LLCSAP_NETBEUI: + return gen_cmp(off_linktype, BPF_H, (long) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + + case LLCSAP_IPX: + /* + * XXX - are there ever SNAP frames for IPX on + * non-Ethernet 802.x networks? + */ + return gen_cmp(off_linktype, BPF_B, + (bpf_int32)LLCSAP_IPX); + + case ETHERTYPE_ATALK: + /* + * 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). + * + * XXX - check for an organization code of + * encapsulated Ethernet as well? + */ + return gen_snap(0x080007, ETHERTYPE_ATALK, + off_linktype); + break; + + default: + /* + * XXX - we don't have to check for IPX 802.3 + * here, but should we check for the IPX Ethertype? + */ + if (proto <= ETHERMTU) { + /* + * This is an LLC SAP value, so check + * the DSAP. + */ + return gen_cmp(off_linktype, BPF_B, + (bpf_int32)proto); + } else { + /* + * This is an Ethernet type; we assume + * that it's unlikely that it'll + * appear in the right place at random, + * and therefore check only the + * location that would hold the Ethernet + * type in a SNAP frame with an organization + * code of 0x000000 (encapsulated Ethernet). + * + * XXX - if we were to check for the SNAP DSAP + * and LSAP, as per XXX, and were also to check + * for an organization code of 0x000000 + * (encapsulated Ethernet), we'd do + * + * return gen_snap(0x000000, proto, + * off_linktype); + * + * here; for now, we don't, as per the above. + * I don't know whether it's worth the + * extra CPU time to do the right check + * or not. + */ + return gen_cmp(off_linktype+6, BPF_H, + (bpf_int32)proto); + } + } + break; + + case DLT_LINUX_SLL: + switch (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) + ((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); + } } break; case DLT_SLIP: - return gen_false(); + case DLT_SLIP_BSDOS: + case DLT_RAW: + /* + * These types don't provide any type field; packets + * are always IP. + * + * XXX - for IPv4, check for a version number of 4, and, + * for IPv6, check for a version number of 6? + */ + switch (proto) { + + case ETHERTYPE_IP: +#ifdef INET6 + case ETHERTYPE_IPV6: +#endif + return gen_true(); /* always true */ + + default: + return gen_false(); /* always false */ + } + break; 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. @@ -803,9 +1238,22 @@ gen_linktype(proto) proto = PPP_NS; break; - case LLC_ISO_LSAP: + case LLCSAP_ISONS: proto = PPP_OSI; break; + + case LLCSAP_8021D: + /* + * I'm assuming the "Bridging PDU"s that go + * over PPP are Spanning Tree Protocol + * Bridging PDUs. + */ + proto = PPP_BRPDU; + break; + + case LLCSAP_IPX: + proto = PPP_IPX; + break; } break; @@ -843,9 +1291,22 @@ gen_linktype(proto) proto = PPP_NS; break; - case LLC_ISO_LSAP: + case LLCSAP_ISONS: proto = PPP_OSI; break; + + case LLCSAP_8021D: + /* + * I'm assuming the "Bridging PDU"s that go + * over PPP are Spanning Tree Protocol + * Bridging PDUs. + */ + proto = PPP_BRPDU; + break; + + case LLCSAP_IPX: + proto = PPP_IPX; + break; } break; @@ -910,7 +1371,73 @@ gen_linktype(proto) proto = htonl(proto); } return (gen_cmp(0, BPF_W, (bpf_int32)proto)); + + case DLT_ARCNET: + /* + * XXX should we check for first fragment if the protocol + * uses PHDS? + */ + switch(proto) { + default: + return gen_false(); +#ifdef INET6 + case ETHERTYPE_IPV6: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(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)); + gen_or(b0, 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)); + gen_or(b0, b1); + return(b1); + case ETHERTYPE_REVARP: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_REVARP))); + case ETHERTYPE_ATALK: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_ATALK))); + } + break; + + case DLT_LTALK: + switch (proto) { + case ETHERTYPE_ATALK: + return gen_true(); + default: + return gen_false(); + } + break; } + + /* + * All the types that have no encapsulation should either be + * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if + * all packets are IP packets, or should be handled in some + * special case, if none of them are (if some are and some + * aren't, the lack of encapsulation is a problem, as we'd + * have to find some other way of determining the packet type). + * + * Therefore, if "off_linktype" is -1, there's an error. + */ + if (off_linktype == -1) + abort(); + + /* + * Any type not handled above should always have an Ethernet + * type at an offset of "off_linktype". (PPP is partially + * handled above - the protocol type is mapped from the + * Ethernet and LLC types we use internally to the corresponding + * PPP type - but the PPP type is always specified by a value + * at "off_linktype", so we don't have to do the code generation + * above.) + */ return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); } @@ -929,8 +1456,8 @@ gen_snap(orgcode, ptype, offset) { u_char snapblock[8]; - snapblock[0] = LLC_SNAP_LSAP; /* DSAP = SNAP */ - snapblock[1] = LLC_SNAP_LSAP; /* SSAP = SNAP */ + snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */ + snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */ snapblock[2] = 0x03; /* control = UI */ snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */ snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */ @@ -1270,6 +1797,9 @@ gen_host(addr, mask, proto, dir) case Q_TCP: bpf_error("'tcp' modifier applied to host"); + case Q_SCTP: + bpf_error("'sctp' modifier applied to host"); + case Q_UDP: bpf_error("'udp' modifier applied to host"); @@ -1285,6 +1815,9 @@ gen_host(addr, mask, proto, dir) case Q_PIM: bpf_error("'pim' modifier applied to host"); + case Q_VRRP: + bpf_error("'vrrp' modifier applied to host"); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -1332,6 +1865,15 @@ gen_host(addr, mask, proto, dir) case Q_CLNP: bpf_error("'clnp' modifier applied to host"); + case Q_STP: + bpf_error("'stp' modifier applied to host"); + + case Q_IPX: + bpf_error("IPX host filtering not implemented"); + + case Q_NETBEUI: + bpf_error("'netbeui' modifier applied to host"); + default: abort(); } @@ -1360,6 +1902,9 @@ gen_host6(addr, mask, proto, dir) case Q_ARP: bpf_error("'arp' modifier applied to ip6 host"); + case Q_SCTP: + bpf_error("'sctp' modifier applied to host"); + case Q_TCP: bpf_error("'tcp' modifier applied to host"); @@ -1378,6 +1923,9 @@ gen_host6(addr, mask, proto, dir) case Q_PIM: bpf_error("'pim' modifier applied to host"); + case Q_VRRP: + bpf_error("'vrrp' modifier applied to host"); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -1424,6 +1972,15 @@ gen_host6(addr, mask, proto, dir) case Q_CLNP: bpf_error("'clnp' modifier applied to host"); + case Q_STP: + bpf_error("'stp' modifier applied to host"); + + case Q_IPX: + bpf_error("IPX host filtering not implemented"); + + case Q_NETBEUI: + bpf_error("'netbeui' modifier applied to host"); + default: abort(); } @@ -1485,6 +2042,14 @@ gen_proto_abbrev(proto) switch (proto) { + case Q_SCTP: + b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + case Q_TCP: b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT); #ifdef INET6 @@ -1532,6 +2097,14 @@ gen_proto_abbrev(proto) #endif break; +#ifndef IPPROTO_VRRP +#define IPPROTO_VRRP 112 +#endif + + case Q_VRRP: + b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT); + break; + case Q_IP: b1 = gen_linktype(ETHERTYPE_IP); break; @@ -1611,7 +2184,7 @@ gen_proto_abbrev(proto) break; case Q_ISO: - b1 = gen_linktype(LLC_ISO_LSAP); + b1 = gen_linktype(LLCSAP_ISONS); break; case Q_ESIS: @@ -1626,6 +2199,18 @@ gen_proto_abbrev(proto) b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); break; + case Q_STP: + b1 = gen_linktype(LLCSAP_8021D); + break; + + case Q_IPX: + b1 = gen_linktype(LLCSAP_IPX); + break; + + case Q_NETBEUI: + b1 = gen_linktype(LLCSAP_NETBEUI); + break; + default: abort(); } @@ -1735,6 +2320,7 @@ gen_port(port, ip_proto, dir) switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: + case IPPROTO_SCTP: b1 = gen_portop(port, ip_proto, dir); break; @@ -1742,6 +2328,8 @@ gen_port(port, ip_proto, dir) tmp = gen_portop(port, IPPROTO_TCP, dir); b1 = gen_portop(port, IPPROTO_UDP, dir); gen_or(tmp, b1); + tmp = gen_portop(port, IPPROTO_SCTP, dir); + gen_or(tmp, b1); break; default: @@ -1805,6 +2393,7 @@ gen_port6(port, ip_proto, dir) switch (ip_proto) { case IPPROTO_UDP: case IPPROTO_TCP: + case IPPROTO_SCTP: b1 = gen_portop6(port, ip_proto, dir); break; @@ -1812,6 +2401,8 @@ gen_port6(port, ip_proto, dir) tmp = gen_portop6(port, IPPROTO_TCP, dir); b1 = gen_portop6(port, IPPROTO_UDP, dir); gen_or(tmp, b1); + tmp = gen_portop6(port, IPPROTO_SCTP, dir); + gen_or(tmp, b1); break; default: @@ -1833,6 +2424,7 @@ lookup_proto(name, proto) case Q_DEFAULT: case Q_IP: + case Q_IPV6: v = pcap_nametoproto(name); if (v == PROTO_UNDEF) bpf_error("unknown ip proto '%s'", name); @@ -2197,7 +2789,7 @@ gen_proto(v, proto, dir) return b1; case Q_ISO: - b0 = gen_linktype(LLC_ISO_LSAP); + b0 = gen_linktype(LLCSAP_ISONS); b1 = gen_cmp(off_nl + 3, BPF_B, (long)v); gen_and(b0, b1); return b1; @@ -2245,6 +2837,10 @@ gen_proto(v, proto, dir) bpf_error("'tcp proto' is bogus"); /* NOTREACHED */ + case Q_SCTP: + bpf_error("'sctp proto' is bogus"); + /* NOTREACHED */ + case Q_ICMP: bpf_error("'icmp proto' is bogus"); /* NOTREACHED */ @@ -2261,6 +2857,10 @@ gen_proto(v, proto, dir) bpf_error("'pim proto' is bogus"); /* NOTREACHED */ + case Q_VRRP: + bpf_error("'vrrp proto' is bogus"); + /* NOTREACHED */ + #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); @@ -2282,6 +2882,15 @@ gen_proto(v, proto, dir) case Q_ESP: bpf_error("'ah proto' is bogus"); + case Q_STP: + bpf_error("'stp proto' is bogus"); + + case Q_IPX: + bpf_error("'ipx proto' is bogus"); + + case Q_NETBEUI: + bpf_error("'netbeui proto' is bogus"); + default: abort(); /* NOTREACHED */ @@ -2335,21 +2944,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( @@ -2410,6 +3025,8 @@ gen_scode(name, q) tmp = gen_host6(&sin6->sin6_addr, &mask128, tproto6, dir); break; + default: + continue; } if (b) gen_or(b, tmp); @@ -2427,13 +3044,16 @@ gen_scode(name, q) } case Q_PORT: - if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP) + if (proto != Q_DEFAULT && + proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) bpf_error("illegal qualifier of 'port'"); if (pcap_nametoport(name, &port, &real_proto) == 0) bpf_error("unknown port '%s'", name); if (proto == Q_UDP) { if (real_proto == IPPROTO_TCP) bpf_error("port '%s' is tcp", name); + else if (real_proto == IPPROTO_SCTP) + bpf_error("port '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_UDP; @@ -2441,10 +3061,23 @@ gen_scode(name, q) if (proto == Q_TCP) { if (real_proto == IPPROTO_UDP) bpf_error("port '%s' is udp", name); + + else if (real_proto == IPPROTO_SCTP) + bpf_error("port '%s' is sctp", name); else /* override PROTO_UNDEF */ real_proto = IPPROTO_TCP; } + if (proto == Q_SCTP) { + if (real_proto == IPPROTO_UDP) + bpf_error("port '%s' is udp", name); + + else if (real_proto == IPPROTO_TCP) + bpf_error("port '%s' is tcp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_SCTP; + } #ifndef INET6 return gen_port(port, real_proto, dir); #else @@ -2465,7 +3098,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*/ @@ -2582,6 +3217,8 @@ gen_ncode(s, v, q) proto = IPPROTO_UDP; else if (proto == Q_TCP) proto = IPPROTO_TCP; + else if (proto == Q_SCTP) + proto = IPPROTO_SCTP; else if (proto == Q_DEFAULT) proto = PROTO_UNDEF; else @@ -2644,6 +3281,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] = @@ -2794,12 +3432,14 @@ gen_load(proto, index, size) index->b = b; break; + case Q_SCTP: case Q_TCP: case Q_UDP: case Q_ICMP: case Q_IGMP: case Q_IGRP: case Q_PIM: + case Q_VRRP: s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); s->s.k = off_nl; sappend(s, xfer_to_a(index)); @@ -3074,6 +3714,8 @@ gen_byteop(op, idx, val) return b; } +static u_char abroadcast[] = { 0x0 }; + struct block * gen_broadcast(proto) int proto; @@ -3086,6 +3728,8 @@ gen_broadcast(proto) case Q_DEFAULT: case Q_LINK: + if (linktype == DLT_ARCNET) + return gen_ahostop(abroadcast, Q_DST); if (linktype == DLT_EN10MB) return gen_ehostop(ebroadcast, Q_DST); if (linktype == DLT_FDDI) @@ -3119,6 +3763,10 @@ gen_multicast(proto) case Q_DEFAULT: case Q_LINK: + if (linktype == DLT_ARCNET) + /* all ARCnet multicasts use the same address */ + return gen_ahostop(abroadcast, Q_DST); + if (linktype == DLT_EN10MB) { /* ether[0] & 1 != 0 */ s = new_stmt(BPF_LD|BPF_B|BPF_ABS); @@ -3196,6 +3844,51 @@ gen_inbound(dir) 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) + return gen_ahostop(eaddr, (int)q.dir); + } + bpf_error("ARCnet address used in non-arc expression"); + /* NOTREACHED */ +} + +static struct block * +gen_ahostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1; + + switch (dir) { + /* src comes first, different from Ethernet */ + case Q_SRC: + return gen_bcmp(0, 1, eaddr); + + case Q_DST: + return gen_bcmp(1, 1, eaddr); + + case Q_AND: + b0 = gen_ahostop(eaddr, Q_SRC); + b1 = gen_ahostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_ahostop(eaddr, Q_SRC); + b1 = gen_ahostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + /* * support IEEE 802.1Q VLAN trunk over ethernet */ @@ -3203,7 +3896,6 @@ struct block * gen_vlan(vlan_num) int vlan_num; { - static u_int orig_linktype = -1, orig_nl = -1; struct block *b0; /* |