1--- gencode.c.cvs 2007-06-14 13:54:12.000000000 -0700 2+++ gencode.c 2007-06-14 13:56:27.531250000 -0700 3@@ -24,6 +24,8 @@ 4 "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.51 2007/06/14 20:54:12 gianluca Exp $ (LBL)"; 5 #endif 6 7+#define ENABLE_WLAN_FILTERING_PATCH 8+ 9 #ifdef HAVE_CONFIG_H 10 #include "config.h" 11 #endif 12@@ -144,7 +146,8 @@ 13 OR_NET, /* relative to the network-layer header */ 14 OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ 15 OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ 16- OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ 17+ OR_TRAN_IPV6, /* relative to the transport-layer header, with IPv6 network layer */ 18+ OR_LINK_AFTER_WIRELESS_HDR /* After the 802.11 variable length header */ 19 }; 20 21 /* 22@@ -199,6 +202,7 @@ 23 static struct block *gen_linktype(int); 24 static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); 25 static struct block *gen_llc_linktype(int); 26+static struct block *gen_802_11_llc_linktype(int); 27 static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); 28 #ifdef INET6 29 static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); 30@@ -242,6 +246,7 @@ 31 static struct slist *xfer_to_a(struct arth *); 32 static struct block *gen_mac_multicast(int); 33 static struct block *gen_len(int, int); 34+static struct block *gen_check_802_11_data_frame(); 35 36 static struct block *gen_ppi_dlt_check(); 37 static struct block *gen_msg_abbrev(int type); 38@@ -1345,6 +1350,138 @@ 39 return s; 40 } 41 42+/* 43+ * Load a value relative to the beginning of the link-layer header after the 802.11 44+ * header, i.e. LLC_SNAP. 45+ * The link-layer header doesn't necessarily begin at the beginning 46+ * of the packet data; there might be a variable-length prefix containing 47+ * radio information. 48+ */ 49+static struct slist * 50+gen_load_ll_after_802_11_rel(offset, size) 51+ u_int offset, size; 52+{ 53+ struct slist *s, *s_load_fc; 54+ struct slist *sjset_qos; 55+ struct slist *s_load; 56+ struct slist *s_ld_a_2; 57+ struct slist *s_add_a_x; 58+ struct slist *s_a_to_x; 59+ struct slist *sjset_data_frame_1; 60+ struct slist *sjset_data_frame_2; 61+ struct slist *s_load_x_0; 62+ 63+ /* 64+ * This code is not compatible with the optimizer, as 65+ * we are generating jmp instructions within a normal 66+ * slist of instructions 67+ * 68+ */ 69+ no_optimize = 1; 70+ 71+ s = gen_llprefixlen(); 72+ 73+ /* 74+ * If "s" is non-null, it has code to arrange that the X register 75+ * contains the length of the prefix preceding the link-layer 76+ * header. 77+ * 78+ * Otherwise, the length of the prefix preceding the link-layer 79+ * header is "off_ll". 80+ */ 81+ if (s != NULL) { 82+ /* 83+ * There's a variable-length prefix preceding the 84+ * link-layer header. "s" points to a list of statements 85+ * that put the length of that prefix into the X register. 86+ * do an indirect load, to use the X register as an offset. 87+ */ 88+ 89+ /* 90+ * Load the Frame Control field 91+ */ 92+ s_load_fc = new_stmt(BPF_LD|BPF_IND|BPF_B); 93+ s_load_fc->s.k = 0; 94+ } else { 95+ /* 96+ * There is no variable-length header preceding the 97+ * link-layer header; add in off_ll, which, if there's 98+ * a fixed-length header preceding the link-layer header, 99+ * is the length of that header. 100+ */ 101+ 102+ /* 103+ * We need to load the Frame control directly, and 104+ * then load X with a fake 0, i.e. the length of the 105+ * non-existing prepended header 106+ */ 107+ 108+ /* 109+ * TODO GV: I'm not sure if 0 is the right constant in this 110+ * case. If the link layer has a fixed length prepended header, 111+ * that should be the value that we put here 112+ */ 113+ 114+ /* Load 0 into X */ 115+ s_load_x_0 = new_stmt(BPF_LDX|BPF_IMM); 116+ s_load_x_0->s.k = 0; 117+ 118+ /* 119+ * TODO GV: I'm not sure if 0 is the right constant in this 120+ * case. If the link layer has a fixed length prepended header, 121+ * that should be the value that we put here 122+ */ 123+ 124+ /* 125+ * load the Frame Control with absolute access 126+ */ 127+ s_load_fc = new_stmt(BPF_LD|BPF_ABS|BPF_B); 128+ s_load_fc->s.k = 0; 129+ s = s_load_x_0; 130+ } 131+ 132+ /* 133+ * Generate the common instructions to check if it's a data frame 134+ * and if so compute the 802.11 header length 135+ */ 136+ sjset_data_frame_1 = new_stmt(JMP(BPF_JSET)); // b3 should be 1 137+ sjset_data_frame_1->s.k = 0x8; 138+ 139+ sjset_data_frame_2 = new_stmt(JMP(BPF_JSET)); // b2 should be 0 140+ sjset_data_frame_2->s.k = 0x04; 141+ 142+ sjset_qos = new_stmt(JMP(BPF_JSET)); 143+ sjset_qos->s.k = 0x80; //QOS bit 144+ 145+ s_ld_a_2 = new_stmt(BPF_LD|BPF_IMM); 146+ s_ld_a_2->s.k = 2; 147+ 148+ s_add_a_x = new_stmt(BPF_ALU|BPF_ADD|BPF_X); 149+ s_a_to_x = new_stmt(BPF_MISC|BPF_TAX); 150+ 151+ s_load = new_stmt(BPF_LD|BPF_IND|size); 152+ s_load->s.k = offset; 153+ 154+ sjset_data_frame_1->s.jt = sjset_data_frame_2; 155+ sjset_data_frame_1->s.jf = s_load; 156+ 157+ sjset_data_frame_2->s.jt = s_load; 158+ sjset_data_frame_2->s.jf = sjset_qos; 159+ 160+ sjset_qos->s.jt = s_ld_a_2; 161+ sjset_qos->s.jf = s_load; 162+ 163+ sappend(s, s_load_fc); 164+ sappend(s_load_fc, sjset_data_frame_1); 165+ sappend(sjset_data_frame_1, sjset_data_frame_2); 166+ sappend(sjset_data_frame_2, sjset_qos); 167+ sappend(sjset_qos, s_ld_a_2); 168+ sappend(s_ld_a_2, s_add_a_x); 169+ sappend(s_add_a_x,s_a_to_x); 170+ sappend(s_a_to_x, s_load); 171+ 172+ return s; 173+} 174 175 /* 176 * Load a value relative to the beginning of the specified header. 177@@ -1367,6 +1504,22 @@ 178 s = gen_load_llrel(offset, size); 179 break; 180 181+#ifdef ENABLE_WLAN_FILTERING_PATCH 182+ 183+ case OR_LINK_AFTER_WIRELESS_HDR: 184+ if (linktype != DLT_IEEE802_11_RADIO 185+ && linktype != DLT_PPI 186+ && linktype != DLT_IEEE802_11 187+ && linktype != DLT_PRISM_HEADER 188+ && linktype != DLT_IEEE802_11_RADIO_AVS) 189+ { 190+ abort(); 191+ return NULL; 192+ } 193+ s = gen_load_ll_after_802_11_rel(offset + 24, size); 194+ break; 195+#endif /* ENABLE_WLAN_FILTERING_PATCH */ 196+ 197 case OR_NET: 198 s = gen_load_llrel(off_nl + offset, size); 199 break; 200@@ -2163,11 +2316,17 @@ 201 break; 202 203 case DLT_PPI: 204+ case DLT_IEEE802_11_RADIO: 205+ case DLT_IEEE802_11: 206+#ifdef ENABLE_WLAN_FILTERING_PATCH 207+ return gen_802_11_llc_linktype(proto); 208+ /*NOTREACHED*/ 209+ break; 210+#endif /* ENABLE_WLAN_FILTERING_PATCH */ 211+ 212 case DLT_FDDI: 213 case DLT_IEEE802: 214- case DLT_IEEE802_11: 215 case DLT_IEEE802_11_RADIO_AVS: 216- case DLT_IEEE802_11_RADIO: 217 case DLT_PRISM_HEADER: 218 case DLT_ATM_RFC1483: 219 case DLT_ATM_CLIP: 220@@ -2711,6 +2870,113 @@ 221 } 222 } 223 224+/* 225+ * Generate code to match a particular packet type, for link-layer types 226+ * using 802.2 LLC headers. 227+ * 228+ * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used 229+ * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues. 230+ * 231+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP 232+ * value, if <= ETHERMTU. We use that to determine whether to 233+ * match the DSAP or both DSAP and LSAP or to check the OUI and 234+ * protocol ID in a SNAP header. 235+ */ 236+static struct block * 237+gen_802_11_llc_linktype(proto) 238+ int proto; 239+{ 240+ struct block *b_check_data_frame; 241+ struct block *b_check_linktype; 242+ 243+ b_check_data_frame = gen_check_802_11_data_frame(); 244+ 245+ /* 246+ * XXX - generate the code that discards non data frames 247+ */ 248+ switch (proto) { 249+ 250+ case LLCSAP_IP: 251+ case LLCSAP_ISONS: 252+ case LLCSAP_NETBEUI: 253+ /* 254+ * XXX - should we check both the DSAP and the 255+ * SSAP, like this, or should we check just the 256+ * DSAP, as we do for other types <= ETHERMTU 257+ * (i.e., other SAP values)? 258+ */ 259+ b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_H, (bpf_u_int32) 260+ ((proto << 8) | proto)); 261+ break; 262+ 263+ case LLCSAP_IPX: 264+ /* 265+ * XXX - are there ever SNAP frames for IPX on 266+ * non-Ethernet 802.x networks? 267+ */ 268+ b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, 269+ (bpf_int32)LLCSAP_IPX); 270+ 271+ break; 272+ 273+#if 0 274+ case ETHERTYPE_ATALK: 275+ /* 276+ * 802.2-encapsulated ETHERTYPE_ATALK packets are 277+ * SNAP packets with an organization code of 278+ * 0x080007 (Apple, for Appletalk) and a protocol 279+ * type of ETHERTYPE_ATALK (Appletalk). 280+ * 281+ * XXX - check for an organization code of 282+ * encapsulated Ethernet as well? 283+ */ 284+ return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype); 285+#endif 286+ default: 287+ /* 288+ * XXX - we don't have to check for IPX 802.3 289+ * here, but should we check for the IPX Ethertype? 290+ */ 291+ if (proto <= ETHERMTU) { 292+ /* 293+ * This is an LLC SAP value, so check 294+ * the DSAP. 295+ */ 296+ b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0, BPF_B, 297+ (bpf_int32)proto); 298+ } else { 299+ /* 300+ * This is an Ethernet type; we assume that it's 301+ * unlikely that it'll appear in the right place 302+ * at random, and therefore check only the 303+ * location that would hold the Ethernet type 304+ * in a SNAP frame with an organization code of 305+ * 0x000000 (encapsulated Ethernet). 306+ * 307+ * XXX - if we were to check for the SNAP DSAP and 308+ * LSAP, as per XXX, and were also to check for an 309+ * organization code of 0x000000 (encapsulated 310+ * Ethernet), we'd do 311+ * 312+ * return gen_snap(0x000000, proto, 313+ * off_linktype); 314+ * 315+ * here; for now, we don't, as per the above. 316+ * I don't know whether it's worth the extra CPU 317+ * time to do the right check or not. 318+ */ 319+ b_check_linktype = gen_cmp(OR_LINK_AFTER_WIRELESS_HDR, 0+6, BPF_H, 320+ (bpf_int32)proto); 321+ } 322+ } 323+ 324+ gen_and(b_check_data_frame, b_check_linktype); 325+ return b_check_linktype; 326+ 327+} 328+ 329+ 330+ 331 static struct block * 332 gen_hostop(addr, mask, dir, proto, src_off, dst_off) 333 bpf_u_int32 addr; 334@@ -2925,6 +3191,17 @@ 335 register struct block *b0, *b1, *b2; 336 register struct slist *s; 337 338+#ifdef ENABLE_WLAN_FILTERING_PATCH 339+ /* 340+ * TODO GV 20070613 341+ * We need to disable the optimizer because the optimizer is buggy 342+ * and wipes out some LD instructions generated by the below 343+ * code to validate the Frame Control bits 344+ * 345+ */ 346+ no_optimize = 1; 347+#endif /* ENABLE_WLAN_FILTERING_PATCH */ 348+ 349 switch (dir) { 350 case Q_SRC: 351 /* 352@@ -4713,6 +4990,32 @@ 353 #endif 354 } 355 356+static struct block * 357+gen_check_802_11_data_frame() 358+{ 359+ struct slist *s; 360+ struct block *b0, *b1; 361+ /* 362+ * Now check for a data frame. 363+ * I.e, check "link[0] & 0x08". 364+ */ 365+ s = gen_load_a(OR_LINK, 0, BPF_B); 366+ b0 = new_block(JMP(BPF_JSET)); 367+ b0->s.k = 0x08; 368+ b0->stmts = s; 369+ 370+ s = gen_load_a(OR_LINK, 0, BPF_B); 371+ b1 = new_block(JMP(BPF_JSET)); 372+ b1->s.k = 0x04; 373+ b1->stmts = s; 374+ gen_not(b1); 375+ 376+ 377+ gen_and(b1, b0); 378+ 379+ return b0; 380+} 381+ 382 383 /* 384 * Generate code that checks whether the packet is a packet for protocol 385