From: Guy Harris Date: Thu, 28 Jan 2016 20:52:36 +0000 (-0800) Subject: Make a half-hearted attempt to handle multiple presence words in radiotap. X-Git-Tag: libpcap-1.8.0-bp~64 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/b9b5924478fef194fcf1cac5d9d23cd5391fa278 Make a half-hearted attempt to handle multiple presence words in radiotap. 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. --- diff --git a/gencode.c b/gencode.c index 481c4d9c..ad1324b0 100644 --- 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;