From 860e02a293042553c2df9790dd17d659665c2d54 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 11 Jun 2007 04:04:30 +0000 Subject: o add minimal radiotap support for 11n --- contrib/tcpdump/ieee802_11.h | 17 +++++ contrib/tcpdump/ieee802_11_radio.h | 55 ++++++++++++--- contrib/tcpdump/print-802_11.c | 134 +++++++++++++++++++++++++++++++++++-- 3 files changed, 191 insertions(+), 15 deletions(-) (limited to 'contrib') diff --git a/contrib/tcpdump/ieee802_11.h b/contrib/tcpdump/ieee802_11.h index fa5a555..7d5c7fc 100644 --- a/contrib/tcpdump/ieee802_11.h +++ b/contrib/tcpdump/ieee802_11.h @@ -1,3 +1,4 @@ +/* $FreeBSD$ */ /* @(#) $Header: /tcpdump/master/tcpdump/ieee802_11.h,v 1.9 2003/07/22 17:36:57 guy Exp $ (LBL) */ /* * Copyright (c) 2001 @@ -30,6 +31,7 @@ #define IEEE802_11_RA_LEN 6 #define IEEE802_11_TA_LEN 6 #define IEEE802_11_SEQ_LEN 2 +#define IEEE802_11_CTL_LEN 2 #define IEEE802_11_IV_LEN 3 #define IEEE802_11_KID_LEN 1 @@ -72,6 +74,7 @@ /* RESERVED 0xF */ +#define CTRL_BAR 0x8 #define CTRL_PS_POLL 0xA #define CTRL_RTS 0xB #define CTRL_CTS 0xC @@ -280,6 +283,20 @@ struct ctrl_end_ack_t { #define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) +struct ctrl_bar_t { + u_int16_t fc; + u_int16_t dur; + u_int8_t ra[6]; + u_int8_t ta[6]; + u_int16_t ctl; + u_int16_t seq; + u_int8_t fcs[4]; +}; + +#define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ + IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\ + IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN) + #define IV_IV(iv) ((iv) & 0xFFFFFF) #define IV_PAD(iv) (((iv) >> 24) & 0x3F) #define IV_KEYID(iv) (((iv) >> 30) & 0x03) diff --git a/contrib/tcpdump/ieee802_11_radio.h b/contrib/tcpdump/ieee802_11_radio.h index c56be01..a2b2f16 100644 --- a/contrib/tcpdump/ieee802_11_radio.h +++ b/contrib/tcpdump/ieee802_11_radio.h @@ -53,7 +53,11 @@ #endif #endif /* _KERNEL */ -/* The radio capture header precedes the 802.11 header. */ +/* + * The radio capture header precedes the 802.11 header. + * + * Note well: all radiotap fields are little-endian. + */ struct ieee80211_radiotap_header { u_int8_t it_version; /* Version 0. Only increases * for drastic changes, @@ -87,15 +91,19 @@ struct ieee80211_radiotap_header { * IEEE80211_RADIOTAP_CHANNEL 2 x u_int16_t MHz, bitmap * * Tx/Rx frequency in MHz, followed by flags (see below). + * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to + * represent an HT channel as there is not enough room in + * the flags word. * * IEEE80211_RADIOTAP_FHSS u_int16_t see below * * For frequency-hopping radios, the hop set (first byte) * and pattern (second byte). * - * IEEE80211_RADIOTAP_RATE u_int8_t 500kb/s + * IEEE80211_RADIOTAP_RATE u_int8_t 500kb/s or index * - * Tx/Rx data rate + * Tx/Rx data rate. If bit 0x80 is set then it represents an + * an MCS index and not an IEEE rate. * * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from * one milliwatt (dBm) @@ -154,6 +162,17 @@ struct ieee80211_radiotap_header { * * Unitless indication of the Rx/Tx antenna for this packet. * The first antenna is antenna 0. + * + * IEEE80211_RADIOTAP_XCHANNEL u_int32_t bitmap + * u_int16_t MHz + * u_int8_t channel number + * u_int8_t .5 dBm + * + * Extended channel specification: flags (see below) followed by + * frequency in MHz, the corresponding IEEE channel number, and + * finally the maximum regulatory transmit power cap in .5 dBm + * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL + * and only one of the two should be present. */ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, @@ -170,17 +189,27 @@ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_ANTENNA = 11, IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, IEEE80211_RADIOTAP_DB_ANTNOISE = 13, + IEEE80211_RADIOTAP_XCHANNEL = 14, IEEE80211_RADIOTAP_EXT = 31 }; #ifndef _KERNEL -/* Channel flags. */ -#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ -#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ -#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ -#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ -#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ -#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ +/* Channel flags; some are used only with XCHANNEL */ +#define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */ +#define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */ +#define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */ +#define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */ +#define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */ +#define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */ +#define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */ +#define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */ +#define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */ +#define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */ +#define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */ +#define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */ +#define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */ +#define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */ +#define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */ #endif /* !_KERNEL */ /* For IEEE80211_RADIOTAP_FLAGS */ @@ -197,5 +226,11 @@ enum ieee80211_radiotap_type { #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received * with fragmentation */ +#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ +#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between + * 802.11 header and payload + * (to 32-bit boundary) + */ +#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */ #endif /* _NET_IF_IEEE80211RADIOTAP_H_ */ diff --git a/contrib/tcpdump/print-802_11.c b/contrib/tcpdump/print-802_11.c index c4ec7ee..4ce21ec 100644 --- a/contrib/tcpdump/print-802_11.c +++ b/contrib/tcpdump/print-802_11.c @@ -1,3 +1,4 @@ +/* $FreeBSD$ */ /* * Copyright (c) 2001 * Fortress Technologies, Inc. All rights reserved. @@ -61,6 +62,27 @@ do { \ printf(" Mbit]"); \ } while (0) +static const int ieee80211_htrates[16] = { + 13, /* IFM_IEEE80211_MCS0 */ + 26, /* IFM_IEEE80211_MCS1 */ + 39, /* IFM_IEEE80211_MCS2 */ + 52, /* IFM_IEEE80211_MCS3 */ + 78, /* IFM_IEEE80211_MCS4 */ + 104, /* IFM_IEEE80211_MCS5 */ + 117, /* IFM_IEEE80211_MCS6 */ + 130, /* IFM_IEEE80211_MCS7 */ + 26, /* IFM_IEEE80211_MCS8 */ + 52, /* IFM_IEEE80211_MCS9 */ + 78, /* IFM_IEEE80211_MCS10 */ + 104, /* IFM_IEEE80211_MCS11 */ + 156, /* IFM_IEEE80211_MCS12 */ + 208, /* IFM_IEEE80211_MCS13 */ + 234, /* IFM_IEEE80211_MCS14 */ + 260, /* IFM_IEEE80211_MCS15 */ +}; +#define PRINT_HT_RATE(_sep, _r, _suf) \ + printf("%s%.1f%s", _sep, (.5 * ieee80211_htrates[(_r) & 0xf]), _suf) + static const char *auth_alg_text[]={"Open System","Shared Key","EAP"}; #define NUM_AUTH_ALGS (sizeof auth_alg_text / sizeof auth_alg_text[0]) @@ -553,6 +575,17 @@ static int ctrl_body_print(u_int16_t fc, const u_char *p) { switch (FC_SUBTYPE(fc)) { + case CTRL_BAR: + printf("BAR"); + if (!TTEST2(*p, CTRL_BAR_HDRLEN)) + return 0; + if (!eflag) + printf(" RA:%s TA:%s CTL(%x) SEQ(%u) ", + etheraddr_string(((const struct ctrl_bar_t *)p)->ra), + etheraddr_string(((const struct ctrl_bar_t *)p)->ta), + EXTRACT_LE_16BITS(&(((const struct ctrl_bar_t *)p)->ctl)), + EXTRACT_LE_16BITS(&(((const struct ctrl_bar_t *)p)->seq))); + break; case CTRL_PS_POLL: printf("Power Save-Poll"); if (!TTEST2(*p, CTRL_PS_POLL_HDRLEN)) @@ -725,6 +758,13 @@ ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp, return; switch (FC_SUBTYPE(fc)) { + case CTRL_BAR: + printf(" RA:%s TA:%s CTL(%x) SEQ(%u) ", + etheraddr_string(((const struct ctrl_bar_t *)p)->ra), + etheraddr_string(((const struct ctrl_bar_t *)p)->ta), + EXTRACT_LE_16BITS(&(((const struct ctrl_bar_t *)p)->ctl)), + EXTRACT_LE_16BITS(&(((const struct ctrl_bar_t *)p)->seq))); + break; case CTRL_PS_POLL: printf("BSSID:%s TA:%s ", etheraddr_string(((const struct ctrl_ps_poll_t *)p)->bssid), @@ -767,6 +807,8 @@ extract_header_length(u_int16_t fc) return MGMT_HDRLEN; case T_CTRL: switch (FC_SUBTYPE(fc)) { + case CTRL_BAR: + return CTRL_BAR_HDRLEN; case CTRL_PS_POLL: return CTRL_PS_POLL_HDRLEN; case CTRL_RTS: @@ -925,6 +967,64 @@ ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p) return ieee802_11_print(p, h->len, h->caplen); } +#define IEEE80211_CHAN_FHSS \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK) +#define IEEE80211_CHAN_A \ + (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) +#define IEEE80211_CHAN_B \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) +#define IEEE80211_CHAN_PUREG \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) +#define IEEE80211_CHAN_G \ + (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) + +#define IS_CHAN_FHSS(flags) \ + ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS) +#define IS_CHAN_A(flags) \ + ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) +#define IS_CHAN_B(flags) \ + ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) +#define IS_CHAN_PUREG(flags) \ + ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG) +#define IS_CHAN_G(flags) \ + ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) +#define IS_CHAN_ANYG(flags) \ + (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags)) + +static void +print_chaninfo(int freq, int flags) +{ + printf("%u MHz", freq); + if (IS_CHAN_FHSS(flags)) + printf(" FHSS"); + if (IS_CHAN_A(flags)) { + if (flags & IEEE80211_CHAN_HALF) + printf(" 11a/10Mhz"); + else if (flags & IEEE80211_CHAN_QUARTER) + printf(" 11a/5Mhz"); + else + printf(" 11a"); + } + if (IS_CHAN_ANYG(flags)) { + if (flags & IEEE80211_CHAN_HALF) + printf(" 11g/10Mhz"); + else if (flags & IEEE80211_CHAN_QUARTER) + printf(" 11g/5Mhz"); + else + printf(" 11g"); + } else if (IS_CHAN_B(flags)) + printf(" 11b"); + if (flags & IEEE80211_CHAN_TURBO) + printf(" Turbo"); + if (flags & IEEE80211_CHAN_HT20) + printf(" ht/20"); + else if (flags & IEEE80211_CHAN_HT40D) + printf(" ht/40-"); + else if (flags & IEEE80211_CHAN_HT40U) + printf(" ht/40+"); + printf(" "); +} + static int print_radiotap_field(struct cpack_state *s, u_int32_t bit) { @@ -935,7 +1035,7 @@ print_radiotap_field(struct cpack_state *s, u_int32_t bit) u_int16_t u16; u_int32_t u32; u_int64_t u64; - } u, u2; + } u, u2, u3, u4; int rc; switch (bit) { @@ -970,6 +1070,18 @@ print_radiotap_field(struct cpack_state *s, u_int32_t bit) case IEEE80211_RADIOTAP_TSFT: rc = cpack_uint64(s, &u.u64); break; + case IEEE80211_RADIOTAP_XCHANNEL: + rc = cpack_uint32(s, &u.u32); + if (rc != 0) + break; + rc = cpack_uint16(s, &u2.u16); + if (rc != 0) + break; + rc = cpack_uint8(s, &u3.u8); + if (rc != 0) + break; + rc = cpack_uint8(s, &u4.u8); + break; default: /* this bit indicates a field whose * size we do not know, so we cannot @@ -986,15 +1098,16 @@ print_radiotap_field(struct cpack_state *s, u_int32_t bit) switch (bit) { case IEEE80211_RADIOTAP_CHANNEL: - printf("%u MHz ", u.u16); - if (u2.u16 != 0) - printf("(0x%04x) ", u2.u16); + print_chaninfo(u.u16, 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 "); + if (u.u8 & 0x80) + PRINT_RATE("", u.u8, " Mb/s "); + else + PRINT_HT_RATE("", u.u8, " Mb/s "); break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: printf("%ddB signal ", u.i8); @@ -1029,6 +1142,14 @@ print_radiotap_field(struct cpack_state *s, u_int32_t bit) printf("wep "); if (u.u8 & IEEE80211_RADIOTAP_F_FRAG) printf("fragmented "); +#if 0 + if (u.u8 & IEEE80211_RADIOTAP_F_FCS) + printf("fcs "); + if (u.u8 & IEEE80211_RADIOTAP_F_DATAPAD) + printf("datapad "); +#endif + if (u.u8 & IEEE80211_RADIOTAP_F_BADFCS) + printf("badfcs "); break; case IEEE80211_RADIOTAP_ANTENNA: printf("antenna %d ", u.u8); @@ -1036,6 +1157,9 @@ print_radiotap_field(struct cpack_state *s, u_int32_t bit) case IEEE80211_RADIOTAP_TSFT: printf("%" PRIu64 "us tsft ", u.u64); break; + case IEEE80211_RADIOTAP_XCHANNEL: + print_chaninfo(u2.u16, u.u32); + break; } return 0; } -- cgit v1.1