| *************** |
| *** 24,29 **** |
| "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.51 2007/06/14 20:54:12 gianluca Exp $ (LBL)"; |
| #endif |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| --- 24,31 ---- |
| "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.51 2007/06/14 20:54:12 gianluca Exp $ (LBL)"; |
| #endif |
| |
| + #define ENABLE_WLAN_FILTERING_PATCH |
| + |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| *************** |
| *** 144,150 **** |
| OR_NET, /* relative to the network-layer header */ |
| OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ |
| OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ |
| - OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ |
| }; |
| |
| /* |
| --- 146,153 ---- |
| OR_NET, /* relative to the network-layer header */ |
| OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ |
| OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ |
| + OR_TRAN_IPV6, /* relative to the transport-layer header, with IPv6 network layer */ |
| + OR_LINK_AFTER_WIRELESS_HDR /* After the 802.11 variable length header */ |
| }; |
| |
| /* |
| *************** |
| *** 199,204 **** |
| static struct block *gen_linktype(int); |
| static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); |
| static struct block *gen_llc_linktype(int); |
| 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); |
| --- 202,208 ---- |
| static struct block *gen_linktype(int); |
| static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); |
| static struct block *gen_llc_linktype(int); |
| + static struct block *gen_802_11_llc_linktype(int); |
| 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); |
| *************** |
| *** 242,247 **** |
| static struct slist *xfer_to_a(struct arth *); |
| static struct block *gen_mac_multicast(int); |
| static struct block *gen_len(int, int); |
| |
| static struct block *gen_ppi_dlt_check(); |
| static struct block *gen_msg_abbrev(int type); |
| --- 246,252 ---- |
| static struct slist *xfer_to_a(struct arth *); |
| static struct block *gen_mac_multicast(int); |
| static struct block *gen_len(int, int); |
| + static struct block *gen_check_802_11_data_frame(); |
| |
| static struct block *gen_ppi_dlt_check(); |
| static struct block *gen_msg_abbrev(int type); |
| *************** |
| *** 1345,1350 **** |
| return s; |
| } |
| |
| |
| /* |
| * Load a value relative to the beginning of the specified header. |
| --- 1350,1487 ---- |
| return s; |
| } |
| |
| + /* |
| + * Load a value relative to the beginning of the link-layer header after the 802.11 |
| + * header, i.e. LLC_SNAP. |
| + * The link-layer header doesn't necessarily begin at the beginning |
| + * of the packet data; there might be a variable-length prefix containing |
| + * radio information. |
| + */ |
| + static struct slist * |
| + gen_load_ll_after_802_11_rel(offset, size) |
| + u_int offset, size; |
| + { |
| + struct slist *s, *s_load_fc; |
| + struct slist *sjset_qos; |
| + struct slist *s_load; |
| + struct slist *s_ld_a_2; |
| + struct slist *s_add_a_x; |
| + struct slist *s_a_to_x; |
| + struct slist *sjset_data_frame_1; |
| + struct slist *sjset_data_frame_2; |
| + struct slist *s_load_x_0; |
| + |
| + /* |
| + * This code is not compatible with the optimizer, as |
| + * we are generating jmp instructions within a normal |
| + * slist of instructions |
| + * |
| + */ |
| + no_optimize = 1; |
| + |
| + s = gen_llprefixlen(); |
| + |
| + /* |
| + * 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) { |
| + /* |
| + * There's a variable-length prefix preceding the |
| + * link-layer header. "s" points to a list of statements |
| + * that put the length of that prefix into the X register. |
| + * do an indirect load, to use the X register as an offset. |
| + */ |
| + |
| + /* |
| + * Load the Frame Control field |
| + */ |
| + s_load_fc = new_stmt(BPF_LD|BPF_IND|BPF_B); |
| + s_load_fc->s.k = 0; |
| + } else { |
| + /* |
| + * There is no variable-length header preceding the |
| + * link-layer header; add in off_ll, which, if there's |
| + * a fixed-length header preceding the link-layer header, |
| + * is the length of that header. |
| + */ |
| + |
| + /* |
| + * We need to load the Frame control directly, and |
| + * then load X with a fake 0, i.e. the length of the |
| + * non-existing prepended header |
| + */ |
| + |
| + /* |
| + * TODO GV: I'm not sure if 0 is the right constant in this |
| + * case. If the link layer has a fixed length prepended header, |
| + * that should be the value that we put here |
| + */ |
| + |
| + /* Load 0 into X */ |
| + s_load_x_0 = new_stmt(BPF_LDX|BPF_IMM); |
| + s_load_x_0->s.k = 0; |
| + |
| + /* |
| + * TODO GV: I'm not sure if 0 is the right constant in this |
| + * case. If the link layer has a fixed length prepended header, |
| + * that should be the value that we put here |
| + */ |
| + |
| + /* |
| + * load the Frame Control with absolute access |
| + */ |
| + s_load_fc = new_stmt(BPF_LD|BPF_ABS|BPF_B); |
| + s_load_fc->s.k = 0; |
| + s = s_load_x_0; |
| + } |
| + |
| + /* |
| + * Generate the common instructions to check if it's a data frame |
| + * and if so compute the 802.11 header length |
| + */ |
| + sjset_data_frame_1 = new_stmt(JMP(BPF_JSET)); // b3 should be 1 |
| + sjset_data_frame_1->s.k = 0x8; |
| + |
| + sjset_data_frame_2 = new_stmt(JMP(BPF_JSET)); // b2 should be 0 |
| + sjset_data_frame_2->s.k = 0x04; |
| + |
| + sjset_qos = new_stmt(JMP(BPF_JSET)); |
| + sjset_qos->s.k = 0x80; //QOS bit |
| + |
| + s_ld_a_2 = new_stmt(BPF_LD|BPF_IMM); |
| + s_ld_a_2->s.k = 2; |
| + |
| + s_add_a_x = new_stmt(BPF_ALU|BPF_ADD|BPF_X); |
| + s_a_to_x = new_stmt(BPF_MISC|BPF_TAX); |
| + |
| + s_load = new_stmt(BPF_LD|BPF_IND|size); |
| + s_load->s.k = offset; |
| + |
| + sjset_data_frame_1->s.jt = sjset_data_frame_2; |
| + sjset_data_frame_1->s.jf = s_load; |
| + |
| + sjset_data_frame_2->s.jt = s_load; |
| + sjset_data_frame_2->s.jf = sjset_qos; |
| + |
| + sjset_qos->s.jt = s_ld_a_2; |
| + sjset_qos->s.jf = s_load; |
| + |
| + sappend(s, s_load_fc); |
| + sappend(s_load_fc, sjset_data_frame_1); |
| + sappend(sjset_data_frame_1, sjset_data_frame_2); |
| + sappend(sjset_data_frame_2, sjset_qos); |
| + sappend(sjset_qos, s_ld_a_2); |
| + sappend(s_ld_a_2, s_add_a_x); |
| + sappend(s_add_a_x,s_a_to_x); |
| + sappend(s_a_to_x, s_load); |
| + |
| + return s; |
| + } |
| |
| /* |
| * Load a value relative to the beginning of the specified header. |
| *************** |
| *** 1367,1372 **** |
| s = gen_load_llrel(offset, size); |
| break; |
| |
| case OR_NET: |
| s = gen_load_llrel(off_nl + offset, size); |
| break; |
| --- 1504,1525 ---- |
| s = gen_load_llrel(offset, size); |
| break; |
| |
| + #ifdef ENABLE_WLAN_FILTERING_PATCH |
| + |
| + case OR_LINK_AFTER_WIRELESS_HDR: |
| + if (linktype != DLT_IEEE802_11_RADIO |
| + && linktype != DLT_PPI |
| + && linktype != DLT_IEEE802_11 |
| + && linktype != DLT_PRISM_HEADER |
| + && linktype != DLT_IEEE802_11_RADIO_AVS) |
| + { |
| + abort(); |
| + return NULL; |
| + } |
| + s = gen_load_ll_after_802_11_rel(offset + 24, size); |
| + break; |
| + #endif /* ENABLE_WLAN_FILTERING_PATCH */ |
| + |
| case OR_NET: |
| s = gen_load_llrel(off_nl + offset, size); |
| break; |
| *************** |
| *** 2163,2173 **** |
| break; |
| |
| case DLT_PPI: |
| case DLT_FDDI: |
| case DLT_IEEE802: |
| - case DLT_IEEE802_11: |
| case DLT_IEEE802_11_RADIO_AVS: |
| - case DLT_IEEE802_11_RADIO: |
| case DLT_PRISM_HEADER: |
| case DLT_ATM_RFC1483: |
| case DLT_ATM_CLIP: |
| --- 2316,2332 ---- |
| break; |
| |
| case DLT_PPI: |
| + case DLT_IEEE802_11_RADIO: |
| + case DLT_IEEE802_11: |
| + #ifdef ENABLE_WLAN_FILTERING_PATCH |
| + return gen_802_11_llc_linktype(proto); |
| + /*NOTREACHED*/ |
| + break; |
| + #endif /* ENABLE_WLAN_FILTERING_PATCH */ |
| + |
| case DLT_FDDI: |
| case DLT_IEEE802: |
| case DLT_IEEE802_11_RADIO_AVS: |
| case DLT_PRISM_HEADER: |
| case DLT_ATM_RFC1483: |
| case DLT_ATM_CLIP: |
| *************** |
| *** 2711,2716 **** |
| } |
| } |
| |
| static struct block * |
| gen_hostop(addr, mask, dir, proto, src_off, dst_off) |
| bpf_u_int32 addr; |
| --- 2870,2982 ---- |
| } |
| } |
| |
| + /* |
| + * Generate code to match a particular packet type, for link-layer types |
| + * using 802.2 LLC headers. |
| + * |
| + * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used |
| + * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. |
| + * |
| + * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP |
| + * value, if <= ETHERMTU. We use that to determine whether to |
| + * match the DSAP or both DSAP and LSAP or to check the OUI and |
| + * protocol ID in a SNAP header. |
| + */ |
| + static struct block * |
| + gen_802_11_llc_linktype(proto) |
| + int proto; |
| + { |
| + struct block *b_check_data_frame; |
| + struct block *b_check_linktype; |
| + |
| + b_check_data_frame = gen_check_802_11_data_frame(); |
| + |
| + /* |
| + * XXX - generate the code that discards non data frames |
| + */ |
| + switch (proto) { |
| + |
| + case LLCSAP_IP: |
| + case LLCSAP_ISONS: |
| + case LLCSAP_NETBEUI: |
| + /* |
| + * XXX - should we check both the DSAP and the |
| + * SSAP, like this, or should we check just the |
| + * DSAP, as we do for other types <= ETHERMTU |
| + * (i.e., other SAP values)? |
| + */ |
| + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_H, (bpf_u_int32) |
| + ((proto << 8) | proto)); |
| + break; |
| + |
| + case LLCSAP_IPX: |
| + /* |
| + * XXX - are there ever SNAP frames for IPX on |
| + * non-Ethernet 802.x networks? |
| + */ |
| + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, |
| + (bpf_int32)LLCSAP_IPX); |
| + |
| + break; |
| + |
| + #if 0 |
| + 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); |
| + #endif |
| + 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. |
| + */ |
| + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, 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. |
| + */ |
| + b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0+6, BPF_H, |
| + (bpf_int32)proto); |
| + } |
| + } |
| + |
| + gen_and(b_check_data_frame, b_check_linktype); |
| + return b_check_linktype; |
| + |
| + } |
| + |
| + |
| + |
| static struct block * |
| gen_hostop(addr, mask, dir, proto, src_off, dst_off) |
| bpf_u_int32 addr; |
| *************** |
| *** 2925,2930 **** |
| register struct block *b0, *b1, *b2; |
| register struct slist *s; |
| |
| switch (dir) { |
| case Q_SRC: |
| /* |
| --- 3191,3207 ---- |
| register struct block *b0, *b1, *b2; |
| register struct slist *s; |
| |
| + #ifdef ENABLE_WLAN_FILTERING_PATCH |
| + /* |
| + * TODO GV 20070613 |
| + * We need to disable the optimizer because the optimizer is buggy |
| + * and wipes out some LD instructions generated by the below |
| + * code to validate the Frame Control bits |
| + * |
| + */ |
| + no_optimize = 1; |
| + #endif /* ENABLE_WLAN_FILTERING_PATCH */ |
| + |
| switch (dir) { |
| case Q_SRC: |
| /* |
| *************** |
| *** 4713,4718 **** |
| #endif |
| } |
| |
| |
| /* |
| * Generate code that checks whether the packet is a packet for protocol |
| --- 4990,5021 ---- |
| #endif |
| } |
| |
| + static struct block * |
| + gen_check_802_11_data_frame() |
| + { |
| + struct slist *s; |
| + struct block *b0, *b1; |
| + /* |
| + * Now check for a data frame. |
| + * I.e, check "link[0] & 0x08". |
| + */ |
| + s = gen_load_a(OR_LINK, 0, BPF_B); |
| + b0 = new_block(JMP(BPF_JSET)); |
| + b0->s.k = 0x08; |
| + b0->stmts = s; |
| + |
| + 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); |
| + |
| + |
| + gen_and(b1, b0); |
| + |
| + return b0; |
| + } |
| + |
| |
| /* |
| * Generate code that checks whether the packet is a packet for protocol |