]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Add the radiotap capture format to tcpdump. radiotap is an extensible
authordyoung <dyoung>
Thu, 23 Sep 2004 21:57:24 +0000 (21:57 +0000)
committerdyoung <dyoung>
Thu, 23 Sep 2004 21:57:24 +0000 (21:57 +0000)
capture format for 802.11 radio statistics such as signal strength,
rx/tx bit rate, and rx/tx channel.

Makefile.in
print-802_11.c

index 3acae8c4aed0059166ed0e16f12bef44966106e5..443f921121e73590c058da836d01dd8a2da5fd62 100644 (file)
@@ -17,7 +17,7 @@
 #  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 #  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 #
-# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.289 2004-07-27 17:04:20 hannes Exp $ (LBL)
+# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.290 2004-09-23 21:57:24 dyoung Exp $ (LBL)
 
 #
 # Various configurable paths (remember to edit Makefile.in, not Makefile)
@@ -65,7 +65,7 @@ INSTALL_DATA = @INSTALL_DATA@
        @rm -f $@
        $(CC) $(CFLAGS) -c $(srcdir)/$*.c
 
-CSRC = addrtoname.c gmpls.c oui.c gmt2local.c ipproto.c l2vpn.c machdep.c parsenfsfh.c \
+CSRC = addrtoname.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c l2vpn.c machdep.c parsenfsfh.c \
        print-802_11.c print-ap1394.c print-ah.c print-arcnet.c \
        print-aodv.c print-arp.c print-ascii.c print-atalk.c print-atm.c \
        print-beep.c print-bfd.c print-bgp.c print-bootp.c print-cdp.c \
@@ -97,7 +97,7 @@ SRC = $(CSRC) $(GENSRC) $(LOCALSRC)
 # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
 # hack the extra indirection
 OBJ =  $(CSRC:.c=.o) $(GENSRC:.c=.o) $(LOCALSRC:.c=.o) $(LIBOBJS)
-HDR =   addrtoname.h appletalk.h bootp.h decnet.h \
+HDR =   addrtoname.h appletalk.h bootp.h cpack.h decnet.h \
        ethertype.h extract.h fddi.h gmt2local.h igrp.h interface.h \
        ipx.h llc.h machdep.h mib.h nfsfh.h nfsv2.h ntp.h ospf.h \
        setsignal.h \
index d6050e48cd13a17b22c6354b3563ac2294f5261e..795168eac359a5b21351b5077b1f701d163b2d9c 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.29 2004-03-17 23:24:35 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.30 2004-09-23 21:57:25 dyoung Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -41,15 +41,20 @@ static const char rcsid[] _U_ =
 
 #include "extract.h"
 
+#include "cpack.h"
+
 #include "ieee802_11.h"
+#include "ieee802_11_radio.h"
 
+#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++) { \
-               printf("%s%2.1f", sep, (.5 * (p.rates.rate[z] & 0x7f))); \
-               if (p.rates.rate[z] & 0x80) printf("*"); \
+               PRINT_RATE(sep, p.rates.rate[z], \
+                       (p.rates.rate[z] & 0x80 ? "*" : "")); \
                sep = " "; \
        } \
        if (p.rates.length != 0) \
@@ -919,8 +924,200 @@ ieee802_11_if_print(const struct pcap_pkthdr *h, const u_char *p)
        return ieee802_11_print(p, h->len, h->caplen);
 }
 
