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