#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.26 2003-11-27 02:18:53 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.10 2005-11-13 20:23:09 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
#include "extract.h"
+#include "cpack.h"
+
#include "ieee802_11.h"
+#include "ieee802_11_radio.h"
+
+#define PRINT_SSID(p) \
+ switch (p.ssid_status) { \
+ case TRUNCATED: \
+ return 0; \
+ case PRESENT: \
+ printf(" ("); \
+ fn_print(p.ssid.ssid, NULL); \
+ printf(")"); \
+ break; \
+ case NOT_PRESENT: \
+ break; \
+ }
+#define PRINT_RATE(_sep, _r, _suf) \
+ printf("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
#define PRINT_RATES(p) \
-do { \
- int z; \
- const char *sep = " ["; \
- for (z = 0; z < p.rates.length ; z++) { \
- printf("%s%2.1f", sep, (.5 * (p.rates.rate[z] & 0x7f))); \
- if (p.rates.rate[z] & 0x80) printf("*"); \
- sep = " "; \
+ switch (p.rates_status) { \
+ case TRUNCATED: \
+ return 0; \
+ case PRESENT: \
+ do { \
+ int z; \
+ const char *sep = " ["; \
+ for (z = 0; z < p.rates.length ; z++) { \
+ PRINT_RATE(sep, p.rates.rate[z], \
+ (p.rates.rate[z] & 0x80 ? "*" : "")); \
+ sep = " "; \
+ } \
+ if (p.rates.length != 0) \
+ printf(" Mbit]"); \
+ } while (0); \
+ break; \
+ case NOT_PRESENT: \
+ break; \
+ }
+
+#define PRINT_DS_CHANNEL(p) \
+ switch (p.ds_status) { \
+ case TRUNCATED: \
+ return 0; \
+ case PRESENT: \
+ printf(" CH: %u", p.ds.channel); \
+ break; \
+ case NOT_PRESENT: \
+ break; \
} \
- if (p.rates.length != 0) \
- printf(" Mbit]"); \
-} while (0)
+ printf("%s", \
+ CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "" );
static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
-static const char *subtype_text[]={
- "Assoc Request",
- "Assoc Response",
- "ReAssoc Request",
- "ReAssoc Response",
- "Probe Request",
- "Probe Response",
- "RESERVED",
- "RESERVED",
- "Beacon",
- "ATIM",
- "Disassociation",
- "Authentication",
- "DeAuthentication",
- "RESERVED",
- "RESERVED"
-};
+#define NUM_AUTH_ALGS (sizeof auth_alg_text / sizeof auth_alg_text[0])
static const char *status_text[] = {
"Succesful", /* 0 */
"Association denied because AP is unable to handle additional associated stations", /* 17 */
"Association denied due to requesting station not supporting all of the " \
"data rates in BSSBasicRateSet parameter", /* 18 */
- NULL
};
+#define NUM_STATUSES (sizeof status_text / sizeof status_text[0])
static const char *reason_text[] = {
"Reserved", /* 0 */
"Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
"Disassociated due to inactivity", /* 4 */
"Disassociated because AP is unable to handle all currently associated stations", /* 5 */
- "Class 2 frame receivedfrom nonauthenticated station", /* 6 */
+ "Class 2 frame received from nonauthenticated station", /* 6 */
"Class 3 frame received from nonassociated station", /* 7 */
"Disassociated because sending station is leaving (or has left) BSS", /* 8 */
"Station requesting (re)association is not authenticated with responding station", /* 9 */
- NULL
};
+#define NUM_REASONS (sizeof reason_text / sizeof reason_text[0])
static int
wep_print(const u_char *p)
return 1;
}
-static int
+static void
parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
{
+ /*
+ * We haven't seen any elements yet.
+ */
+ pbody->challenge_status = NOT_PRESENT;
+ pbody->ssid_status = NOT_PRESENT;
+ pbody->rates_status = NOT_PRESENT;
+ pbody->ds_status = NOT_PRESENT;
+ pbody->cf_status = NOT_PRESENT;
+ pbody->tim_status = NOT_PRESENT;
+
for (;;) {
if (!TTEST2(*(p + offset), 1))
- return 1;
+ return;
switch (*(p + offset)) {
case E_SSID:
+ /* Present, possibly truncated */
+ pbody->ssid_status = TRUNCATED;
if (!TTEST2(*(p + offset), 2))
- return 0;
+ return;
memcpy(&pbody->ssid, p + offset, 2);
offset += 2;
- if (pbody->ssid.length <= 0)
- break;
- if (!TTEST2(*(p + offset), pbody->ssid.length))
- return 0;
- memcpy(&pbody->ssid.ssid, p + offset,
- pbody->ssid.length);
- offset += pbody->ssid.length;
+ if (pbody->ssid.length != 0) {
+ if (pbody->ssid.length >
+ sizeof(pbody->ssid.ssid) - 1)
+ return;
+ if (!TTEST2(*(p + offset), pbody->ssid.length))
+ return;
+ memcpy(&pbody->ssid.ssid, p + offset,
+ pbody->ssid.length);
+ offset += pbody->ssid.length;
+ }
pbody->ssid.ssid[pbody->ssid.length] = '\0';
+ /* Present and not truncated */
+ pbody->ssid_status = PRESENT;
break;
case E_CHALLENGE:
+ /* Present, possibly truncated */
+ pbody->challenge_status = TRUNCATED;
if (!TTEST2(*(p + offset), 2))
- return 0;
+ return;
memcpy(&pbody->challenge, p + offset, 2);
offset += 2;
- if (pbody->challenge.length <= 0)
- break;
- if (!TTEST2(*(p + offset), pbody->challenge.length))
- return 0;
- memcpy(&pbody->challenge.text, p + offset,
- pbody->challenge.length);
- offset += pbody->challenge.length;
+ if (pbody->challenge.length != 0) {
+ if (pbody->challenge.length >
+ sizeof(pbody->challenge.text) - 1)
+ return;
+ if (!TTEST2(*(p + offset), pbody->challenge.length))
+ return;
+ memcpy(&pbody->challenge.text, p + offset,
+ pbody->challenge.length);
+ offset += pbody->challenge.length;
+ }
pbody->challenge.text[pbody->challenge.length] = '\0';
+ /* Present and not truncated */
+ pbody->challenge_status = PRESENT;
break;
case E_RATES:
+ /* Present, possibly truncated */
+ pbody->rates_status = TRUNCATED;
if (!TTEST2(*(p + offset), 2))
- return 0;
+ return;
memcpy(&(pbody->rates), p + offset, 2);
offset += 2;
- if (pbody->rates.length <= 0)
- break;
- if (!TTEST2(*(p + offset), pbody->rates.length))
- return 0;
- memcpy(&pbody->rates.rate, p + offset,
- pbody->rates.length);
- offset += pbody->rates.length;
+ if (pbody->rates.length != 0) {
+ if (pbody->rates.length > sizeof pbody->rates.rate)
+ return;
+ if (!TTEST2(*(p + offset), pbody->rates.length))
+ return;
+ memcpy(&pbody->rates.rate, p + offset,
+ pbody->rates.length);
+ offset += pbody->rates.length;
+ }
+ /* Present and not truncated */
+ pbody->rates_status = PRESENT;
break;
case E_DS:
+ /* Present, possibly truncated */
+ pbody->ds_status = TRUNCATED;
if (!TTEST2(*(p + offset), 3))
- return 0;
+ return;
memcpy(&pbody->ds, p + offset, 3);
offset += 3;
+ /* Present and not truncated */
+ pbody->ds_status = PRESENT;
break;
case E_CF:
+ /* Present, possibly truncated */
+ pbody->cf_status = TRUNCATED;
if (!TTEST2(*(p + offset), 8))
- return 0;
+ return;
memcpy(&pbody->cf, p + offset, 8);
offset += 8;
+ /* Present and not truncated */
+ pbody->cf_status = PRESENT;
break;
case E_TIM:
+ /* Present, possibly truncated */
+ pbody->tim_status = TRUNCATED;
if (!TTEST2(*(p + offset), 2))
- return 0;
+ return;
memcpy(&pbody->tim, p + offset, 2);
offset += 2;
if (!TTEST2(*(p + offset), 3))
- return 0;
+ return;
memcpy(&pbody->tim.count, p + offset, 3);
offset += 3;
if (pbody->tim.length <= 3)
break;
+ if (pbody->rates.length > sizeof pbody->tim.bitmap)
+ return;
if (!TTEST2(*(p + offset), pbody->tim.length - 3))
- return 0;
+ return;
memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3),
(pbody->tim.length - 3));
offset += pbody->tim.length - 3;
+ /* Present and not truncated */
+ pbody->tim_status = PRESENT;
break;
default:
#if 0
printf("(1) unhandled element_id (%d) ",
*(p + offset) );
#endif
+ if (!TTEST2(*(p + offset), 2))
+ return;
+ if (!TTEST2(*(p + offset + 2), *(p + offset + 1)))
+ return;
offset += *(p + offset + 1) + 2;
break;
}
}
- return 1;
}
/*********************************************************************************
*********************************************************************************/
static int
-handle_beacon(u_int16_t fc, const u_char *p)
+handle_beacon(const u_char *p)
{
struct mgmt_body_t pbody;
int offset = 0;
if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
IEEE802_11_CAPINFO_LEN))
return 0;
- memcpy(&pbody.timestamp, p, 8);
+ memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
offset += IEEE802_11_TSTAMP_LEN;
pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
offset += IEEE802_11_BCNINT_LEN;
pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
offset += IEEE802_11_CAPINFO_LEN;
- if (!parse_elements(&pbody, p, offset))
- return 0;
+ parse_elements(&pbody, p, offset);
- printf(" (");
- fn_print(pbody.ssid.ssid, NULL);
- printf(")");
+ PRINT_SSID(pbody);
PRINT_RATES(pbody);
- printf(" %s CH: %u%s",
- CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS",
- pbody.ds.channel,
- CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
+ printf(" %s",
+ CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
+ PRINT_DS_CHANNEL(pbody);
return 1;
}
static int
-handle_assoc_request(u_int16_t fc, const u_char *p)
+handle_assoc_request(const u_char *p)
{
struct mgmt_body_t pbody;
int offset = 0;
pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
offset += IEEE802_11_LISTENINT_LEN;
- if (!parse_elements(&pbody, p, offset))
- return 0;
+ parse_elements(&pbody, p, offset);
- printf(" (");
- fn_print(pbody.ssid.ssid, NULL);
- printf(")");
+ PRINT_SSID(pbody);
PRINT_RATES(pbody);
return 1;
}
static int
-handle_assoc_response(u_int16_t fc, const u_char *p)
+handle_assoc_response(const u_char *p)
{
struct mgmt_body_t pbody;
int offset = 0;
pbody.aid = EXTRACT_LE_16BITS(p+offset);
offset += IEEE802_11_AID_LEN;
- if (!parse_elements(&pbody, p, offset))
- return 0;
+ parse_elements(&pbody, p, offset);
printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
- (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a"));
+ (pbody.status_code < NUM_STATUSES
+ ? status_text[pbody.status_code]
+ : "n/a"));
return 1;
}
static int
-handle_reassoc_request(u_int16_t fc, const u_char *p)
+handle_reassoc_request(const u_char *p)
{
struct mgmt_body_t pbody;
int offset = 0;
memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
offset += IEEE802_11_AP_LEN;
- if (!parse_elements(&pbody, p, offset))
- return 0;
+ parse_elements(&pbody, p, offset);
- printf(" (");
- fn_print(pbody.ssid.ssid, NULL);
- printf(") AP : %s", etheraddr_string( pbody.ap ));
+ PRINT_SSID(pbody);
+ printf(" AP : %s", etheraddr_string( pbody.ap ));
return 1;
}
static int
-handle_reassoc_response(u_int16_t fc, const u_char *p)
+handle_reassoc_response(const u_char *p)
{
/* Same as a Association Reponse */
- return handle_assoc_response(fc, p);
+ return handle_assoc_response(p);
}
static int
-handle_probe_request(u_int16_t fc, const u_char *p)
+handle_probe_request(const u_char *p)
{
struct mgmt_body_t pbody;
int offset = 0;
memset(&pbody, 0, sizeof(pbody));
- if (!parse_elements(&pbody, p, offset))
- return 0;
+ parse_elements(&pbody, p, offset);
- printf(" (");
- fn_print(pbody.ssid.ssid, NULL);
- printf(")");
+ PRINT_SSID(pbody);
PRINT_RATES(pbody);
return 1;
}
static int
-handle_probe_response(u_int16_t fc, const u_char *p)
+handle_probe_response(const u_char *p)
{
struct mgmt_body_t pbody;
int offset = 0;
pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
offset += IEEE802_11_CAPINFO_LEN;
- if (!parse_elements(&pbody, p, offset))
- return 0;
+ parse_elements(&pbody, p, offset);
- printf(" (");
- fn_print(pbody.ssid.ssid, NULL);
- printf(") ");
+ PRINT_SSID(pbody);
PRINT_RATES(pbody);
- printf(" CH: %u%s", pbody.ds.channel,
- CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
+ PRINT_DS_CHANNEL(pbody);
return 1;
}
}
static int
-handle_disassoc(u_int16_t fc, const u_char *p)
+handle_disassoc(const u_char *p)
{
struct mgmt_body_t pbody;
pbody.reason_code = EXTRACT_LE_16BITS(p);
printf(": %s",
- (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
- : "Reserved" );
+ (pbody.reason_code < NUM_REASONS)
+ ? reason_text[pbody.reason_code]
+ : "Reserved" );
return 1;
}
static int
-handle_auth(u_int16_t fc, const u_char *p)
+handle_auth(const u_char *p)
{
struct mgmt_body_t pbody;
int offset = 0;
pbody.status_code = EXTRACT_LE_16BITS(p + offset);
offset += 2;
- if (!parse_elements(&pbody, p, offset))
- return 0;
+ parse_elements(&pbody, p, offset);
if ((pbody.auth_alg == 1) &&
((pbody.auth_trans_seq_num == 2) ||
(pbody.auth_trans_seq_num == 3))) {
printf(" (%s)-%x [Challenge Text] %s",
- (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg]
- : "Reserved",
+ (pbody.auth_alg < NUM_AUTH_ALGS)
+ ? auth_alg_text[pbody.auth_alg]
+ : "Reserved",
pbody.auth_trans_seq_num,
((pbody.auth_trans_seq_num % 2)
- ? ((pbody.status_code < 19)
+ ? ((pbody.status_code < NUM_STATUSES)
? status_text[pbody.status_code]
: "n/a") : ""));
return 1;
}
printf(" (%s)-%x: %s",
- (pbody.auth_alg < 4) ? auth_alg_text[pbody.auth_alg] : "Reserved",
+ (pbody.auth_alg < NUM_AUTH_ALGS)
+ ? auth_alg_text[pbody.auth_alg]
+ : "Reserved",
pbody.auth_trans_seq_num,
(pbody.auth_trans_seq_num % 2)
- ? ((pbody.status_code < 19) ? status_text[pbody.status_code]
- : "n/a")
+ ? ((pbody.status_code < NUM_STATUSES)
+ ? status_text[pbody.status_code]
+ : "n/a")
: "");
return 1;
}
static int
-handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh,
- const u_char *p)
+handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
{
struct mgmt_body_t pbody;
int offset = 0;
pbody.reason_code = EXTRACT_LE_16BITS(p);
offset += IEEE802_11_REASON_LEN;
- reason = (pbody.reason_code < 10) ? reason_text[pbody.reason_code]
- : "Reserved";
+ reason = (pbody.reason_code < NUM_REASONS)
+ ? reason_text[pbody.reason_code]
+ : "Reserved";
if (eflag) {
printf(": %s", reason);
mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
const u_char *p)
{
- printf("%s", subtype_text[FC_SUBTYPE(fc)]);
-
switch (FC_SUBTYPE(fc)) {
case ST_ASSOC_REQUEST:
- return handle_assoc_request(fc, p);
+ printf("Assoc Request");
+ return handle_assoc_request(p);
case ST_ASSOC_RESPONSE:
- return handle_assoc_response(fc, p);
+ printf("Assoc Response");
+ return handle_assoc_response(p);
case ST_REASSOC_REQUEST:
- return handle_reassoc_request(fc, p);
+ printf("ReAssoc Request");
+ return handle_reassoc_request(p);
case ST_REASSOC_RESPONSE:
- return handle_reassoc_response(fc, p);
+ printf("ReAssoc Response");
+ return handle_reassoc_response(p);
case ST_PROBE_REQUEST:
- return handle_probe_request(fc, p);
+ printf("Probe Request");
+ return handle_probe_request(p);
case ST_PROBE_RESPONSE:
- return handle_probe_response(fc, p);
+ printf("Probe Response");
+ return handle_probe_response(p);
case ST_BEACON:
- return handle_beacon(fc, p);
+ printf("Beacon");
+ return handle_beacon(p);
case ST_ATIM:
+ printf("ATIM");
return handle_atim();
case ST_DISASSOC:
- return handle_disassoc(fc, p);
+ printf("Disassociation");
+ return handle_disassoc(p);
case ST_AUTH:
+ printf("Authentication");
if (!TTEST2(*p, 3))
return 0;
if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
printf("Authentication (Shared-Key)-3 ");
return wep_print(p);
}
- return handle_auth(fc, p);
+ return handle_auth(p);
case ST_DEAUTH:
- return handle_deauth(fc, pmh, p);
+ printf("DeAuthentication");
+ return handle_deauth(pmh, p);
break;
default:
printf("Unhandled Management subtype(%x)",
printf("(LLC %s) ",
etherproto_string(
htons(extracted_ethertype)));
- if (!xflag && !qflag)
+ if (!suppress_default_print)
default_print(p, caplen);
}
break;
/*
* This is the top level routine of the printer. 'p' points
* to the 802.11 header of the packet, 'h->ts' is the timestamp,
- * 'h->length' is the length of the packet off the wire, and 'h->caplen'
+ * 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
u_int
return ieee802_11_print(p, h->len, h->caplen);
}
+static int
+print_radiotap_field(struct cpack_state *s, u_int32_t bit)
+{
+ union {
+ int8_t i8;
+ u_int8_t u8;
+ int16_t i16;
+ u_int16_t u16;
+ u_int32_t u32;
+ u_int64_t u64;
+ } u, u2;
+ int rc;
+
+ switch (bit) {
+ case IEEE80211_RADIOTAP_FLAGS:
+ case IEEE80211_RADIOTAP_RATE:
+ case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+ case IEEE80211_RADIOTAP_DB_ANTNOISE:
+ case IEEE80211_RADIOTAP_ANTENNA:
+ rc = cpack_uint8(s, &u.u8);
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+ case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+ rc = cpack_int8(s, &u.i8);
+ break;
+ case IEEE80211_RADIOTAP_CHANNEL:
+ rc = cpack_uint16(s, &u.u16);
+ if (rc != 0)
+ break;
+ rc = cpack_uint16(s, &u2.u16);
+ break;
+ case IEEE80211_RADIOTAP_FHSS:
+ case IEEE80211_RADIOTAP_LOCK_QUALITY:
+ case IEEE80211_RADIOTAP_TX_ATTENUATION:
+ rc = cpack_uint16(s, &u.u16);
+ break;
+ case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
+ rc = cpack_uint8(s, &u.u8);
+ break;
+ case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ rc = cpack_int8(s, &u.i8);
+ break;
+ case IEEE80211_RADIOTAP_TSFT:
+ rc = cpack_uint64(s, &u.u64);
+ break;
+ default:
+ /* this bit indicates a field whose
+ * size we do not know, so we cannot
+ * proceed.
+ */
+ printf("[0x%08x] ", bit);
+ return -1;
+ }
+
+ if (rc != 0) {
+ printf("[|802.11]");
+ return rc;
+ }
+
+ switch (bit) {
+ case IEEE80211_RADIOTAP_CHANNEL:
+ printf("%u MHz ", u.u16);
+ if (u2.u16 != 0)
+ printf("(0x%04x) ", u2.u16);
+ break;
+ case IEEE80211_RADIOTAP_FHSS:
+ printf("fhset %d fhpat %d ", u.u16 & 0xff, (u.u16 >> 8) & 0xff);
+ break;
+ case IEEE80211_RADIOTAP_RATE:
+ PRINT_RATE("", u.u8, " Mb/s ");
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+ printf("%ddB signal ", u.i8);
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+ printf("%ddB noise ", u.i8);
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+ printf("%ddB signal ", u.u8);
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTNOISE:
+ printf("%ddB noise ", u.u8);
+ break;
+ case IEEE80211_RADIOTAP_LOCK_QUALITY:
+ printf("%u sq ", u.u16);
+ break;
+ case IEEE80211_RADIOTAP_TX_ATTENUATION:
+ printf("%d tx power ", -(int)u.u16);
+ break;
+ case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
+ printf("%ddB tx power ", -(int)u.u8);
+ break;
+ case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ printf("%ddBm tx power ", u.i8);
+ break;
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (u.u8 & IEEE80211_RADIOTAP_F_CFP)
+ printf("cfp ");
+ if (u.u8 & IEEE80211_RADIOTAP_F_SHORTPRE)
+ printf("short preamble ");
+ if (u.u8 & IEEE80211_RADIOTAP_F_WEP)
+ printf("wep ");
+ if (u.u8 & IEEE80211_RADIOTAP_F_FRAG)
+ printf("fragmented ");
+ break;
+ case IEEE80211_RADIOTAP_ANTENNA:
+ printf("antenna %d ", u.u8);
+ break;
+ case IEEE80211_RADIOTAP_TSFT:
+ printf("%" PRIu64 "us tsft ", u.u64);
+ break;
+ }
+ return 0;
+}
+
static u_int
ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
+{
+#define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
+#define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
+#define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
+#define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
+#define BITNO_2(x) (((x) & 2) ? 1 : 0)
+#define BIT(n) (1 << n)
+#define IS_EXTENDED(__p) \
+ (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
+
+ struct cpack_state cpacker;
+ struct ieee80211_radiotap_header *hdr;
+ u_int32_t present, next_present;
+ u_int32_t *presentp, *last_presentp;
+ enum ieee80211_radiotap_type bit;
+ int bit0;
+ const u_char *iter;
+ u_int len;
+
+ if (caplen < sizeof(*hdr)) {
+ printf("[|802.11]");
+ return caplen;
+ }
+
+ hdr = (struct ieee80211_radiotap_header *)p;
+
+ len = EXTRACT_LE_16BITS(&hdr->it_len);
+
+ if (caplen < len) {
+ printf("[|802.11]");
+ return caplen;
+ }
+ for (last_presentp = &hdr->it_present;
+ IS_EXTENDED(last_presentp) &&
+ (u_char*)(last_presentp + 1) <= p + len;
+ last_presentp++);
+
+ /* are there more bitmap extensions than bytes in header? */
+ if (IS_EXTENDED(last_presentp)) {
+ printf("[|802.11]");
+ return caplen;
+ }
+
+ iter = (u_char*)(last_presentp + 1);
+
+ if (cpack_init(&cpacker, (u_int8_t*)iter, len - (iter - p)) != 0) {
+ /* XXX */
+ printf("[|802.11]");
+ return caplen;
+ }
+
+ for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
+ presentp++, bit0 += 32) {
+ for (present = EXTRACT_LE_32BITS(presentp); present;
+ present = next_present) {
+ /* clear the least significant bit that is set */
+ next_present = present & (present - 1);
+
+ /* extract the least significant bit that is set */
+ bit = (enum ieee80211_radiotap_type)
+ (bit0 + BITNO_32(present ^ next_present));
+
+ if (print_radiotap_field(&cpacker, bit) != 0)
+ goto out;
+ }
+ }
+out:
+ return len + ieee802_11_print(p + len, length - len, caplen - len);
+#undef BITNO_32
+#undef BITNO_16
+#undef BITNO_8
+#undef BITNO_4
+#undef BITNO_2
+#undef BIT
+}
+
+static u_int
+ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
{
u_int32_t caphdr_len;
}
if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
- return ieee802_11_radio_print(p, length, caplen);
+ return ieee802_11_avs_radio_print(p, length, caplen);
if (caplen < PRISM_HDR_LEN) {
printf("[|802.11]");