+static int
+print_radiotap_field(struct cpack_state *s, u_int32_t bit)
+{
+       union {
+               int8_t          i8;
+               u_int8_t        u8;
+               int16_t         i16;
+               u_int16_t       u16;
+               u_int32_t       u32;
+               u_int64_t       u64;
+       } u, u2;
+       int rc;
+
+       switch (bit) {
+       case IEEE80211_RADIOTAP_FLAGS:
+       case IEEE80211_RADIOTAP_RATE:
+       case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+       case IEEE80211_RADIOTAP_DB_ANTNOISE:
+       case IEEE80211_RADIOTAP_ANTENNA:
+               rc = cpack_uint8(s, &u.u8);
+               break;
+       case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+       case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+               rc = cpack_int8(s, &u.i8);
+               break;
+       case IEEE80211_RADIOTAP_CHANNEL:
+               rc = cpack_uint16(s, &u.u16);
+               if (rc != 0)
+                       break;
+               rc = cpack_uint16(s, &u2.u16);
+               break;
+       case IEEE80211_RADIOTAP_FHSS:
+       case IEEE80211_RADIOTAP_LOCK_QUALITY:
+       case IEEE80211_RADIOTAP_TX_ATTENUATION:
+               rc = cpack_uint16(s, &u.u16);
+               break;
+       case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
+               rc = cpack_uint8(s, &u.u8);
+               break;
+       case IEEE80211_RADIOTAP_DBM_TX_POWER:
+               rc = cpack_uint8(s, &u.i8);
+               break;
+       case IEEE80211_RADIOTAP_TSFT:
+               rc = cpack_uint64(s, &u.u64);
+               break;
+       default:
+               /* this bit indicates a field whose
+                * size we do not know, so we cannot
+                * proceed.
+                */
+               printf("[0x%08x] ", bit);
+               return -1;
+       }
+
+       if (rc != 0) {
+               printf("[|802.11]");
+               return rc;
+       }
+
+       switch (bit) {
+       case IEEE80211_RADIOTAP_CHANNEL:
+               printf("%u MHz ", u.u16);
+               if (u2.u16 != 0)
+                       printf("(0x%04x) ", u2.u16);
+               break;
+       case IEEE80211_RADIOTAP_FHSS:
+               printf("fhset %d fhpat %d ", u.u16 & 0xff, (u.u16 >> 8) & 0xff);
+               break;
+       case IEEE80211_RADIOTAP_RATE:
+               PRINT_RATE("", u.u8, " Mb/s ");
+               break;
+       case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+               printf("%ddB signal ", u.i8);
+               break;
+       case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+               printf("%ddB noise ", u.i8);
+               break;
+       case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+               printf("%ddB signal ", u.u8);
+               break;
+       case IEEE80211_RADIOTAP_DB_ANTNOISE:
+               printf("%ddB noise ", u.u8);
+               break;
+       case IEEE80211_RADIOTAP_LOCK_QUALITY:
+               printf("%u sq ", u.u16);
+               break;
+       case IEEE80211_RADIOTAP_TX_ATTENUATION:
+               printf("%d tx power ", -(int)u.u16);
+               break;
+       case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
+               printf("%ddB tx power ", -(int)u.u8);
+               break;
+       case IEEE80211_RADIOTAP_DBM_TX_POWER:
+               printf("%ddBm tx power ", u.i8);
+               break;
+       case IEEE80211_RADIOTAP_FLAGS:
+               if (u.u8 & IEEE80211_RADIOTAP_F_CFP)
+                       printf("cfp ");
+               if (u.u8 & IEEE80211_RADIOTAP_F_SHORTPRE)
+                       printf("short preamble ");
+               if (u.u8 & IEEE80211_RADIOTAP_F_WEP)
+                       printf("wep ");
+               if (u.u8 & IEEE80211_RADIOTAP_F_FRAG)
+                       printf("fragmented ");
+               break;
+       case IEEE80211_RADIOTAP_ANTENNA:
+               printf("antenna %d ", u.u8);
+               break;
+       case IEEE80211_RADIOTAP_TSFT:
+               printf("%" PRIu64 "us tsft ", u.u64);
+               break;
+       }
+       return 0;
+}
+
 static u_int
 ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen)
+{
+#define        BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
+#define        BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
+#define        BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
+#define        BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
+#define        BITNO_2(x) (((x) & 2) ? 1 : 0)
+#define        BIT(n)  (1 << n)
+#define        IS_EXTENDED(__p)        \
+           (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
+
+       struct cpack_state cpacker;
+       struct ieee80211_radiotap_header *hdr;
+       u_int32_t present, next_present;
+       u_int32_t *presentp, *last_presentp;
+       enum ieee80211_radiotap_type bit;
+       int bit0;
+       const u_char *iter;
+       u_int len;
+
+       if (caplen < sizeof(*hdr)) {
+               printf("[|802.11]");
+               return caplen;
+       }
+
+       hdr = (struct ieee80211_radiotap_header *)p;
+
+       len = EXTRACT_LE_16BITS(&hdr->it_len);
+
+       if (caplen < len) {
+               printf("[|802.11]");
+               return caplen;
+       }
+       for (last_presentp = &hdr->it_present;
+            IS_EXTENDED(last_presentp) &&
+            (u_char*)(last_presentp + 1) <= p + len;
+            last_presentp++);
+
+       /* are there more bitmap extensions than bytes in header? */
+       if (IS_EXTENDED(last_presentp)) {
+               printf("[|802.11]");
+               return caplen;
+       }
+
+       iter = (u_char*)(last_presentp + 1);
+
+       if (cpack_init(&cpacker, (u_int8_t*)iter, len - (iter - p)) != 0) {
+               /* XXX */
+               printf("[|802.11]");
+               return caplen;
+       }
+
+       for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
+            presentp++, bit0 += 32) {
+               for (present = EXTRACT_LE_32BITS(presentp); present;
+                    present = next_present) {
+                       /* clear the least significant bit that is set */
+                       next_present = present & (present - 1);
+
+                       /* extract the least significant bit that is set */
+                       bit = bit0 + BITNO_32(present ^ next_present);
+
+                       if (print_radiotap_field(&cpacker, bit) != 0)
+                               goto out;
+               }
+       }
+out:
+       return len + ieee802_11_print(p + len, length - len, caplen - len);
+#undef BITNO_32
+#undef BITNO_16
+#undef BITNO_8
+#undef BITNO_4
+#undef BITNO_2
+#undef BIT
+}
+
+static u_int
+ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
 {
        u_int32_t caphdr_len;
 
@@ -972,7 +1169,7 @@ prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
        }
 
        if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
-               return ieee802_11_radio_print(p, length, caplen);
+               return ieee802_11_avs_radio_print(p, length, caplen);
 
        if (caplen < PRISM_HDR_LEN) {
                printf("[|802.11]");