This diff makes tcpdump display details of association requests.
These are interesting because clients announce HT capabilities there.
We can share some printing code with beacons.
Use with something like tcpdump -s 1500 -v -y IEEE802_11_RADIO -i iwn0
Index: print-802_11.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-802_11.c,v
retrieving revision 1.32
diff -u -p -r1.32 print-802_11.c
--- print-802_11.c 21 Feb 2016 16:09:47 -0000 1.32
+++ print-802_11.c 1 Sep 2016 12:21:43 -0000
@@ -101,7 +101,9 @@ void ieee80211_print_essid(u_int8_t *,
void ieee80211_print_country(u_int8_t *, u_int);
void ieee80211_print_htcaps(u_int8_t *, u_int);
void ieee80211_print_htop(u_int8_t *, u_int);
-int ieee80211_elements(struct ieee80211_frame *, u_int);
+int ieee80211_print_beacon(struct ieee80211_frame *, u_int);
+int ieee80211_print_assocreq(struct ieee80211_frame *, u_int);
+int ieee80211_print_elements(uint8_t *);
int ieee80211_frame(struct ieee80211_frame *, u_int);
int ieee80211_print(struct ieee80211_frame *, u_int);
u_int ieee80211_any2ieee(u_int, u_int);
@@ -589,37 +591,74 @@ ieee80211_print_htop(u_int8_t *data, u_i
}
int
-ieee80211_elements(struct ieee80211_frame *wh, u_int flen)
+ieee80211_print_beacon(struct ieee80211_frame *wh, u_int len)
{
- u_int8_t *buf, *frm;
- u_int64_t tstamp;
- u_int16_t bintval, capinfo;
- int i;
+ uint64_t tstamp;
+ uint16_t bintval, capinfo;
+ uint8_t *frm;
+
+ if (len < sizeof(tstamp) + sizeof(bintval) + sizeof(capinfo))
+ return 1; /* truncated */
- buf = (u_int8_t *)wh;
frm = (u_int8_t *)&wh[1];
- TCHECK2(*frm, 8);
bcopy(frm, &tstamp, sizeof(u_int64_t));
frm += 8;
-
if (vflag > 1)
printf(", timestamp %llu", letoh64(tstamp));
- TCHECK2(*frm, 2);
bcopy(frm, &bintval, sizeof(u_int16_t));
frm += 2;
-
if (vflag > 1)
printf(", interval %u", letoh16(bintval));
- TCHECK2(*frm, 2);
bcopy(frm, &capinfo, sizeof(u_int16_t));
frm += 2;
+ if (vflag)
+ printb(", caps", letoh16(capinfo), IEEE80211_CAPINFO_BITS);
+
+ return ieee80211_print_elements(frm);
+}
+
+int
+ieee80211_print_assocreq(struct ieee80211_frame *wh, u_int len)
+{
+ uint8_t subtype;
+ uint16_t capinfo, lintval;
+ uint8_t *frm;
+
+ subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+
+ if (len < sizeof(capinfo) + sizeof(lintval) +
+ (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ ?
+ IEEE80211_ADDR_LEN : 0))
+ return 1; /* truncated */
+
+ frm = (u_int8_t *)&wh[1];
+ bcopy(frm, &capinfo, sizeof(u_int16_t));
+ frm += 2;
if (vflag)
- printb(", caps", letoh16(capinfo),
- IEEE80211_CAPINFO_BITS);
+ printb(", caps", letoh16(capinfo), IEEE80211_CAPINFO_BITS);
+
+ bcopy(frm, &lintval, sizeof(u_int16_t));
+ frm += 2;
+ if (vflag > 1)
+ printf(", listen interval %u", letoh16(lintval));
+
+ if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
+ if (vflag)
+ printf(", AP %s", etheraddr_string(frm));
+ frm += IEEE80211_ADDR_LEN;
+ }
+
+ return ieee80211_print_elements(frm);
+}
+
+int
+ieee80211_print_elements(uint8_t *frm)
+{
+ int i;
while (TTEST2(*frm, 2)) {
u_int len = frm[1];
@@ -628,7 +667,7 @@ ieee80211_elements(struct ieee80211_fram
if (!TTEST2(*data, len))
break;
-#define ELEM_CHECK(l) if (len != l) break
+#define ELEM_CHECK(l) if (len != l) goto trunc
switch (*frm) {
case IEEE80211_ELEMID_SSID:
@@ -789,7 +828,12 @@ ieee80211_frame(struct ieee80211_frame *
switch (subtype) {
case IEEE80211_FC0_SUBTYPE_BEACON:
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
- if (ieee80211_elements(wh, len) != 0)
+ if (ieee80211_print_beacon(wh, len) != 0)
+ goto trunc;
+ break;
+ case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
+ case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
+ if (ieee80211_print_assocreq(wh, len) != 0)
goto trunc;
break;
case IEEE80211_FC0_SUBTYPE_AUTH: