X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/11c74648d158aebefe901a3d81b98e3acde987c4..fd3868c20d8b989d6bfce697a2e7a2c99cd1f296:/gencode.c diff --git a/gencode.c b/gencode.c index 0cf2bfa6..e59953ff 100644 --- a/gencode.c +++ b/gencode.c @@ -193,6 +193,11 @@ struct addrinfo { (cs)->is_geneve = 0; \ } +/* + * Offset "not set" value. + */ +#define OFFSET_NOT_SET 0xffffffffU + /* * Absolute offsets, which are offsets from the beginning of the raw * packet data, are, in the general case, the sum of a variable value @@ -270,7 +275,7 @@ struct _compiler_state { u_int vlan_stack_depth; /* XXX */ - int pcap_fddipad; + u_int pcap_fddipad; #ifdef INET6 /* @@ -335,8 +340,8 @@ struct _compiler_state { * * For Linux cooked sockets, it's the offset of the type field. * - * off_linktype.constant_part is set to -1 for no encapsulation, - * in which case, IP is assumed. + * off_linktype.constant_part is set to OFFSET_NOT_SET for no + * encapsulation, in which case, IP is assumed. */ bpf_abs_offset off_linktype; @@ -518,7 +523,8 @@ static struct block *gen_host6(compiler_state_t *, struct in6_addr *, struct in6_addr *, int, int, int); #endif #ifndef INET6 -static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int); +static struct block *gen_gateway(compiler_state_t *, const u_char *, + bpf_u_int32 **, int, int); #endif static struct block *gen_ipfrag(compiler_state_t *); static struct block *gen_portatom(compiler_state_t *, int, bpf_int32); @@ -658,6 +664,9 @@ int pcap_compile(pcap_t *p, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask) { +#ifdef _WIN32 + static int done = 0; +#endif compiler_state_t cstate; const char * volatile xbuf = buf; yyscan_t scanner = NULL; @@ -665,14 +674,6 @@ pcap_compile(pcap_t *p, struct bpf_program *program, u_int len; int rc; -#ifdef _WIN32 - static int done = 0; - - if (!done) - pcap_wsockinit(); - done = 1; -#endif - /* * If this pcap_t hasn't been activated, it doesn't have a * link-layer type, so we can't use it. @@ -680,12 +681,41 @@ pcap_compile(pcap_t *p, struct bpf_program *program, if (!p->activated) { pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "not-yet-activated pcap_t passed to pcap_compile"); - rc = -1; - goto quit; + return (-1); } + +#ifdef _WIN32 + if (!done) + pcap_wsockinit(); + done = 1; +#endif + +#ifdef HAVE_REMOTE + /* + * If the device on which we're capturing need to be notified + * that a new filter is being compiled, do so. + * + * This allows them to save a copy of it, in case, for example, + * they're implementing a form of remote packet capture, and + * want the remote machine to filter out the packets in which + * it's sending the packets it's captured. + * + * XXX - the fact that we happen to be compiling a filter + * doesn't necessarily mean we'll be installing it as the + * filter for this pcap_t; we might be running it from userland + * on captured packets to do packet classification. We really + * need a better way of handling this, but this is all that + * the WinPcap code did. + */ + if (p->save_current_filter_op != NULL) + (p->save_current_filter_op)(p, buf); +#endif + initchunks(&cstate); cstate.no_optimize = 0; +#ifdef INET6 cstate.ai = NULL; +#endif cstate.ic.root = NULL; cstate.ic.cur_mark = 0; cstate.bpf_pcap = p; @@ -1107,7 +1137,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) * SLIP doesn't have a link level type. The 16 byte * header is hacked into our SLIP driver. */ - cstate->off_linktype.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; cstate->off_linkpl.constant_part = 16; cstate->off_nl = 0; cstate->off_nl_nosnap = 0; /* no 802.2 LLC */ @@ -1115,7 +1145,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) case DLT_SLIP_BSDOS: /* XXX this may be the same as the DLT_PPP_BSDOS case */ - cstate->off_linktype.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* XXX end */ cstate->off_linkpl.constant_part = 24; cstate->off_nl = 0; @@ -1301,7 +1331,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) case DLT_RAW: case DLT_IPV4: case DLT_IPV6: - cstate->off_linktype.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; cstate->off_linkpl.constant_part = 0; cstate->off_nl = 0; cstate->off_nl_nosnap = 0; /* no 802.2 LLC */ @@ -1320,7 +1350,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) * but really it just indicates whether there is a "short" or * "long" DDP packet following. */ - cstate->off_linktype.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; cstate->off_linkpl.constant_part = 0; cstate->off_nl = 0; cstate->off_nl_nosnap = 0; /* no 802.2 LLC */ @@ -1348,7 +1378,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) * XXX - we should set this to handle SNAP-encapsulated * frames (NLPID of 0x80). */ - cstate->off_linktype.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; cstate->off_linkpl.constant_part = 0; cstate->off_nl = 0; cstate->off_nl_nosnap = 0; /* no 802.2 LLC */ @@ -1360,7 +1390,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) * so lets start with offset 4 for now and increments later on (FIXME); */ case DLT_MFR: - cstate->off_linktype.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; cstate->off_linkpl.constant_part = 0; cstate->off_nl = 4; cstate->off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */ @@ -1441,7 +1471,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) case DLT_JUNIPER_ES: cstate->off_linktype.constant_part = 6; - cstate->off_linkpl.constant_part = -1; /* not really a network layer but raw IP addresses */ + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* not really a network layer but raw IP addresses */ cstate->off_nl = -1; /* not really a network layer but raw IP addresses */ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */ break; @@ -1454,36 +1484,36 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) break; case DLT_BACNET_MS_TP: - cstate->off_linktype.constant_part = -1; - cstate->off_linkpl.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; break; case DLT_JUNIPER_SERVICES: cstate->off_linktype.constant_part = 12; - cstate->off_linkpl.constant_part = -1; /* L3 proto location dep. on cookie type */ + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* L3 proto location dep. on cookie type */ cstate->off_nl = -1; /* L3 proto location dep. on cookie type */ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */ break; case DLT_JUNIPER_VP: cstate->off_linktype.constant_part = 18; - cstate->off_linkpl.constant_part = -1; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; break; case DLT_JUNIPER_ST: cstate->off_linktype.constant_part = 18; - cstate->off_linkpl.constant_part = -1; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; break; case DLT_JUNIPER_ISM: cstate->off_linktype.constant_part = 8; - cstate->off_linkpl.constant_part = -1; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; break; @@ -1493,7 +1523,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) case DLT_JUNIPER_FIBRECHANNEL: case DLT_JUNIPER_ATM_CEMIC: cstate->off_linktype.constant_part = 8; - cstate->off_linkpl.constant_part = -1; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; break; @@ -1505,8 +1535,8 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) cstate->off_opc = 4; cstate->off_dpc = 4; cstate->off_sls = 7; - cstate->off_linktype.constant_part = -1; - cstate->off_linkpl.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; break; @@ -1518,8 +1548,8 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) cstate->off_opc = 8; cstate->off_dpc = 8; cstate->off_sls = 11; - cstate->off_linktype.constant_part = -1; - cstate->off_linkpl.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; break; @@ -1531,14 +1561,14 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) cstate->off_opc = 24; cstate->off_dpc = 24; cstate->off_sls = 27; - cstate->off_linktype.constant_part = -1; - cstate->off_linkpl.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; break; case DLT_PFSYNC: - cstate->off_linktype.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; cstate->off_linkpl.constant_part = 4; cstate->off_nl = 0; cstate->off_nl_nosnap = 0; @@ -1548,8 +1578,8 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) /* * Currently, only raw "link[N:M]" filtering is supported. */ - cstate->off_linktype.constant_part = -1; /* variable, min 15, max 71 steps of 7 */ - cstate->off_linkpl.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */ + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; /* variable, min 16, max 71 steps of 7 */ cstate->off_nl_nosnap = -1; /* no 802.2 LLC */ break; @@ -1584,8 +1614,8 @@ init_linktype(compiler_state_t *cstate, pcap_t *p) */ if (cstate->linktype >= DLT_MATCHING_MIN && cstate->linktype <= DLT_MATCHING_MAX) { - cstate->off_linktype.constant_part = -1; - cstate->off_linkpl.constant_part = -1; + cstate->off_linktype.constant_part = OFFSET_NOT_SET; + cstate->off_linkpl.constant_part = OFFSET_NOT_SET; cstate->off_nl = -1; cstate->off_nl_nosnap = -1; } else { @@ -1989,6 +2019,41 @@ gen_ether_linktype(compiler_state_t *cstate, int proto) } } +static struct block * +gen_loopback_linktype(compiler_state_t *cstate, int proto) +{ + /* + * For DLT_NULL, the link-layer header is a 32-bit word + * containing an AF_ value in *host* byte order, and for + * DLT_ENC, the link-layer header begins with a 32-bit + * word 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 + * same as the host byte order on this machine. + * + * For DLT_LOOP, the link-layer header is a 32-bit + * word containing an AF_ value in *network* byte order. + */ + if (cstate->linktype == DLT_NULL || cstate->linktype == DLT_ENC) { + /* + * The AF_ value is in host byte order, but the BPF + * interpreter will convert it to network byte order. + * + * If this is a save file, and it's from a machine + * with the opposite byte order to ours, we byte-swap + * the AF_ value. + * + * Then we run it through "htonl()", and generate + * code to compare against the result. + */ + if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped) + proto = SWAPLONG(proto); + proto = htonl(proto); + } + return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto)); +} + /* * "proto" is an Ethernet type value and for IPNET, if it is not IPv4 * or IPv6 then we have an error. @@ -2925,6 +2990,14 @@ gen_prevlinkhdr_check(compiler_state_t *cstate) /*NOTREACHED*/ } +/* + * The three different values we should check for when checking for an + * IPv6 packet with DLT_NULL. + */ +#define BSD_AFNUM_INET6_BSD 24 /* NetBSD, OpenBSD, BSD/OS, Npcap */ +#define BSD_AFNUM_INET6_FREEBSD 28 /* FreeBSD */ +#define BSD_AFNUM_INET6_DARWIN 30 /* OS X, iOS, other Darwin-based OSes */ + /* * Generate code to match a particular packet type by matching the * link-layer type field or fields in the 802.2 LLC header. @@ -3145,39 +3218,71 @@ gen_linktype(compiler_state_t *cstate, int 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, - * 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 - * same as the host byte order on this machine. - * - * For DLT_LOOP, the link-layer header is a 32-bit - * word containing an AF_ value in *network* byte order. - * - * XXX - AF_ values may, unfortunately, be platform- - * dependent; for example, FreeBSD's AF_INET6 is 24 - * whilst NetBSD's and OpenBSD's is 26. - * - * This means that, when reading a capture file, just - * checking for our AF_INET6 value won't work if the - * capture file came from another OS. - */ switch (proto) { case ETHERTYPE_IP: - proto = AF_INET; - break; + return (gen_loopback_linktype(cstate, AF_INET)); -#ifdef INET6 case ETHERTYPE_IPV6: - proto = AF_INET6; - break; -#endif + /* + * AF_ values may, unfortunately, be platform- + * dependent; AF_INET isn't, because everybody + * used 4.2BSD's value, but AF_INET6 is, because + * 4.2BSD didn't have a value for it (given that + * IPv6 didn't exist back in the early 1980's), + * and they all picked their own values. + * + * This means that, if we're reading from a + * savefile, we need to check for all the + * possible values. + * + * If we're doing a live capture, we only need + * to check for this platform's value; however, + * Npcap uses 24, which isn't Windows's AF_INET6 + * value. (Given the multiple different values, + * programs that read pcap files shouldn't be + * checking for their platform's AF_INET6 value + * anyway, they should check for all of the + * possible values. and they might as well do + * that even for live captures.) + */ + if (cstate->bpf_pcap->rfile != NULL) { + /* + * Savefile - check for all three + * possible IPv6 values. + */ + b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_BSD); + b1 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_FREEBSD); + gen_or(b0, b1); + b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_DARWIN); + gen_or(b0, b1); + return (b1); + } else { + /* + * Live capture, so we only need to + * check for the value used on this + * platform. + */ +#ifdef _WIN32 + /* + * Npcap doesn't use Windows's AF_INET6, + * as that collides with AF_IPX on + * some BSDs (both have the value 23). + * Instead, it uses 24. + */ + return (gen_loopback_linktype(cstate, 24)); +#else /* _WIN32 */ +#ifdef AF_INET6 + return (gen_loopback_linktype(cstate, AF_INET6)); +#else /* AF_INET6 */ + /* + * I guess this platform doesn't support + * IPv6, so we just reject all packets. + */ + return gen_false(cstate); +#endif /* AF_INET6 */ +#endif /* _WIN32 */ + } default: /* @@ -3188,25 +3293,6 @@ gen_linktype(compiler_state_t *cstate, int proto) return gen_false(cstate); } - if (cstate->linktype == DLT_NULL || cstate->linktype == DLT_ENC) { - /* - * The AF_ value is in host byte order, but - * the BPF interpreter will convert it to - * network byte order. - * - * If this is a save file, and it's from a - * machine with the opposite byte order to - * ours, we byte-swap the AF_ value. - * - * Then we run it through "htonl()", and - * generate code to compare against the result. - */ - if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped) - proto = SWAPLONG(proto); - proto = htonl(proto); - } - return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto)); - #ifdef HAVE_NET_PFVAR_H case DLT_PFLOG: /* @@ -3428,9 +3514,9 @@ gen_linktype(compiler_state_t *cstate, int proto) * Does this link-layer header type have a field * indicating the type of the next protocol? If * so, off_linktype.constant_part will be the offset of that - * field in the packet; if not, it will be -1. + * field in the packet; if not, it will be OFFSET_NOT_SET. */ - if (cstate->off_linktype.constant_part != (u_int)-1) { + if (cstate->off_linktype.constant_part != OFFSET_NOT_SET) { /* * Yes; assume it's an Ethernet type. (If * it's not, it needs to be handled specially @@ -4841,11 +4927,8 @@ gen_host6(compiler_state_t *cstate, struct in6_addr *addr, #ifndef INET6 static struct block * -gen_gateway(eaddr, alist, proto, dir) - const u_char *eaddr; - bpf_u_int32 **alist; - int proto; - int dir; +gen_gateway(compiler_state_t *cstate, const u_char *eaddr, bpf_u_int32 **alist, + int proto, int dir) { struct block *b0, *b1, *tmp; @@ -6248,7 +6331,7 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q) if (alist == NULL || *alist == NULL) bpf_error(cstate, "unknown host '%s'", name); tproto = proto; - if (cstate->off_linktype.constant_part == (u_int)-1 && + if (cstate->off_linktype.constant_part == OFFSET_NOT_SET && tproto == Q_DEFAULT) tproto = Q_IP; b = gen_host(cstate, **alist++, 0xffffffff, tproto, dir, q.addr); @@ -6267,7 +6350,7 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q) cstate->ai = res; b = tmp = NULL; tproto = tproto6 = proto; - if (cstate->off_linktype.constant_part == -1 && + if (cstate->off_linktype.constant_part == OFFSET_NOT_SET && tproto == Q_DEFAULT) { tproto = Q_IP; tproto6 = Q_IPV6; @@ -6409,7 +6492,7 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q) alist = pcap_nametoaddr(name); if (alist == NULL || *alist == NULL) bpf_error(cstate, "unknown host '%s'", name); - b = gen_gateway(eaddr, alist, proto, dir); + b = gen_gateway(cstate, eaddr, alist, proto, dir); free(eaddr); return b; #else