aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Marcus Clarke <marcus@FreeBSD.org>2005-12-09 04:03:57 +0000
committerJoe Marcus Clarke <marcus@FreeBSD.org>2005-12-09 04:03:57 +0000
commitd8fea3bfc456e80347df2b3a8dcc20f39b020626 (patch)
tree31f069b75946d8dd073d38ad198e5e079e3c6265
parent2bf362529454d4eb50ed9cf3b35fc35f502d5243 (diff)
downloadports-d8fea3bfc456e80347df2b3a8dcc20f39b020626.tar.gz
ports-d8fea3bfc456e80347df2b3a8dcc20f39b020626.zip
* Fix a bug in caclulating the 802.11 header length for QoS data frames
(way bad regression from previous code) * Add support for packets w/ data padding between the 802.11 header and the payload (as indicated in the radiotap flags) * Add support for handling FCS indication in the radiotap flags * Fix display of TSF (previous code was not byte swapping) * Update ieee80211_mhz2ieee in radiotap.c to handle more channels * Nuke some #if 0 code leftover in radiotap.c Submitted by: sam
Notes
Notes: svn path=/head/; revision=150702
-rw-r--r--net/ethereal/Makefile2
-rw-r--r--net/ethereal/files/patch-epan_dissectors_packet-ieee80211.c240
-rw-r--r--net/ethereal/files/patch-epan_dissectors_packet-radiotap.c206
-rw-r--r--net/wireshark/Makefile2
-rw-r--r--net/wireshark/files/patch-epan_dissectors_packet-ieee80211.c240
-rw-r--r--net/wireshark/files/patch-epan_dissectors_packet-radiotap.c206
6 files changed, 894 insertions, 2 deletions
diff --git a/net/ethereal/Makefile b/net/ethereal/Makefile
index 0505bf786d11..82ac483e7908 100644
--- a/net/ethereal/Makefile
+++ b/net/ethereal/Makefile
@@ -7,7 +7,7 @@
PORTNAME= ethereal
PORTVERSION= 0.10.13
-PORTREVISION= 2
+PORTREVISION= 3
CATEGORIES= net ipv6
MASTER_SITES= ${MASTER_SITE_SOURCEFORGE} \
ftp://ftp.ethereal.com/pub/ethereal/all-versions/
diff --git a/net/ethereal/files/patch-epan_dissectors_packet-ieee80211.c b/net/ethereal/files/patch-epan_dissectors_packet-ieee80211.c
new file mode 100644
index 000000000000..e2e1179952f5
--- /dev/null
+++ b/net/ethereal/files/patch-epan_dissectors_packet-ieee80211.c
@@ -0,0 +1,240 @@
+--- epan/dissectors/packet-ieee80211.c.orig Mon Oct 10 06:23:01 2005
++++ epan/dissectors/packet-ieee80211.c Tue Dec 6 18:53:33 2005
+@@ -74,6 +74,10 @@
+ #include <ctype.h>
+ #include "isprint.h"
+
++#ifndef roundup2
++#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
++#endif
++
+ /* Defragment fragmented 802.11 datagrams */
+ static gboolean wlan_defragment = TRUE;
+
+@@ -635,11 +639,11 @@
+ case DATA_FRAME:
+ len = (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
+ DATA_SHORT_HDR_LEN;
+- if( IS_DATA_QOS(fcf))
++ if (fcf & 0x80)
+ return len + 2;
+ else
+ return len;
+-
++
+ default:
+ return 4; /* XXX */
+ }
+@@ -1922,6 +1926,23 @@
+ ether_to_str(addr));
+ }
+
++static guint32
++crc32_802_tvb_padded(tvbuff_t *tvb, guint hdr_len, guint hdr_size, guint len)
++{
++ guint32 c_crc;
++
++ c_crc = crc32_ccitt_tvb(tvb, hdr_len);
++ c_crc = crc32_ccitt_seed(tvb_get_ptr(tvb, hdr_size, len), len, ~c_crc);
++
++ /* Byte reverse. */
++ c_crc = ((unsigned char)(c_crc>>0)<<24) |
++ ((unsigned char)(c_crc>>8)<<16) |
++ ((unsigned char)(c_crc>>16)<<8) |
++ ((unsigned char)(c_crc>>24)<<0);
++
++ return ( c_crc );
++}
++
+ typedef enum {
+ ENCAP_802_2,
+ ENCAP_IPX,
+@@ -1935,7 +1956,7 @@
+ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree, gboolean fixed_length_header,
+ gboolean has_radio_information, gint fcs_len,
+- gboolean wlan_broken_fc)
++ gboolean wlan_broken_fc, gboolean datapad)
+ {
+ guint16 fcf, flags, frame_type_subtype;
+ guint16 seq_control;
+@@ -1950,7 +1971,7 @@
+ proto_tree *hdr_tree = NULL;
+ proto_tree *flag_tree;
+ proto_tree *fc_tree;
+- guint16 hdr_len;
++ guint16 hdr_len, ohdr_len;
+ gboolean has_fcs;
+ gint len, reported_len, ivlen;
+ gboolean save_fragmented;
+@@ -1994,6 +2015,9 @@
+ hdr_len = DATA_LONG_HDR_LEN;
+ else
+ hdr_len = find_header_length (fcf);
++ ohdr_len = hdr_len;
++ if (datapad)
++ hdr_len = roundup2(hdr_len, 4);
+ frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
+
+ /*if (check_col (pinfo->cinfo, COL_INFO))
+@@ -2495,9 +2519,13 @@
+ reported_len -= 4;
+ if (tree)
+ {
+- guint32 fcs = crc32_802_tvb(tvb, hdr_len + len);
+ guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
++ guint32 fcs;
+
++ if (datapad)
++ fcs = crc32_802_tvb_padded(tvb, ohdr_len, hdr_len, len);
++ else
++ fcs = crc32_802_tvb(tvb, hdr_len + len);
+ if (fcs == sent_fcs)
+ proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
+ hdr_len + len, 4, sent_fcs,
+@@ -2530,35 +2558,46 @@
+ proto_item *qos_fields;
+ proto_tree *qos_tree;
+
++ guint16 qosoff;
+ guint16 qos_control;
+ guint16 qos_priority;
+ guint16 qos_ack_policy;
+ guint16 qos_eosp;
+ guint16 qos_field_content;
+
+- qos_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len - 2, 2,
++ /*
++ * We calculate the offset to the QoS header data as
++ * an offset relative to the end of the header. But
++ * when the header has been padded to align the data
++ * this must be done relative to true header size, not
++ * the padded/aligned value. To simplify this work we
++ * stash the original header size in ohdr_len instead
++ * of recalculating it.
++ */
++ qosoff = ohdr_len - 2;
++ qos_fields = proto_tree_add_text(hdr_tree, tvb, qosoff, 2,
+ "QoS parameters");
+ qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters);
+
+- qos_control = tvb_get_letohs(tvb, hdr_len - 2);
++ qos_control = tvb_get_letohs(tvb, qosoff + 0);
+ qos_priority = COOK_QOS_PRIORITY(qos_control);
+ qos_ack_policy = COOK_QOS_ACK_POLICY(qos_control);
+ qos_eosp = COOK_QOS_EOSP(qos_control);
+ qos_field_content = COOK_QOS_FIELD_CONTENT( qos_control);
+
+ proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
+- hdr_len - 2, 2, qos_priority,
++ qosoff, 2, qos_priority,
+ "Priority: %d (%s) (%s)",
+ qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]);
+
+ if(flags & FLAG_FROM_DS) {
+ proto_tree_add_boolean (qos_tree, hf_qos_eosp, tvb,
+- hdr_len - 2, 1, qos_eosp);
++ qosoff, 1, qos_eosp);
+
+ if(IS_DATA_CF_POLL(frame_type_subtype)) {
+ /* txop limit */
+ proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
+- hdr_len - 1, 1, qos_field_content, "TXOP Limit: %d ", qos_field_content);
++ qosoff + 1, 1, qos_field_content, "TXOP Limit: %d ", qos_field_content);
+
+ }else {
+ /* qap ps buffer state */
+@@ -2572,7 +2611,7 @@
+ buf_ac = COOK_PS_BUF_AC(qos_field_content); /*access category */
+ buf_load = COOK_PS_BUF_LOAD(qos_field_content);
+
+- qos_ps_buf_state_fields = proto_tree_add_text(qos_tree, tvb, hdr_len - 1, 1,
++ qos_ps_buf_state_fields = proto_tree_add_text(qos_tree, tvb, qosoff + 1, 1,
+ "QAP PS Buffer State: 0x%x", qos_field_content);
+ qos_ps_buf_state_tree = proto_item_add_subtree (qos_ps_buf_state_fields, ett_qos_ps_buf_state);
+
+@@ -2581,25 +2620,25 @@
+ 1, 1, buf_state);
+
+ proto_tree_add_uint_format (qos_ps_buf_state_tree, hf_qos_buf_ac, tvb,
+- hdr_len - 1, 1, buf_ac, "Priority: %d (%s)",
++ qosoff + 1, 1, buf_ac, "Priority: %d (%s)",
+ buf_ac, wme_acs[buf_ac]);
+
+ proto_tree_add_uint_format (qos_ps_buf_state_tree, hf_qos_buf_load, tvb,
+- hdr_len - 1, 1, buf_load, "Buffered load: %d ", (buf_load * 4096));
++ qosoff + 1, 1, buf_load, "Buffered load: %d ", (buf_load * 4096));
+ */
+
+ }
+ } else if(qos_eosp) {
+ /* txop limit requested */
+ proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
+- hdr_len - 1, 1, qos_field_content, "Queue Size: %d ", (qos_field_content * 254));
++ qosoff + 1, 1, qos_field_content, "Queue Size: %d ", (qos_field_content * 254));
+ } else {
+ /* queue size */
+ proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
+- hdr_len - 1, 1, qos_field_content, "TXOP Limit Requested: %d ", qos_field_content);
++ qosoff + 1, 1, qos_field_content, "TXOP Limit Requested: %d ", qos_field_content);
+ }
+
+- proto_tree_add_uint (qos_tree, hf_qos_ack_policy, tvb, hdr_len - 2, 1,
++ proto_tree_add_uint (qos_tree, hf_qos_ack_policy, tvb, qosoff, 1,
+ qos_ack_policy);
+
+ } /* end of qos control field */
+@@ -2957,7 +2996,17 @@
+ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+ {
+ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
+- pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
++ pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE);
++}
++
++/*
++ * Dissect 802.11 with a variable-length link-layer header and data padding.
++ */
++static void
++dissect_ieee80211_datapad (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
++{
++ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
++ pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, TRUE);
+ }
+
+ /*
+@@ -2968,7 +3017,7 @@
+ dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+ {
+ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE,
+- pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
++ pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE);
+ }
+
+ /*
+@@ -2979,7 +3028,7 @@
+ static void
+ dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+ {
+- dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, 0, TRUE);
++ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, 0, TRUE, FALSE);
+ }
+
+ /*
+@@ -2989,7 +3038,7 @@
+ static void
+ dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+ {
+- dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, 0, FALSE);
++ dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, 0, FALSE, FALSE);
+ }
+
+ static void
+@@ -3773,6 +3822,7 @@
+ register_dissector("wlan", dissect_ieee80211, proto_wlan);
+ register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
+ register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
++ register_dissector("wlan_datapad", dissect_ieee80211_datapad, proto_wlan);
+ register_init_routine(wlan_defragment_init);
+
+ wlan_tap = register_tap("wlan");
diff --git a/net/ethereal/files/patch-epan_dissectors_packet-radiotap.c b/net/ethereal/files/patch-epan_dissectors_packet-radiotap.c
new file mode 100644
index 000000000000..ece82f94e19e
--- /dev/null
+++ b/net/ethereal/files/patch-epan_dissectors_packet-radiotap.c
@@ -0,0 +1,206 @@
+--- epan/dissectors/packet-radiotap.c.orig Mon Oct 10 06:23:07 2005
++++ epan/dissectors/packet-radiotap.c Tue Dec 6 18:34:19 2005
+@@ -73,7 +73,6 @@
+ IEEE80211_RADIOTAP_ANTENNA = 11,
+ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+ IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+- IEEE80211_RADIOTAP_FCS = 14,
+ IEEE80211_RADIOTAP_EXT = 31
+ };
+
+@@ -121,6 +120,11 @@
+ #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
+ * with fragmentation
+ */
++#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
++#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
++ * 802.11 header and payload
++ * (to 32-bit boundary)
++ */
+
+ /* protocol */
+ static int proto_radiotap = -1;
+@@ -140,11 +144,14 @@
+ static int hf_radiotap_db_antnoise = -1;
+ static int hf_radiotap_txpower = -1;
+ static int hf_radiotap_preamble = -1;
++static int hf_radiotap_fcs = -1;
++static int hf_radiotap_datapad = -1;
+
+ static gint ett_radiotap = -1;
+ static gint ett_radiotap_present = -1;
+
+ static dissector_handle_t ieee80211_handle;
++static dissector_handle_t ieee80211_datapad_handle;
+
+ static void
+ dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+@@ -190,6 +197,12 @@
+ { 0, NULL },
+ };
+
++ static const value_string truefalse_type[] = {
++ { 0, "False" },
++ { 1, "True" },
++ { 0, NULL },
++ };
++
+ static hf_register_info hf[] = {
+ { &hf_radiotap_version,
+ { "Header revision", "radiotap.version",
+@@ -208,6 +221,14 @@
+ { "Preamble", "radiotap.flags.preamble",
+ FT_UINT32, BASE_DEC, VALS(preamble_type), 0x0, "", HFILL } },
+
++ /* XXX for debugging */
++ { &hf_radiotap_fcs,
++ { "FCS", "radiotap.flags.fcs",
++ FT_UINT32, BASE_DEC, VALS(truefalse_type), 0x0, "", HFILL } },
++ { &hf_radiotap_datapad,
++ { "DATAPAD", "radiotap.flags.datapad",
++ FT_UINT32, BASE_DEC, VALS(truefalse_type), 0x0, "", HFILL } },
++
+ { &hf_radiotap_mactime,
+ { "MAC timestamp", "radiotap.mactime",
+ FT_UINT64, BASE_DEC, NULL, 0x0, "", HFILL } },
+@@ -257,6 +278,7 @@
+ static int
+ ieee80211_mhz2ieee(int freq, int flags)
+ {
++#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990)
+ if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */
+ if (freq == 2484)
+ return 14;
+@@ -265,16 +287,28 @@
+ else
+ return 15 + ((freq - 2512) / 20);
+ } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */
+- return (freq - 5000) / 5;
++ if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq))
++ return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
++ if (freq <= 5000)
++ return (freq - 4000) / 5;
++ else
++ return (freq - 5000) / 5;
+ } else { /* either, guess */
+ if (freq == 2484)
+ return 14;
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+- if (freq < 5000)
+- return 15 + ((freq - 2512) / 20);
++ if (freq < 5000) {
++ if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq))
++ return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400)/5;
++ else if (freq > 4900)
++ return (freq - 4000) / 5;
++ else
++ return 15 + ((freq - 2512) / 20);
++ }
+ return (freq - 5000) / 5;
+ }
++#undef IS_CHAN_IN_PUBLIC_SAFETY_BAND
+ }
+
+ static void
+@@ -294,7 +328,7 @@
+ guint32 length;
+ guint32 rate, freq, flags;
+ gint8 dbm;
+- guint8 db;
++ guint8 db, rflags;
+ guint32 present, next_present;
+ int bit;
+
+@@ -334,6 +368,7 @@
+ */
+ offset += sizeof(struct ieee80211_radiotap_header);
+
++ rflags = 0;
+ for (; present; present = next_present) {
+ /* clear the least significant bit that is set */
+ next_present = present & (present - 1);
+@@ -344,45 +379,16 @@
+ switch (bit) {
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (tree) {
++ rflags = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(radiotap_tree, hf_radiotap_preamble,
+- tvb, 0, 0, (tvb_get_guint8(tvb, offset) &
+- IEEE80211_RADIOTAP_F_SHORTPRE) != 0);
++ tvb, 0, 0, (rflags&IEEE80211_RADIOTAP_F_SHORTPRE) != 0);
++ proto_tree_add_uint(radiotap_tree, hf_radiotap_fcs,
++ tvb, 0, 0, (rflags&IEEE80211_RADIOTAP_F_FCS) != 0);
++ proto_tree_add_uint(radiotap_tree, hf_radiotap_datapad,
++ tvb, 0, 0, (rflags&IEEE80211_RADIOTAP_F_DATAPAD) != 0);
+ }
+ offset++;
+ /* XXX CFP, WEP, FRAG */
+-#if 0
+- capability = tvb_get_letohs (tvb, offset);
+-
+- cap_item = proto_tree_add_uint_format (tree, ff_capture,
+- tvb, offset, 2,
+- capability,
+- "Capability Information: 0x%04X",
+- capability);
+- cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
+- proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
+- capability);
+- if (ESS_SET (capability) != 0) /* This is an AP */
+- proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
+- capability);
+-
+- else /* This is a STA */
+- proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
+- capability);
+-#endif
+ break;
+ case IEEE80211_RADIOTAP_RATE:
+ rate = tvb_get_guint8(tvb, offset) & 0x7f;
+@@ -480,8 +486,8 @@
+ break;
+ case IEEE80211_RADIOTAP_TSFT:
+ if (tree) {
+- proto_tree_add_item(radiotap_tree, hf_radiotap_mactime,
+- tvb, offset, 8, FALSE);
++ proto_tree_add_uint64(radiotap_tree, hf_radiotap_mactime,
++ tvb, offset, 8, tvb_get_letoh64(tvb, offset));
+ }
+ offset+=8;
+ break;
+@@ -495,8 +501,11 @@
+ }
+ }
+
++ if (rflags & IEEE80211_RADIOTAP_F_FCS)
++ pinfo->pseudo_header->ieee_802_11.fcs_len = 4;
+ /* dissect the 802.11 header next */
+- call_dissector(ieee80211_handle,
++ 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
+@@ -513,6 +522,7 @@
+
+ /* handle for 802.11 dissector */
+ ieee80211_handle = find_dissector("wlan");
++ ieee80211_datapad_handle = find_dissector("wlan_datapad");
+
+ radiotap_handle = create_dissector_handle(dissect_radiotap, proto_radiotap);
+
diff --git a/net/wireshark/Makefile b/net/wireshark/Makefile
index 0505bf786d11..82ac483e7908 100644
--- a/net/wireshark/Makefile
+++ b/net/wireshark/Makefile
@@ -7,7 +7,7 @@
PORTNAME= ethereal
PORTVERSION= 0.10.13
-PORTREVISION= 2
+PORTREVISION= 3
CATEGORIES= net ipv6
MASTER_SITES= ${MASTER_SITE_SOURCEFORGE} \
ftp://ftp.ethereal.com/pub/ethereal/all-versions/
diff --git a/net/wireshark/files/patch-epan_dissectors_packet-ieee80211.c b/net/wireshark/files/patch-epan_dissectors_packet-ieee80211.c
new file mode 100644
index 000000000000..e2e1179952f5
--- /dev/null
+++ b/net/wireshark/files/patch-epan_dissectors_packet-ieee80211.c
@@ -0,0 +1,240 @@
+--- epan/dissectors/packet-ieee80211.c.orig Mon Oct 10 06:23:01 2005
++++ epan/dissectors/packet-ieee80211.c Tue Dec 6 18:53:33 2005
+@@ -74,6 +74,10 @@
+ #include <ctype.h>
+ #include "isprint.h"
+
++#ifndef roundup2
++#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
++#endif
++
+ /* Defragment fragmented 802.11 datagrams */
+ static gboolean wlan_defragment = TRUE;
+
+@@ -635,11 +639,11 @@
+ case DATA_FRAME:
+ len = (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
+ DATA_SHORT_HDR_LEN;
+- if( IS_DATA_QOS(fcf))
++ if (fcf & 0x80)
+ return len + 2;
+ else
+ return len;
+-
++
+ default:
+ return 4; /* XXX */
+ }
+@@ -1922,6 +1926,23 @@
+ ether_to_str(addr));
+ }
+
++static guint32
++crc32_802_tvb_padded(tvbuff_t *tvb, guint hdr_len, guint hdr_size, guint len)
++{
++ guint32 c_crc;
++
++ c_crc = crc32_ccitt_tvb(tvb, hdr_len);
++ c_crc = crc32_ccitt_seed(tvb_get_ptr(tvb, hdr_size, len), len, ~c_crc);
++
++ /* Byte reverse. */
++ c_crc = ((unsigned char)(c_crc>>0)<<24) |
++ ((unsigned char)(c_crc>>8)<<16) |
++ ((unsigned char)(c_crc>>16)<<8) |
++ ((unsigned char)(c_crc>>24)<<0);
++
++ return ( c_crc );
++}
++
+ typedef enum {
+ ENCAP_802_2,
+ ENCAP_IPX,
+@@ -1935,7 +1956,7 @@
+ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree, gboolean fixed_length_header,
+ gboolean has_radio_information, gint fcs_len,
+- gboolean wlan_broken_fc)
++ gboolean wlan_broken_fc, gboolean datapad)
+ {
+ guint16 fcf, flags, frame_type_subtype;
+ guint16 seq_control;
+@@ -1950,7 +1971,7 @@
+ proto_tree *hdr_tree = NULL;
+ proto_tree *flag_tree;
+ proto_tree *fc_tree;
+- guint16 hdr_len;
++ guint16 hdr_len, ohdr_len;
+ gboolean has_fcs;
+ gint len, reported_len, ivlen;
+ gboolean save_fragmented;
+@@ -1994,6 +2015,9 @@
+ hdr_len = DATA_LONG_HDR_LEN;
+ else
+ hdr_len = find_header_length (fcf);
++ ohdr_len = hdr_len;
++ if (datapad)
++ hdr_len = roundup2(hdr_len, 4);
+ frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
+
+ /*if (check_col (pinfo->cinfo, COL_INFO))
+@@ -2495,9 +2519,13 @@
+ reported_len -= 4;
+ if (tree)
+ {
+- guint32 fcs = crc32_802_tvb(tvb, hdr_len + len);
+ guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
++ guint32 fcs;
+
++ if (datapad)
++ fcs = crc32_802_tvb_padded(tvb, ohdr_len, hdr_len, len);
++ else
++ fcs = crc32_802_tvb(tvb, hdr_len + len);
+ if (fcs == sent_fcs)
+ proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
+ hdr_len + len, 4, sent_fcs,
+@@ -2530,35 +2558,46 @@
+ proto_item *qos_fields;
+ proto_tree *qos_tree;
+
++ guint16 qosoff;
+ guint16 qos_control;
+ guint16 qos_priority;
+ guint16 qos_ack_policy;
+ guint16 qos_eosp;
+ guint16 qos_field_content;
+
+- qos_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len - 2, 2,
++ /*
++ * We calculate the offset to the QoS header data as
++ * an offset relative to the end of the header. But
++ * when the header has been padded to align the data
++ * this must be done relative to true header size, not
++ * the padded/aligned value. To simplify this work we
++ * stash the original header size in ohdr_len instead
++ * of recalculating it.
++ */
++ qosoff = ohdr_len - 2;
++ qos_fields = proto_tree_add_text(hdr_tree, tvb, qosoff, 2,
+ "QoS parameters");
+ qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters);
+
+- qos_control = tvb_get_letohs(tvb, hdr_len - 2);
++ qos_control = tvb_get_letohs(tvb, qosoff + 0);
+ qos_priority = COOK_QOS_PRIORITY(qos_control);
+ qos_ack_policy = COOK_QOS_ACK_POLICY(qos_control);
+ qos_eosp = COOK_QOS_EOSP(qos_control);
+ qos_field_content = COOK_QOS_FIELD_CONTENT( qos_control);
+
+ proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
+- hdr_len - 2, 2, qos_priority,
++ qosoff, 2, qos_priority,
+ "Priority: %d (%s) (%s)",
+ qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]);
+
+ if(flags & FLAG_FROM_DS) {
+ proto_tree_add_boolean (qos_tree, hf_qos_eosp, tvb,
+- hdr_len - 2, 1, qos_eosp);
++ qosoff, 1, qos_eosp);
+
+ if(IS_DATA_CF_POLL(frame_type_subtype)) {
+ /* txop limit */
+ proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
+- hdr_len - 1, 1, qos_field_content, "TXOP Limit: %d ", qos_field_content);
++ qosoff + 1, 1, qos_field_content, "TXOP Limit: %d ", qos_field_content);
+
+ }else {
+ /* qap ps buffer state */
+@@ -2572,7 +2611,7 @@
+ buf_ac = COOK_PS_BUF_AC(qos_field_content); /*access category */
+ buf_load = COOK_PS_BUF_LOAD(qos_field_content);
+
+- qos_ps_buf_state_fields = proto_tree_add_text(qos_tree, tvb, hdr_len - 1, 1,
++ qos_ps_buf_state_fields = proto_tree_add_text(qos_tree, tvb, qosoff + 1, 1,
+ "QAP PS Buffer State: 0x%x", qos_field_content);
+ qos_ps_buf_state_tree = proto_item_add_subtree (qos_ps_buf_state_fields, ett_qos_ps_buf_state);
+
+@@ -2581,25 +2620,25 @@
+ 1, 1, buf_state);
+
+ proto_tree_add_uint_format (qos_ps_buf_state_tree, hf_qos_buf_ac, tvb,
+- hdr_len - 1, 1, buf_ac, "Priority: %d (%s)",
++ qosoff + 1, 1, buf_ac, "Priority: %d (%s)",
+ buf_ac, wme_acs[buf_ac]);
+
+ proto_tree_add_uint_format (qos_ps_buf_state_tree, hf_qos_buf_load, tvb,
+- hdr_len - 1, 1, buf_load, "Buffered load: %d ", (buf_load * 4096));
++ qosoff + 1, 1, buf_load, "Buffered load: %d ", (buf_load * 4096));
+ */
+
+ }
+ } else if(qos_eosp) {
+ /* txop limit requested */
+ proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
+- hdr_len - 1, 1, qos_field_content, "Queue Size: %d ", (qos_field_content * 254));
++ qosoff + 1, 1, qos_field_content, "Queue Size: %d ", (qos_field_content * 254));
+ } else {
+ /* queue size */
+ proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
+- hdr_len - 1, 1, qos_field_content, "TXOP Limit Requested: %d ", qos_field_content);
++ qosoff + 1, 1, qos_field_content, "TXOP Limit Requested: %d ", qos_field_content);
+ }
+
+- proto_tree_add_uint (qos_tree, hf_qos_ack_policy, tvb, hdr_len - 2, 1,
++ proto_tree_add_uint (qos_tree, hf_qos_ack_policy, tvb, qosoff, 1,
+ qos_ack_policy);
+
+ } /* end of qos control field */
+@@ -2957,7 +2996,17 @@
+ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+ {
+ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
+- pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
++ pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE);
++}
++
++/*
++ * Dissect 802.11 with a variable-length link-layer header and data padding.
++ */
++static void
++dissect_ieee80211_datapad (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
++{
++ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
++ pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, TRUE);
+ }
+
+ /*
+@@ -2968,7 +3017,7 @@
+ dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+ {
+ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE,
+- pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
++ pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE);
+ }
+
+ /*
+@@ -2979,7 +3028,7 @@
+ static void
+ dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+ {
+- dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, 0, TRUE);
++ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, 0, TRUE, FALSE);
+ }
+
+ /*
+@@ -2989,7 +3038,7 @@
+ static void
+ dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+ {
+- dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, 0, FALSE);
++ dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, 0, FALSE, FALSE);
+ }
+
+ static void
+@@ -3773,6 +3822,7 @@
+ register_dissector("wlan", dissect_ieee80211, proto_wlan);
+ register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
+ register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
++ register_dissector("wlan_datapad", dissect_ieee80211_datapad, proto_wlan);
+ register_init_routine(wlan_defragment_init);
+
+ wlan_tap = register_tap("wlan");
diff --git a/net/wireshark/files/patch-epan_dissectors_packet-radiotap.c b/net/wireshark/files/patch-epan_dissectors_packet-radiotap.c
new file mode 100644
index 000000000000..ece82f94e19e
--- /dev/null
+++ b/net/wireshark/files/patch-epan_dissectors_packet-radiotap.c
@@ -0,0 +1,206 @@
+--- epan/dissectors/packet-radiotap.c.orig Mon Oct 10 06:23:07 2005
++++ epan/dissectors/packet-radiotap.c Tue Dec 6 18:34:19 2005
+@@ -73,7 +73,6 @@
+ IEEE80211_RADIOTAP_ANTENNA = 11,
+ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+ IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+- IEEE80211_RADIOTAP_FCS = 14,
+ IEEE80211_RADIOTAP_EXT = 31
+ };
+
+@@ -121,6 +120,11 @@
+ #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
+ * with fragmentation
+ */
++#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
++#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
++ * 802.11 header and payload
++ * (to 32-bit boundary)
++ */
+
+ /* protocol */
+ static int proto_radiotap = -1;
+@@ -140,11 +144,14 @@
+ static int hf_radiotap_db_antnoise = -1;
+ static int hf_radiotap_txpower = -1;
+ static int hf_radiotap_preamble = -1;
++static int hf_radiotap_fcs = -1;
++static int hf_radiotap_datapad = -1;
+
+ static gint ett_radiotap = -1;
+ static gint ett_radiotap_present = -1;
+
+ static dissector_handle_t ieee80211_handle;
++static dissector_handle_t ieee80211_datapad_handle;
+
+ static void
+ dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+@@ -190,6 +197,12 @@
+ { 0, NULL },
+ };
+
++ static const value_string truefalse_type[] = {
++ { 0, "False" },
++ { 1, "True" },
++ { 0, NULL },
++ };
++
+ static hf_register_info hf[] = {
+ { &hf_radiotap_version,
+ { "Header revision", "radiotap.version",
+@@ -208,6 +221,14 @@
+ { "Preamble", "radiotap.flags.preamble",
+ FT_UINT32, BASE_DEC, VALS(preamble_type), 0x0, "", HFILL } },
+
++ /* XXX for debugging */
++ { &hf_radiotap_fcs,
++ { "FCS", "radiotap.flags.fcs",
++ FT_UINT32, BASE_DEC, VALS(truefalse_type), 0x0, "", HFILL } },
++ { &hf_radiotap_datapad,
++ { "DATAPAD", "radiotap.flags.datapad",
++ FT_UINT32, BASE_DEC, VALS(truefalse_type), 0x0, "", HFILL } },
++
+ { &hf_radiotap_mactime,
+ { "MAC timestamp", "radiotap.mactime",
+ FT_UINT64, BASE_DEC, NULL, 0x0, "", HFILL } },
+@@ -257,6 +278,7 @@
+ static int
+ ieee80211_mhz2ieee(int freq, int flags)
+ {
++#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990)
+ if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */
+ if (freq == 2484)
+ return 14;
+@@ -265,16 +287,28 @@
+ else
+ return 15 + ((freq - 2512) / 20);
+ } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */
+- return (freq - 5000) / 5;
++ if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq))
++ return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
++ if (freq <= 5000)
++ return (freq - 4000) / 5;
++ else
++ return (freq - 5000) / 5;
+ } else { /* either, guess */
+ if (freq == 2484)
+ return 14;
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+- if (freq < 5000)
+- return 15 + ((freq - 2512) / 20);
++ if (freq < 5000) {
++ if (IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq))
++ return ((freq * 10) + (((freq % 5) == 2) ? 5 : 0) - 49400)/5;
++ else if (freq > 4900)
++ return (freq - 4000) / 5;
++ else
++ return 15 + ((freq - 2512) / 20);
++ }
+ return (freq - 5000) / 5;
+ }
++#undef IS_CHAN_IN_PUBLIC_SAFETY_BAND
+ }
+
+ static void
+@@ -294,7 +328,7 @@
+ guint32 length;
+ guint32 rate, freq, flags;
+ gint8 dbm;
+- guint8 db;
++ guint8 db, rflags;
+ guint32 present, next_present;
+ int bit;
+
+@@ -334,6 +368,7 @@
+ */
+ offset += sizeof(struct ieee80211_radiotap_header);
+
++ rflags = 0;
+ for (; present; present = next_present) {
+ /* clear the least significant bit that is set */
+ next_present = present & (present - 1);
+@@ -344,45 +379,16 @@
+ switch (bit) {
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (tree) {
++ rflags = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(radiotap_tree, hf_radiotap_preamble,
+- tvb, 0, 0, (tvb_get_guint8(tvb, offset) &
+- IEEE80211_RADIOTAP_F_SHORTPRE) != 0);
++ tvb, 0, 0, (rflags&IEEE80211_RADIOTAP_F_SHORTPRE) != 0);
++ proto_tree_add_uint(radiotap_tree, hf_radiotap_fcs,
++ tvb, 0, 0, (rflags&IEEE80211_RADIOTAP_F_FCS) != 0);
++ proto_tree_add_uint(radiotap_tree, hf_radiotap_datapad,
++ tvb, 0, 0, (rflags&IEEE80211_RADIOTAP_F_DATAPAD) != 0);
+ }
+ offset++;
+ /* XXX CFP, WEP, FRAG */
+-#if 0
+- capability = tvb_get_letohs (tvb, offset);
+-
+- cap_item = proto_tree_add_uint_format (tree, ff_capture,
+- tvb, offset, 2,
+- capability,
+- "Capability Information: 0x%04X",
+- capability);
+- cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
+- proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
+- capability);
+- if (ESS_SET (capability) != 0) /* This is an AP */
+- proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
+- capability);
+-
+- else /* This is a STA */
+- proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
+- capability);
+- proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
+- capability);
+-#endif
+ break;
+ case IEEE80211_RADIOTAP_RATE:
+ rate = tvb_get_guint8(tvb, offset) & 0x7f;
+@@ -480,8 +486,8 @@
+ break;
+ case IEEE80211_RADIOTAP_TSFT:
+ if (tree) {
+- proto_tree_add_item(radiotap_tree, hf_radiotap_mactime,
+- tvb, offset, 8, FALSE);
++ proto_tree_add_uint64(radiotap_tree, hf_radiotap_mactime,
++ tvb, offset, 8, tvb_get_letoh64(tvb, offset));
+ }
+ offset+=8;
+ break;
+@@ -495,8 +501,11 @@
+ }
+ }
+
++ if (rflags & IEEE80211_RADIOTAP_F_FCS)
++ pinfo->pseudo_header->ieee_802_11.fcs_len = 4;
+ /* dissect the 802.11 header next */
+- call_dissector(ieee80211_handle,
++ 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
+@@ -513,6 +522,7 @@
+
+ /* handle for 802.11 dissector */
+ ieee80211_handle = find_dissector("wlan");
++ ieee80211_datapad_handle = find_dissector("wlan_datapad");
+
+ radiotap_handle = create_dissector_handle(dissect_radiotap, proto_radiotap);
+