Make tcpdump display the HT-operation element in 802.11n management frames.
Sample output from hackroom:
htop=<40MHz channels 40:39,protect non-HT,non-greenfield STA,non-HT STA>
ok?
Index: print-802_11.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-802_11.c,v
retrieving revision 1.22
diff -u -p -r1.22 print-802_11.c
--- print-802_11.c 17 Jul 2015 19:43:43 -0000 1.22
+++ print-802_11.c 17 Jul 2015 22:32:01 -0000
@@ -81,6 +81,7 @@ void ieee80211_print_element(u_int8_t *
void ieee80211_print_essid(u_int8_t *, u_int);
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_frame(struct ieee80211_frame *, u_int);
int ieee80211_print(struct ieee80211_frame *, u_int);
@@ -350,6 +351,98 @@ ieee80211_print_htcaps(u_int8_t *data, u
printf(">");
}
+/* Caller checks len */
+void
+ieee80211_print_htop(u_int8_t *data, u_int len)
+{
+ u_int8_t primary_chan;
+ u_int8_t htopinfo[5];
+ u_int8_t basic_mcs[16];
+ int sco, prot;
+
+ if (len < sizeof(primary_chan) + sizeof(htopinfo) + sizeof(basic_mcs)) {
+ ieee80211_print_element(data, len);
+ return;
+ }
+
+ htopinfo[0] = data[1];
+
+ printf("=<");
+
+ /* primary channel and secondary channel offset */
+ primary_chan = data[0];
+ sco = ((htopinfo[0] & IEEE80211_HTOP0_SCO_MASK)
+ >> IEEE80211_HTOP0_SCO_SHIFT);
+ if (sco == 0)
+ printf("20Mhz channel %d", primary_chan);
+ else if (sco == 1)
+ printf("40MHz channels %d:%d", primary_chan, primary_chan + 1);
+ else if (sco == 3)
+ printf("40MHz channels %d:%d", primary_chan, primary_chan - 1);
+ else
+ printf("20Mhz channel %d [invalid secondary channel offset %d]",
+ primary_chan, sco);
+
+ /* STA channel width */
+ if ((htopinfo[0] & IEEE80211_HTOP0_CHW) == 0)
+ printf(",STA chanw 20MHz");
+
+ /* reduced interframe space (RIFS) permitted */
+ if (htopinfo[0] & IEEE80211_HTOP0_RIFS)
+ printf(",RIFS");
+
+ htopinfo[1] = data[2];
+
+ /* protection requirements for HT transmissions */
+ prot = ((htopinfo[1] & IEEE80211_HTOP1_PROT_MASK)
+ >> IEEE80211_HTOP1_PROT_SHIFT);
+ if (prot == 1)
+ printf(",protect non-member");
+ else if (prot == 2)
+ printf(",protect 20MHz");
+ else if (prot == 3)
+ printf(",protect non-HT");
+
+ /* non-greenfield STA present */
+ if (htopinfo[1] & IEEE80211_HTOP1_NONGF_STA)
+ printf(",non-greenfield STA");
+
+ /* non-HT STA present */
+ if (htopinfo[1] & IEEE80211_HTOP1_OBSS_NONHT_STA)
+ printf(",non-HT STA");
+
+ htopinfo[3] = data[4];
+
+ /* dual-beacon */
+ if (htopinfo[3] & IEEE80211_HTOP2_DUALBEACON)
+ printf(",dualbeacon");
+
+ /* dual CTS protection */
+ if (htopinfo[3] & IEEE80211_HTOP2_DUALCTSPROT)
+ printf(",dualctsprot");
+
+ htopinfo[4] = data[5];
+
+ /* space-time block coding (STBC) beacon */
+ if ((htopinfo[4] << 8) & IEEE80211_HTOP2_DUALCTSPROT)
+ printf(",STBC beacon");
+
+ /* L-SIG (non-HT signal field) TX opportunity (TXOP) protection */
+ if ((htopinfo[4] << 8) & IEEE80211_HTOP2_LSIGTXOP)
+ printf(",lsigtxprot");
+
+ /* phased-coexistence operation (PCO) active */
+ if ((htopinfo[4] << 8) & IEEE80211_HTOP2_PCOACTIVE) {
+ /* PCO phase */
+ if ((htopinfo[4] << 8) & IEEE80211_HTOP2_PCOPHASE40)
+ printf(",pco40MHz");
+ else
+ printf(",pco20MHz");
+ }
+
+ printf(">");
+}
+
int
ieee80211_elements(struct ieee80211_frame *wh, u_int flen)
{
@@ -479,6 +572,11 @@ ieee80211_elements(struct ieee80211_fram
printf(", htcaps");
if (vflag)
ieee80211_print_htcaps(data, len);
+ break;
+ case IEEE80211_ELEMID_HTOP:
+ printf(", htop");
+ if (vflag)
+ ieee80211_print_htop(data, len);
break;
case IEEE80211_ELEMID_POWER_CONSTRAINT:
ELEM_CHECK(1);