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);

Reply via email to