Home | History | Annotate | Download | only in libpcap
      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