]> The Tcpdump Group git mirrors - libpcap/commitdiff
Make a half-hearted attempt to handle multiple presence words in radiotap.
authorGuy Harris <[email protected]>
Thu, 28 Jan 2016 20:52:36 +0000 (12:52 -0800)
committerGuy Harris <[email protected]>
Thu, 28 Jan 2016 20:52:36 +0000 (12:52 -0800)
Just assume that anything modern enough to have multiple presence words
is also modern enough not to "helpfully" insert padding between the
802.11 header and the 802.11 payload.

Addresses GitHub issue the-tcpdump-group/tcpdump#497.

gencode.c

index 481c4d9c358a5ade099ba458a907502b837c8139..ad1324b09d6270e8be8ce5c9ca01e11129db7d6b 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -2448,8 +2448,9 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
        struct slist *sjset_data_frame_1;
        struct slist *sjset_data_frame_2;
        struct slist *sjset_qos;
-       struct slist *sjset_radiotap_flags;
-       struct slist *sjset_radiotap_tsft;
+       struct slist *sjset_radiotap_flags_present;
+       struct slist *sjset_radiotap_ext_present;
+       struct slist *sjset_radiotap_tsft_present;
        struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
        struct slist *s_roundup;
 
@@ -2565,32 +2566,54 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
         * little-endian, so we byte-swap all of the values
         * we test against, as they will be loaded as big-endian
         * values.
+        *
+        * XXX - in the general case, we would have to scan through
+        * *all* the presence bits, if there's more than one word of
+        * presence bits.  That would require a loop, meaning that
+        * we wouldn't be able to run the filter in the kernel.
+        *
+        * We assume here that the Atheros adapters that insert the
+        * annoying padding don't have multiple antennae and therefore
+        * do not generate radiotap headers with multiple presence words.
         */
        if (linktype == DLT_IEEE802_11_RADIO) {
                /*
                 * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
-                * in the presence flag?
+                * in the first presence flag word?
                 */
                sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W);
                s2->s.k = 4;
                sappend(s, s2);
 
-               sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
-               sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
-               sappend(s, sjset_radiotap_flags);
+               sjset_radiotap_flags_present = new_stmt(JMP(BPF_JSET));
+               sjset_radiotap_flags_present->s.k = SWAPLONG(0x00000002);
+               sappend(s, sjset_radiotap_flags_present);
 
                /*
                 * If not, skip all of this.
                 */
-               sjset_radiotap_flags->s.jf = snext;
+               sjset_radiotap_flags_present->s.jf = snext;
+
+               /*
+                * Otherwise, is the "extension" bit set in that word?
+                */
+               sjset_radiotap_ext_present = new_stmt(JMP(BPF_JSET));
+               sjset_radiotap_ext_present->s.k = SWAPLONG(0x80000000);
+               sappend(s, sjset_radiotap_ext_present);
+               sjset_radiotap_flags_present->s.jt = sjset_radiotap_ext_present;
+
+               /*
+                * If so, skip all of this.
+                */
+               sjset_radiotap_ext_present->s.jt = snext;
 
                /*
                 * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
                 */
-               sjset_radiotap_tsft = sjset_radiotap_flags->s.jt =
-                   new_stmt(JMP(BPF_JSET));
-               sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
-               sappend(s, sjset_radiotap_tsft);
+               sjset_radiotap_tsft_present = new_stmt(JMP(BPF_JSET));
+               sjset_radiotap_tsft_present->s.k = SWAPLONG(0x00000001);
+               sappend(s, sjset_radiotap_tsft_present);
+               sjset_radiotap_ext_present->s.jf = sjset_radiotap_tsft_present;
 
                /*
                 * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
@@ -2601,9 +2624,10 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
                 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
                 * is set.
                 */
-               sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+               s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
                s2->s.k = 16;
                sappend(s, s2);
+               sjset_radiotap_tsft_present->s.jt = s2;
 
                sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
                sjset_tsft_datapad->s.k = 0x20;
@@ -2617,9 +2641,10 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext)
                 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
                 * is set.
                 */
-               sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+               s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
                s2->s.k = 8;
                sappend(s, s2);
+               sjset_radiotap_tsft_present->s.jf = s2;
 
                sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
                sjset_notsft_datapad->s.k = 0x20;