diff options
-rw-r--r-- | capture_info.c | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee80211.c | 21 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee80211.h | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-radiotap.c | 68 |
4 files changed, 76 insertions, 18 deletions
diff --git a/capture_info.c b/capture_info.c index a385886295..d9bc8fbfcd 100644 --- a/capture_info.c +++ b/capture_info.c @@ -50,6 +50,7 @@ #include <epan/dissectors/packet-sll.h> #include <epan/dissectors/packet-tr.h> #include <epan/dissectors/packet-ieee80211.h> +#include <epan/dissectors/packet-radiotap.h> #include <epan/dissectors/packet-chdlc.h> #include <epan/dissectors/packet-prism.h> #include <epan/dissectors/packet-ipfc.h> @@ -191,6 +192,9 @@ capture_info_packet(packet_counts *counts, gint wtap_linktype, const guchar *pd, case WTAP_ENCAP_IEEE_802_11_WITH_RADIO: capture_ieee80211(pd, 0, caplen, counts); break; + case WTAP_ENCAP_IEEE_802_11_WLAN_RADIOTAP: + capture_radiotap(pd, 0, caplen, counts); + break; case WTAP_ENCAP_CHDLC: capture_chdlc(pd, 0, caplen, counts); break; diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c index e872a904a6..fae0b430c9 100644 --- a/epan/dissectors/packet-ieee80211.c +++ b/epan/dissectors/packet-ieee80211.c @@ -739,7 +739,8 @@ find_header_length (guint16 fcf) /* ************************************************************************* */ static void capture_ieee80211_common (const guchar * pd, int offset, int len, - packet_counts * ld, gboolean fixed_length_header) + packet_counts * ld, gboolean fixed_length_header, + gboolean datapad) { guint16 fcf, hdr_length; @@ -748,7 +749,7 @@ capture_ieee80211_common (const guchar * pd, int offset, int len, return; } - fcf = pletohs (&pd[0]); + fcf = pletohs (&pd[offset]); if (IS_PROTECTED(FCF_FLAGS(fcf))) { @@ -768,6 +769,8 @@ capture_ieee80211_common (const guchar * pd, int offset, int len, hdr_length = DATA_LONG_HDR_LEN; else hdr_length = find_header_length (fcf); + if (datapad) + hdr_length = roundup2(hdr_length, 4); /* I guess some bridges take Netware Ethernet_802_3 frames, which are 802.3 frames (with a length field rather than a type field, but with no 802.2 header in the payload), @@ -803,7 +806,17 @@ capture_ieee80211_common (const guchar * pd, int offset, int len, void capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld) { - capture_ieee80211_common (pd, offset, len, ld, FALSE); + capture_ieee80211_common (pd, offset, len, ld, FALSE, FALSE); +} + +/* + * Handle 802.11 with a variable-length link-layer header and data padding. + */ +void +capture_ieee80211_datapad (const guchar * pd, int offset, int len, + packet_counts * ld) +{ + capture_ieee80211_common (pd, offset, len, ld, FALSE, TRUE); } /* @@ -813,7 +826,7 @@ capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld) void capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld) { - capture_ieee80211_common (pd, offset, len, ld, TRUE); + capture_ieee80211_common (pd, offset, len, ld, TRUE, FALSE); } diff --git a/epan/dissectors/packet-ieee80211.h b/epan/dissectors/packet-ieee80211.h index 6ab638d2c4..3760c76f6d 100644 --- a/epan/dissectors/packet-ieee80211.h +++ b/epan/dissectors/packet-ieee80211.h @@ -28,6 +28,7 @@ */ void capture_ieee80211 (const guchar *, int, int, packet_counts *); +void capture_ieee80211_datapad (const guchar *, int, int, packet_counts *); void capture_ieee80211_fixed (const guchar *, int, int, packet_counts *); void ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, diff --git a/epan/dissectors/packet-radiotap.c b/epan/dissectors/packet-radiotap.c index 24cf9870e6..84ff2db803 100644 --- a/epan/dissectors/packet-radiotap.c +++ b/epan/dissectors/packet-radiotap.c @@ -156,23 +156,75 @@ static dissector_handle_t ieee80211_datapad_handle; static void dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +#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) + void capture_radiotap(const guchar *pd, int offset, int len, packet_counts *ld) { const struct ieee80211_radiotap_header *hdr; + guint16 it_len; + guint32 present; + guint8 rflags; + int rt_offset; if(!BYTES_ARE_IN_FRAME(offset, len, (int)sizeof(*hdr))) { ld->other ++; return; } hdr = (const struct ieee80211_radiotap_header *)pd; - if(!BYTES_ARE_IN_FRAME(offset, len, hdr->it_len)) { + it_len = pletohs(&hdr->it_len); + if(!BYTES_ARE_IN_FRAME(offset, len, it_len)) { ld->other ++; return; } + if(it_len > len) { + /* Header length is bigger than total packet length */ + ld->other ++; + return; + } + + if(it_len < sizeof(*hdr)) { + /* Header length is shorter than fixed-length portion of header */ + ld->other ++; + return; + } + + present = pletohl(&hdr->it_present); + rt_offset = sizeof(*hdr); + + rflags = 0; + + /* + * IEEE80211_RADIOTAP_TSFT is the lowest-order bit. + */ + if (present & BIT(IEEE80211_RADIOTAP_TSFT)) { + /* That field is present, and it's 8 bits long. */ + rt_offset += 8; + } + + /* + * IEEE80211_RADIOTAP_FLAGS is the next bit. + */ + if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) { + /* That field is present; fetch it. */ + if(!BYTES_ARE_IN_FRAME(rt_offset, len, 1)) { + ld->other ++; + return; + } + rflags = pd[rt_offset]; + } + /* 802.11 header follows */ - capture_ieee80211(pd, offset + hdr->it_len, len, ld); + if (rflags & IEEE80211_RADIOTAP_F_DATAPAD) + capture_ieee80211_datapad(pd, offset + it_len, len, ld); + else + capture_ieee80211(pd, offset + it_len, len, ld); } void @@ -314,12 +366,6 @@ ieee80211_mhz2ieee(int freq, int flags) static void dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { -#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) proto_tree *radiotap_tree = NULL; proto_tree *pt, *present_tree; proto_item *ti; @@ -507,12 +553,6 @@ dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) call_dissector((rflags & IEEE80211_RADIOTAP_F_DATAPAD) ? ieee80211_datapad_handle : ieee80211_handle, tvb_new_subset(tvb, length, -1, -1), pinfo, tree); -#undef BITNO_32 -#undef BITNO_16 -#undef BITNO_8 -#undef BITNO_4 -#undef BITNO_2 -#undef BIT } void |