X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/f61b55ff8bfc0fe40d41c9ffacb64f0c2cd80b24..bc6f4cb8a61b5c60a8027b34b5e680977ab6ac4a:/gencode.c?ds=sidebyside diff --git a/gencode.c b/gencode.c index b9f75ccb..81da02ef 100644 --- a/gencode.c +++ b/gencode.c @@ -21,7 +21,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.35 2005-11-17 04:50:13 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.41 2006-09-13 07:02:15 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -668,20 +668,26 @@ gen_ncmp(offrel, offset, size, mask, jtype, reverse, v) static int reg_ll_size; /* - * This is the offset of the beginning of the link-layer header. + * This is the offset of the beginning of the link-layer header from + * the beginning of the raw packet data. + * * It's usually 0, except for 802.11 with a fixed-length radio header. + * (For 802.11 with a variable-length radio header, we have to generate + * code to compute that offset; off_ll is 0 in that case.) */ static u_int off_ll; /* * This is the offset of the beginning of the MAC-layer header. - * It's usually 0, except for ATM LANE. + * 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. */ static u_int off_mac; /* * "off_linktype" is the offset to information in the link-layer header - * giving the packet type. + * giving the packet type. This offset is relative to the beginning + * of the link-layer header (i.e., it doesn't include off_ll). * * For Ethernet, it's the offset of the Ethernet type field. * @@ -734,6 +740,8 @@ static u_int off_payload; /* * These are offsets to the beginning of the network-layer header. + * They are relative to the beginning of the link-layer header (i.e., + * they don't include off_ll). * * If the link layer never uses 802.2 LLC: * @@ -956,9 +964,9 @@ init_linktype(p) * the Prism header is fixed-length. */ off_ll = 144; - off_linktype = 144+24; - off_nl = 144+32; /* Prism+802.11+802.2+SNAP */ - off_nl_nosnap = 144+27; /* Prism+802.11+802.2 */ + off_linktype = 24; + off_nl = 32; /* Prism+802.11+802.2+SNAP */ + off_nl_nosnap = 27; /* Prism+802.11+802.2 */ return; case DLT_IEEE802_11_RADIO_AVS: @@ -974,12 +982,23 @@ init_linktype(p) * 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. + * of the radio header. We should handle that the + * same way we handle the length at the beginning + * of the radiotap header. + * + * XXX - in Linux, do any drivers that supply an AVS + * header supply a link-layer type other than + * ARPHRD_IEEE80211_PRISM? If so, we should map that + * to DLT_IEEE802_11_RADIO_AVS; if not, or if there are + * any drivers that supply an AVS header but supply + * an ARPHRD value of ARPHRD_IEEE80211_PRISM, we'll + * have to check the header in the generated code to + * determine whether it's Prism or AVS. */ off_ll = 64; - off_linktype = 64+24; - off_nl = 64+32; /* Radio+802.11+802.2+SNAP */ - off_nl_nosnap = 64+27; /* Radio+802.11+802.2 */ + off_linktype = 24; + off_nl = 32; /* Radio+802.11+802.2+SNAP */ + off_nl_nosnap = 27; /* Radio+802.11+802.2 */ return; case DLT_IEEE802_11_RADIO: @@ -1081,6 +1100,17 @@ init_linktype(p) off_nl_nosnap = 0; /* no 802.2 LLC */ return; + /* + * the only BPF-interesting FRF.16 frames are non-control frames; + * Frame Relay has a variable length link-layer + * so lets start with offset 4 for now and increments later on (FIXME); + */ + case DLT_MFR: + off_linktype = -1; + off_nl = 4; + off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */ + return; + case DLT_APPLE_IP_OVER_IEEE1394: off_linktype = 16; off_nl = 18; @@ -1229,6 +1259,9 @@ gen_load_llrel(offset, size) * If "s" is non-null, it has code to arrange that the X register * contains the length of the prefix preceding the link-layer * header. + * + * Otherwise, the length of the prefix preceding the link-layer + * header is "off_ll". */ if (s != NULL) { s2 = new_stmt(BPF_LD|BPF_IND|size); @@ -1236,7 +1269,7 @@ gen_load_llrel(offset, size) sappend(s, s2); } else { s = new_stmt(BPF_LD|BPF_ABS|size); - s->s.k = offset; + s->s.k = offset + off_ll; } return s; } @@ -1254,11 +1287,12 @@ gen_load_a(offrel, offset, size) switch (offrel) { case OR_PACKET: - s = gen_load_llrel(offset, size); + s = new_stmt(BPF_LD|BPF_ABS|size); + s->s.k = offset; break; case OR_LINK: - s = gen_load_llrel(off_ll + offset, size); + s = gen_load_llrel(offset, size); break; case OR_NET: @@ -3368,18 +3402,24 @@ gen_gateway(eaddr, alist, proto, dir) case Q_IP: case Q_ARP: case Q_RARP: - if (linktype == DLT_EN10MB) - b0 = gen_ehostop(eaddr, Q_OR); - else if (linktype == DLT_FDDI) - b0 = gen_fhostop(eaddr, Q_OR); - else if (linktype == DLT_IEEE802) - b0 = gen_thostop(eaddr, Q_OR); - else if (linktype == DLT_IEEE802_11 || - linktype == DLT_IEEE802_11_RADIO_AVS || - linktype == DLT_IEEE802_11_RADIO || - linktype == DLT_PRISM_HEADER) - b0 = gen_wlanhostop(eaddr, Q_OR); - else if (linktype == DLT_SUNATM && is_lane) { + switch (linktype) { + case DLT_EN10MB: + b0 = gen_ehostop(eaddr, Q_OR); + break; + case DLT_FDDI: + b0 = gen_fhostop(eaddr, Q_OR); + break; + case DLT_IEEE802: + b0 = gen_thostop(eaddr, Q_OR); + break; + case DLT_IEEE802_11: + case DLT_IEEE802_11_RADIO_AVS: + case DLT_IEEE802_11_RADIO: + case DLT_PRISM_HEADER: + 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 @@ -3394,12 +3434,15 @@ gen_gateway(eaddr, alist, proto, dir) */ b0 = gen_ehostop(eaddr, Q_OR); gen_and(b1, b0); - } else if (linktype == DLT_IP_OVER_FC) - b0 = gen_ipfchostop(eaddr, Q_OR); - else - bpf_error( + } + 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"); - + } b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST); while (*alist) { tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR, @@ -4991,7 +5034,14 @@ gen_mcode(s1, s2, masklen, q) /* Convert mask len to mask */ if (masklen > 32) bpf_error("mask length must be <= 32"); - m = 0xffffffff << (32 - masklen); + if (masklen == 0) { + /* + * X << 32 is not guaranteed by C to be 0; it's + * undefined. + */ + m = 0; + } else + m = 0xffffffff << (32 - masklen); if ((n & ~m) != 0) bpf_error("non-network bits set in \"%s/%d\"", s1, masklen); @@ -5186,18 +5236,20 @@ gen_ecode(eaddr, q) struct block *b, *tmp; if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { - if (linktype == DLT_EN10MB) - return gen_ehostop(eaddr, (int)q.dir); - if (linktype == DLT_FDDI) - return gen_fhostop(eaddr, (int)q.dir); - if (linktype == DLT_IEEE802) - return gen_thostop(eaddr, (int)q.dir); - if (linktype == DLT_IEEE802_11 || - linktype == DLT_IEEE802_11_RADIO_AVS || - linktype == DLT_IEEE802_11_RADIO || - linktype == DLT_PRISM_HEADER) - return gen_wlanhostop(eaddr, (int)q.dir); - if (linktype == DLT_SUNATM && is_lane) { + switch (linktype) { + case DLT_EN10MB: + return gen_ehostop(eaddr, (int)q.dir); + case DLT_FDDI: + return gen_fhostop(eaddr, (int)q.dir); + case DLT_IEEE802: + return gen_thostop(eaddr, (int)q.dir); + case DLT_IEEE802_11: + case DLT_IEEE802_11_RADIO_AVS: + case DLT_IEEE802_11_RADIO: + case DLT_PRISM_HEADER: + return gen_wlanhostop(eaddr, (int)q.dir); + case DLT_SUNATM: + if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated @@ -5214,9 +5266,13 @@ gen_ecode(eaddr, q) gen_and(tmp, b); return b; } - if (linktype == DLT_IP_OVER_FC) - return gen_ipfchostop(eaddr, (int)q.dir); + break; + case DLT_IP_OVER_FC: + return gen_ipfchostop(eaddr, (int)q.dir); + default: bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); + break; + } } bpf_error("ethernet address used in non-ether expression"); /* NOTREACHED */ @@ -5751,22 +5807,25 @@ gen_broadcast(proto) case Q_DEFAULT: case Q_LINK: - if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX) - return gen_ahostop(abroadcast, Q_DST); - if (linktype == DLT_EN10MB) - return gen_ehostop(ebroadcast, Q_DST); - if (linktype == DLT_FDDI) - return gen_fhostop(ebroadcast, Q_DST); - if (linktype == DLT_IEEE802) - return gen_thostop(ebroadcast, Q_DST); - if (linktype == DLT_IEEE802_11 || - linktype == DLT_IEEE802_11_RADIO_AVS || - linktype == DLT_IEEE802_11_RADIO || - linktype == DLT_PRISM_HEADER) - return gen_wlanhostop(ebroadcast, Q_DST); - if (linktype == DLT_IP_OVER_FC) - return gen_ipfchostop(ebroadcast, Q_DST); - if (linktype == DLT_SUNATM && is_lane) { + switch (linktype) { + case DLT_ARCNET: + case DLT_ARCNET_LINUX: + return gen_ahostop(abroadcast, Q_DST); + case DLT_EN10MB: + return gen_ehostop(ebroadcast, Q_DST); + case DLT_FDDI: + return gen_fhostop(ebroadcast, Q_DST); + case DLT_IEEE802: + return gen_thostop(ebroadcast, Q_DST); + case DLT_IEEE802_11: + case DLT_IEEE802_11_RADIO_AVS: + case DLT_IEEE802_11_RADIO: + case DLT_PRISM_HEADER: + return gen_wlanhostop(ebroadcast, Q_DST); + case DLT_IP_OVER_FC: + return gen_ipfchostop(ebroadcast, Q_DST); + case DLT_SUNATM: + if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated @@ -5782,8 +5841,11 @@ gen_broadcast(proto) b0 = gen_ehostop(ebroadcast, Q_DST); gen_and(b1, b0); return b0; - } - bpf_error("not a broadcast link"); + } + break; + default: + bpf_error("not a broadcast link"); + } break; case Q_IP: @@ -5830,154 +5892,146 @@ gen_multicast(proto) case Q_DEFAULT: case Q_LINK: - if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX) - /* all ARCnet multicasts use the same address */ - return gen_ahostop(abroadcast, Q_DST); - - if (linktype == DLT_EN10MB) { - /* ether[0] & 1 != 0 */ - return gen_mac_multicast(0); - } - - if (linktype == DLT_FDDI) { - /* - * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX - * - * XXX - was that referring to bit-order issues? - */ - /* fddi[1] & 1 != 0 */ - return gen_mac_multicast(1); - } - - if (linktype == DLT_IEEE802) { - /* tr[2] & 1 != 0 */ - return gen_mac_multicast(2); - } - - if (linktype == DLT_IEEE802_11 || - linktype == DLT_IEEE802_11_RADIO_AVS || - linktype == DLT_IEEE802_11_RADIO || - linktype == DLT_PRISM_HEADER) { - /* - * Oh, yuk. - * - * For control frames, there is no DA. - * - * For management frames, DA is at an - * offset of 4 from the beginning of - * the packet. - * - * For data frames, DA is at an offset - * of 4 from the beginning of the packet - * if To DS is clear and at an offset of - * 16 from the beginning of the packet - * if To DS is set. - */ - - /* - * Generate the tests to be done for data frames. - * - * First, check for To DS set, i.e. "link[1] & 0x01". - */ - s = gen_load_a(OR_LINK, 1, BPF_B); - b1 = new_block(JMP(BPF_JSET)); - b1->s.k = 0x01; /* To DS */ - b1->stmts = s; - - /* - * If To DS is set, the DA is at 16. - */ - b0 = gen_mac_multicast(16); - gen_and(b1, b0); - - /* - * Now, check for To DS not set, i.e. check - * "!(link[1] & 0x01)". - */ - s = gen_load_a(OR_LINK, 1, BPF_B); - b2 = new_block(JMP(BPF_JSET)); - b2->s.k = 0x01; /* To DS */ - b2->stmts = s; - gen_not(b2); - - /* - * If To DS is not set, the DA is at 4. - */ - b1 = gen_mac_multicast(4); - gen_and(b2, b1); - - /* - * Now OR together the last two checks. That gives - * the complete set of checks for data frames. - */ - gen_or(b1, b0); - - /* - * Now check for a data 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 checks done for data frames. - */ - gen_and(b1, b0); - - /* - * 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); - b2 = new_block(JMP(BPF_JSET)); - b2->s.k = 0x08; - b2->stmts = s; - gen_not(b2); - - /* - * For management frames, the DA is at 4. - */ - b1 = gen_mac_multicast(4); - gen_and(b2, b1); - - /* - * OR that with the checks done for data frames. - * That gives the checks done for management and - * data frames. - */ - gen_or(b1, b0); - - /* - * If the low-order bit of the type value is 1, - * this is either a control frame or a frame - * with a reserved type, and thus not a - * frame with an SA. - * - * I.e., check "!(link[0] & 0x04)". - */ - s = gen_load_a(OR_LINK, 0, BPF_B); - b1 = new_block(JMP(BPF_JSET)); - b1->s.k = 0x04; - b1->stmts = s; - gen_not(b1); - - /* - * AND that with the checks for data and management - * frames. - */ - gen_and(b1, b0); - return b0; - } - - if (linktype == DLT_IP_OVER_FC) { - b0 = gen_mac_multicast(2); - return b0; - } - - if (linktype == DLT_SUNATM && is_lane) { + switch (linktype) { + case DLT_ARCNET: + case DLT_ARCNET_LINUX: + /* all ARCnet multicasts use the same address */ + return gen_ahostop(abroadcast, Q_DST); + case DLT_EN10MB: + /* ether[0] & 1 != 0 */ + return gen_mac_multicast(0); + case DLT_FDDI: + /* + * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX + * + * XXX - was that referring to bit-order issues? + */ + /* fddi[1] & 1 != 0 */ + return gen_mac_multicast(1); + case DLT_IEEE802: + /* tr[2] & 1 != 0 */ + return gen_mac_multicast(2); + case DLT_IEEE802_11: + case DLT_IEEE802_11_RADIO_AVS: + case DLT_IEEE802_11_RADIO: + case DLT_PRISM_HEADER: + /* + * Oh, yuk. + * + * For control frames, there is no DA. + * + * For management frames, DA is at an + * offset of 4 from the beginning of + * the packet. + * + * For data frames, DA is at an offset + * of 4 from the beginning of the packet + * if To DS is clear and at an offset of + * 16 from the beginning of the packet + * if To DS is set. + */ + + /* + * Generate the tests to be done for data frames. + * + * First, check for To DS set, i.e. "link[1] & 0x01". + */ + s = gen_load_a(OR_LINK, 1, BPF_B); + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x01; /* To DS */ + b1->stmts = s; + + /* + * If To DS is set, the DA is at 16. + */ + b0 = gen_mac_multicast(16); + gen_and(b1, b0); + + /* + * Now, check for To DS not set, i.e. check + * "!(link[1] & 0x01)". + */ + s = gen_load_a(OR_LINK, 1, BPF_B); + b2 = new_block(JMP(BPF_JSET)); + b2->s.k = 0x01; /* To DS */ + b2->stmts = s; + gen_not(b2); + + /* + * If To DS is not set, the DA is at 4. + */ + b1 = gen_mac_multicast(4); + gen_and(b2, b1); + + /* + * Now OR together the last two checks. That gives + * the complete set of checks for data frames. + */ + gen_or(b1, b0); + + /* + * Now check for a data 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 checks done for data frames. + */ + gen_and(b1, b0); + + /* + * 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); + b2 = new_block(JMP(BPF_JSET)); + b2->s.k = 0x08; + b2->stmts = s; + gen_not(b2); + + /* + * For management frames, the DA is at 4. + */ + b1 = gen_mac_multicast(4); + gen_and(b2, b1); + + /* + * OR that with the checks done for data frames. + * That gives the checks done for management and + * data frames. + */ + gen_or(b1, b0); + + /* + * If the low-order bit of the type value is 1, + * this is either a control frame or a frame + * with a reserved type, and thus not a + * frame with an SA. + * + * I.e., check "!(link[0] & 0x04)". + */ + s = gen_load_a(OR_LINK, 0, BPF_B); + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x04; + b1->stmts = s; + gen_not(b1); + + /* + * AND that with the checks for data and management + * frames. + */ + gen_and(b1, b0); + return b0; + case DLT_IP_OVER_FC: + b0 = gen_mac_multicast(2); + return b0; + case DLT_SUNATM: + if (is_lane) { /* * Check that the packet doesn't begin with an * LE Control marker. (We've already generated @@ -5991,10 +6045,13 @@ gen_multicast(proto) b0 = gen_mac_multicast(off_mac); gen_and(b1, b0); return b0; - } - - /* Link not known to support multicasts */ - break; + } + break; + default: + break; + } + /* Link not known to support multicasts */ + break; case Q_IP: b0 = gen_linktype(ETHERTYPE_IP);