]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-802_11.c
add support for AS-PIC cookies
[tcpdump] / print-802_11.c
index 9c5bde92bad5fd1eb8cc8ddc2fed2903820a3eb0..b4a1c7e94c61848186cf59113037c44f2195101f 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.27 2003-11-27 02:51:04 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.1 2005-04-20 19:32:41 guy 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) \
@@ -224,7 +229,7 @@ parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
  *********************************************************************************/
 
 static int
-handle_beacon(u_int16_t fc, const u_char *p)
+handle_beacon(const u_char *p)
 {
        struct mgmt_body_t pbody;
        int offset = 0;
@@ -257,7 +262,7 @@ handle_beacon(u_int16_t fc, const u_char *p)
 }
 
 static int
-handle_assoc_request(u_int16_t fc, const u_char *p)
+handle_assoc_request(const u_char *p)
 {
        struct mgmt_body_t pbody;
        int offset = 0;
@@ -282,7 +287,7 @@ handle_assoc_request(u_int16_t fc, const u_char *p)
 }
 
 static int
-handle_assoc_response(u_int16_t fc, const u_char *p)
+handle_assoc_response(const u_char *p)
 {
        struct mgmt_body_t pbody;
        int offset = 0;
@@ -310,7 +315,7 @@ handle_assoc_response(u_int16_t fc, const u_char *p)
 }
 
 static int
-handle_reassoc_request(u_int16_t fc, const u_char *p)
+handle_reassoc_request(const u_char *p)
 {
        struct mgmt_body_t pbody;
        int offset = 0;
@@ -338,14 +343,14 @@ handle_reassoc_request(u_int16_t fc, const u_char *p)
 }
 
 static int
-handle_reassoc_response(u_int16_t fc, const u_char *p)
+handle_reassoc_response(const u_char *p)
 {
        /* Same as a Association Reponse */
-       return handle_assoc_response(fc, p);
+       return handle_assoc_response(p);
 }
 
 static int
-handle_probe_request(u_int16_t fc, const u_char *p)
+handle_probe_request(const u_char *p)
 {
        struct mgmt_body_t  pbody;
        int offset = 0;
@@ -364,7 +369,7 @@ handle_probe_request(u_int16_t fc, const u_char *p)
 }
 
 static int
-handle_probe_response(u_int16_t fc, const u_char *p)
+handle_probe_response(const u_char *p)
 {
        struct mgmt_body_t  pbody;
        int offset = 0;
@@ -403,7 +408,7 @@ handle_atim(void)
 }
 
 static int
-handle_disassoc(u_int16_t fc, const u_char *p)
+handle_disassoc(const u_char *p)
 {
        struct mgmt_body_t  pbody;
 
@@ -421,7 +426,7 @@ handle_disassoc(u_int16_t fc, const u_char *p)
 }
 
 static int
-handle_auth(u_int16_t fc, const u_char *p)
+handle_auth(const u_char *p)
 {
        struct mgmt_body_t  pbody;
        int offset = 0;
@@ -465,8 +470,7 @@ handle_auth(u_int16_t fc, const u_char *p)
 }
 
 static int
-handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh,
-    const u_char *p)
+handle_deauth(const struct mgmt_header_t *pmh, const u_char *p)
 {
        struct mgmt_body_t  pbody;
        int offset = 0;
@@ -504,23 +508,23 @@ mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
 
        switch (FC_SUBTYPE(fc)) {
        case ST_ASSOC_REQUEST:
-               return handle_assoc_request(fc, p);
+               return handle_assoc_request(p);
        case ST_ASSOC_RESPONSE:
-               return handle_assoc_response(fc, p);
+               return handle_assoc_response(p);
        case ST_REASSOC_REQUEST:
-               return handle_reassoc_request(fc, p);
+               return handle_reassoc_request(p);
        case ST_REASSOC_RESPONSE:
-               return handle_reassoc_response(fc, p);
+               return handle_reassoc_response(p);
        case ST_PROBE_REQUEST:
-               return handle_probe_request(fc, p);
+               return handle_probe_request(p);
        case ST_PROBE_RESPONSE:
-               return handle_probe_response(fc, p);
+               return handle_probe_response(p);
        case ST_BEACON:
-               return handle_beacon(fc, p);
+               return handle_beacon(p);
        case ST_ATIM:
                return handle_atim();
        case ST_DISASSOC:
-               return handle_disassoc(fc, p);
+               return handle_disassoc(p);
        case ST_AUTH:
                if (!TTEST2(*p, 3))
                        return 0;
@@ -528,9 +532,9 @@ mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
                        printf("Authentication (Shared-Key)-3 ");
                        return wep_print(p);
                }
-               return handle_auth(fc, p);
+               return handle_auth(p);
        case ST_DEAUTH:
-               return handle_deauth(fc, pmh, p);
+               return handle_deauth(pmh, p);
                break;
        default:
                printf("Unhandled Management subtype(%x)",
@@ -911,7 +915,7 @@ ieee802_11_print(const u_char *p, u_int length, u_int caplen)
 /*
  * This is the top level routine of the printer.  'p' points
  * to the 802.11 header of the packet, 'h->ts' is the timestamp,
- * 'h->length' is the length of the packet off the wire, and 'h->caplen'
+ * 'h->len' is the length of the packet off the wire, and 'h->caplen'
  * is the number of bytes actually captured.
  */
 u_int
@@ -920,8 +924,201 @@ 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_int8(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 = (enum ieee80211_radiotap_type)
+                           (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;
 
@@ -973,7 +1170,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]");