X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/4244b90c1591882140ee9e58ecfc3e3264c910b3..e5aebee6d80c8909048dc1ce865e9adb97d94fd7:/gencode.c diff --git a/gencode.c b/gencode.c index 15448a6b..e8c5fb0f 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.186 2003-02-14 07:48:25 guy Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.209 2004-08-27 07:37:10 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -70,6 +70,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,8 +97,8 @@ 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 @@ -208,7 +212,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 +230,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) @@ -736,7 +743,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; @@ -821,7 +835,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 */ @@ -844,13 +860,14 @@ init_linktype(type) off_nl_nosnap = 144+27; /* Prism+802.11+802.2 */ return; - case DLT_IEEE802_11_RADIO: + 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. + * 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, @@ -863,6 +880,29 @@ init_linktype(type) 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 */ /* @@ -938,6 +978,51 @@ 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; + +#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 */ @@ -1172,6 +1257,7 @@ gen_linktype(proto) case DLT_EN10MB: return gen_ether_linktype(proto); + /*NOTREACHED*/ break; case DLT_C_HDLC: @@ -1183,6 +1269,7 @@ gen_linktype(proto) default: return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); + /*NOTREACHED*/ break; } break; @@ -1196,6 +1283,7 @@ gen_linktype(proto) case DLT_ATM_CLIP: case DLT_IP_OVER_FC: return gen_llc(proto); + /*NOTREACHED*/ break; case DLT_SUNATM: @@ -1391,6 +1479,7 @@ gen_linktype(proto) (bpf_int32)proto); } } + /*NOTREACHED*/ break; case DLT_SLIP: @@ -1414,9 +1503,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: /* @@ -1521,9 +1612,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 @@ -1561,7 +1656,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 @@ -1581,6 +1676,24 @@ 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: /* @@ -1622,6 +1735,7 @@ gen_linktype(proto) return (gen_cmp(off_linktype, BPF_B, (bpf_int32)ARCTYPE_ATALK)); } + /*NOTREACHED*/ break; case DLT_LTALK: @@ -1631,6 +1745,7 @@ gen_linktype(proto) default: return gen_false(); } + /*NOTREACHED*/ break; case DLT_FRELAY: @@ -1676,7 +1791,14 @@ gen_linktype(proto) default: return gen_false(); } + /*NOTREACHED*/ break; + + 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"); } /* @@ -1689,7 +1811,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(); /* @@ -2459,7 +2581,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); @@ -2945,8 +3067,8 @@ gen_proto_abbrev(proto) 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; @@ -3603,6 +3725,7 @@ 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: @@ -3860,7 +3983,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) { @@ -4043,6 +4166,7 @@ gen_mcode(s1, s2, masklen, q) bpf_error("Mask syntax for networks only"); /* NOTREACHED */ } + /* NOTREACHED */ } struct block * @@ -4645,6 +4769,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 @@ -4674,7 +4800,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 */ } /* @@ -4852,6 +4979,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 @@ -4885,7 +5017,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 */ } /* @@ -4931,8 +5064,23 @@ 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; + default: - bpf_error("inbound/outbound not supported on linktype %d\n", + bpf_error("inbound/outbound not supported on linktype %d", linktype); b0 = NULL; /* NOTREACHED */ @@ -4940,6 +5088,116 @@ 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; @@ -5025,7 +5283,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; } @@ -5047,7 +5376,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); @@ -5056,21 +5385,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); @@ -5079,7 +5408,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);