On Wed, Feb 03, 2016 at 01:36:50PM +0100, Mark Kettenis wrote:
> > Date: Wed, 3 Feb 2016 13:27:50 +0100
> > From: Stefan Sperling <[email protected]>
> > 
> > Currently, tcpdump displays 802.11 control frames as "type#4" and
> > doesn't give more information than that.
> > 
> > This diff makes tcpdump show the subtype of such frames, and pretty-print
> > a few subtypes in verbose mode. There are more subtypes but these can
> > be pretty-printed later.
> > 
> > This can be tested with:
> > 
> >  ifconfig iwn0 mediaopt monitor up
> >  tcpdump -n -i iwn0 -y IEEE802_11_RADIO -v -s 1500 type ctl
> > 
> > Whether such frames can be seen depends on the driver's RX filter
> > settings in monitor mode. Another driver I've tested with is zyd(4).
> > 
> > ok?
> 
> ok kettenis@

I spotted a bug in my diff. A missing t += 6 inside this if-block:

+                       if (subtype == IEEE80211_FC0_SUBTYPE_BAR ||
+                           subtype == IEEE80211_FC0_SUBTYPE_BA) {


Also, s/BA/ba/ in one printf.

Fixed version below.

Index: print-802_11.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-802_11.c,v
retrieving revision 1.29
diff -u -p -r1.29 print-802_11.c
--- print-802_11.c      1 Feb 2016 10:09:44 -0000       1.29
+++ print-802_11.c      3 Feb 2016 12:40:59 -0000
@@ -37,6 +37,25 @@
 #include "addrtoname.h"
 #include "interface.h"
 
+const char *ieee80211_ctl_subtype_name[] = {
+       "reserved#0",
+       "reserved#1",
+       "reserved#2",
+       "reserved#3",
+       "reserved#4",
+       "reserved#5",
+       "reserved#6",
+       "wrapper",
+       "block ack request",
+       "block ack", 
+       "ps poll", 
+       "rts", 
+       "cts", 
+       "ack", 
+       "cf-end", 
+       "cf-end-ack", 
+};
+
 const char *ieee80211_mgt_subtype_name[] = {
        "association request",
        "association response",
@@ -813,6 +832,70 @@ ieee80211_frame(struct ieee80211_frame *
                        break;
                }
                break;
+       case IEEE80211_FC0_TYPE_CTL: {
+               u_int8_t *t = (u_int8_t *) wh;
+
+               printf(": %s", ieee80211_ctl_subtype_name[
+                   subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
+               if (!vflag)
+                       break;
+
+               /* See 802.11 2012 "8.3.1 Control frames". */
+               t += 2; /* skip Frame Control */
+               switch (subtype) {
+               case IEEE80211_FC0_SUBTYPE_RTS:
+               case IEEE80211_FC0_SUBTYPE_BAR:
+               case IEEE80211_FC0_SUBTYPE_BA:
+                       TCHECK2(*t, 2); /* Duration */
+                       printf(", duration %dms", (t[0] || t[1] << 8));
+                       t += 2;
+                       TCHECK2(*t, 6); /* RA */
+                       printf(", ra %s", etheraddr_string(t));
+                       t += 6;
+                       TCHECK2(*t, 6); /* TA */
+                       printf(", ta %s", etheraddr_string(t));
+                       if (subtype == IEEE80211_FC0_SUBTYPE_BAR ||
+                           subtype == IEEE80211_FC0_SUBTYPE_BA) {
+                               u_int16_t ctrl;
+
+                               t += 6; 
+                               TCHECK2(*t, 2); /* BAR/BA control */
+                               ctrl = t[0] | (t[1] << 8);
+                               if (ctrl & IEEE80211_BA_ACK_POLICY)
+                                       printf(", no ack");
+                               else
+                                       printf(", normal ack");
+                               if ((ctrl & IEEE80211_BA_MULTI_TID) == 0 &&
+                                   (ctrl & IEEE80211_BA_COMPRESSED) == 0)
+                                       printf(", basic variant");
+                               else if ((ctrl & IEEE80211_BA_MULTI_TID) &&
+                                   (ctrl & IEEE80211_BA_COMPRESSED))
+                                       printf(", multi-tid variant");
+                               else if (ctrl & IEEE80211_BA_COMPRESSED)
+                                       printf(", compressed variant");
+                       }
+                       break;
+               case IEEE80211_FC0_SUBTYPE_CTS:
+               case IEEE80211_FC0_SUBTYPE_ACK:
+                       TCHECK2(*t, 2); /* Duration */
+                       printf(", duration %dms", (t[0] || t[1] << 8));
+                       t += 2;
+                       TCHECK2(*t, 6); /* RA */
+                       printf(", ra %s", etheraddr_string(t));
+                       break;
+               case IEEE80211_FC0_SUBTYPE_PS_POLL:
+                       TCHECK2(*t, 2); /* AID */
+                       printf(", aid 0x%x", (t[0] || t[1] << 8));
+                       t += 2;
+                       TCHECK2(*t, 6); /* BSSID(RA) */
+                       printf(", ra %s", etheraddr_string(t));
+                       t += 6;
+                       TCHECK2(*t, 6); /* TA */
+                       printf(", ta %s", etheraddr_string(t));
+                       break;
+               }
+               break;
+       }
        default:
                printf(": type#%d", type);
                break;

> 
> > Index: print-802_11.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/tcpdump/print-802_11.c,v
> > retrieving revision 1.29
> > diff -u -p -r1.29 print-802_11.c
> > --- print-802_11.c  1 Feb 2016 10:09:44 -0000       1.29
> > +++ print-802_11.c  3 Feb 2016 12:21:20 -0000
> > @@ -37,6 +37,25 @@
> >  #include "addrtoname.h"
> >  #include "interface.h"
> >  
> > +const char *ieee80211_ctl_subtype_name[] = {
> > +   "reserved#0",
> > +   "reserved#1",
> > +   "reserved#2",
> > +   "reserved#3",
> > +   "reserved#4",
> > +   "reserved#5",
> > +   "reserved#6",
> > +   "wrapper",
> > +   "block ack request",
> > +   "block ack", 
> > +   "ps poll", 
> > +   "rts", 
> > +   "cts", 
> > +   "ack", 
> > +   "cf-end", 
> > +   "cf-end-ack", 
> > +};
> > +
> >  const char *ieee80211_mgt_subtype_name[] = {
> >     "association request",
> >     "association response",
> > @@ -813,6 +832,69 @@ ieee80211_frame(struct ieee80211_frame *
> >                     break;
> >             }
> >             break;
> > +   case IEEE80211_FC0_TYPE_CTL: {
> > +           u_int8_t *t = (u_int8_t *) wh;
> > +
> > +           printf(": %s", ieee80211_ctl_subtype_name[
> > +               subtype >> IEEE80211_FC0_SUBTYPE_SHIFT]);
> > +           if (!vflag)
> > +                   break;
> > +
> > +           /* See 802.11 2012 "8.3.1 Control frames". */
> > +           t += 2; /* skip Frame Control */
> > +           switch (subtype) {
> > +           case IEEE80211_FC0_SUBTYPE_RTS:
> > +           case IEEE80211_FC0_SUBTYPE_BAR:
> > +           case IEEE80211_FC0_SUBTYPE_BA:
> > +                   TCHECK2(*t, 2); /* Duration */
> > +                   printf(", duration %dms", (t[0] || t[1] << 8));
> > +                   t += 2;
> > +                   TCHECK2(*t, 6); /* RA */
> > +                   printf(", ra %s", etheraddr_string(t));
> > +                   t += 6;
> > +                   TCHECK2(*t, 6); /* TA */
> > +                   printf(", ta %s", etheraddr_string(t));
> > +                   if (subtype == IEEE80211_FC0_SUBTYPE_BAR ||
> > +                       subtype == IEEE80211_FC0_SUBTYPE_BA) {
> > +                           u_int16_t ctrl;
> > +
> > +                           TCHECK2(*t, 2); /* BAR/BA control */
> > +                           ctrl = t[0] | (t[1] << 8);
> > +                           if (ctrl & IEEE80211_BA_ACK_POLICY)
> > +                                   printf(", no ack");
> > +                           else
> > +                                   printf(", normal ack");
> > +                           if ((ctrl & IEEE80211_BA_MULTI_TID) == 0 &&
> > +                               (ctrl & IEEE80211_BA_COMPRESSED) == 0)
> > +                                   printf(", basic variant");
> > +                           else if ((ctrl & IEEE80211_BA_MULTI_TID) &&
> > +                               (ctrl & IEEE80211_BA_COMPRESSED))
> > +                                   printf(", multi-tid variant");
> > +                           else if (ctrl & IEEE80211_BA_COMPRESSED)
> > +                                   printf(", compressed variant");
> > +                   }
> > +                   break;
> > +           case IEEE80211_FC0_SUBTYPE_CTS:
> > +           case IEEE80211_FC0_SUBTYPE_ACK:
> > +                   TCHECK2(*t, 2); /* Duration */
> > +                   printf(", duration %dms", (t[0] || t[1] << 8));
> > +                   t += 2;
> > +                   TCHECK2(*t, 6); /* RA */
> > +                   printf(", ra %s", etheraddr_string(t));
> > +                   break;
> > +           case IEEE80211_FC0_SUBTYPE_PS_POLL:
> > +                   TCHECK2(*t, 2); /* AID */
> > +                   printf(", aid 0x%x", (t[0] || t[1] << 8));
> > +                   t += 2;
> > +                   TCHECK2(*t, 6); /* BSSID(RA) */
> > +                   printf(", RA %s", etheraddr_string(t));
> > +                   t += 6;
> > +                   TCHECK2(*t, 6); /* TA */
> > +                   printf(", ta %s", etheraddr_string(t));
> > +                   break;
> > +           }
> > +           break;
> > +   }
> >     default:
> >             printf(": type#%d", type);
> >             break;
> > 
> > 

Reply via email to