X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/a12a6ed1a2782a13a92bbe69b2c6bdac108e39aa..3566868596fe1d31a2228881c385d96a0bedb74d:/contrib/libpcap/gencode.c diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c index bd3822496d..2a0fb51253 100644 --- a/contrib/libpcap/gencode.c +++ b/contrib/libpcap/gencode.c @@ -21,7 +21,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.290.2.16 2008-09-22 20:16:01 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.309 2008-12-23 20:13:29 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -31,6 +31,14 @@ static const char rcsid[] _U_ = #ifdef WIN32 #include #else /* WIN32 */ +#if HAVE_INTTYPES_H +#include +#elif HAVE_STDINT_H +#include +#endif +#ifdef HAVE_SYS_BITYPES_H +#include +#endif #include #include #endif /* WIN32 */ @@ -39,7 +47,7 @@ static const char rcsid[] _U_ = * XXX - why was this included even on UNIX? */ #ifdef __MINGW32__ -#include "IP6_misc.h" +#include "ip6_misc.h" #endif #ifndef WIN32 @@ -49,6 +57,7 @@ static const char rcsid[] _U_ = #endif #include +#include #endif /* WIN32 */ @@ -73,6 +82,7 @@ static const char rcsid[] _U_ = #include "sunatmpos.h" #include "ppp.h" #include "pcap/sll.h" +#include "pcap/ipnet.h" #include "arcnet.h" #ifdef HAVE_NET_PFVAR_H #include @@ -158,6 +168,17 @@ enum e_offrel { OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ }; +#ifdef INET6 +/* + * As errors are handled by a longjmp, anything allocated must be freed + * in the longjmp handler, so it must be reachable from that handler. + * One thing that's allocated is the result of pcap_nametoaddrinfo(); + * it must be freed with freeaddrinfo(). This variable points to any + * addrinfo structure that would need to be freed. + */ +static struct addrinfo *ai; +#endif + /* * 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 @@ -203,6 +224,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_ipnet_linktype(int); static struct block *gen_linux_sll_linktype(int); static struct slist *gen_load_prism_llprefixlen(void); static struct slist *gen_load_avs_llprefixlen(void); @@ -368,10 +390,34 @@ syntax() static bpf_u_int32 netmask; static int snaplen; int no_optimize; +#ifdef WIN32 +static int +pcap_compile_unsafe(pcap_t *p, struct bpf_program *program, + const char *buf, int optimize, bpf_u_int32 mask); int pcap_compile(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) +{ + int result; + + EnterCriticalSection(&g_PcapCompileCriticalSection); + + result = pcap_compile_unsafe(p, program, buf, optimize, mask); + + LeaveCriticalSection(&g_PcapCompileCriticalSection); + + return result; +} + +static int +pcap_compile_unsafe(pcap_t *p, struct bpf_program *program, + const char *buf, int optimize, bpf_u_int32 mask) +#else /* WIN32 */ +int +pcap_compile(pcap_t *p, struct bpf_program *program, + const char *buf, int optimize, bpf_u_int32 mask) +#endif /* WIN32 */ { extern int n_errors; const char * volatile xbuf = buf; @@ -383,6 +429,12 @@ pcap_compile(pcap_t *p, struct bpf_program *program, bpf_pcap = p; init_regs(); if (setjmp(top_ctx)) { +#ifdef INET6 + if (ai != NULL) { + freeaddrinfo(ai); + ai = NULL; + } +#endif lex_cleanup(); freechunks(); return (-1); @@ -723,7 +775,8 @@ static int reg_off_ll; * This is the offset of the beginning of the MAC-layer header from * the beginning of the link-layer header. * It's usually 0, except for ATM LANE, where it's the offset, relative - * to the beginning of the raw packet data, of the Ethernet header. + * to the beginning of the raw packet data, of the Ethernet header, and + * for Ethernet with various additional information. */ static u_int off_mac; @@ -1115,6 +1168,8 @@ init_linktype(p) return; case DLT_RAW: + case DLT_IPV4: + case DLT_IPV6: off_linktype = -1; off_macpl = 0; off_nl = 0; @@ -1187,26 +1242,6 @@ init_linktype(p) 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_macpl = -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_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - case DLT_SYMANTEC_FIREWALL: off_linktype = 6; off_macpl = 44; @@ -1315,6 +1350,16 @@ init_linktype(p) off_nl_nosnap = -1; return; + case DLT_JUNIPER_VS: + case DLT_JUNIPER_SRX_E2E: + case DLT_JUNIPER_FIBRECHANNEL: + case DLT_JUNIPER_ATM_CEMIC: + off_linktype = 8; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + case DLT_MTP2: off_li = 2; off_sio = 3; @@ -1360,146 +1405,54 @@ init_linktype(p) return; #endif - case DLT_LINUX_LAPD: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - - case DLT_USB: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - - case DLT_BLUETOOTH_HCI_H4: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - - case DLT_USB_LINUX: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - - case DLT_CAN20B: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - - case DLT_IEEE802_15_4_LINUX: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - - case DLT_IEEE802_16_MAC_CPS_RADIO: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - - case DLT_IEEE802_15_4: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; - - case DLT_SITA: + case DLT_AX25_KISS: /* * Currently, only raw "link[N:M]" filtering is supported. */ - off_linktype = -1; + off_linktype = -1; /* variable, min 15, max 71 steps of 7 */ off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; + off_nl = -1; /* variable, min 16, max 71 steps of 7 */ + off_nl_nosnap = -1; /* no 802.2 LLC */ + off_mac = 1; /* step over the kiss length byte */ return; - case DLT_RAIF1: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; + case DLT_IPNET: + off_linktype = 1; + off_macpl = 24; /* ipnet header length */ + off_nl = 0; off_nl_nosnap = -1; return; - case DLT_IPMB: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; + case DLT_NETANALYZER: + off_mac = 4; /* MAC header is past 4-byte pseudo-header */ + off_linktype = 16; /* includes 4-byte pseudo-header */ + off_macpl = 18; /* pseudo-header+Ethernet header length */ + off_nl = 0; /* Ethernet II */ + off_nl_nosnap = 3; /* 802.3+802.2 */ return; - case DLT_BLUETOOTH_HCI_H4_WITH_PHDR: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; + case DLT_NETANALYZER_TRANSPARENT: + off_mac = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */ + off_linktype = 24; /* includes 4-byte pseudo-header+preamble+SFD */ + off_macpl = 26; /* pseudo-header+preamble+SFD+Ethernet header length */ + off_nl = 0; /* Ethernet II */ + off_nl_nosnap = 3; /* 802.3+802.2 */ return; - case DLT_AX25_KISS: + default: /* - * Currently, only raw "link[N:M]" filtering is supported. + * For values in the range in which we've assigned new + * DLT_ values, only raw "link[N:M]" filtering is supported. */ - off_linktype = -1; /* variable, min 15, max 71 steps of 7 */ - off_macpl = -1; - off_nl = -1; /* variable, min 16, max 71 steps of 7 */ - off_nl_nosnap = -1; /* no 802.2 LLC */ - off_mac = 1; /* step over the kiss length byte */ - return; + if (linktype >= DLT_MATCHING_MIN && + linktype <= DLT_MATCHING_MAX) { + off_linktype = -1; + off_macpl = -1; + off_nl = -1; + off_nl_nosnap = -1; + return; + } - case DLT_IEEE802_15_4_NONASK_PHY: - /* - * Currently, only raw "link[N:M]" filtering is supported. - */ - off_linktype = -1; - off_macpl = -1; - off_nl = -1; - off_nl_nosnap = -1; - return; } bpf_error("unknown data link type %d", linktype); /* NOTREACHED */ @@ -1933,6 +1886,33 @@ gen_ether_linktype(proto) } } +/* + * "proto" is an Ethernet type value and for IPNET, if it is not IPv4 + * or IPv6 then we have an error. + */ +static struct block * +gen_ipnet_linktype(proto) + register int proto; +{ + switch (proto) { + + case ETHERTYPE_IP: + return gen_cmp(OR_LINK, off_linktype, BPF_B, + (bpf_int32)IPH_AF_INET); + /* NOTREACHED */ + + case ETHERTYPE_IPV6: + return gen_cmp(OR_LINK, off_linktype, BPF_B, + (bpf_int32)IPH_AF_INET6); + /* NOTREACHED */ + + default: + break; + } + + return gen_false(); +} + /* * Generate code to match a particular packet type. * @@ -2944,6 +2924,8 @@ gen_linktype(proto) switch (linktype) { case DLT_EN10MB: + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: return gen_ether_linktype(proto); /*NOTREACHED*/ break; @@ -3074,6 +3056,32 @@ gen_linktype(proto) /*NOTREACHED*/ break; + case DLT_IPV4: + /* + * Raw IPv4, so no type field. + */ + if (proto == ETHERTYPE_IP) + return gen_true(); /* always true */ + + /* Checking for something other than IPv4; always false */ + return gen_false(); + /*NOTREACHED*/ + break; + + case DLT_IPV6: + /* + * Raw IPv6, so no type field. + */ +#ifdef INET6 + if (proto == ETHERTYPE_IPV6) + return gen_true(); /* always true */ +#endif + + /* Checking for something other than IPv6; always false */ + return gen_false(); + /*NOTREACHED*/ + break; + case DLT_PPP: case DLT_PPP_PPPD: case DLT_PPP_SERIAL: @@ -3321,6 +3329,11 @@ gen_linktype(proto) case DLT_JUNIPER_VP: case DLT_JUNIPER_ST: case DLT_JUNIPER_ISM: + case DLT_JUNIPER_VS: + case DLT_JUNIPER_SRX_E2E: + case DLT_JUNIPER_FIBRECHANNEL: + case DLT_JUNIPER_ATM_CEMIC: + /* just lets verify the magic number for now - * on ATM we may have up to 6 different encapsulations on the wire * and need a lot of heuristics to figure out that the payload @@ -3330,6 +3343,9 @@ gen_linktype(proto) */ return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ + case DLT_IPNET: + return gen_ipnet_linktype(proto); + case DLT_LINUX_IRDA: bpf_error("IrDA link-layer type filtering not implemented"); @@ -3353,6 +3369,7 @@ gen_linktype(proto) case DLT_USB: case DLT_USB_LINUX: + case DLT_USB_LINUX_MMAPPED: bpf_error("USB link-layer type filtering not implemented"); case DLT_BLUETOOTH_HCI_H4: @@ -3360,11 +3377,13 @@ gen_linktype(proto) bpf_error("Bluetooth link-layer type filtering not implemented"); case DLT_CAN20B: - bpf_error("CAN20B link-layer type filtering not implemented"); + case DLT_CAN_SOCKETCAN: + bpf_error("CAN link-layer type filtering not implemented"); case DLT_IEEE802_15_4: case DLT_IEEE802_15_4_LINUX: case DLT_IEEE802_15_4_NONASK_PHY: + case DLT_IEEE802_15_4_NOFCS: bpf_error("IEEE 802.15.4 link-layer type filtering not implemented"); case DLT_IEEE802_16_MAC_CPS_RADIO: @@ -3639,6 +3658,30 @@ gen_ehostop(eaddr, dir) b1 = gen_ehostop(eaddr, Q_DST); gen_or(b0, b1); return b1; + + case Q_ADDR1: + bpf_error("'addr1' is only supported on 802.11 with 802.11 headers"); + break; + + case Q_ADDR2: + bpf_error("'addr2' is only supported on 802.11 with 802.11 headers"); + break; + + case Q_ADDR3: + bpf_error("'addr3' is only supported on 802.11 with 802.11 headers"); + break; + + case Q_ADDR4: + bpf_error("'addr4' is only supported on 802.11 with 802.11 headers"); + break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11 with 802.11 headers"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11 with 802.11 headers"); + break; } abort(); /* NOTREACHED */ @@ -3681,6 +3724,30 @@ gen_fhostop(eaddr, dir) b1 = gen_fhostop(eaddr, Q_DST); gen_or(b0, b1); return b1; + + case Q_ADDR1: + bpf_error("'addr1' is only supported on 802.11"); + break; + + case Q_ADDR2: + bpf_error("'addr2' is only supported on 802.11"); + break; + + case Q_ADDR3: + bpf_error("'addr3' is only supported on 802.11"); + break; + + case Q_ADDR4: + bpf_error("'addr4' is only supported on 802.11"); + break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11"); + break; } abort(); /* NOTREACHED */ @@ -3715,6 +3782,30 @@ gen_thostop(eaddr, dir) b1 = gen_thostop(eaddr, Q_DST); gen_or(b0, b1); return b1; + + case Q_ADDR1: + bpf_error("'addr1' is only supported on 802.11"); + break; + + case Q_ADDR2: + bpf_error("'addr2' is only supported on 802.11"); + break; + + case Q_ADDR3: + bpf_error("'addr3' is only supported on 802.11"); + break; + + case Q_ADDR4: + bpf_error("'addr4' is only supported on 802.11"); + break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11"); + break; } abort(); /* NOTREACHED */ @@ -4008,8 +4099,79 @@ gen_wlanhostop(eaddr, dir) gen_and(b1, b0); return b0; + case Q_RA: + /* + * Not present in management frames; addr1 in other + * frames. + */ + + /* + * If the high-order bit of the type value is 0, this + * is a management frame. + * I.e, check "(link[0] & 0x08)". + */ + s = gen_load_a(OR_LINK, 0, BPF_B); + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x08; + b1->stmts = s; + + /* + * Check addr1. + */ + b0 = gen_bcmp(OR_LINK, 4, 6, eaddr); + + /* + * AND that with the check of addr1. + */ + gen_and(b1, b0); + return (b0); + + case Q_TA: + /* + * Not present in management frames; addr2, if present, + * in other frames. + */ + + /* + * Not present in CTS or ACK control frames. + */ + b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, + IEEE80211_FC0_TYPE_MASK); + gen_not(b0); + b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS, + IEEE80211_FC0_SUBTYPE_MASK); + gen_not(b1); + b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK, + IEEE80211_FC0_SUBTYPE_MASK); + gen_not(b2); + gen_and(b1, b2); + gen_or(b0, b2); + + /* + * If the high-order bit of the type value is 0, this + * is a management frame. + * I.e, check "(link[0] & 0x08)". + */ + s = gen_load_a(OR_LINK, 0, BPF_B); + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x08; + b1->stmts = s; + + /* + * AND that with the check for frames other than + * CTS and ACK frames. + */ + gen_and(b1, b2); + + /* + * Check addr2. + */ + b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); + gen_and(b2, b1); + return b1; + /* - * XXX - add RA, TA, and BSSID keywords? + * XXX - add BSSID keyword? */ case Q_ADDR1: return (gen_bcmp(OR_LINK, 4, 6, eaddr)); @@ -4105,6 +4267,30 @@ gen_ipfchostop(eaddr, dir) b1 = gen_ipfchostop(eaddr, Q_DST); gen_or(b0, b1); return b1; + + case Q_ADDR1: + bpf_error("'addr1' is only supported on 802.11"); + break; + + case Q_ADDR2: + bpf_error("'addr2' is only supported on 802.11"); + break; + + case Q_ADDR3: + bpf_error("'addr3' is only supported on 802.11"); + break; + + case Q_ADDR4: + bpf_error("'addr4' is only supported on 802.11"); + break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11"); + break; } abort(); /* NOTREACHED */ @@ -4298,6 +4484,9 @@ gen_host(addr, mask, proto, dir, type) case Q_VRRP: bpf_error("'vrrp' modifier applied to %s", typestr); + case Q_CARP: + bpf_error("'carp' modifier applied to %s", typestr); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -4417,6 +4606,9 @@ gen_host6(addr, mask, proto, dir, type) case Q_VRRP: bpf_error("'vrrp' modifier applied to %s", typestr); + case Q_CARP: + bpf_error("'carp' modifier applied to %s", typestr); + case Q_ATALK: bpf_error("ATALK host filtering not implemented"); @@ -4501,6 +4693,8 @@ gen_gateway(eaddr, alist, proto, dir) case Q_RARP: switch (linktype) { case DLT_EN10MB: + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: b0 = gen_ehostop(eaddr, Q_OR); break; case DLT_FDDI: @@ -4517,29 +4711,30 @@ gen_gateway(eaddr, alist, proto, dir) b0 = gen_wlanhostop(eaddr, Q_OR); break; case DLT_SUNATM: - if (is_lane) { - /* - * Check that the packet doesn't begin with an - * LE Control marker. (We've already generated - * a test for LANE.) - */ - b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, - BPF_H, 0xFF00); - gen_not(b1); + if (!is_lane) + bpf_error( + "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); + /* + * Check that the packet doesn't begin with an + * LE Control marker. (We've already generated + * a test for LANE.) + */ + b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, + BPF_H, 0xFF00); + gen_not(b1); - /* - * Now check the MAC address. - */ - b0 = gen_ehostop(eaddr, Q_OR); - gen_and(b1, b0); - } + /* + * Now check the MAC address. + */ + b0 = gen_ehostop(eaddr, Q_OR); + gen_and(b1, b0); break; case DLT_IP_OVER_FC: b0 = gen_ipfchostop(eaddr, Q_OR); break; default: bpf_error( - "'gateway' supported only on ethernet/FDDI/token ring/802.11/Fibre Channel"); + "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); } b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); while (*alist) { @@ -4629,6 +4824,14 @@ gen_proto_abbrev(proto) b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT); break; +#ifndef IPPROTO_CARP +#define IPPROTO_CARP 112 +#endif + + case Q_CARP: + b1 = gen_proto(IPPROTO_CARP, Q_IP, Q_DEFAULT); + break; + case Q_IP: b1 = gen_linktype(ETHERTYPE_IP); break; @@ -4810,7 +5013,7 @@ gen_ipfrag() struct slist *s; struct block *b; - /* not ip frag */ + /* not IPv4 frag other than the first frag */ s = gen_load_a(OR_NET, 6, BPF_H); b = new_block(JMP(BPF_JSET)); b->s.k = 0x1fff; @@ -4853,7 +5056,7 @@ gen_portop(port, proto, dir) { struct block *b0, *b1, *tmp; - /* ip proto 'proto' */ + /* ip proto 'proto' and not a fragment other than the first fragment */ tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); @@ -4945,6 +5148,7 @@ gen_portop6(port, proto, dir) struct block *b0, *b1, *tmp; /* ip6 proto 'proto' */ + /* XXX - catch the first fragment of a fragmented packet? */ b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { @@ -5046,7 +5250,7 @@ gen_portrangeop(port1, port2, proto, dir) { struct block *b0, *b1, *tmp; - /* ip proto 'proto' */ + /* ip proto 'proto' and not a fragment other than the first fragment */ tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); @@ -5150,6 +5354,7 @@ gen_portrangeop6(port1, port2, proto, dir) struct block *b0, *b1, *tmp; /* ip6 proto 'proto' */ + /* XXX - catch the first fragment of a fragmented packet? */ b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); switch (dir) { @@ -5427,12 +5632,9 @@ gen_protochain(v, proto, dir) /* * in short, - * A = P[X]; - * X = X + (P[X + 1] + 1) * 8; + * A = P[X + packet head]; + * X = X + (P[X + packet head + 1] + 1) * 8; */ - /* A = X */ - s[i] = new_stmt(BPF_MISC|BPF_TXA); - i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); s[i]->s.k = off_macpl + off_nl; @@ -5441,19 +5643,9 @@ gen_protochain(v, proto, dir) s[i] = new_stmt(BPF_ST); s[i]->s.k = reg2; i++; - /* A = X */ - s[i] = new_stmt(BPF_MISC|BPF_TXA); - i++; - /* A += 1 */ - s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); - s[i]->s.k = 1; - i++; - /* X = A */ - s[i] = new_stmt(BPF_MISC|BPF_TAX); - i++; - /* A = P[X + packet head]; */ + /* A = P[X + packet head + 1]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_macpl + off_nl; + s[i]->s.k = off_macpl + off_nl + 1; i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); @@ -5463,6 +5655,10 @@ gen_protochain(v, proto, dir) s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); s[i]->s.k = 8; i++; + /* A += X */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_X); + s[i]->s.k = 0; + i++; /* X = A; */ s[i] = new_stmt(BPF_MISC|BPF_TAX); i++; @@ -5786,6 +5982,10 @@ gen_proto(v, proto, dir) bpf_error("'vrrp proto' is bogus"); /* NOTREACHED */ + case Q_CARP: + bpf_error("'carp proto' is bogus"); + /* NOTREACHED */ + #ifdef INET6 case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); @@ -5869,6 +6069,8 @@ gen_scode(name, q) switch (linktype) { case DLT_EN10MB: + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: eaddr = pcap_ether_hostton(name); if (eaddr == NULL) bpf_error( @@ -5969,6 +6171,7 @@ gen_scode(name, q) res0 = res = pcap_nametoaddrinfo(name); if (res == NULL) bpf_error("unknown host '%s'", name); + ai = res; b = tmp = NULL; tproto = tproto6 = proto; if (off_linktype == -1 && tproto == Q_DEFAULT) { @@ -6002,6 +6205,7 @@ gen_scode(name, q) gen_or(b, tmp); b = tmp; } + ai = NULL; freeaddrinfo(res0); if (b == NULL) { bpf_error("unknown host '%s'%s", name, @@ -6048,6 +6252,10 @@ gen_scode(name, q) /* override PROTO_UNDEF */ real_proto = IPPROTO_SCTP; } + if (port < 0) + bpf_error("illegal port number %d < 0", port); + if (port > 65535) + bpf_error("illegal port number %d > 65535", port); #ifndef INET6 return gen_port(port, real_proto, dir); #else @@ -6089,6 +6297,15 @@ gen_scode(name, q) /* override PROTO_UNDEF */ real_proto = IPPROTO_SCTP; } + if (port1 < 0) + bpf_error("illegal port number %d < 0", port1); + if (port1 > 65535) + bpf_error("illegal port number %d > 65535", port1); + if (port2 < 0) + bpf_error("illegal port number %d < 0", port2); + if (port2 > 65535) + bpf_error("illegal port number %d > 65535", port2); + #ifndef INET6 return gen_portrange(port1, port2, real_proto, dir); #else @@ -6240,6 +6457,9 @@ gen_ncode(s, v, q) else bpf_error("illegal qualifier of 'port'"); + if (v > 65535) + bpf_error("illegal port number %u > 65535", v); + #ifndef INET6 return gen_port((int)v, proto, dir); #else @@ -6263,6 +6483,9 @@ gen_ncode(s, v, q) else bpf_error("illegal qualifier of 'portrange'"); + if (v > 65535) + bpf_error("illegal port number %u > 65535", v); + #ifndef INET6 return gen_portrange((int)v, (int)v, proto, dir); #else @@ -6314,6 +6537,7 @@ gen_mcode6(s1, s2, masklen, q) res = pcap_nametoaddrinfo(s1); if (!res) bpf_error("invalid ip6 address %s", s1); + ai = res; if (res->ai_next) bpf_error("%s resolved to multiple address", s1); addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; @@ -6344,6 +6568,7 @@ gen_mcode6(s1, s2, masklen, q) case Q_NET: b = gen_host6(addr, &mask, q.proto, q.dir, q.addr); + ai = NULL; freeaddrinfo(res); return b; @@ -6365,6 +6590,8 @@ gen_ecode(eaddr, q) if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { switch (linktype) { case DLT_EN10MB: + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: return gen_ehostop(eaddr, (int)q.dir); case DLT_FDDI: return gen_fhostop(eaddr, (int)q.dir); @@ -6494,7 +6721,7 @@ gen_load(proto, inst, size) /* * Load into the X register the offset computed into the - * register specifed by "index". + * register specified by "index". */ s = xfer_to_x(inst); @@ -6526,7 +6753,7 @@ gen_load(proto, inst, size) * the link-layer header. Add to it the offset computed * into the register specified by "index", and move that * into the X register. Otherwise, just load into the X - * register the offset computed into the register specifed + * register the offset computed into the register specified * by "index". */ if (s != NULL) { @@ -6575,7 +6802,7 @@ gen_load(proto, inst, size) * payload. Add to it the offset computed into the * register specified by "index", and move that into * the X register. Otherwise, just load into the X - * register the offset computed into the register specifed + * register the offset computed into the register specified * by "index". */ if (s != NULL) { @@ -6620,6 +6847,7 @@ gen_load(proto, inst, size) case Q_IGRP: case Q_PIM: case Q_VRRP: + case Q_CARP: /* * The offset is relative to the beginning of * the transport-layer header. @@ -6968,6 +7196,8 @@ gen_broadcast(proto) case DLT_ARCNET_LINUX: return gen_ahostop(abroadcast, Q_DST); case DLT_EN10MB: + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: return gen_ehostop(ebroadcast, Q_DST); case DLT_FDDI: return gen_fhostop(ebroadcast, Q_DST); @@ -7006,6 +7236,13 @@ gen_broadcast(proto) break; case Q_IP: + /* + * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff) + * as an indication that we don't know the netmask, and fail + * in that case. + */ + if (netmask == PCAP_NETMASK_UNKNOWN) + bpf_error("netmask not known, so 'ip broadcast' not supported"); b0 = gen_linktype(ETHERTYPE_IP); hostmask = ~netmask; b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask); @@ -7056,6 +7293,8 @@ gen_multicast(proto) /* all ARCnet multicasts use the same address */ return gen_ahostop(abroadcast, Q_DST); case DLT_EN10MB: + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: /* ether[0] & 1 != 0 */ return gen_mac_multicast(0); case DLT_FDDI: @@ -7253,6 +7492,16 @@ gen_inbound(dir) dir); break; + case DLT_IPNET: + if (dir) { + /* match outgoing packets */ + b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_OUTBOUND); + } else { + /* match incoming packets */ + b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_INBOUND); + } + break; + case DLT_LINUX_SLL: if (dir) { /* @@ -7309,6 +7558,11 @@ gen_inbound(dir) case DLT_JUNIPER_VP: case DLT_JUNIPER_ST: case DLT_JUNIPER_ISM: + case DLT_JUNIPER_VS: + case DLT_JUNIPER_SRX_E2E: + case DLT_JUNIPER_FIBRECHANNEL: + case DLT_JUNIPER_ATM_CEMIC: + /* juniper flags (including direction) are stored * the byte after the 3-byte magic number */ if (dir) { @@ -7589,6 +7843,30 @@ gen_ahostop(eaddr, dir) b1 = gen_ahostop(eaddr, Q_DST); gen_or(b0, b1); return b1; + + case Q_ADDR1: + bpf_error("'addr1' is only supported on 802.11"); + break; + + case Q_ADDR2: + bpf_error("'addr2' is only supported on 802.11"); + break; + + case Q_ADDR3: + bpf_error("'addr3' is only supported on 802.11"); + break; + + case Q_ADDR4: + bpf_error("'addr4' is only supported on 802.11"); + break; + + case Q_RA: + bpf_error("'ra' is only supported on 802.11"); + break; + + case Q_TA: + bpf_error("'ta' is only supported on 802.11"); + break; } abort(); /* NOTREACHED */ @@ -7643,9 +7921,15 @@ gen_vlan(vlan_num) switch (linktype) { case DLT_EN10MB: - /* check for VLAN */ + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: + /* check for VLAN, including QinQ */ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); + b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, + (bpf_int32)ETHERTYPE_8021QINQ); + gen_or(b0,b1); + b0 = b1; /* If a specific VLAN is requested, check VLAN id */ if (vlan_num >= 0) { @@ -7706,6 +7990,8 @@ gen_mpls(label_num) case DLT_C_HDLC: /* fall through */ case DLT_EN10MB: + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: b0 = gen_linktype(ETHERTYPE_MPLS); break;