Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (c) 2001
      3  *	Fortress Technologies, Inc.  All rights reserved.
      4  *      Charlie Lenahan (clenahan (at) fortresstech.com)
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that: (1) source code distributions
      8  * retain the above copyright notice and this paragraph in its entirety, (2)
      9  * distributions including binary code include the above copyright notice and
     10  * this paragraph in its entirety in the documentation or other materials
     11  * provided with the distribution, and (3) all advertising materials mentioning
     12  * features or use of this software display the following acknowledgement:
     13  * ``This product includes software developed by the University of California,
     14  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     15  * the University nor the names of its contributors may be used to endorse
     16  * or promote products derived from this software without specific prior
     17  * written permission.
     18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     19  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     21  */
     22 
     23 #ifndef lint
     24 static const char rcsid[] _U_ =
     25     "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.15 2007/07/22 23:14:14 guy Exp $ (LBL)";
     26 #endif
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include <tcpdump-stdinc.h>
     33 
     34 #include <stdio.h>
     35 #include <pcap.h>
     36 #include <string.h>
     37 
     38 #include "interface.h"
     39 #include "addrtoname.h"
     40 #include "ethertype.h"
     41 
     42 #include "extract.h"
     43 
     44 #include "cpack.h"
     45 
     46 #include "ieee802_11.h"
     47 #include "ieee802_11_radio.h"
     48 
     49 #define PRINT_SSID(p) \
     50 	switch (p.ssid_status) { \
     51 	case TRUNCATED: \
     52 		return 0; \
     53 	case PRESENT: \
     54 		printf(" ("); \
     55 		fn_print(p.ssid.ssid, NULL); \
     56 		printf(")"); \
     57 		break; \
     58 	case NOT_PRESENT: \
     59 		break; \
     60 	}
     61 
     62 #define PRINT_RATE(_sep, _r, _suf) \
     63 	printf("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
     64 #define PRINT_RATES(p) \
     65 	switch (p.rates_status) { \
     66 	case TRUNCATED: \
     67 		return 0; \
     68 	case PRESENT: \
     69 		do { \
     70 			int z; \
     71 			const char *sep = " ["; \
     72 			for (z = 0; z < p.rates.length ; z++) { \
     73 				PRINT_RATE(sep, p.rates.rate[z], \
     74 					(p.rates.rate[z] & 0x80 ? "*" : "")); \
     75 				sep = " "; \
     76 			} \
     77 			if (p.rates.length != 0) \
     78 				printf(" Mbit]"); \
     79 		} while (0); \
     80 		break; \
     81 	case NOT_PRESENT: \
     82 		break; \
     83 	}
     84 
     85 #define PRINT_DS_CHANNEL(p) \
     86 	switch (p.ds_status) { \
     87 	case TRUNCATED: \
     88 		return 0; \
     89 	case PRESENT: \
     90 		printf(" CH: %u", p.ds.channel); \
     91 		break; \
     92 	case NOT_PRESENT: \
     93 		break; \
     94 	} \
     95 	printf("%s", \
     96 	    CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "" );
     97 
     98 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
     99 #define NUM_AUTH_ALGS	(sizeof auth_alg_text / sizeof auth_alg_text[0])
    100 
    101 static const char *status_text[] = {
    102 	"Succesful",  /*  0  */
    103 	"Unspecified failure",  /*  1  */
    104 	"Reserved",	  /*  2  */
    105 	"Reserved",	  /*  3  */
    106 	"Reserved",	  /*  4  */
    107 	"Reserved",	  /*  5  */
    108 	"Reserved",	  /*  6  */
    109 	"Reserved",	  /*  7  */
    110 	"Reserved",	  /*  8  */
    111 	"Reserved",	  /*  9  */
    112 	"Cannot Support all requested capabilities in the Capability Information field",	  /*  10  */
    113 	"Reassociation denied due to inability to confirm that association exists",	  /*  11  */
    114 	"Association denied due to reason outside the scope of the standard",	  /*  12  */
    115 	"Responding station does not support the specified authentication algorithm ",	  /*  13  */
    116 	"Received an Authentication frame with authentication transaction " \
    117 		"sequence number out of expected sequence",	  /*  14  */
    118 	"Authentication rejected because of challenge failure",	  /*  15 */
    119 	"Authentication rejected due to timeout waiting for next frame in sequence",	  /*  16 */
    120 	"Association denied because AP is unable to handle additional associated stations",	  /*  17 */
    121 	"Association denied due to requesting station not supporting all of the " \
    122 		"data rates in BSSBasicRateSet parameter",	  /*  18 */
    123 };
    124 #define NUM_STATUSES	(sizeof status_text / sizeof status_text[0])
    125 
    126 static const char *reason_text[] = {
    127 	"Reserved", /* 0 */
    128 	"Unspecified reason", /* 1 */
    129 	"Previous authentication no longer valid",  /* 2 */
    130 	"Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
    131 	"Disassociated due to inactivity", /* 4 */
    132 	"Disassociated because AP is unable to handle all currently associated stations", /* 5 */
    133 	"Class 2 frame received from nonauthenticated station", /* 6 */
    134 	"Class 3 frame received from nonassociated station", /* 7 */
    135 	"Disassociated because sending station is leaving (or has left) BSS", /* 8 */
    136 	"Station requesting (re)association is not authenticated with responding station", /* 9 */
    137 };
    138 #define NUM_REASONS	(sizeof reason_text / sizeof reason_text[0])
    139 
    140 static int
    141 wep_print(const u_char *p)
    142 {
    143 	u_int32_t iv;
    144 
    145 	if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN))
    146 		return 0;
    147 	iv = EXTRACT_LE_32BITS(p);
    148 
    149 	printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
    150 	    IV_KEYID(iv));
    151 
    152 	return 1;
    153 }
    154 
    155 static void
    156 parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
    157 {
    158 	/*
    159 	 * We haven't seen any elements yet.
    160 	 */
    161 	pbody->challenge_status = NOT_PRESENT;
    162 	pbody->ssid_status = NOT_PRESENT;
    163 	pbody->rates_status = NOT_PRESENT;
    164 	pbody->ds_status = NOT_PRESENT;
    165 	pbody->cf_status = NOT_PRESENT;
    166 	pbody->tim_status = NOT_PRESENT;
    167 
    168 	for (;;) {
    169 		if (!TTEST2(*(p + offset), 1))
    170 			return;
    171 		switch (*(p + offset)) {
    172 		case E_SSID:
    173 			/* Present, possibly truncated */
    174 			pbody->ssid_status = TRUNCATED;
    175 			if (!TTEST2(*(p + offset), 2))
    176 				return;
    177 			memcpy(&pbody->ssid, p + offset, 2);
    178 			offset += 2;
    179 			if (pbody->ssid.length != 0) {
    180 				if (pbody->ssid.length >
    181 				    sizeof(pbody->ssid.ssid) - 1)
    182 					return;
    183 				if (!TTEST2(*(p + offset), pbody->ssid.length))
    184 					return;
    185 				memcpy(&pbody->ssid.ssid, p + offset,
    186 				    pbody->ssid.length);
    187 				offset += pbody->ssid.length;
    188 			}
    189 			pbody->ssid.ssid[pbody->ssid.length] = '\0';
    190 			/* Present and not truncated */
    191 			pbody->ssid_status = PRESENT;
    192 			break;
    193 		case E_CHALLENGE:
    194 			/* Present, possibly truncated */
    195 			pbody->challenge_status = TRUNCATED;
    196 			if (!TTEST2(*(p + offset), 2))
    197 				return;
    198 			memcpy(&pbody->challenge, p + offset, 2);
    199 			offset += 2;
    200 			if (pbody->challenge.length != 0) {
    201 				if (pbody->challenge.length >
    202 				    sizeof(pbody->challenge.text) - 1)
    203 					return;
    204 				if (!TTEST2(*(p + offset), pbody->challenge.length))
    205 					return;
    206 				memcpy(&pbody->challenge.text, p + offset,
    207 				    pbody->challenge.length);
    208 				offset += pbody->challenge.length;
    209 			}
    210 			pbody->challenge.text[pbody->challenge.length] = '\0';
    211 			/* Present and not truncated */
    212 			pbody->challenge_status = PRESENT;
    213 			break;
    214 		case E_RATES:
    215 			/* Present, possibly truncated */
    216 			pbody->rates_status = TRUNCATED;
    217 			if (!TTEST2(*(p + offset), 2))
    218 				return;
    219 			memcpy(&(pbody->rates), p + offset, 2);
    220 			offset += 2;
    221 			if (pbody->rates.length != 0) {
    222 				if (pbody->rates.length > sizeof pbody->rates.rate)
    223 					return;
    224 				if (!TTEST2(*(p + offset), pbody->rates.length))
    225 					return;
    226 				memcpy(&pbody->rates.rate, p + offset,
    227 				    pbody->rates.length);
    228 				offset += pbody->rates.length;
    229 			}
    230 			/* Present and not truncated */
    231 			pbody->rates_status = PRESENT;
    232 			break;
    233 		case E_DS:
    234 			/* Present, possibly truncated */
    235 			pbody->ds_status = TRUNCATED;
    236 			if (!TTEST2(*(p + offset), 3))
    237 				return;
    238 			memcpy(&pbody->ds, p + offset, 3);
    239 			offset += 3;
    240 			/* Present and not truncated */
    241 			pbody->ds_status = PRESENT;
    242 			break;
    243 		case E_CF:
    244 			/* Present, possibly truncated */
    245 			pbody->cf_status = TRUNCATED;
    246 			if (!TTEST2(*(p + offset), 8))
    247 				return;
    248 			memcpy(&pbody->cf, p + offset, 8);
    249 			offset += 8;
    250 			/* Present and not truncated */
    251 			pbody->cf_status = PRESENT;
    252 			break;
    253 		case E_TIM:
    254 			/* Present, possibly truncated */
    255 			pbody->tim_status = TRUNCATED;
    256 			if (!TTEST2(*(p + offset), 2))
    257 				return;
    258 			memcpy(&pbody->tim, p + offset, 2);
    259 			offset += 2;
    260 			if (!TTEST2(*(p + offset), 3))
    261 				return;
    262 			memcpy(&pbody->tim.count, p + offset, 3);
    263 			offset += 3;
    264 
    265 			if (pbody->tim.length <= 3)
    266 				break;
    267 			if (pbody->tim.length - 3 > sizeof pbody->tim.bitmap)
    268 				return;
    269 			if (!TTEST2(*(p + offset), pbody->tim.length - 3))
    270 				return;
    271 			memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3),
    272 			    (pbody->tim.length - 3));
    273 			offset += pbody->tim.length - 3;
    274 			/* Present and not truncated */
    275 			pbody->tim_status = PRESENT;
    276 			break;
    277 		default:
    278 #if 0
    279 			printf("(1) unhandled element_id (%d)  ",
    280 			    *(p + offset) );
    281 #endif
    282 			if (!TTEST2(*(p + offset), 2))
    283 				return;
    284 			if (!TTEST2(*(p + offset + 2), *(p + offset + 1)))
    285 				return;
    286 			offset += *(p + offset + 1) + 2;
    287 			break;
    288 		}
    289 	}
    290 }
    291 
    292 /*********************************************************************************
    293  * Print Handle functions for the management frame types
    294  *********************************************************************************/
    295 
    296 static int
    297 handle_beacon(const u_char *p)
    298 {
    299 	struct mgmt_body_t pbody;
    300 	int offset = 0;
    301 
    302 	memset(&pbody, 0, sizeof(pbody));
    303 
    304 	if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
    305 	    IEEE802_11_CAPINFO_LEN))
    306 		return 0;
    307 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
    308 	offset += IEEE802_11_TSTAMP_LEN;
    309 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
    310 	offset += IEEE802_11_BCNINT_LEN;
    311 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
    312 	offset += IEEE802_11_CAPINFO_LEN;
    313 
    314 	parse_elements(&pbody, p, offset);
    315 
    316 	PRINT_SSID(pbody);
    317 	PRINT_RATES(pbody);
    318 	printf(" %s",
    319 	    CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
    320 	PRINT_DS_CHANNEL(pbody);
    321 
    322 	return 1;
    323 }
    324 
    325 static int
    326 handle_assoc_request(const u_char *p)
    327 {
    328 	struct mgmt_body_t pbody;
    329 	int offset = 0;
    330 
    331 	memset(&pbody, 0, sizeof(pbody));
    332 
    333 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN))
    334 		return 0;
    335 	pbody.capability_info = EXTRACT_LE_16BITS(p);
    336 	offset += IEEE802_11_CAPINFO_LEN;
    337 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
    338 	offset += IEEE802_11_LISTENINT_LEN;
    339 
    340 	parse_elements(&pbody, p, offset);
    341 
    342 	PRINT_SSID(pbody);
    343 	PRINT_RATES(pbody);
    344 	return 1;
    345 }
    346 
    347 static int
    348 handle_assoc_response(const u_char *p)
    349 {
    350 	struct mgmt_body_t pbody;
    351 	int offset = 0;
    352 
    353 	memset(&pbody, 0, sizeof(pbody));
    354 
    355 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
    356 	    IEEE802_11_AID_LEN))
    357 		return 0;
    358 	pbody.capability_info = EXTRACT_LE_16BITS(p);
    359 	offset += IEEE802_11_CAPINFO_LEN;
    360 	pbody.status_code = EXTRACT_LE_16BITS(p+offset);
    361 	offset += IEEE802_11_STATUS_LEN;
    362 	pbody.aid = EXTRACT_LE_16BITS(p+offset);
    363 	offset += IEEE802_11_AID_LEN;
    364 
    365 	parse_elements(&pbody, p, offset);
    366 
    367 	printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
    368 	    CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
    369 	    (pbody.status_code < NUM_STATUSES
    370 		? status_text[pbody.status_code]
    371 		: "n/a"));
    372 
    373 	return 1;
    374 }
    375 
    376 static int
    377 handle_reassoc_request(const u_char *p)
    378 {
    379 	struct mgmt_body_t pbody;
    380 	int offset = 0;
    381 
    382 	memset(&pbody, 0, sizeof(pbody));
    383 
    384 	if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
    385 	    IEEE802_11_AP_LEN))
    386 		return 0;
    387 	pbody.capability_info = EXTRACT_LE_16BITS(p);
    388 	offset += IEEE802_11_CAPINFO_LEN;
    389 	pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
    390 	offset += IEEE802_11_LISTENINT_LEN;
    391 	memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
    392 	offset += IEEE802_11_AP_LEN;
    393 
    394 	parse_elements(&pbody, p, offset);
    395 
    396 	PRINT_SSID(pbody);
    397 	printf(" AP : %s", etheraddr_string( pbody.ap ));
    398 
    399 	return 1;
    400 }
    401 
    402 static int
    403 handle_reassoc_response(const u_char *p)
    404 {
    405 	/* Same as a Association Reponse */
    406 	return handle_assoc_response(p);
    407 }
    408 
    409 static int
    410 handle_probe_request(const u_char *p)
    411 {
    412 	struct mgmt_body_t  pbody;
    413 	int offset = 0;
    414 
    415 	memset(&pbody, 0, sizeof(pbody));
    416 
    417 	parse_elements(&pbody, p, offset);
    418 
    419 	PRINT_SSID(pbody);
    420 	PRINT_RATES(pbody);
    421 
    422 	return 1;
    423 }
    424 
    425 static int
    426 handle_probe_response(const u_char *p)
    427 {
    428 	struct mgmt_body_t  pbody;
    429 	int offset = 0;
    430 
    431 	memset(&pbody, 0, sizeof(pbody));
    432 
    433 	if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
    434 	    IEEE802_11_CAPINFO_LEN))
    435 		return 0;
    436 
    437 	memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
    438 	offset += IEEE802_11_TSTAMP_LEN;
    439 	pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
    440 	offset += IEEE802_11_BCNINT_LEN;
    441 	pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
    442 	offset += IEEE802_11_CAPINFO_LEN;
    443 
    444 	parse_elements(&pbody, p, offset);
    445 
    446 	PRINT_SSID(pbody);
    447 	PRINT_RATES(pbody);
    448 	PRINT_DS_CHANNEL(pbody);
    449 
    450 	return 1;
    451 }
    452 
    453 static int
    454 handle_atim(void)
    455 {
    456 	/* the frame body for ATIM is null. */
    457 	return 1;
    458 }
    459 
    460 static int
    461 handle_disassoc(const u_char *p)
    462 {
    463 	struct mgmt_body_t  pbody;
    464 
    465 	memset(&pbody, 0, sizeof(pbody));
    466 
    467 	if (!TTEST2(*p, IEEE802_11_REASON_LEN))
    468 		return 0;
    469 	pbody.reason_code = EXTRACT_LE_16BITS(p);
    470 
    471 	printf(": %s",
    472 	    (pbody.reason_code < NUM_REASONS)
    473 		? reason_text[pbody.reason_code]
    474 		: "Reserved" );
    475 
    476 	return 1;
    477 }
    478 
    479 static int
    480 handle_auth(const u_char *p)
    481 {
    482 	struct mgmt_body_t  pbody;
    483 	int offset = 0;
    484 
    485 	memset(&pbody, 0, sizeof(pbody));
    486 
    487 	if (!TTEST2(*p, 6))
    488 		return 0;
    489 	pbody.auth_alg = EXTRACT_LE_16BITS(p);
    490 	offset += 2;
    491 	pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
    492 	offset += 2;
    493 	pbody.status_code = EXTRACT_LE_16BITS(p + offset);
    494 	offset += 2;
    495 
    496 	parse_elements(&pbody, p, offset);
    497 
    498 	if ((pbody.auth_alg == 1) &&
    499 	    ((pbody.auth_trans_seq_num == 2) ||
    500 	     (pbody.auth_trans_seq_num == 3))) {
    501 		printf(" (%s)-%x [Challenge Text] %s",
    502 		    (pbody.auth_alg < NUM_AUTH_ALGS)
    503 			? auth_alg_text[pbody.auth_alg]
    504 			: "Reserved",
    505 		    pbody.auth_trans_seq_num,
    506 		    ((pbody.auth_trans_seq_num % 2)
    507 		        ? ((pbody.status_code < NUM_STATUSES)
    508 			       ? status_text[pbody.status_code]
    509 			       : "n/a") : ""));
    510 		return 1;
    511 	}
    512 	printf(" (%s)-%x: %s",
    513 	    (pbody.auth_alg < NUM_AUTH_ALGS)
    514 		? auth_alg_text[pbody.auth_alg]
    515 		: "Reserved",
    516 	    pbody.auth_trans_seq_num,
    517 	    (pbody.auth_trans_seq_num % 2)
    518 	        ? ((pbody.status_code < NUM_STATUSES)
    519 		    ? status_text[pbody.status_code]
    520 	            : "n/a")
    521 	        : "");
    522 
    523 	return 1;
    524 }
    525 
    526 static int
    527 handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
    528 {
    529 	struct mgmt_body_t  pbody;
    530 	int offset = 0;
    531 	const char *reason = NULL;
    532 
    533 	memset(&pbody, 0, sizeof(pbody));
    534 
    535 	if (!TTEST2(*p, IEEE802_11_REASON_LEN))
    536 		return 0;
    537 	pbody.reason_code = EXTRACT_LE_16BITS(p);
    538 	offset += IEEE802_11_REASON_LEN;
    539 
    540 	reason = (pbody.reason_code < NUM_REASONS)
    541 			? reason_text[pbody.reason_code]
    542 			: "Reserved";
    543 
    544 	if (eflag) {
    545 		printf(": %s", reason);
    546 	} else {
    547 		printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
    548 	}
    549 	return 1;
    550 }
    551 
    552 
    553 /*********************************************************************************
    554  * Print Body funcs
    555  *********************************************************************************/
    556 
    557 
    558 static int
    559 mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
    560     const u_char *p)
    561 {
    562 	switch (FC_SUBTYPE(fc)) {
    563 	case ST_ASSOC_REQUEST:
    564 		printf("Assoc Request");
    565 		return handle_assoc_request(p);
    566 	case ST_ASSOC_RESPONSE:
    567 		printf("Assoc Response");
    568 		return handle_assoc_response(p);
    569 	case ST_REASSOC_REQUEST:
    570 		printf("ReAssoc Request");
    571 		return handle_reassoc_request(p);
    572 	case ST_REASSOC_RESPONSE:
    573 		printf("ReAssoc Response");
    574 		return handle_reassoc_response(p);
    575 	case ST_PROBE_REQUEST:
    576 		printf("Probe Request");
    577 		return handle_probe_request(p);
    578 	case ST_PROBE_RESPONSE:
    579 		printf("Probe Response");
    580 		return handle_probe_response(p);
    581 	case ST_BEACON:
    582 		printf("Beacon");
    583 		return handle_beacon(p);
    584 	case ST_ATIM:
    585 		printf("ATIM");
    586 		return handle_atim();
    587 	case ST_DISASSOC:
    588 		printf("Disassociation");
    589 		return handle_disassoc(p);
    590 	case ST_AUTH:
    591 		printf("Authentication");
    592 		if (!TTEST2(*p, 3))
    593 			return 0;
    594 		if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
    595 			printf("Authentication (Shared-Key)-3 ");
    596 			return wep_print(p);
    597 		}
    598 		return handle_auth(p);
    599 	case ST_DEAUTH:
    600 		printf("DeAuthentication");
    601 		return handle_deauth(pmh, p);
    602 		break;
    603 	default:
    604 		printf("Unhandled Management subtype(%x)",
    605 		    FC_SUBTYPE(fc));
    606 		return 1;
    607 	}
    608 }
    609 
    610 
    611 /*********************************************************************************
    612  * Handles printing all the control frame types
    613  *********************************************************************************/
    614 
    615 static int
    616 ctrl_body_print(u_int16_t fc, const u_char *p)
    617 {
    618 	switch (FC_SUBTYPE(fc)) {
    619 	case CTRL_PS_POLL:
    620 		printf("Power Save-Poll");
    621 		if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN))
    622 			return 0;
    623 		printf(" AID(%x)",
    624 		    EXTRACT_LE_16BITS(&(((const struct ctrl_ps_poll_t *)p)->aid)));
    625 		break;
    626 	case CTRL_RTS:
    627 		printf("Request-To-Send");
    628 		if (!TTEST2(*p, CTRL_RTS_HDRLEN))
    629 			return 0;
    630 		if (!eflag)
    631 			printf(" TA:%s ",
    632 			    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
    633 		break;
    634 	case CTRL_CTS:
    635 		printf("Clear-To-Send");
    636 		if (!TTEST2(*p, CTRL_CTS_HDRLEN))
    637 			return 0;
    638 		if (!eflag)
    639 			printf(" RA:%s ",
    640 			    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
    641 		break;
    642 	case CTRL_ACK:
    643 		printf("Acknowledgment");
    644 		if (!TTEST2(*p, CTRL_ACK_HDRLEN))
    645 			return 0;
    646 		if (!eflag)
    647 			printf(" RA:%s ",
    648 			    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
    649 		break;
    650 	case CTRL_CF_END:
    651 		printf("CF-End");
    652 		if (!TTEST2(*p, CTRL_END_HDRLEN))
    653 			return 0;
    654 		if (!eflag)
    655 			printf(" RA:%s ",
    656 			    etheraddr_string(((const struct ctrl_end_t *)p)->ra));
    657 		break;
    658 	case CTRL_END_ACK:
    659 		printf("CF-End+CF-Ack");
    660 		if (!TTEST2(*p, CTRL_END_ACK_HDRLEN))
    661 			return 0;
    662 		if (!eflag)
    663 			printf(" RA:%s ",
    664 			    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra));
    665 		break;
    666 	default:
    667 		printf("Unknown Ctrl Subtype");
    668 	}
    669 	return 1;
    670 }
    671 
    672 /*
    673  * Print Header funcs
    674  */
    675 
    676 /*
    677  *  Data Frame - Address field contents
    678  *
    679  *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
    680  *    0    |  0      |  DA    | SA     | BSSID  | n/a
    681  *    0    |  1      |  DA    | BSSID  | SA     | n/a
    682  *    1    |  0      |  BSSID | SA     | DA     | n/a
    683  *    1    |  1      |  RA    | TA     | DA     | SA
    684  */
    685 
    686 static void
    687 data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
    688     const u_int8_t **dstp)
    689 {
    690 	u_int subtype = FC_SUBTYPE(fc);
    691 
    692 	if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
    693 	    DATA_FRAME_IS_QOS(subtype)) {
    694 		printf("CF ");
    695 		if (DATA_FRAME_IS_CF_ACK(subtype)) {
    696 			if (DATA_FRAME_IS_CF_POLL(subtype))
    697 				printf("Ack/Poll");
    698 			else
    699 				printf("Ack");
    700 		} else {
    701 			if (DATA_FRAME_IS_CF_POLL(subtype))
    702 				printf("Poll");
    703 		}
    704 		if (DATA_FRAME_IS_QOS(subtype))
    705 			printf("+QoS");
    706 		printf(" ");
    707 	}
    708 
    709 #define ADDR1  (p + 4)
    710 #define ADDR2  (p + 10)
    711 #define ADDR3  (p + 16)
    712 #define ADDR4  (p + 24)
    713 
    714 	if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
    715 		if (srcp != NULL)
    716 			*srcp = ADDR2;
    717 		if (dstp != NULL)
    718 			*dstp = ADDR1;
    719 		if (!eflag)
    720 			return;
    721 		printf("DA:%s SA:%s BSSID:%s ",
    722 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
    723 		    etheraddr_string(ADDR3));
    724 	} else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
    725 		if (srcp != NULL)
    726 			*srcp = ADDR3;
    727 		if (dstp != NULL)
    728 			*dstp = ADDR1;
    729 		if (!eflag)
    730 			return;
    731 		printf("DA:%s BSSID:%s SA:%s ",
    732 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
    733 		    etheraddr_string(ADDR3));
    734 	} else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
    735 		if (srcp != NULL)
    736 			*srcp = ADDR2;
    737 		if (dstp != NULL)
    738 			*dstp = ADDR3;
    739 		if (!eflag)
    740 			return;
    741 		printf("BSSID:%s SA:%s DA:%s ",
    742 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
    743 		    etheraddr_string(ADDR3));
    744 	} else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
    745 		if (srcp != NULL)
    746 			*srcp = ADDR4;
    747 		if (dstp != NULL)
    748 			*dstp = ADDR3;
    749 		if (!eflag)
    750 			return;
    751 		printf("RA:%s TA:%s DA:%s SA:%s ",
    752 		    etheraddr_string(ADDR1), etheraddr_string(ADDR2),
    753 		    etheraddr_string(ADDR3), etheraddr_string(ADDR4));
    754 	}
    755 
    756 #undef ADDR1
    757 #undef ADDR2
    758 #undef ADDR3
    759 #undef ADDR4
    760 }
    761 
    762 static void
    763 mgmt_header_print(const u_char *p, const u_int8_t **srcp,
    764     const u_int8_t **dstp)
    765 {
    766 	const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
    767 
    768 	if (srcp != NULL)
    769 		*srcp = hp->sa;
    770 	if (dstp != NULL)
    771 		*dstp = hp->da;
    772 	if (!eflag)
    773 		return;
    774 
    775 	printf("BSSID:%s DA:%s SA:%s ",
    776 	    etheraddr_string((hp)->bssid), etheraddr_string((hp)->da),
    777 	    etheraddr_string((hp)->sa));
    778 }
    779 
    780 static void
    781 ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
    782     const u_int8_t **dstp)
    783 {
    784 	if (srcp != NULL)
    785 		*srcp = NULL;
    786 	if (dstp != NULL)
    787 		*dstp = NULL;
    788 	if (!eflag)
    789 		return;
    790 
    791 	switch (FC_SUBTYPE(fc)) {
    792 	case CTRL_PS_POLL:
    793 		printf("BSSID:%s TA:%s ",
    794 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid),
    795 		    etheraddr_string(((const struct ctrl_ps_poll_t *)p)->ta));
    796 		break;
    797 	case CTRL_RTS:
    798 		printf("RA:%s TA:%s ",
    799 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ra),
    800 		    etheraddr_string(((const struct ctrl_rts_t *)p)->ta));
    801 		break;
    802 	case CTRL_CTS:
    803 		printf("RA:%s ",
    804 		    etheraddr_string(((const struct ctrl_cts_t *)p)->ra));
    805 		break;
    806 	case CTRL_ACK:
    807 		printf("RA:%s ",
    808 		    etheraddr_string(((const struct ctrl_ack_t *)p)->ra));
    809 		break;
    810 	case CTRL_CF_END:
    811 		printf("RA:%s BSSID:%s ",
    812 		    etheraddr_string(((const struct ctrl_end_t *)p)->ra),
    813 		    etheraddr_string(((const struct ctrl_end_t *)p)->bssid));
    814 		break;
    815 	case CTRL_END_ACK:
    816 		printf("RA:%s BSSID:%s ",
    817 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->ra),
    818 		    etheraddr_string(((const struct ctrl_end_ack_t *)p)->bssid));
    819 		break;
    820 	default:
    821 		printf("(H) Unknown Ctrl Subtype");
    822 		break;
    823 	}
    824 }
    825 
    826 static int
    827 extract_header_length(u_int16_t fc)
    828 {
    829 	int len;
    830 
    831 	switch (FC_TYPE(fc)) {
    832 	case T_MGMT:
    833 		return MGMT_HDRLEN;
    834 	case T_CTRL:
    835 		switch (FC_SUBTYPE(fc)) {
    836 		case CTRL_PS_POLL:
    837 			return CTRL_PS_POLL_HDRLEN;
    838 		case CTRL_RTS:
    839 			return CTRL_RTS_HDRLEN;
    840 		case CTRL_CTS:
    841 			return CTRL_CTS_HDRLEN;
    842 		case CTRL_ACK:
    843 			return CTRL_ACK_HDRLEN;
    844 		case CTRL_CF_END:
    845 			return CTRL_END_HDRLEN;
    846 		case CTRL_END_ACK:
    847 			return CTRL_END_ACK_HDRLEN;
    848 		default:
    849 			return 0;
    850 		}
    851 	case T_DATA:
    852 		len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
    853 		if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
    854 			len += 2;
    855 		return len;
    856 	default:
    857 		printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
    858 		return 0;
    859 	}
    860 }
    861 
    862 /*
    863  * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp"
    864  * to point to the source and destination MAC addresses in any case if
    865  * "srcp" and "dstp" aren't null.
    866  */
    867 static inline void
    868 ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
    869     const u_int8_t **dstp)
    870 {
    871 	if (vflag) {
    872 		if (FC_MORE_DATA(fc))
    873 			printf("More Data ");
    874 		if (FC_MORE_FLAG(fc))
    875 			printf("More Fragments ");
    876 		if (FC_POWER_MGMT(fc))
    877 			printf("Pwr Mgmt ");
    878 		if (FC_RETRY(fc))
    879 			printf("Retry ");
    880 		if (FC_ORDER(fc))
    881 			printf("Strictly Ordered ");
    882 		if (FC_WEP(fc))
    883 			printf("WEP Encrypted ");
    884 		if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
    885 			printf("%dus ",
    886 			    EXTRACT_LE_16BITS(
    887 			        &((const struct mgmt_header_t *)p)->duration));
    888 	}
    889 
    890 	switch (FC_TYPE(fc)) {
    891 	case T_MGMT:
    892 		mgmt_header_print(p, srcp, dstp);
    893 		break;
    894 	case T_CTRL:
    895 		ctrl_header_print(fc, p, srcp, dstp);
    896 		break;
    897 	case T_DATA:
    898 		data_header_print(fc, p, srcp, dstp);
    899 		break;
    900 	default:
    901 		printf("(header) unknown IEEE802.11 frame type (%d)",
    902 		    FC_TYPE(fc));
    903 		*srcp = NULL;
    904 		*dstp = NULL;
    905 		break;
    906 	}
    907 }
    908 
    909 #ifndef roundup2
    910 #define	roundup2(x, y)	(((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
    911 #endif
    912 
    913 static u_int
    914 ieee802_11_print(const u_char *p, u_int length, u_int caplen, int pad)
    915 {
    916 	u_int16_t fc;
    917 	u_int hdrlen;
    918 	const u_int8_t *src, *dst;
    919 	u_short extracted_ethertype;
    920 
    921 	if (caplen < IEEE802_11_FC_LEN) {
    922 		printf("[|802.11]");
    923 		return caplen;
    924 	}
    925 
    926 	fc = EXTRACT_LE_16BITS(p);
    927 	hdrlen = extract_header_length(fc);
    928 	if (pad)
    929 		hdrlen = roundup2(hdrlen, 4);
    930 
    931 	if (caplen < hdrlen) {
    932 		printf("[|802.11]");
    933 		return hdrlen;
    934 	}
    935 
    936 	ieee_802_11_hdr_print(fc, p, &src, &dst);
    937 
    938 	/*
    939 	 * Go past the 802.11 header.
    940 	 */
    941 	length -= hdrlen;
    942 	caplen -= hdrlen;
    943 	p += hdrlen;
    944 
    945 	switch (FC_TYPE(fc)) {
    946 	case T_MGMT:
    947 		if (!mgmt_body_print(fc,
    948 		    (const struct mgmt_header_t *)(p - hdrlen), p)) {
    949 			printf("[|802.11]");
    950 			return hdrlen;
    951 		}
    952 		break;
    953 	case T_CTRL:
    954 		if (!ctrl_body_print(fc, p - hdrlen)) {
    955 			printf("[|802.11]");
    956 			return hdrlen;
    957 		}
    958 		break;
    959 	case T_DATA:
    960 		if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
    961 			return hdrlen;	/* no-data frame */
    962 		/* There may be a problem w/ AP not having this bit set */
    963 		if (FC_WEP(fc)) {
    964 			if (!wep_print(p)) {
    965 				printf("[|802.11]");
    966 				return hdrlen;
    967 			}
    968 		} else if (llc_print(p, length, caplen, dst, src,
    969 		    &extracted_ethertype) == 0) {
    970 			/*
    971 			 * Some kinds of LLC packet we cannot
    972 			 * handle intelligently
    973 			 */
    974 			if (!eflag)
    975 				ieee_802_11_hdr_print(fc, p - hdrlen, NULL,
    976 				    NULL);
    977 			if (extracted_ethertype)
    978 				printf("(LLC %s) ",
    979 				    etherproto_string(
    980 				        htons(extracted_ethertype)));
    981 			if (!suppress_default_print)
    982 				default_print(p, caplen);
    983 		}
    984 		break;
    985 	default:
    986 		printf("unknown 802.11 frame type (%d)", FC_TYPE(fc));
    987 		break;
    988 	}
    989 
    990 	return hdrlen;
    991 }
    992 
    993 /*
    994  * This is the top level routine of the printer.  'p' points
    995  * to the 802.11 header of the packet, 'h->ts' is the timestamp,
    996  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
    997  * is the number of bytes actually captured.
    998  */
    999 u_int
   1000 ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
   1001 {
   1002 	return ieee802_11_print(p, h->len, h->caplen, 0);
   1003 }
   1004 
   1005 static int
   1006 print_radiotap_field(struct cpack_state *s, u_int32_t bit, int *pad)
   1007 {
   1008 	union {
   1009 		int8_t		i8;
   1010 		u_int8_t	u8;
   1011 		int16_t		i16;
   1012 		u_int16_t	u16;
   1013 		u_int32_t	u32;
   1014 		u_int64_t	u64;
   1015 	} u, u2;
   1016 	int rc;
   1017 
   1018 	switch (bit) {
   1019 	case IEEE80211_RADIOTAP_FLAGS:
   1020 		rc = cpack_uint8(s, &u.u8);
   1021 		if (u.u8 & IEEE80211_RADIOTAP_F_DATAPAD)
   1022 			*pad = 1;
   1023 		break;
   1024 	case IEEE80211_RADIOTAP_RATE:
   1025 	case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
   1026 	case IEEE80211_RADIOTAP_DB_ANTNOISE:
   1027 	case IEEE80211_RADIOTAP_ANTENNA:
   1028 		rc = cpack_uint8(s, &u.u8);
   1029 		break;
   1030 	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
   1031 	case IEEE80211_RADIOTAP_DBM_ANTNOISE:
   1032 		rc = cpack_int8(s, &u.i8);
   1033 		break;
   1034 	case IEEE80211_RADIOTAP_CHANNEL:
   1035 		rc = cpack_uint16(s, &u.u16);
   1036 		if (rc != 0)
   1037 			break;
   1038 		rc = cpack_uint16(s, &u2.u16);
   1039 		break;
   1040 	case IEEE80211_RADIOTAP_FHSS:
   1041 	case IEEE80211_RADIOTAP_LOCK_QUALITY:
   1042 	case IEEE80211_RADIOTAP_TX_ATTENUATION:
   1043 		rc = cpack_uint16(s, &u.u16);
   1044 		break;
   1045 	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
   1046 		rc = cpack_uint8(s, &u.u8);
   1047 		break;
   1048 	case IEEE80211_RADIOTAP_DBM_TX_POWER:
   1049 		rc = cpack_int8(s, &u.i8);
   1050 		break;
   1051 	case IEEE80211_RADIOTAP_TSFT:
   1052 		rc = cpack_uint64(s, &u.u64);
   1053 		break;
   1054 	default:
   1055 		/* this bit indicates a field whose
   1056 		 * size we do not know, so we cannot
   1057 		 * proceed.
   1058 		 */
   1059 		printf("[0x%08x] ", bit);
   1060 		return -1;
   1061 	}
   1062 
   1063 	if (rc != 0) {
   1064 		printf("[|802.11]");
   1065 		return rc;
   1066 	}
   1067 
   1068 	switch (bit) {
   1069 	case IEEE80211_RADIOTAP_CHANNEL:
   1070 		printf("%u MHz ", u.u16);
   1071 		if (u2.u16 != 0)
   1072 			printf("(0x%04x) ", u2.u16);
   1073 		break;
   1074 	case IEEE80211_RADIOTAP_FHSS:
   1075 		printf("fhset %d fhpat %d ", u.u16 & 0xff, (u.u16 >> 8) & 0xff);
   1076 		break;
   1077 	case IEEE80211_RADIOTAP_RATE:
   1078 		PRINT_RATE("", u.u8, " Mb/s ");
   1079 		break;
   1080 	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
   1081 		printf("%ddB signal ", u.i8);
   1082 		break;
   1083 	case IEEE80211_RADIOTAP_DBM_ANTNOISE:
   1084 		printf("%ddB noise ", u.i8);
   1085 		break;
   1086 	case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
   1087 		printf("%ddB signal ", u.u8);
   1088 		break;
   1089 	case IEEE80211_RADIOTAP_DB_ANTNOISE:
   1090 		printf("%ddB noise ", u.u8);
   1091 		break;
   1092 	case IEEE80211_RADIOTAP_LOCK_QUALITY:
   1093 		printf("%u sq ", u.u16);
   1094 		break;
   1095 	case IEEE80211_RADIOTAP_TX_ATTENUATION:
   1096 		printf("%d tx power ", -(int)u.u16);
   1097 		break;
   1098 	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
   1099 		printf("%ddB tx power ", -(int)u.u8);
   1100 		break;
   1101 	case IEEE80211_RADIOTAP_DBM_TX_POWER:
   1102 		printf("%ddBm tx power ", u.i8);
   1103 		break;
   1104 	case IEEE80211_RADIOTAP_FLAGS:
   1105 		if (u.u8 & IEEE80211_RADIOTAP_F_CFP)
   1106 			printf("cfp ");
   1107 		if (u.u8 & IEEE80211_RADIOTAP_F_SHORTPRE)
   1108 			printf("short preamble ");
   1109 		if (u.u8 & IEEE80211_RADIOTAP_F_WEP)
   1110 			printf("wep ");
   1111 		if (u.u8 & IEEE80211_RADIOTAP_F_FRAG)
   1112 			printf("fragmented ");
   1113 		if (u.u8 & IEEE80211_RADIOTAP_F_BADFCS)
   1114 			printf("bad-fcs ");
   1115 		break;
   1116 	case IEEE80211_RADIOTAP_ANTENNA:
   1117 		printf("antenna %d ", u.u8);
   1118 		break;
   1119 	case IEEE80211_RADIOTAP_TSFT:
   1120 		printf("%" PRIu64 "us tsft ", u.u64);
   1121 		break;
   1122 	}
   1123 	return 0;
   1124 }
   1125 
   1126 static u_int
   1127 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
   1128 {
   1129 #define	BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
   1130 #define	BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
   1131 #define	BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
   1132 #define	BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
   1133 #define	BITNO_2(x) (((x) & 2) ? 1 : 0)
   1134 #define	BIT(n)	(1 << n)
   1135 #define	IS_EXTENDED(__p)	\
   1136 	    (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
   1137 
   1138 	struct cpack_state cpacker;
   1139 	struct ieee80211_radiotap_header *hdr;
   1140 	u_int32_t present, next_present;
   1141 	u_int32_t *presentp, *last_presentp;
   1142 	enum ieee80211_radiotap_type bit;
   1143 	int bit0;
   1144 	const u_char *iter;
   1145 	u_int len;
   1146 	int pad;
   1147 
   1148 	if (caplen < sizeof(*hdr)) {
   1149 		printf("[|802.11]");
   1150 		return caplen;
   1151 	}
   1152 
   1153 	hdr = (struct ieee80211_radiotap_header *)p;
   1154 
   1155 	len = EXTRACT_LE_16BITS(&hdr->it_len);
   1156 
   1157 	if (caplen < len) {
   1158 		printf("[|802.11]");
   1159 		return caplen;
   1160 	}
   1161 	for (last_presentp = &hdr->it_present;
   1162 	     IS_EXTENDED(last_presentp) &&
   1163 	     (u_char*)(last_presentp + 1) <= p + len;
   1164 	     last_presentp++);
   1165 
   1166 	/* are there more bitmap extensions than bytes in header? */
   1167 	if (IS_EXTENDED(last_presentp)) {
   1168 		printf("[|802.11]");
   1169 		return caplen;
   1170 	}
   1171 
   1172 	iter = (u_char*)(last_presentp + 1);
   1173 
   1174 	if (cpack_init(&cpacker, (u_int8_t*)iter, len - (iter - p)) != 0) {
   1175 		/* XXX */
   1176 		printf("[|802.11]");
   1177 		return caplen;
   1178 	}
   1179 
   1180 	/* Assume no Atheros padding between 802.11 header and body */
   1181 	pad = 0;
   1182 	for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
   1183 	     presentp++, bit0 += 32) {
   1184 		for (present = EXTRACT_LE_32BITS(presentp); present;
   1185 		     present = next_present) {
   1186 			/* clear the least significant bit that is set */
   1187 			next_present = present & (present - 1);
   1188 
   1189 			/* extract the least significant bit that is set */
   1190 			bit = (enum ieee80211_radiotap_type)
   1191 			    (bit0 + BITNO_32(present ^ next_present));
   1192 
   1193 			if (print_radiotap_field(&cpacker, bit, &pad) != 0)
   1194 				goto out;
   1195 		}
   1196 	}
   1197 out:
   1198 	return len + ieee802_11_print(p + len, length - len, caplen - len, pad);
   1199 #undef BITNO_32
   1200 #undef BITNO_16
   1201 #undef BITNO_8
   1202 #undef BITNO_4
   1203 #undef BITNO_2
   1204 #undef BIT
   1205 }
   1206 
   1207 static u_int
   1208 ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
   1209 {
   1210 	u_int32_t caphdr_len;
   1211 
   1212 	caphdr_len = EXTRACT_32BITS(p + 4);
   1213 	if (caphdr_len < 8) {
   1214 		/*
   1215 		 * Yow!  The capture header length is claimed not
   1216 		 * to be large enough to include even the version
   1217 		 * cookie or capture header length!
   1218 		 */
   1219 		printf("[|802.11]");
   1220 		return caplen;
   1221 	}
   1222 
   1223 	if (caplen < caphdr_len) {
   1224 		printf("[|802.11]");
   1225 		return caplen;
   1226 	}
   1227 
   1228 	return caphdr_len + ieee802_11_print(p + caphdr_len,
   1229 	    length - caphdr_len, caplen - caphdr_len, 0);
   1230 }
   1231 
   1232 #define PRISM_HDR_LEN		144
   1233 
   1234 #define WLANCAP_MAGIC_COOKIE_V1	0x80211001
   1235 
   1236 /*
   1237  * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
   1238  * containing information such as radio information, which we
   1239  * currently ignore.
   1240  *
   1241  * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
   1242  * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
   1243  * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
   1244  * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
   1245  * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
   1246  * the first 4 bytes of the header are used to indicate which it is).
   1247  */
   1248 u_int
   1249 prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
   1250 {
   1251 	u_int caplen = h->caplen;
   1252 	u_int length = h->len;
   1253 
   1254 	if (caplen < 4) {
   1255 		printf("[|802.11]");
   1256 		return caplen;
   1257 	}
   1258 
   1259 	if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
   1260 		return ieee802_11_avs_radio_print(p, length, caplen);
   1261 
   1262 	if (caplen < PRISM_HDR_LEN) {
   1263 		printf("[|802.11]");
   1264 		return caplen;
   1265 	}
   1266 
   1267 	return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
   1268 	    length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN, 0);
   1269 }
   1270 
   1271 /*
   1272  * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
   1273  * header, containing information such as radio information, which we
   1274  * currently ignore.
   1275  */
   1276 u_int
   1277 ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
   1278 {
   1279 	u_int caplen = h->caplen;
   1280 	u_int length = h->len;
   1281 
   1282 	if (caplen < 8) {
   1283 		printf("[|802.11]");
   1284 		return caplen;
   1285 	}
   1286 
   1287 	return ieee802_11_radio_print(p, length, caplen);
   1288 }
   1289