summaryrefslogtreecommitdiffstats
path: root/contrib/tcpdump/print-802_11.c
diff options
context:
space:
mode:
authormlaier <mlaier@FreeBSD.org>2007-10-16 02:31:48 +0000
committermlaier <mlaier@FreeBSD.org>2007-10-16 02:31:48 +0000
commit7407d685ab0d1977958bae143bdcc3b53dacea31 (patch)
tree8c8221dcf086879544da49d1342bacd303933fa6 /contrib/tcpdump/print-802_11.c
parentf0e5d335e38c264eb2fca7e15e417b70c8908f54 (diff)
downloadFreeBSD-src-7407d685ab0d1977958bae143bdcc3b53dacea31.zip
FreeBSD-src-7407d685ab0d1977958bae143bdcc3b53dacea31.tar.gz
Resolve merge conflicts
Approved by: re (kensmith) Obtained from: tcpdump.org
Diffstat (limited to 'contrib/tcpdump/print-802_11.c')
-rw-r--r--contrib/tcpdump/print-802_11.c298
1 files changed, 188 insertions, 110 deletions
diff --git a/contrib/tcpdump/print-802_11.c b/contrib/tcpdump/print-802_11.c
index 4ce21ec..1046fda 100644
--- a/contrib/tcpdump/print-802_11.c
+++ b/contrib/tcpdump/print-802_11.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.5 2005/07/30 21:37:50 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.15 2007/07/22 23:14:14 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -47,20 +47,54 @@ static const char rcsid[] _U_ =
#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++) { \
- PRINT_RATE(sep, p.rates.rate[z], \
- (p.rates.rate[z] & 0x80 ? "*" : "")); \
- 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 int ieee80211_htrates[16] = {
13, /* IFM_IEEE80211_MCS0 */
@@ -140,94 +174,141 @@ 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->tim.length - 3 > 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;
}
/*********************************************************************************
@@ -245,24 +326,20 @@ handle_beacon(const u_char *p)
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;
}
@@ -282,12 +359,9 @@ handle_assoc_request(const u_char *p)
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;
}
@@ -310,8 +384,7 @@ handle_assoc_response(const u_char *p)
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 " : "",
@@ -340,12 +413,10 @@ handle_reassoc_request(const u_char *p)
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;
}
@@ -365,12 +436,9 @@ handle_probe_request(const u_char *p)
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;
@@ -395,15 +463,11 @@ handle_probe_response(const u_char *p)
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;
}
@@ -451,8 +515,7 @@ handle_auth(const u_char *p)
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) ||
@@ -657,22 +720,23 @@ static void
data_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
const u_int8_t **dstp)
{
- switch (FC_SUBTYPE(fc)) {
- case DATA_DATA:
- case DATA_NODATA:
- break;
- case DATA_DATA_CF_ACK:
- case DATA_NODATA_CF_ACK:
- printf("CF Ack ");
- break;
- case DATA_DATA_CF_POLL:
- case DATA_NODATA_CF_POLL:
- printf("CF Poll ");
- break;
- case DATA_DATA_CF_ACK_POLL:
- case DATA_NODATA_CF_ACK_POLL:
- printf("CF Ack/Poll ");
- break;
+ u_int subtype = FC_SUBTYPE(fc);
+
+ if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
+ DATA_FRAME_IS_QOS(subtype)) {
+ printf("CF ");
+ if (DATA_FRAME_IS_CF_ACK(subtype)) {
+ if (DATA_FRAME_IS_CF_POLL(subtype))
+ printf("Ack/Poll");
+ else
+ printf("Ack");
+ } else {
+ if (DATA_FRAME_IS_CF_POLL(subtype))
+ printf("Poll");
+ }
+ if (DATA_FRAME_IS_QOS(subtype))
+ printf("+QoS");
+ printf(" ");
}
#define ADDR1 (p + 4)
@@ -802,6 +866,8 @@ ctrl_header_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
static int
extract_header_length(u_int16_t fc)
{
+ int len;
+
switch (FC_TYPE(fc)) {
case T_MGMT:
return MGMT_HDRLEN;
@@ -825,7 +891,10 @@ extract_header_length(u_int16_t fc)
return 0;
}
case T_DATA:
- return (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
+ len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
+ if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
+ len += 2;
+ return len;
default:
printf("unknown IEEE802.11 frame type (%d)", FC_TYPE(fc));
return 0;
@@ -879,8 +948,12 @@ ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, const u_int8_t **srcp,
}
}
+#ifndef roundup2
+#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
+#endif
+
static u_int
-ieee802_11_print(const u_char *p, u_int length, u_int caplen)
+ieee802_11_print(const u_char *p, u_int length, u_int caplen, int pad)
{
u_int16_t fc;
u_int hdrlen;
@@ -894,6 +967,8 @@ ieee802_11_print(const u_char *p, u_int length, u_int caplen)
fc = EXTRACT_LE_16BITS(p);
hdrlen = extract_header_length(fc);
+ if (pad)
+ hdrlen = roundup2(hdrlen, 4);
if (caplen < hdrlen) {
printf("[|802.11]");
@@ -924,6 +999,8 @@ ieee802_11_print(const u_char *p, u_int length, u_int caplen)
}
break;
case T_DATA:
+ if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
+ return hdrlen; /* no-data frame */
/* There may be a problem w/ AP not having this bit set */
if (FC_WEP(fc)) {
if (!wep_print(p)) {
@@ -964,7 +1041,7 @@ ieee802_11_print(const u_char *p, u_int length, u_int caplen)
u_int
ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
{
- return ieee802_11_print(p, h->len, h->caplen);
+ return ieee802_11_print(p, h->len, h->caplen, 0);
}
#define IEEE80211_CHAN_FHSS \
@@ -1026,7 +1103,7 @@ print_chaninfo(int freq, int flags)
}
static int
-print_radiotap_field(struct cpack_state *s, u_int32_t bit)
+print_radiotap_field(struct cpack_state *s, u_int32_t bit, int *pad)
{
union {
int8_t i8;
@@ -1040,6 +1117,10 @@ print_radiotap_field(struct cpack_state *s, u_int32_t bit)
switch (bit) {
case IEEE80211_RADIOTAP_FLAGS:
+ rc = cpack_uint8(s, &u.u8);
+ if (u.u8 & IEEE80211_RADIOTAP_F_DATAPAD)
+ *pad = 1;
+ break;
case IEEE80211_RADIOTAP_RATE:
case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
case IEEE80211_RADIOTAP_DB_ANTNOISE:
@@ -1142,14 +1223,8 @@ 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 ");
+ printf("bad-fcs ");
break;
case IEEE80211_RADIOTAP_ANTENNA:
printf("antenna %d ", u.u8);
@@ -1184,6 +1259,7 @@ ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
int bit0;
const u_char *iter;
u_int len;
+ int pad;
if (caplen < sizeof(*hdr)) {
printf("[|802.11]");
@@ -1217,6 +1293,8 @@ ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
return caplen;
}
+ /* Assume no Atheros padding between 802.11 header and body */
+ pad = 0;
for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
presentp++, bit0 += 32) {
for (present = EXTRACT_LE_32BITS(presentp); present;
@@ -1228,12 +1306,12 @@ ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
bit = (enum ieee80211_radiotap_type)
(bit0 + BITNO_32(present ^ next_present));
- if (print_radiotap_field(&cpacker, bit) != 0)
+ if (print_radiotap_field(&cpacker, bit, &pad) != 0)
goto out;
}
}
out:
- return len + ieee802_11_print(p + len, length - len, caplen - len);
+ return len + ieee802_11_print(p + len, length - len, caplen - len, pad);
#undef BITNO_32
#undef BITNO_16
#undef BITNO_8
@@ -1264,7 +1342,7 @@ ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
}
return caphdr_len + ieee802_11_print(p + caphdr_len,
- length - caphdr_len, caplen - caphdr_len);
+ length - caphdr_len, caplen - caphdr_len, 0);
}
#define PRISM_HDR_LEN 144
@@ -1303,7 +1381,7 @@ prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
}
return PRISM_HDR_LEN + ieee802_11_print(p + PRISM_HDR_LEN,
- length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN);
+ length - PRISM_HDR_LEN, caplen - PRISM_HDR_LEN, 0);
}
/*
OpenPOWER on IntegriCloud