Stephen Fisher:
[obnox/wireshark/wip.git] / epan / dissectors / packet-ieee80211.c
index 41cb541cb79b5f5771e0c0d9dc1a47159ad270ae..18de9b6101ce7a37b8a7d3988e818ad7a98e757b 100644 (file)
@@ -5,8 +5,8 @@
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * Copied from README.developer
 #include <stdio.h>
 #include <stdlib.h>
 
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
 #include <string.h>
 #include <glib.h>
 #include <epan/bitswap.h>
 #include <epan/proto.h>
 #include <epan/packet.h>
-#include <epan/resolv.h>
+#include <epan/addr_resolv.h>
 #include <epan/strutil.h>
-#include "prefs.h"
-#include "reassemble.h"
+#include <epan/prefs.h>
+#include <epan/reassemble.h>
 #include "packet-ipx.h"
 #include "packet-llc.h"
 #include "packet-ieee80211.h"
-#include "etypes.h"
-#include "crc32.h"
+#include <epan/etypes.h>
+#include <epan/oui.h>
+#include <epan/crc32.h>
+#include <epan/tap.h>
+#include <epan/emem.h>
+
+#include <ctype.h>
+#include "isprint.h"
+
+#ifdef HAVE_AIRPCAP
+#include <airpcap.h>
+#else
+/* XXX - This is probably a bit much */
+#define MAX_ENCRYPTION_KEYS 64
+#endif
+
+#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;
@@ -83,21 +96,27 @@ static GHashTable *wlan_fragment_table = NULL;
 static GHashTable *wlan_reassembled_table = NULL;
 
 /* Stuff for the WEP decoder */
-static guint num_wepkeys = 0;
+/* XXX - Instead of making the user specify the number of WEP keys manually,
+ * we may want to change the "WEP key count" option to a toggle that
+ * enables/disables WEP decryption, and automatically figure out how
+ * many keys we have by parsing the key list.
+ */
+static gint num_wepkeys = 0;
 static guint8 **wep_keys = NULL;
 static int *wep_keylens = NULL;
 static void init_wepkeys(void);
 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
+static int weak_iv(guchar *iv);
 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
 
 /* #define USE_ENV */
 /* When this is set, an unlimited number of WEP keys can be set in the
    environment:
 
-   ETHEREAL_WEPKEYNUM=##
-   ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
-   ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
+   WIRESHARK_WEPKEYNUM=##
+   WIRESHARK_WEPKEY1=aa:bb:cc:dd:...
+   WIRESHARK_WEPKEY2=aa:bab:cc:dd:ee:...
 
    ... you get the idea.
 
@@ -105,7 +124,7 @@ static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
  */
 
 #ifndef USE_ENV
-static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
+static char *wep_keystr[MAX_ENCRYPTION_KEYS];
 #endif
 
 /* ************************************************************************* */
@@ -116,45 +135,120 @@ static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
 /* ************************************************************************* */
 /*  Define some very useful macros that are used to analyze frame types etc. */
 /* ************************************************************************* */
-#define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4))     /* Create key to (sub)type */
-#define COOK_PROT_VERSION(x)  ((x) & 0x3)
-#define COOK_FRAME_TYPE(x)    (((x) & 0xC) >> 2)
-#define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
-#define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
-#define COOK_ASSOC_ID(x)      ((x) & 0x3FFF)
-#define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
-#define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
-#define COOK_QOS_PRIORITY(x)    ((x) & 0x0007)
-#define COOK_QOS_ACK_POLICY(x)  (((x) & 0x0060) >> 5)
-#define COOK_FLAGS(x)           (((x) & 0xFF00) >> 8)
-#define COOK_DS_STATUS(x)       ((x) & 0x3)
-#define COOK_WEP_KEY(x)       (((x) & 0xC0) >> 6)
 
-#define KEY_EXTIV              0x20
-#define EXTIV_LEN              8
+/*
+ * Extract the protocol version from the frame control field
+ */
+#define FCF_PROT_VERSION(x)  ((x) & 0x3)
+
+/*
+ * Extract the frame type from the frame control field.
+ */
+#define FCF_FRAME_TYPE(x)    (((x) & 0xC) >> 2)
+
+/*
+ * Extract the frame subtype from the frame control field.
+ */
+#define FCF_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
+
+/*
+ * Convert the frame type and subtype from the frame control field into
+ * one of the MGT_, CTRL_, or DATA_ values.
+ */
+#define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+FCF_FRAME_SUBTYPE(x))  /* Create key to (sub)type */
+
+/*
+ * The subtype field of a data frame is, in effect, composed of 4 flag
+ * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have
+ * any data), and QoS.
+ */
+#define DATA_FRAME_IS_CF_ACK(x)  ((x) & 0x01)
+#define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02)
+#define DATA_FRAME_IS_NULL(x)    ((x) & 0x04)
+#define DATA_FRAME_IS_QOS(x)     ((x) & 0x08)
+
+/*
+ * Extract the flags from the frame control field.
+ */
+#define FCF_FLAGS(x)           (((x) & 0xFF00) >> 8)
 
+/*
+ * Bits from the flags field.
+ */
 #define FLAG_TO_DS             0x01
 #define FLAG_FROM_DS           0x02
 #define FLAG_MORE_FRAGMENTS    0x04
 #define FLAG_RETRY             0x08
 #define FLAG_POWER_MGT         0x10
 #define FLAG_MORE_DATA         0x20
-#define FLAG_WEP               0x40
+#define FLAG_PROTECTED         0x40
 #define FLAG_ORDER             0x80
 
+/*
+ * Test bits in the flags field.
+ */
 #define IS_TO_DS(x)            ((x) & FLAG_TO_DS)
 #define IS_FROM_DS(x)          ((x) & FLAG_FROM_DS)
 #define HAVE_FRAGMENTS(x)      ((x) & FLAG_MORE_FRAGMENTS)
 #define IS_RETRY(x)            ((x) & FLAG_RETRY)
 #define POWER_MGT_STATUS(x)    ((x) & FLAG_POWER_MGT)
 #define HAS_MORE_DATA(x)       ((x) & FLAG_MORE_DATA)
-#define IS_WEP(x)              (!wlan_ignore_wep && ((x) & FLAG_WEP))
+#define IS_PROTECTED(x)        (!wlan_ignore_wep && ((x) & FLAG_PROTECTED))
 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
 
-#define MGT_RESERVED_RANGE(x)  (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
-#define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
-#define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
-#define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
+/*
+ * Extract subfields from the flags field.
+ */
+#define FLAGS_DS_STATUS(x)          ((x) & (FLAG_FROM_DS|FLAG_TO_DS))
+
+/*
+ * Extract an indication of the types of addresses in a data frame from
+ * the frame control field.
+ */
+#define FCF_ADDR_SELECTOR(x) ((x) & ((FLAG_TO_DS|FLAG_FROM_DS) << 8))
+
+#define DATA_ADDR_T1         0
+#define DATA_ADDR_T2         (FLAG_FROM_DS << 8)
+#define DATA_ADDR_T3         (FLAG_TO_DS << 8)
+#define DATA_ADDR_T4         ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
+
+/*
+ * Extract the fragment number and sequence number from the sequence
+ * control field.
+ */
+#define SEQCTL_FRAGMENT_NUMBER(x) ((x) & 0x000F)
+#define SEQCTL_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
+
+/*
+ * Extract subfields from the QoS control field.
+ */
+#define QOS_TID(x)           ((x) & 0x000F)
+#define QOS_PRIORITY(x)       ((x) & 0x0007)
+#define QOS_EOSP(x)          (((x) & 0x0010) >> 4) /* end of service period */
+#define QOS_ACK_POLICY(x)     (((x) & 0x0060) >> 5)
+#define QOS_FIELD_CONTENT(x)  (((x) & 0xFF00) >> 8)
+
+#define QOS_FLAG_EOSP          0x08
+
+/*
+ * Extract subfields from the result of QOS_FIELD_CONTENT().
+ */
+#define QOS_PS_BUF_STATE(x)    (((x) & 0x02) >> 1)
+#define QOS_PS_BUF_AC(x)       (((x) & 0x0C) >> 2)
+#define QOS_PS_BUF_LOAD(x)     (((x) & 0xF0) >> 4)
+
+/*
+ * Extract the association ID from the value in an association ID field.
+ */
+#define ASSOC_ID(x)             ((x) & 0x3FFF)
+
+/*
+ * Extract subfields from the key octet in WEP-encrypted frames.
+ */
+#define KEY_OCTET_WEP_KEY(x)    (((x) & 0xC0) >> 6)
+
+#define KEY_EXTIV              0x20
+#define EXTIV_LEN              8
 
 
 /* ************************************************************************* */
@@ -168,41 +262,53 @@ static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
 #define DATA_LONG_HDR_LEN      30
 #define MGT_FRAME_HDR_LEN      24      /* Length of Managment frame-headers */
 
-#define MGT_ASSOC_REQ        0x00      /* Management - association request        */
-#define MGT_ASSOC_RESP       0x01      /* Management - association response       */
-#define MGT_REASSOC_REQ      0x02      /* Management - reassociation request      */
-#define MGT_REASSOC_RESP     0x03      /* Management - reassociation response     */
-#define MGT_PROBE_REQ        0x04      /* Management - Probe request              */
-#define MGT_PROBE_RESP       0x05      /* Management - Probe response             */
-#define MGT_BEACON           0x08      /* Management - Beacon frame               */
-#define MGT_ATIM             0x09      /* Management - ATIM                       */
-#define MGT_DISASS           0x0A      /* Management - Disassociation             */
-#define MGT_AUTHENTICATION   0x0B      /* Management - Authentication             */
-#define MGT_DEAUTHENTICATION 0x0C      /* Management - Deauthentication           */
-#define MGT_ACTION           0x0D      /* Management - Action */
-
-#define CTRL_PS_POLL         0x1A      /* Control - power-save poll               */
-#define CTRL_RTS             0x1B      /* Control - request to send               */
-#define CTRL_CTS             0x1C      /* Control - clear to send                 */
-#define CTRL_ACKNOWLEDGEMENT 0x1D      /* Control - acknowledgement               */
-#define CTRL_CFP_END         0x1E      /* Control - contention-free period end    */
-#define CTRL_CFP_ENDACK      0x1F      /* Control - contention-free period end/ack */
-
-#define DATA                 0x20      /* Data - Data                             */
-#define DATA_CF_ACK          0x21      /* Data - Data + CF acknowledge            */
-#define DATA_CF_POLL         0x22      /* Data - Data + CF poll                   */
-#define DATA_CF_ACK_POLL     0x23      /* Data - Data + CF acknowledge + CF poll  */
-#define DATA_NULL_FUNCTION   0x24      /* Data - Null function (no data)          */
-#define DATA_CF_ACK_NOD      0x25      /* Data - CF ack (no data)                 */
-#define DATA_CF_POLL_NOD     0x26       /* Data - Data + CF poll (No data)         */
-#define DATA_CF_ACK_POLL_NOD 0x27      /* Data - CF ack + CF poll (no data)       */
-#define DATA_QOS_DATA        0x28      /* Data - QoS Data                         */
-#define DATA_QOS_NULL        0x2c      /* Data - QoS Null                         */
+/*
+ * COMPOSE_FRAME_TYPE() values for management frames.
+ */
+#define MGT_ASSOC_REQ        0x00      /* association request        */
+#define MGT_ASSOC_RESP       0x01      /* association response       */
+#define MGT_REASSOC_REQ      0x02      /* reassociation request      */
+#define MGT_REASSOC_RESP     0x03      /* reassociation response     */
+#define MGT_PROBE_REQ        0x04      /* Probe request              */
+#define MGT_PROBE_RESP       0x05      /* Probe response             */
+#define MGT_BEACON           0x08      /* Beacon frame               */
+#define MGT_ATIM             0x09      /* ATIM                       */
+#define MGT_DISASS           0x0A      /* Disassociation             */
+#define MGT_AUTHENTICATION   0x0B      /* Authentication             */
+#define MGT_DEAUTHENTICATION 0x0C      /* Deauthentication           */
+#define MGT_ACTION           0x0D      /* Action */
+
+/*
+ * COMPOSE_FRAME_TYPE() values for control frames.
+ */
+#define CTRL_BLOCK_ACK_REQ   0x18      /* Block ack Request                */
+#define CTRL_BLOCK_ACK      0x19       /* Block ack                        */
+#define CTRL_PS_POLL         0x1A      /* power-save poll               */
+#define CTRL_RTS             0x1B      /* request to send               */
+#define CTRL_CTS             0x1C      /* clear to send                 */
+#define CTRL_ACKNOWLEDGEMENT 0x1D      /* acknowledgement               */
+#define CTRL_CFP_END         0x1E      /* contention-free period end    */
+#define CTRL_CFP_ENDACK      0x1F      /* contention-free period end/ack */
 
-#define DATA_ADDR_T1         0
-#define DATA_ADDR_T2         (FLAG_FROM_DS << 8)
-#define DATA_ADDR_T3         (FLAG_TO_DS << 8)
-#define DATA_ADDR_T4         ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
+/*
+ * COMPOSE_FRAME_TYPE() values for data frames.
+ */
+#define DATA                        0x20       /* Data                       */
+#define DATA_CF_ACK                 0x21       /* Data + CF-Ack              */
+#define DATA_CF_POLL                0x22       /* Data + CF-Poll             */
+#define DATA_CF_ACK_POLL            0x23       /* Data + CF-Ack + CF-Poll    */
+#define DATA_NULL_FUNCTION          0x24       /* Null function (no data)    */
+#define DATA_CF_ACK_NOD             0x25       /* CF-Ack (no data)           */
+#define DATA_CF_POLL_NOD            0x26       /* CF-Poll (No data)          */
+#define DATA_CF_ACK_POLL_NOD        0x27       /* CF-Ack + CF-Poll (no data) */
+
+#define DATA_QOS_DATA               0x28       /* QoS Data                   */
+#define DATA_QOS_DATA_CF_ACK        0x29       /* QoS Data + CF-Ack          */
+#define DATA_QOS_DATA_CF_POLL       0x2A       /* QoS Data + CF-Poll             */
+#define DATA_QOS_DATA_CF_ACK_POLL   0x2B       /* QoS Data + CF-Ack + CF-Poll    */
+#define DATA_QOS_NULL              0x2C        /* QoS Null                       */
+#define DATA_QOS_CF_POLL_NOD       0x2E        /* QoS CF-Poll (No Data)                  */
+#define DATA_QOS_CF_ACK_POLL_NOD    0x2F       /* QoS CF-Ack + CF-Poll (No Data) */
 
 
 /* ************************************************************************* */
@@ -246,12 +352,35 @@ static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
 #define TAG_COUNTRY_INFO         0x07
 #define TAG_FH_HOPPING_PARAMETER 0x08
 #define TAG_FH_HOPPING_TABLE     0x09
+#define TAG_REQUEST             0x0A
+#define TAG_QBSS_LOAD           0x0B
+#define TAG_EDCA_PARAM_SET      0x0C
+#define TAG_TRAF_SPEC           0x0D
+#define TAG_TRAF_CLASS          0x0E
+#define TAG_SCHEDULE            0x0F
 #define TAG_CHALLENGE_TEXT       0x10
+#define TAG_POWER_CONSTRAINT    0x20
+#define TAG_POWER_CAPABILITY    0x21
+#define TAG_TPC_REQUEST                 0x22
+#define TAG_TPC_REPORT          0x23
+#define TAG_SUPPORTED_CHANNELS  0x24
+#define TAG_CHANNEL_SWITCH_ANN  0x25
+#define TAG_MEASURE_REQ                 0x26
+#define TAG_MEASURE_REP                 0x27
+#define TAG_QUIET               0x28
+#define TAG_IBSS_DFS            0x29
 #define TAG_ERP_INFO             0x2A
+#define TAG_TS_DELAY            0x2B
+#define TAG_TCLAS_PROCESS       0x2C
+#define TAG_QOS_CAPABILITY      0x2E
 #define TAG_ERP_INFO_OLD         0x2F  /* IEEE Std 802.11g/D4.0 */
 #define TAG_RSN_IE               0x30
 #define TAG_EXT_SUPP_RATES       0x32
+#define TAG_AGERE_PROPRIETARY   0x80
+#define TAG_CISCO_UNKNOWN_1     0x85   /* Cisco Compatible eXtensions? */
+#define TAG_CISCO_UNKNOWN_2     0x88   /* Cisco Compatible eXtensions? */
 #define TAG_VENDOR_SPECIFIC_IE  0xDD
+#define TAG_SYMBOL_PROPRIETARY  0xAD
 
 #define WPA_OUI        "\x00\x50\xF2"
 #define RSN_OUI "\x00\x0F\xAC"
@@ -275,22 +404,31 @@ static const value_string frame_type_subtype_vals[] = {
        {MGT_AUTHENTICATION,   "Authentication"},
        {MGT_DEAUTHENTICATION, "Deauthentication"},
        {MGT_ACTION,           "Action"},
+
+       {CTRL_BLOCK_ACK_REQ,   "802.11 Block Ack Req"},
+       {CTRL_BLOCK_ACK,       "802.11 Block Ack"},
        {CTRL_PS_POLL,         "Power-Save poll"},
        {CTRL_RTS,             "Request-to-send"},
        {CTRL_CTS,             "Clear-to-send"},
        {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
        {CTRL_CFP_END,         "CF-End (Control-frame)"},
        {CTRL_CFP_ENDACK,      "CF-End + CF-Ack (Control-frame)"},
+
        {DATA,                 "Data"},
-       {DATA_CF_ACK,          "Data + CF-Acknowledgement"},
+       {DATA_CF_ACK,          "Data + CF-Ack"},
        {DATA_CF_POLL,         "Data + CF-Poll"},
-       {DATA_CF_ACK_POLL,     "Data + CF-Acknowledgement/Poll"},
+       {DATA_CF_ACK_POLL,     "Data + CF-Ack + CF-Poll"},
        {DATA_NULL_FUNCTION,   "Null function (No data)"},
-       {DATA_CF_ACK_NOD,      "Data + Acknowledgement (No data)"},
-       {DATA_CF_POLL_NOD,     "Data + CF-Poll (No data)"},
-       {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
+       {DATA_CF_ACK_NOD,      "Acknowledgement (No data)"},
+       {DATA_CF_POLL_NOD,     "CF-Poll (No data)"},
+       {DATA_CF_ACK_POLL_NOD, "CF-Ack/Poll (No data)"},
        {DATA_QOS_DATA,        "QoS Data"},
-       {DATA_QOS_NULL,        "QoS Null (No data)"},
+       {DATA_QOS_DATA_CF_ACK,  "QoS Data + CF-Acknowledgment"},
+       {DATA_QOS_DATA_CF_POLL, "QoS Data + CF-Poll"},
+       {DATA_QOS_DATA_CF_ACK_POLL, "QoS Data + CF-Ack + CF-Poll"},
+       {DATA_QOS_NULL,        "QoS Null function (No data)"},
+       {DATA_QOS_CF_POLL_NOD,  "QoS CF-Poll (No Data)"},
+       {DATA_QOS_CF_ACK_POLL_NOD,  "QoS CF-Ack + CF-Poll (No data)"},
        {0,                    NULL}
 };
 
@@ -332,7 +470,21 @@ static const char *wme_acs[4] = {
        "Voice",
 };
 
+
+#define CAT_SPECTRUM_MGMT      0
+#define CAT_QOS                        1
+#define CAT_DLS                        2
+#define CAT_BLOCK_ACK          3
+#define CAT_MGMT_NOTIFICATION  17
+
+#define SM_ACTION_MEASUREMENT_REQUEST  0
+#define SM_ACTION_MEASUREMENT_REPORT   1
+#define SM_ACTION_TPC_REQUEST          2
+#define SM_ACTION_TPC_REPORT           3
+#define SM_ACTION_CHAN_SWITCH_ANNC     4
+
 static int proto_wlan = -1;
+static packet_info * g_pinfo;
 
 /* ************************************************************************* */
 /*                Header field info values for radio information             */
@@ -359,7 +511,7 @@ static int hf_fc_more_frag = -1;
 static int hf_fc_retry = -1;
 static int hf_fc_pwr_mgt = -1;
 static int hf_fc_more_data = -1;
-static int hf_fc_wep = -1;
+static int hf_fc_protected = -1;
 static int hf_fc_order = -1;
 
 
@@ -387,6 +539,16 @@ static int hf_addr = -1;   /* Source or destination address subfield */
 /* ************************************************************************* */
 static int hf_qos_priority = -1;
 static int hf_qos_ack_policy = -1;
+static int hf_qos_eosp = -1;
+static int hf_qos_field_content = -1;
+/*static int hf_qos_txop_limit = -1;*/
+/*     FIXME: hf_ values not defined
+static int hf_qos_buf_state = -1;
+static int hf_qos_buf_ac = -1;
+static int hf_qos_buf_load = -1;
+*/
+/*static int hf_qos_txop_dur_req = -1;
+static int hf_qos_queue_size = -1;*/
 
 /* ************************************************************************* */
 /*                Header values for sequence number field                    */
@@ -445,6 +607,10 @@ static int ff_cf_pbcc = -1;
 static int ff_cf_agility = -1;
 static int ff_short_slot_time = -1;
 static int ff_dsss_ofdm = -1;
+static int ff_cf_spec_man = -1;
+static int ff_cf_apsd = -1;
+static int ff_cf_del_blk_ack = -1;
+static int ff_cf_imm_blk_ack = -1;
 
 /* ************************************************************************* */
 /*                       Tagged value format fields                          */
@@ -452,12 +618,19 @@ static int ff_dsss_ofdm = -1;
 static int tag_number = -1;
 static int tag_length = -1;
 static int tag_interpretation = -1;
+static int tag_oui = -1;
 
 
+static int tim_length = -1;
+static int tim_dtim_count = -1;
+static int tim_dtim_period = -1;
+static int tim_bmapctl = -1;
+
 
 static int hf_fixed_parameters = -1;   /* Protocol payload for management frames */
 static int hf_tagged_parameters = -1;  /* Fixed payload item */
 static int hf_wep_iv = -1;
+static int hf_wep_iv_weak = -1;
 static int hf_tkip_extiv = -1;
 static int hf_ccmp_extiv = -1;
 static int hf_wep_key = -1;
@@ -470,6 +643,24 @@ static int rsn_cap_no_pairwise = -1;
 static int rsn_cap_ptksa_replay_counter = -1;
 static int rsn_cap_gtksa_replay_counter = -1;
 
+static int hf_aironet_ie_type = -1;
+static int hf_aironet_ie_version = -1;
+static int hf_aironet_ie_data = -1;
+static int hf_aironet_ie_qos_unk1 = -1;
+static int hf_aironet_ie_qos_paramset = -1;
+static int hf_aironet_ie_qos_val = -1;
+
+/*QBSS - Version 1,2,802.11e*/
+
+static int hf_qbss2_cal = -1;
+static int hf_qbss2_gl = -1;
+static int hf_qbss_cu = -1;
+static int hf_qbss2_cu = -1;
+static int hf_qbss_scount = -1;
+static int hf_qbss2_scount = -1;
+static int hf_qbss_version = -1;
+static int hf_qbss_adc = -1;
+
 /* ************************************************************************* */
 /*                               Protocol trees                              */
 /* ************************************************************************* */
@@ -484,10 +675,13 @@ static gint ett_80211_mgt = -1;
 static gint ett_fixed_parameters = -1;
 static gint ett_tagged_parameters = -1;
 static gint ett_qos_parameters = -1;
+static gint ett_qos_ps_buf_state = -1;
 static gint ett_wep_parameters = -1;
 
 static gint ett_rsn_cap_tree = -1;
 
+static gint ett_80211_mgt_ie = -1;
+
 static const fragment_items frag_items = {
        &ett_fragment,
        &ett_fragments,
@@ -504,9 +698,11 @@ static const fragment_items frag_items = {
 
 static dissector_handle_t llc_handle;
 static dissector_handle_t ipx_handle;
-static dissector_handle_t eth_handle;
+static dissector_handle_t eth_withoutfcs_handle;
 static dissector_handle_t data_handle;
 
+static int wlan_tap = -1;
+
 /* ************************************************************************* */
 /*            Return the length of the current header (in bytes)             */
 /* ************************************************************************* */
@@ -515,7 +711,7 @@ find_header_length (guint16 fcf)
 {
   int len;
 
-  switch (COOK_FRAME_TYPE (fcf)) {
+  switch (FCF_FRAME_TYPE (fcf)) {
 
   case MGT_FRAME:
     return MGT_FRAME_HDR_LEN;
@@ -531,22 +727,20 @@ find_header_length (guint16 fcf)
     case CTRL_PS_POLL:
     case CTRL_CFP_END:
     case CTRL_CFP_ENDACK:
+    case CTRL_BLOCK_ACK_REQ:
+    case CTRL_BLOCK_ACK:
       return 16;
     }
     return 4;  /* XXX */
 
   case DATA_FRAME:
-    len = (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
+    len = (FCF_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
                                                      DATA_SHORT_HDR_LEN;
-    switch (COMPOSE_FRAME_TYPE (fcf)) {
-
-    case DATA_QOS_DATA:
-    case DATA_QOS_NULL:
+    if (DATA_FRAME_IS_QOS(COMPOSE_FRAME_TYPE(fcf)))
       return len + 2;
-
-    default:
+    else
       return len;
-    }
+
   default:
     return 4;  /* XXX */
   }
@@ -558,7 +752,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;
 
@@ -567,9 +762,9 @@ capture_ieee80211_common (const guchar * pd, int offset, int len,
     return;
   }
 
-  fcf = pletohs (&pd[0]);
+  fcf = pletohs (&pd[offset]);
 
-  if (IS_WEP(COOK_FLAGS(fcf)))
+  if (IS_PROTECTED(FCF_FLAGS(fcf)))
     {
       ld->other++;
       return;
@@ -587,6 +782,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),
@@ -622,7 +819,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);
 }
 
 /*
@@ -632,7 +839,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);
 }
 
 
@@ -690,7 +897,7 @@ add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
     case FIELD_TIMESTAMP:
       dataptr = tvb_get_ptr (tvb, offset, 8);
       memset (out_buff, 0, SHORT_STR);
-      snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
+      g_snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
                dataptr[7],
                dataptr[6],
                dataptr[5],
@@ -704,11 +911,15 @@ add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
       break;
 
     case FIELD_BEACON_INTERVAL:
-      temp_double = (double) tvb_get_letohs (tvb, offset);
+      capability = tvb_get_letohs (tvb, offset);
+      temp_double = (double)capability;
       temp_double = temp_double * 1024 / 1000000;
       proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
                                    temp_double,"Beacon Interval: %f [Seconds]",
                                    temp_double);
+      if (check_col (g_pinfo->cinfo, COL_INFO)) {
+          col_append_fstr(g_pinfo->cinfo, COL_INFO, ",BI=%d", capability);
+      }
       break;
 
 
@@ -740,10 +951,18 @@ add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
                              capability);
       proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
                              capability);
+      proto_tree_add_boolean (cap_tree, ff_cf_spec_man, 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_cf_apsd, tvb, offset, 2,
+                             capability);
       proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
                              capability);
+      proto_tree_add_boolean (cap_tree, ff_cf_del_blk_ack, tvb, offset, 2,
+                             capability);
+      proto_tree_add_boolean (cap_tree, ff_cf_imm_blk_ack, tvb, offset, 2,
+                             capability);
       break;
 
     case FIELD_AUTH_ALG:
@@ -767,8 +986,8 @@ add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
       break;
 
     case FIELD_ASSOC_ID:
-      proto_tree_add_uint(tree, ff_assoc_id, tvb, offset, 2, 
-                         COOK_ASSOC_ID(tvb_get_letohs(tvb,offset)));
+      proto_tree_add_uint(tree, ff_assoc_id, tvb, offset, 2,
+                         ASSOC_ID(tvb_get_letohs(tvb,offset)));
       /* proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE); */
       break;
 
@@ -798,7 +1017,7 @@ add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
     }
 }
 
-static char *wpa_cipher_str[] = 
+static const char *wpa_cipher_str[] =
 {
   "NONE",
   "WEP (40-bit)",
@@ -808,7 +1027,7 @@ static char *wpa_cipher_str[] =
   "WEP (104-bit)",
 };
 
-static char *
+static const char *
 wpa_cipher_idx2str(guint idx)
 {
   if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
@@ -816,14 +1035,14 @@ wpa_cipher_idx2str(guint idx)
   return "UNKNOWN";
 }
 
-static char *wpa_keymgmt_str[] = 
+static const char *wpa_keymgmt_str[] =
 {
   "NONE",
   "WPA",
   "PSK",
 };
 
-static char *
+static const char *
 wpa_keymgmt_idx2str(guint idx)
 {
   if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
@@ -831,17 +1050,17 @@ wpa_keymgmt_idx2str(guint idx)
   return "UNKNOWN";
 }
 
-static void 
-dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
-               guint32 tag_len, const guint8 *tag_val)
+static void
+dissect_vendor_ie_wpawme(proto_tree * ietree, proto_tree * tree, tvbuff_t * tvb,
+       int offset, guint32 tag_len, const guint8 *tag_val)
 {
       guint32 tag_val_off = 0;
-      char out_buff[SHORT_STR], *pos;
+      char out_buff[SHORT_STR];
       guint i;
-       
+
       /* Wi-Fi Protected Access (WPA) Information Element */
       if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
-        snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
+        g_snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
                   tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
         offset += 6;
@@ -849,14 +1068,14 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
         if (tag_val_off + 4 <= tag_len) {
           /* multicast cipher suite */
           if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
-            snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s", 
+            g_snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
                       wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
             proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
             offset += 4;
             tag_val_off += 4;
             /* unicast cipher suites */
             if (tag_val_off + 2 <= tag_len) {
-              snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
+              g_snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
                         pletohs(tag_val + tag_val_off));
               proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
               offset += 2;
@@ -864,7 +1083,7 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
               i = 1;
               while (tag_val_off + 4 <= tag_len) {
                 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
-                  snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s", 
+                  g_snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
                             i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
                   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
                   offset += 4;
@@ -876,7 +1095,7 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
               }
              /* authenticated key management suites */
               if (tag_val_off + 2 <= tag_len) {
-                snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
+                g_snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
                           pletohs(tag_val + tag_val_off));
                 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
                 offset += 2;
@@ -884,7 +1103,7 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
                 i = 1;
                 while (tag_val_off + 4 <= tag_len) {
                   if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
-                    snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s", 
+                    g_snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
                               i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
                     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
                     offset += 4;
@@ -901,22 +1120,24 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
         if (tag_val_off < tag_len)
           proto_tree_add_string(tree, tag_interpretation, tvb,
                                  offset, tag_len - tag_val_off, "Not interpreted");
+       proto_item_append_text(ietree, ": WPA");
       } else if (tag_val_off + 7 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x00", 5)) {
       /* Wireless Multimedia Enhancements (WME) Information Element */
-        snprintf(out_buff, SHORT_STR, "WME IE: type %u, subtype %u, version %u, parameter set %u",
+        g_snprintf(out_buff, SHORT_STR, "WME IE: type %u, subtype %u, version %u, parameter set %u",
                 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
                 tag_val[tag_val_off + 6]);
         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
+       proto_item_append_text(ietree, ": WME");
       } else if (tag_val_off + 24 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x01", 5)) {
       /* Wireless Multimedia Enhancements (WME) Parameter Element */
-        snprintf(out_buff, SHORT_STR, "WME PE: type %u, subtype %u, version %u, parameter set %u",
+        g_snprintf(out_buff, SHORT_STR, "WME PE: type %u, subtype %u, version %u, parameter set %u",
                 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
                 tag_val[tag_val_off + 6]);
         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
        offset += 8;
        tag_val_off += 8;
        for (i = 0; i < 4; i++) {
-         snprintf(out_buff, SHORT_STR, "WME AC Parameters: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
+         g_snprintf(out_buff, SHORT_STR, "WME AC Parameters: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
                   (tag_val[tag_val_off] & 0x60) >> 5,
                   wme_acs[(tag_val[tag_val_off] & 0x60) >> 5],
                   (tag_val[tag_val_off] & 0x10) ? "" : "not ",
@@ -928,6 +1149,7 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
          offset += 4;
          tag_val_off += 4;
        }
+       proto_item_append_text(ietree, ": WME");
       } else if (tag_val_off + 56 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x02", 5)) {
       /* Wireless Multimedia Enhancements (WME) TSPEC Element */
        guint16 ts_info, msdu_size, surplus_bandwidth;
@@ -945,16 +1167,16 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
          {48, "Delay Bound"},
          {0, NULL}
        };
-       char *field;
+       const char *field;
 
-        snprintf(out_buff, SHORT_STR, "WME TSPEC: type %u, subtype %u, version %u",
+        g_snprintf(out_buff, SHORT_STR, "WME TSPEC: type %u, subtype %u, version %u",
                 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5]);
         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
        offset += 6;
        tag_val_off += 6;
 
        ts_info = tvb_get_letohs(tvb, offset);
-       snprintf(out_buff, SHORT_STR, "WME TS Info: Priority %u (%s) (%s), Contention-based access %sset, %s",
+       g_snprintf(out_buff, SHORT_STR, "WME TS Info: Priority %u (%s) (%s), Contention-based access %sset, %s",
                 (ts_info >> 11) & 0x7, qos_tags[(ts_info >> 11) & 0x7], qos_acs[(ts_info >> 11) & 0x7],
                 (ts_info & 0x0080) ? "" : "not ",
                 direction[(ts_info >> 5) & 0x3]);
@@ -963,19 +1185,19 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
        tag_val_off += 2;
 
        msdu_size = tvb_get_letohs(tvb, offset);
-       snprintf(out_buff, SHORT_STR, "WME TSPEC: %s MSDU Size %u",
+       g_snprintf(out_buff, SHORT_STR, "WME TSPEC: %s MSDU Size %u",
                 (msdu_size & 0x8000) ? "Fixed" : "Nominal", msdu_size & 0x7fff);
        proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
        offset += 2;
        tag_val_off += 2;
 
-       snprintf(out_buff, SHORT_STR, "WME TSPEC: Maximum MSDU Size %u", tvb_get_letohs(tvb, offset));
+       g_snprintf(out_buff, SHORT_STR, "WME TSPEC: Maximum MSDU Size %u", tvb_get_letohs(tvb, offset));
        proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
        offset += 2;
        tag_val_off += 2;
 
-       while ((field = val_to_str(tag_val_off, fields, NULL))) {
-         snprintf(out_buff, SHORT_STR, "WME TSPEC: %s %u", field, tvb_get_letohl(tvb, offset));
+       while ((field = val_to_str(tag_val_off, fields, "Unknown"))) {
+         g_snprintf(out_buff, SHORT_STR, "WME TSPEC: %s %u", field, tvb_get_letohl(tvb, offset));
          proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
          offset += 4;
          tag_val_off += 4;
@@ -984,36 +1206,123 @@ dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
        }
 
        surplus_bandwidth = tvb_get_letohs(tvb, offset);
-       snprintf(out_buff, SHORT_STR, "WME TSPEC: Surplus Bandwidth Allowance Factor %u.%u",
+       g_snprintf(out_buff, SHORT_STR, "WME TSPEC: Surplus Bandwidth Allowance Factor %u.%u",
                 (surplus_bandwidth >> 13) & 0x7, (surplus_bandwidth & 0x1fff));
        offset += 2;
        tag_val_off += 2;
 
-       snprintf(out_buff, SHORT_STR, "WME TSPEC: Medium Time %u", tvb_get_letohs(tvb, offset));
+       g_snprintf(out_buff, SHORT_STR, "WME TSPEC: Medium Time %u", tvb_get_letohs(tvb, offset));
        proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
        offset += 2;
-       tag_val_off += 2;                
-      } else if (tag_val_off + 4 <= tag_len && !memcmp(tag_val, RSN_OUI"\x04", 4)) {
-       /* IEEE 802.11i / Key Data Encapsulation / Data Type=4 - PMKID.
-        * This is only used within EAPOL-Key frame Key Data. */
-       pos = out_buff;
-       pos += snprintf(pos, out_buff + SHORT_STR - pos, "RSN PMKID: ");
-       if (tag_len - 4 != PMKID_LEN) {
-         pos += snprintf(pos, out_buff + SHORT_STR - pos,
-                         "(invalid PMKID len=%d, expected 16) ", tag_len - 4);
+       tag_val_off += 2;
+       proto_item_append_text(ietree, ": WME");
+      }
+}
+
+static void
+dissect_vendor_ie_rsn(proto_tree * ietree, proto_tree * tree, tvbuff_t * tvb,
+       int offset, guint32 tag_len, const guint8 *tag_val)
+{
+       guint32 tag_val_off = 0;
+       char out_buff[SHORT_STR], *pos;
+       guint i;
+
+       if (tag_val_off + 4 <= tag_len && !memcmp(tag_val, RSN_OUI"\x04", 4)) {
+               /* IEEE 802.11i / Key Data Encapsulation / Data Type=4 - PMKID.
+                * This is only used within EAPOL-Key frame Key Data. */
+               pos = out_buff;
+               pos += g_snprintf(pos, out_buff + SHORT_STR - pos, "RSN PMKID: ");
+               if (tag_len - 4 != PMKID_LEN) {
+                       pos += g_snprintf(pos, out_buff + SHORT_STR - pos,
+                               "(invalid PMKID len=%d, expected 16) ", tag_len - 4);
+               }
+               for (i = 0; i < tag_len - 4; i++) {
+                       pos += g_snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
+                               tag_val[tag_val_off + 4 + i]);
+               }
+               proto_tree_add_string(tree, tag_interpretation, tvb, offset,
+                       tag_len, out_buff);
+       }
+       proto_item_append_text(ietree, ": RSN");
+}
+
+typedef enum {
+       AIRONET_IE_VERSION = 3,
+       AIRONET_IE_QOS,
+       AIRONET_IE_QBSS_V2 = 14
+} aironet_ie_type_t;
+
+static const value_string aironet_ie_type_vals[] = {
+        { AIRONET_IE_VERSION,  "CCX version"},
+        { AIRONET_IE_QOS,      "Qos"},
+        { AIRONET_IE_QBSS_V2,  "QBSS V2 - CCA"},
+
+       { 0,                    NULL }
+};
+
+static void
+dissect_vendor_ie_aironet(proto_item * aironet_item, proto_tree * ietree,
+       tvbuff_t * tvb, int offset, guint32 tag_len)
+{
+       guint8  type;
+       int i;
+       gboolean dont_change = FALSE; /* Don't change the IE item text to default */
+
+       type = tvb_get_guint8(tvb, offset);
+       proto_tree_add_item (ietree, hf_aironet_ie_type, tvb, offset, 1, TRUE);
+       offset += 1;
+
+       switch (type) {
+       case AIRONET_IE_VERSION:
+               proto_tree_add_item (ietree, hf_aironet_ie_version, tvb, offset, 1, TRUE);
+               proto_item_append_text(aironet_item, ": Aironet CCX version = %d",
+                       tvb_get_guint8(tvb, offset));
+               dont_change = TRUE;
+               break;
+       case AIRONET_IE_QOS:
+               proto_tree_add_item (ietree, hf_aironet_ie_qos_unk1, tvb, offset, 1, TRUE);
+               offset += 1;
+               proto_tree_add_item (ietree, hf_aironet_ie_qos_paramset, tvb, offset, 1, TRUE);
+               offset += 1;
+
+               /* XXX: just copied over from WME. Maybe "Best Effort" and "Background"
+                *      need to be swapped. Also, the "TXOP" may be TXOP - or not.
+                */
+               for (i = 0; i < 4; i++) {
+                       guint8 byte1, byte2;
+                       guint16 txop;
+                       byte1 = tvb_get_guint8(tvb, offset);
+                       byte2 = tvb_get_guint8(tvb, offset + 1);
+                       txop = tvb_get_letohs(tvb, offset + 2);
+                       proto_tree_add_bytes_format(ietree, hf_aironet_ie_qos_val, tvb, offset, 4,
+                               tvb_get_ptr(tvb, offset, 4),
+                               "CCX QoS Parameters??: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
+                               (byte1 & 0x60) >> 5, wme_acs[(byte1 & 0x60) >> 5],
+                               (byte1 & 0x10) ? "" : "not ", byte1 & 0x0f,
+                               byte2 & 0x0f, (byte2 & 0xf0) >> 4,
+                               txop);
+                       offset += 4;
+               }
+               break;
+       case AIRONET_IE_QBSS_V2:
+               /* Extract Values */
+               proto_tree_add_item (ietree, hf_qbss2_scount, tvb, offset, 2, TRUE);
+               proto_tree_add_item (ietree, hf_qbss2_cu, tvb, offset + 2, 1, FALSE);
+               proto_tree_add_item (ietree, hf_qbss2_cal, tvb, offset + 3, 1, FALSE);
+               proto_tree_add_item (ietree, hf_qbss2_gl, tvb, offset + 4, 1, FALSE);
+               break;
+       default:
+               proto_tree_add_item(ietree, hf_aironet_ie_data, tvb, offset,
+                       tag_len - 1, FALSE);
+               break;
        }
-       for (i = 0; i < tag_len - 4; i++) {
-         pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
-                         tag_val[tag_val_off + 4 + i]);
+       if (!dont_change) {
+               proto_item_append_text(aironet_item, ": Aironet %s",
+                       val_to_str(type, aironet_ie_type_vals, "Unknown"));
        }
-       proto_tree_add_string(tree, tag_interpretation, tvb, offset,
-                             tag_len, out_buff);
-      } else
-        proto_tree_add_string(tree, tag_interpretation, 
-                       tvb, offset, tag_len, "Not interpreted");
 }
 
-static void 
+static void
 dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
               guint32 tag_len, const guint8 *tag_val)
 {
@@ -1030,7 +1339,7 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
     return;
   }
 
-  snprintf(out_buff, SHORT_STR, "RSN IE, version %u",
+  g_snprintf(out_buff, SHORT_STR, "RSN IE, version %u",
           pletohs(&tag_val[tag_val_off]));
   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
 
@@ -1042,7 +1351,7 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
 
   /* multicast cipher suite */
   if (!memcmp(&tag_val[tag_val_off], RSN_OUI, 3)) {
-    snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s", 
+    g_snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
             wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
     offset += 4;
@@ -1054,7 +1363,7 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
 
   /* unicast cipher suites */
   count = pletohs(tag_val + tag_val_off);
-  snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", count);
+  g_snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", count);
   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
   offset += 2;
   tag_val_off += 2;
@@ -1062,7 +1371,7 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
   while (tag_val_off + 4 <= tag_len && i <= count) {
     if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
       goto done;
-    snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
+    g_snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
             i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
     offset += 4;
@@ -1075,7 +1384,7 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
 
   /* authenticated key management suites */
   count = pletohs(tag_val + tag_val_off);
-  snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", count);
+  g_snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", count);
   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
   offset += 2;
   tag_val_off += 2;
@@ -1083,7 +1392,7 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
   while (tag_val_off + 4 <= tag_len && i <= count) {
     if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
       goto done;
-    snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s", 
+    g_snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
             i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
     offset += 4;
@@ -1095,7 +1404,7 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
     goto done;
 
   rsn_capab = pletohs(&tag_val[tag_val_off]);
-  snprintf(out_buff, SHORT_STR, "RSN Capabilities 0x%04x", rsn_capab);
+  g_snprintf(out_buff, SHORT_STR, "RSN Capabilities 0x%04x", rsn_capab);
   cap_item = proto_tree_add_uint_format(tree, rsn_cap, tvb,
                                        offset, 2, rsn_capab,
                                        "RSN Capabilities: 0x%04X", rsn_capab);
@@ -1115,7 +1424,7 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
     goto done;
 
   count = pletohs(tag_val + tag_val_off);
-  snprintf(out_buff, SHORT_STR, "# of PMKIDs: %u", count);
+  g_snprintf(out_buff, SHORT_STR, "# of PMKIDs: %u", count);
   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
   offset += 2;
   tag_val_off += 2;
@@ -1126,9 +1435,9 @@ dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
     if (tag_val_off + PMKID_LEN > tag_len)
       goto done;
     pos = out_buff;
-    pos += snprintf(pos, out_buff + SHORT_STR - pos, "PMKID %u: ", i);
+    pos += g_snprintf(pos, out_buff + SHORT_STR - pos, "PMKID %u: ", i);
     for (j = 0; j < PMKID_LEN; j++) {
-      pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
+      pos += g_snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
                      tag_val[tag_val_off + j]);
     }
     proto_tree_add_string(tree, tag_interpretation, tvb, offset,
@@ -1162,7 +1471,30 @@ static const value_string tag_num_vals[] = {
        { TAG_ERP_INFO_OLD,         "ERP Information" },
        { TAG_RSN_IE,               "RSN Information" },
        { TAG_EXT_SUPP_RATES,       "Extended Supported Rates" },
+       { TAG_CISCO_UNKNOWN_1,      "Cisco Unknown 1 + Device Name" },
+       { TAG_CISCO_UNKNOWN_2,      "Cisco Unknown 2" },
        { TAG_VENDOR_SPECIFIC_IE,   "Vendor Specific" },
+       { TAG_SYMBOL_PROPRIETARY,   "Symbol Proprietary"},
+       { TAG_AGERE_PROPRIETARY,    "Agere Proprietary"},
+       { TAG_REQUEST,              "Request"},
+       { TAG_QBSS_LOAD,            "QBSS Load Element"},
+       { TAG_EDCA_PARAM_SET,       "EDCA Parameter Set"},
+       { TAG_TRAF_SPEC,            "Traffic Specification"},
+       { TAG_TRAF_CLASS,           "Traffic Classification"},
+       { TAG_SCHEDULE,             "Schedule"},
+       { TAG_TS_DELAY,             "TS Delay"},
+       { TAG_TCLAS_PROCESS,        "TCLAS Processing"},
+       { TAG_QOS_CAPABILITY,       "QoS Capability"},
+       { TAG_POWER_CONSTRAINT,     "Power Constraint"},
+       { TAG_POWER_CAPABILITY,     "Power Capability"},
+       { TAG_TPC_REQUEST,          "TPC Request"},
+       { TAG_TPC_REPORT,           "TPC Report"},
+       { TAG_SUPPORTED_CHANNELS,   "Supported Channels"},
+       { TAG_CHANNEL_SWITCH_ANN,   "Channel Switch Announcement"},
+       { TAG_MEASURE_REQ,          "Measurement Request"},
+       { TAG_MEASURE_REP,          "Measurement Report"},
+       { TAG_QUIET,                "Quiet"},
+       { TAG_IBSS_DFS,             "IBSS DFS"},
        { 0,                        NULL }
 };
 
@@ -1173,17 +1505,30 @@ static const value_string environment_vals[] = {
        { 0,    NULL }
 };
 
+static int beacon_padding = 0; /* beacon padding bug */
 static int
-add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
+add_tagged_field (packet_info * pinfo, proto_tree * tree, tvbuff_t * tvb, int offset)
 {
+  guint32 oui;
+  const guint8 *tag_val;
   const guint8 *tag_data_ptr;
   guint32 tag_no, tag_len;
   unsigned int i;
   int n, ret;
   char out_buff[SHORT_STR];
-
+  char print_buff[SHORT_STR];
+  proto_tree * orig_tree=tree;
+  proto_item *ti;
 
   tag_no = tvb_get_guint8(tvb, offset);
+  tag_len = tvb_get_guint8(tvb, offset + 1);
+
+  ti=proto_tree_add_text(orig_tree,tvb,offset,tag_len+2,"%s",
+                         val_to_str(tag_no, tag_num_vals,
+                         (tag_no >= 17 && tag_no <= 31) ?
+                         "Reserved for challenge text" : "Reserved tag number" ));
+  tree=proto_item_add_subtree(ti,ett_80211_mgt_ie);
+
   proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
                              "Tag Number: %u (%s)",
                              tag_no,
@@ -1191,190 +1536,396 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
                                         (tag_no >= 17 && tag_no <= 31) ?
                                         "Reserved for challenge text" :
                                         "Reserved tag number"));
-
-  tag_len = tvb_get_guint8(tvb, offset + 1);
-  proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
-
-  tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
+  proto_tree_add_uint (tree, (tag_no==TAG_TIM ? tim_length : tag_length), tvb, offset + 1, 1, tag_len);
 
   switch (tag_no)
     {
 
-
     case TAG_SSID:
-      memset (out_buff, 0, SHORT_STR);
-
-      memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
-      out_buff[tag_len + 1] = 0;
-
-      proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
-                            tag_len, out_buff);
+      if(beacon_padding == 0) /* padding bug */
+      {
+        char *ssid;
+
+        ssid = tvb_get_ephemeral_string(tvb, offset + 2, tag_len);
+        proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+                               tag_len, ssid);
+        if (check_col (pinfo->cinfo, COL_INFO)) {
+          if (tag_len > 0) {
+            col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID: \"%s\"",
+                            format_text(ssid, tag_len));
+          } else {
+            col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID: Broadcast");
+          }
+        }
+        if (tag_len > 0) {
+          proto_item_append_text(ti, ": \"%s\"",
+                                 format_text(ssid, tag_len));
+        } else {
+          proto_item_append_text(ti, ": Broadcast");
+        }
+       beacon_padding++; /* padding bug */
+      }
       break;
 
-
-
     case TAG_SUPP_RATES:
     case TAG_EXT_SUPP_RATES:
-      memset (out_buff, 0, SHORT_STR);
-      strcpy (out_buff, "Supported rates: ");
-      n = strlen (out_buff);
-
-      for (i = 0; i < tag_len && n < SHORT_STR; i++)
-       {
-           ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
-                          (tag_data_ptr[i] & 0x7F) * 0.5,
-                          (tag_data_ptr[i] & 0x80) ? "(B)" : "");
-           if (ret == -1 || ret >= SHORT_STR - n) {
-             /* Some versions of snprintf return -1 if they'd truncate
-                the output. Others return <buf_size> or greater.  */
-             break;
-           }
-           n += ret;
-       }
-      if (n < SHORT_STR)
-       snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
+      if (tag_len < 1)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len,
+               "Tag length %u too short, must be > 0", tag_len);
+        break;
+      }
+      tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
 
+      tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
+      for (i = 0, n = 0; i < tag_len && n < SHORT_STR; i++) {
+        ret = g_snprintf (print_buff + n, SHORT_STR - n, "%2.1f%s ",
+                        (tag_data_ptr[i] & 0x7F) * 0.5,
+                        (tag_data_ptr[i] & 0x80) ? "(B)" : "");
+        if (ret == -1 || ret >= SHORT_STR - n) {
+          /* Some versions of snprintf return -1 if they'd truncate
+             the output. Others return <buf_size> or greater.  */
+          break;
+        }
+        n += ret;
+      }
+      g_snprintf (out_buff, SHORT_STR, "Supported rates: %s [Mbit/sec]", print_buff);
       out_buff[SHORT_STR-1] = '\0';
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
                             tag_len, out_buff);
+      proto_item_append_text(ti, ": %s", print_buff);
       break;
 
-
-
     case TAG_FH_PARAMETER:
-      memset (out_buff, 0, SHORT_STR);
-
-      snprintf (out_buff, SHORT_STR,
-               "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
-               "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
-               tag_data_ptr[3], tag_data_ptr[4]);
-
+      if (tag_len < 5)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 5",
+                             tag_len);
+        break;
+      }
+      g_snprintf (out_buff, SHORT_STR,
+               "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, Hop Index %2d",
+               tvb_get_letohs(tvb, offset + 2),
+               tvb_get_guint8(tvb, offset + 4),
+               tvb_get_guint8(tvb, offset + 5),
+               tvb_get_guint8(tvb, offset + 6));
+      out_buff[SHORT_STR-1] = '\0';
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
-                            tag_len, out_buff);
+                             tag_len, out_buff);
       break;
 
-
-
     case TAG_DS_PARAMETER:
-      memset (out_buff, 0, SHORT_STR);
-
-      snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
+      if (tag_len < 1)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 1",
+                             tag_len);
+        break;
+      }
+      g_snprintf (out_buff, SHORT_STR, "Current Channel: %u",
+                tvb_get_guint8(tvb, offset + 2));
+      out_buff[SHORT_STR-1] = '\0';
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
-                            tag_len, out_buff);
+                             tag_len, out_buff);
+      proto_item_append_text(ti, ": %s", out_buff);
       break;
 
-
     case TAG_CF_PARAMETER:
-      memset (out_buff, 0, SHORT_STR);
-
-      snprintf (out_buff, SHORT_STR,
-               "CFP count %u, CFP period %u, CFP max duration %u, "
-               "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
-               pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
-
-      proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
-                            tag_len, out_buff);
+      if (tag_len < 6)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 6",
+                             tag_len);
+        break;
+      }
+      g_snprintf (out_buff, SHORT_STR, "CFP count: %u",
+                tvb_get_guint8(tvb, offset + 2));
+      out_buff[SHORT_STR-1] = '\0';
+      proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 2,
+                                   1, out_buff, "%s", out_buff);
+      g_snprintf (out_buff, SHORT_STR, "CFP period: %u",
+                tvb_get_guint8(tvb, offset + 3));
+      out_buff[SHORT_STR-1] = '\0';
+      proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 3,
+                                   1, out_buff, "%s", out_buff);
+      g_snprintf (out_buff, SHORT_STR, "CFP max duration: %u",
+                tvb_get_letohs(tvb, offset + 4));
+      out_buff[SHORT_STR-1] = '\0';
+      proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 4,
+                                   2, out_buff, "%s", out_buff);
+      g_snprintf (out_buff, SHORT_STR, "CFP Remaining: %u",
+                tvb_get_letohs(tvb, offset + 6));
+      out_buff[SHORT_STR-1] = '\0';
+      proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 6,
+                                   2, out_buff, "%s", out_buff);
+      proto_item_append_text(ti, ": CFP count %u, CFP period %u, CFP max duration %u, "
+                             "CFP Remaining %u",
+                             tvb_get_guint8(tvb, offset + 2),
+                             tvb_get_guint8(tvb, offset + 3),
+                             tvb_get_letohs(tvb, offset + 4),
+                             tvb_get_letohs(tvb, offset + 6));
       break;
 
-
     case TAG_TIM:
-      memset (out_buff, 0, SHORT_STR);
-      snprintf (out_buff, SHORT_STR,
-               "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
-               "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
-               tag_data_ptr[2]);
-      proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
-                            tag_len, out_buff);
+      if (tag_len < 4)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 4",
+                             tag_len);
+        break;
+      }
+      {
+        guint8 bmapctl;
+        guint8 bmapoff;
+        guint8 bmaplen;
+        const guint8* bmap;
+
+        proto_tree_add_item(tree, tim_dtim_count, tvb,
+                            offset + 2, 1, TRUE);
+        proto_tree_add_item(tree, tim_dtim_period, tvb,
+                            offset + 3, 1, TRUE);
+        proto_item_append_text(ti, ": DTIM %u of %u bitmap",
+                               tvb_get_guint8(tvb, offset + 2),
+                               tvb_get_guint8(tvb, offset + 3));
+
+        bmapctl = tvb_get_guint8(tvb, offset + 4);
+        bmapoff = bmapctl>>1;
+        proto_tree_add_uint_format(tree, tim_bmapctl, tvb,
+                            offset + 4, 1, bmapctl,
+                            "Bitmap Control: 0x%02X (mcast:%u, bitmap offset %u)",
+                            bmapctl, bmapctl&1, bmapoff);
+
+        bmaplen = tag_len - 3;
+        bmap = tvb_get_ptr(tvb, offset + 5, bmaplen);
+        if (bmaplen==1 && 0==bmap[0] && !(bmapctl&1)) {
+          proto_item_append_text(ti, " empty");
+        } else {
+          if (bmapctl&1) {
+            proto_item_append_text(ti, " mcast");
+          }
+        }
+        if (bmaplen>1 || bmap[0]) {
+          int len=g_snprintf (out_buff, SHORT_STR,
+                            "Bitmap: traffic for AID's:");
+          int i=0;
+          for (i=0;i<bmaplen*8;i++) {
+            if (bmap[i/8] & (1<<(i%8))) {
+              int aid=i+2*bmapoff*8;
+              len+=g_snprintf (out_buff+len, SHORT_STR-len," %u", aid);
+              proto_item_append_text(ti, " %u", aid);
+              if (len>=SHORT_STR) {
+                break;
+              }
+            }
+          }
+          out_buff[SHORT_STR-1] = '\0';
+          proto_tree_add_string_format (tree, tag_interpretation, tvb, offset + 5,
+               bmaplen, out_buff, "%s", out_buff);
+        }
+      }
       break;
 
-
-
     case TAG_IBSS_PARAMETER:
-      memset (out_buff, 0, SHORT_STR);
-      snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
-               pletohs (tag_data_ptr));
-
+      if (tag_len < 2)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 2",
+                             tag_len);
+        break;
+      }
+      g_snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
+                tvb_get_letohs(tvb, offset + 2));
+      out_buff[SHORT_STR-1] = '\0';
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
                             tag_len, out_buff);
+      proto_item_append_text(ti, ": %s", out_buff);
       break;
 
+    case TAG_COUNTRY_INFO: /* IEEE 802.11d-2001 and IEEE 802.11j-2004 */
+      {
+        char ccode[2+1];
 
-    case TAG_COUNTRY_INFO:
-      memset (out_buff, 0, SHORT_STR);
-
-      snprintf (out_buff, SHORT_STR, "Country Code: %c%c, %s Environment",
-               tag_data_ptr[0], tag_data_ptr[1], 
-               val_to_str(tag_data_ptr[2], environment_vals,"Unknown (0x%02x)"));
-
-      n = strlen (out_buff);
-
-      for (i = 3; (i + 3) <= tag_len && n < SHORT_STR; i += 3)
-      { 
-        ret = snprintf(out_buff + n, SHORT_STR - n,
-                       ", Start Channel: %u, Channels: %u, Max TX Power: %d dBm",
-                       tag_data_ptr[i], tag_data_ptr[i + 1],
-                       (gint)tag_data_ptr[i + 2]);
-
-        if (ret == -1 || ret >= SHORT_STR - n) {
-          /* Some versions of snprintf return -1 if they'd truncate
-             the output. Others return <buf_size> or greater.  */
+        if (tag_len < 3)
+        {
+          proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 3",
+                               tag_len);
           break;
         }
-        n += ret;
+        tvb_memcpy(tvb, ccode, offset + 2, 2);
+        ccode[2] = '\0';
+        g_snprintf (out_buff, SHORT_STR, "Country Code: %s, %s Environment",
+                 format_text(ccode, 2),
+                 val_to_str(tvb_get_guint8(tvb, offset + 4), environment_vals,"Unknown (0x%02x)"));
+        out_buff[SHORT_STR-1] = '\0';
+        proto_item_append_text(ti, ": %s", out_buff);
+        proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,3, out_buff);
+
+        for (i = 3; (i + 3) <= tag_len; i += 3)
+        {
+         guint8 val1, val2, val3;
+         val1 = tvb_get_guint8(tvb, offset + 2 + i);
+         val2 = tvb_get_guint8(tvb, offset + 3 + i);
+         val3 = tvb_get_guint8(tvb, offset + 4 + i);
+
+         if (val1 <= 200) {  /* 802.11d */
+            proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 2+i,3, out_buff,
+                                       "  Start Channel: %u, Channels: %u, Max TX Power: %d dBm",
+                                       val1, val2, (gint) val3);
+         } else {  /* 802.11j */
+            proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 2+i,3, out_buff,
+                                       "  Reg Extension Id: %u, Regulatory Class: %u, Coverage Class: %u",
+                                       val1, val2, val3);
+         }
+        }
       }
-
-      proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,tag_len, out_buff);
       break;
 
+    case TAG_QBSS_LOAD:
+      if (tag_len < 4 || tag_len >5)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Wrong QBSS Tag Length %u", tag_len);
+        break;
+      }
+
+      if (tag_len == 4)
+      {
+        /* QBSS Version 1 */
+        proto_tree_add_string (tree, tag_interpretation, tvb, offset + 1,
+          tag_len, "Cisco QBSS Version 1 - non CCA");
+
+        /* Extract Values */
+        proto_tree_add_uint (tree, hf_qbss_version, tvb, offset + 2, tag_len, 1);
+        proto_tree_add_item (tree, hf_qbss_scount, tvb, offset + 2, 2, TRUE);
+        proto_tree_add_item (tree, hf_qbss_cu, tvb, offset + 4, 1, FALSE);
+        proto_tree_add_item (tree, hf_qbss_adc, tvb, offset + 5, 1, FALSE);
+      }
+      else if (tag_len == 5)
+      {
+         /* QBSS Version 2 */
+         proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+           tag_len, "802.11e CCA Version");
+
+         /* Extract Values */
+         proto_tree_add_uint (tree, hf_qbss_version, tvb, offset + 2, tag_len, 2);
+         proto_tree_add_item (tree, hf_qbss_scount, tvb, offset + 2, 2, TRUE);
+         proto_tree_add_item (tree, hf_qbss_cu, tvb, offset + 4, 1, FALSE);
+         proto_tree_add_item (tree, hf_qbss_adc, tvb, offset + 5, 2, FALSE);
+      }
+      break;
 
     case TAG_FH_HOPPING_PARAMETER:
-      memset (out_buff, 0, SHORT_STR);
-      snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u", 
-                       tag_data_ptr[0], tag_data_ptr[1]);
+      if (tag_len < 2)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 2",
+                             tag_len);
+        break;
+      }
+      g_snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u",
+                tvb_get_guint8(tvb, offset + 2),
+                tvb_get_guint8(tvb, offset + 3));
+      out_buff[SHORT_STR-1] = '\0';
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, tag_len, out_buff);
-                            
-
+      proto_item_append_text(ti, ": %s", out_buff);
       break;
 
-
     case TAG_CHALLENGE_TEXT:
-      memset (out_buff, 0, SHORT_STR);
-      snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
+      g_snprintf (out_buff, SHORT_STR, "Challenge text: %s",
+                tvb_bytes_to_str(tvb, offset + 2, tag_len));
+      out_buff[SHORT_STR-1] = '\0';
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
                             tag_len, out_buff);
-
       break;
 
-
-
     case TAG_ERP_INFO:
     case TAG_ERP_INFO_OLD:
-      memset (out_buff, 0, SHORT_STR);
+      {
+        guint8 erp_info;
 
-      snprintf (out_buff, SHORT_STR,
-               "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)",
-               tag_data_ptr[0],
-               tag_data_ptr[0] & 0x01 ? "" : "no ",
-               tag_data_ptr[0] & 0x02 ? "" : "do not ",
-               tag_data_ptr[0] & 0x04 ? "short or long": "long");
-      proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
-                            tag_len, out_buff);
+        if (tag_len < 1)
+        {
+          proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 1",
+                               tag_len);
+          break;
+        }
+        erp_info = tvb_get_guint8 (tvb, offset + 2);
+        g_snprintf (print_buff, SHORT_STR, "%sNon-ERP STAs, %suse protection, %s preambles",
+                  erp_info & 0x01 ? "" : "no ",
+                  erp_info & 0x02 ? "" : "do not ",
+                  /* 802.11g, 7.3.2.13: 1 means "one or more ... STAs
+                   * are not short preamble capable" */
+                  erp_info & 0x04 ? "long": "short or long");
+        print_buff[SHORT_STR-1] = '\0';
+        g_snprintf (out_buff, SHORT_STR,
+                  "ERP info: 0x%x (%s)",erp_info,print_buff);
+        out_buff[SHORT_STR-1] = '\0';
+        proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+                               tag_len, out_buff);
+        proto_item_append_text(ti, ": %s", print_buff);
+      }
+      break;
 
+    case TAG_CISCO_UNKNOWN_1:
+      /* The Name of the sending device starts at offset 10 and is up to
+         15 or 16 bytes in length, \0 padded */
+      if (tag_len < 26)
+      {
+        proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 26",
+                             tag_len);
+        break;
+      }
+      /* A cisco AP transmits the first 15 bytes of the AP name, probably
+         followed by '\0' for ASCII termination */
+      g_snprintf (out_buff, SHORT_STR, "%.16s",
+                tvb_format_stringzpad(tvb, offset + 12, 16));
+      out_buff[SHORT_STR-1] = '\0';
+      proto_tree_add_string_format (tree, tag_interpretation, tvb, offset + 2,
+                            tag_len, "", "Tag interpretation: Unknown + Name: %s #Clients: %u",
+                            out_buff,
+                            /* Total number off associated clients and
+                               repeater access points */
+                            tvb_get_guint8(tvb, offset + 28));
+      if (check_col (pinfo->cinfo, COL_INFO)) {
+          col_append_fstr(pinfo->cinfo, COL_INFO, ", Name: \"%s\"", out_buff);
+      }
       break;
 
     case TAG_VENDOR_SPECIFIC_IE:
-      dissect_vendor_specific_ie(tree, tvb, offset + 2, tag_len,
-                                tag_data_ptr);
+      tvb_ensure_bytes_exist (tvb, offset + 2, tag_len);
+      if (tag_len >= 3) {
+               oui = tvb_get_ntoh24(tvb, offset + 2);
+               tag_val = tvb_get_ptr(tvb, offset + 2, tag_len);
+
+#define WPAWME_OUI     0x0050F2
+#define RSNOUI_VAL     0x000FAC
+
+               switch (oui) {
+               case WPAWME_OUI:
+                       dissect_vendor_ie_wpawme(ti, tree, tvb, offset + 2, tag_len, tag_val);
+                       break;
+               case RSNOUI_VAL:
+                       dissect_vendor_ie_rsn(ti, tree, tvb, offset + 2, tag_len, tag_val);
+                       break;
+               case OUI_CISCOWL:       /* Cisco Wireless (Aironet) */
+                       dissect_vendor_ie_aironet(ti, tree, tvb, offset + 5, tag_len - 3);
+                       break;
+               default:
+                       proto_tree_add_bytes_format (tree, tag_oui, tvb, offset + 2, 3,
+                               "", "Vendor: %s", get_manuf_name(tag_val));
+                       proto_item_append_text(ti, ": %s", get_manuf_name(tag_val));
+                       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 5,
+                               tag_len - 3, "Not interpreted");
+                       break;
+               }
+
+      }
       break;
 
     case TAG_RSN_IE:
-      dissect_rsn_ie(tree, tvb, offset + 2, tag_len, tag_data_ptr);
+      dissect_rsn_ie(tree, tvb, offset + 2, tag_len,
+                     tvb_get_ptr (tvb, offset + 2, tag_len));
       break;
 
-
     default:
+      tvb_ensure_bytes_exist (tvb, offset + 2, tag_len);
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
                             tag_len, "Not interpreted");
+      proto_item_append_text(ti, ": Tag %u Len %u", tag_no, tag_len);
       break;
     }
 
@@ -1382,13 +1933,14 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 }
 
 void
-ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, proto_tree * tree,
-       int tagged_parameters_len)
+ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, packet_info * pinfo,
+       proto_tree * tree, int tagged_parameters_len)
 {
   int next_len;
 
+  beacon_padding = 0; /* this is for the beacon padding confused with ssid fix */
   while (tagged_parameters_len > 0) {
-    if ((next_len=add_tagged_field (tree, tvb, offset))==0)
+    if ((next_len=add_tagged_field (pinfo, tree, tvb, offset))==0)
       break;
     if (next_len > tagged_parameters_len) {
       /* XXX - flag this as an error? */
@@ -1406,17 +1958,17 @@ static void
 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
        proto_tree * tree)
 {
-  proto_item *ti = NULL;
-  proto_tree *mgt_tree;
-  proto_tree *fixed_tree;
-  proto_tree *tagged_tree;
-  int offset;
-  int tagged_parameter_tree_len;
+      proto_item *ti = NULL;
+      proto_tree *mgt_tree;
+      proto_tree *fixed_tree;
+      proto_tree *tagged_tree;
+      int offset;
+      int tagged_parameter_tree_len;
 
-  CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
+      g_pinfo = pinfo;
+
+      CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
 
-  if (tree)
-    {
       ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
       mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
 
@@ -1427,14 +1979,13 @@ dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
          fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
          add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
          add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
-
          offset = 4;   /* Size of fixed fields */
+
          tagged_parameter_tree_len =
              tvb_reported_length_remaining(tvb, offset);
          tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
                                                   tagged_parameter_tree_len);
-
-         ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+         ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
              tagged_parameter_tree_len);
          break;
 
@@ -1444,15 +1995,13 @@ dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
          add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
          add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
          add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
-
          offset = 6;   /* Size of fixed fields */
 
          tagged_parameter_tree_len =
              tvb_reported_length_remaining(tvb, offset);
          tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
                                                   tagged_parameter_tree_len);
-
-         ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+         ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
              tagged_parameter_tree_len);
          break;
 
@@ -1462,30 +2011,28 @@ dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
          add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
          add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
          add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
-
          offset = 10;  /* Size of fixed fields */
+
          tagged_parameter_tree_len =
              tvb_reported_length_remaining(tvb, offset);
          tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
                                                   tagged_parameter_tree_len);
-
-         ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+         ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
              tagged_parameter_tree_len);
          break;
 
        case MGT_REASSOC_RESP:
-         fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
+         fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
          add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
          add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
          add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
-
          offset = 6;   /* Size of fixed fields */
+
          tagged_parameter_tree_len =
              tvb_reported_length_remaining(tvb, offset);
          tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
                                                   tagged_parameter_tree_len);
-
-         ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+         ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
              tagged_parameter_tree_len);
          break;
 
@@ -1496,8 +2043,7 @@ dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
              tvb_reported_length_remaining(tvb, offset);
          tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
                                                   tagged_parameter_tree_len);
-
-         ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+         ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
              tagged_parameter_tree_len);
          break;
 
@@ -1507,32 +2053,29 @@ dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
          add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
          add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
          add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
-
          offset = 12;  /* Size of fixed fields */
+
          tagged_parameter_tree_len =
              tvb_reported_length_remaining(tvb, offset);
          tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
                                                   tagged_parameter_tree_len);
-
-         ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+         ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
              tagged_parameter_tree_len);
          break;
 
 
        case MGT_BEACON:                /* Dissect protocol payload fields  */
          fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
-
          add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
          add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
          add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
-
          offset = 12;  /* Size of fixed fields */
+
          tagged_parameter_tree_len =
              tvb_reported_length_remaining(tvb, offset);
          tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
                                                   tagged_parameter_tree_len);
-
-         ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+         ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
              tagged_parameter_tree_len);
          break;
 
@@ -1552,7 +2095,6 @@ dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
          add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
          add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
          add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
-
          offset = 6;   /* Size of fixed fields */
 
          tagged_parameter_tree_len =
@@ -1563,8 +2105,7 @@ dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
                                                       tvb,
                                                       offset,
                                                       tagged_parameter_tree_len);
-
-             ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+             ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
                tagged_parameter_tree_len);
            }
          break;
@@ -1577,61 +2118,103 @@ dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
 
 
        case MGT_ACTION:
-         fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 3);
-         add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
-
          switch (tvb_get_guint8(tvb, 0))
            {
 
-           case 17:    /* Management notification frame */
+           case CAT_SPECTRUM_MGMT:
+             switch (tvb_get_guint8(tvb, 1))
+               {
+               case SM_ACTION_MEASUREMENT_REQUEST:
+               case SM_ACTION_MEASUREMENT_REPORT:
+               case SM_ACTION_TPC_REQUEST:
+               case SM_ACTION_TPC_REPORT:
+                 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 3);
+                 add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
+                 add_fixed_field (fixed_tree, tvb, 1, FIELD_ACTION_CODE);
+                 add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
+                 offset = 3;   /* Size of fixed fields */
+                 break;
+
+               case SM_ACTION_CHAN_SWITCH_ANNC:
+                 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
+                 add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
+                 offset = 2;   /* Size of fixed fields */
+                 break;
+
+               default:
+                 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
+                 add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
+                 offset = 2;   /* Size of fixed fields */
+                 break;
+               }
+             break;
+
+           case CAT_MGMT_NOTIFICATION: /* Management notification frame */
+             fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
+             add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
              add_fixed_field (fixed_tree, tvb, 1, FIELD_WME_ACTION_CODE);
              add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
              add_fixed_field (fixed_tree, tvb, 3, FIELD_WME_STATUS_CODE);
-
              offset = 4;       /* Size of fixed fields */
-
-             tagged_parameter_tree_len =
-               tvb_reported_length_remaining(tvb, offset);
-             if (tagged_parameter_tree_len != 0)
-               {
-                 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
-                                                          tagged_parameter_tree_len);
-
-                 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
-                                                   tagged_parameter_tree_len);
-               }
              break;
 
-           default:    /* Management action frame */
-             add_fixed_field (fixed_tree, tvb, 1, FIELD_ACTION_CODE);
-             add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
+           default:
+             fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 1);
+             add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
+             offset = 1;       /* Size of fixed fields */
              break;
            }
+
+           tagged_parameter_tree_len =
+             tvb_reported_length_remaining(tvb, offset);
+           if (tagged_parameter_tree_len != 0)
+             {
+               tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+                                                        tagged_parameter_tree_len);
+               ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
+                                                 tagged_parameter_tree_len);
+             }
          break;
        }
-    }
 }
 
 static void
-set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
+set_src_addr_cols(packet_info *pinfo, const guint8 *addr, const char *type)
 {
   if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
     col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
                    get_ether_name(addr), type);
   if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
-    col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
-                    ether_to_str(addr), type);
+    col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s",
+                    ether_to_str(addr));
 }
 
 static void
-set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
+set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, const char *type)
 {
   if (check_col(pinfo->cinfo, COL_RES_DL_DST))
     col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
                     get_ether_name(addr), type);
   if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
-    col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
-                    ether_to_str(addr), type);
+    col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s",
+                    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 {
@@ -1647,20 +2230,22 @@ static void
 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;
   guint32 seq_number, frag_number;
   gboolean more_frags;
-  const guint8 *src = NULL, *dst = NULL;
+  const guint8 *src = NULL;
+  const guint8 *dst = NULL;
+  const guint8 *bssid = NULL;
   proto_item *ti = NULL;
   proto_item *flag_item;
   proto_item *fc_item;
   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;
@@ -1669,6 +2254,12 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
   volatile encap_t encap_type;
   guint8 octet1, octet2;
   char out_buff[SHORT_STR];
+  gint is_iv_bad;
+  guchar iv_buff[4];
+  wlan_hdr *volatile whdr;
+  static wlan_hdr whdrs[4];
+
+  whdr= &whdrs[0];
 
   if (check_col (pinfo->cinfo, COL_PROTOCOL))
     col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
@@ -1698,6 +2289,9 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
     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))
@@ -1705,9 +2299,10 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
           val_to_str(frame_type_subtype, frame_type_subtype_vals,
               "Unrecognized (Reserved frame)"));
 
-  flags = COOK_FLAGS (fcf);
+  flags = FCF_FLAGS (fcf);
   more_frags = HAVE_FRAGMENTS (flags);
 
+
   /* Add the radio information, if present, and the FC to the current tree */
   if (tree)
     {
@@ -1735,11 +2330,11 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
       }
 
       proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
-                          tvb, 
+                          tvb,
                           wlan_broken_fc?1:0, 1,
                           frame_type_subtype);
 
-      fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 
+      fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb,
                                            0, 2,
                                            fcf,
                                            "Frame Control: 0x%04X (%s)",
@@ -1748,57 +2343,57 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
       fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
 
 
-      proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 
+      proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb,
                           wlan_broken_fc?1:0, 1,
-                          COOK_PROT_VERSION (fcf));
+                          FCF_PROT_VERSION (fcf));
 
-      proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 
+      proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb,
                           wlan_broken_fc?1:0, 1,
-                          COOK_FRAME_TYPE (fcf));
+                          FCF_FRAME_TYPE (fcf));
 
       proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
-                          tvb, 
+                          tvb,
                           wlan_broken_fc?1:0, 1,
-                          COOK_FRAME_SUBTYPE (fcf));
+                          FCF_FRAME_SUBTYPE (fcf));
 
       flag_item =
-       proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 
+       proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb,
                                    wlan_broken_fc?0:1, 1,
                                    flags, "Flags: 0x%X", flags);
 
       flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
 
-      proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 
+      proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb,
                           wlan_broken_fc?0:1, 1,
-                          COOK_DS_STATUS (flags));
-      proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1, 
+                          FLAGS_DS_STATUS (flags));
+      proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1,
                                     flags);
-      proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1, 
+      proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1,
                                     flags);
 
-      proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 
+      proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb,
                              wlan_broken_fc?0:1, 1,
                              flags);
 
-      proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 
+      proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb,
                              wlan_broken_fc?0:1, 1, flags);
 
-      proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 
+      proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb,
                              wlan_broken_fc?0:1, 1, flags);
 
-      proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 
+      proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb,
                              wlan_broken_fc?0:1, 1,
                              flags);
 
-      proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb,
+      proto_tree_add_boolean (flag_tree, hf_fc_protected, tvb,
                              wlan_broken_fc?0:1, 1, flags);
 
-      proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 
+      proto_tree_add_boolean (flag_tree, hf_fc_order, tvb,
                              wlan_broken_fc?0:1, 1, flags);
 
       if (frame_type_subtype == CTRL_PS_POLL)
        proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
-                           COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
+                           ASSOC_ID(tvb_get_letohs(tvb,2)));
 
       else
          proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
@@ -1813,7 +2408,7 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
   frag_number = 0;
   seq_number = 0;
 
-  switch (COOK_FRAME_TYPE (fcf))
+  switch (FCF_FRAME_TYPE (fcf))
     {
 
     case MGT_FRAME:
@@ -1828,9 +2423,24 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
 
+      /* for tap */
+      SET_ADDRESS(&whdr->bssid, AT_ETHER, 6, tvb_get_ptr(tvb, 16,6));
+      SET_ADDRESS(&whdr->src, AT_ETHER, 6, src);
+      SET_ADDRESS(&whdr->dst, AT_ETHER, 6, dst);
+      whdr->type = frame_type_subtype;
+
       seq_control = tvb_get_letohs(tvb, 22);
-      frag_number = COOK_FRAGMENT_NUMBER(seq_control);
-      seq_number = COOK_SEQUENCE_NUMBER(seq_control);
+      frag_number = SEQCTL_FRAGMENT_NUMBER(seq_control);
+      seq_number = SEQCTL_SEQUENCE_NUMBER(seq_control);
+
+      if (check_col (pinfo->cinfo, COL_INFO))
+      {
+       col_append_fstr(pinfo->cinfo, COL_INFO,
+          ",SN=%d", seq_number);
+
+       col_append_fstr(pinfo->cinfo, COL_INFO,
+          ",FN=%d",frag_number);
+      }
 
       if (tree)
        {
@@ -1938,11 +2548,47 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
              proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
            }
          break;
+
+       case CTRL_BLOCK_ACK_REQ:
+         {
+           src = tvb_get_ptr (tvb, 10, 6);
+           dst = tvb_get_ptr (tvb, 4, 6);
+
+           set_src_addr_cols(pinfo, src, "TA");
+           set_dst_addr_cols(pinfo, dst, "RA");
+
+           if (tree)
+           {
+             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, src);
+
+             proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, dst);
+           }
+         /* TODO BAR */
+         break;
+         }
+
+       case CTRL_BLOCK_ACK:
+         {
+           src = tvb_get_ptr (tvb, 10, 6);
+           dst = tvb_get_ptr (tvb, 4, 6);
+
+           set_src_addr_cols(pinfo, src, "TA");
+           set_dst_addr_cols(pinfo, dst, "RA");
+
+           if (tree)
+           {
+             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, src);
+
+             proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, dst);
+           }
+           /* TODO BAR Format */
+           break;
+         }
        }
       break;
 
     case DATA_FRAME:
-      addr_type = COOK_ADDR_SELECTOR (fcf);
+      addr_type = FCF_ADDR_SELECTOR (fcf);
 
       /* In order to show src/dst address we must always do the following */
       switch (addr_type)
@@ -1951,24 +2597,28 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
        case DATA_ADDR_T1:
          src = tvb_get_ptr (tvb, 10, 6);
          dst = tvb_get_ptr (tvb, 4, 6);
+         bssid = tvb_get_ptr (tvb, 16, 6);
          break;
 
 
        case DATA_ADDR_T2:
          src = tvb_get_ptr (tvb, 16, 6);
          dst = tvb_get_ptr (tvb, 4, 6);
+         bssid = tvb_get_ptr (tvb, 10, 6);
          break;
 
 
        case DATA_ADDR_T3:
          src = tvb_get_ptr (tvb, 10, 6);
          dst = tvb_get_ptr (tvb, 16, 6);
+         bssid = tvb_get_ptr (tvb, 4, 6);
          break;
 
 
        case DATA_ADDR_T4:
          src = tvb_get_ptr (tvb, 24, 6);
          dst = tvb_get_ptr (tvb, 16, 6);
+         bssid = tvb_get_ptr (tvb, 16, 6);
          break;
        }
 
@@ -1977,9 +2627,25 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
 
+      /* for tap */
+
+      SET_ADDRESS(&whdr->bssid, AT_ETHER, 6, bssid);
+      SET_ADDRESS(&whdr->src, AT_ETHER, 6, src);
+      SET_ADDRESS(&whdr->dst, AT_ETHER, 6, dst);
+      whdr->type = frame_type_subtype;
+
       seq_control = tvb_get_letohs(tvb, 22);
-      frag_number = COOK_FRAGMENT_NUMBER(seq_control);
-      seq_number = COOK_SEQUENCE_NUMBER(seq_control);
+      frag_number = SEQCTL_FRAGMENT_NUMBER(seq_control);
+      seq_number = SEQCTL_SEQUENCE_NUMBER(seq_control);
+
+      if (check_col (pinfo->cinfo, COL_INFO))
+      {
+       col_append_fstr(pinfo->cinfo, COL_INFO,
+          ",SN=%d", seq_number);
+
+       col_append_fstr(pinfo->cinfo, COL_INFO,
+          ",FN=%d",frag_number);
+      }
 
       /* Now if we have a tree we start adding stuff */
       if (tree)
@@ -2117,75 +2783,146 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
          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,
-                       "Frame check sequence: 0x%08x (correct)", sent_fcs);
+                       "Frame check sequence: 0x%08x [correct]", sent_fcs);
              else
                proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
                        hdr_len + len, 4, sent_fcs,
-                       "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
+                       "Frame check sequence: 0x%08x [incorrect, should be 0x%08x]",
                        sent_fcs, fcs);
            }
        }
     }
 
-  if (tree && (frame_type_subtype == DATA_QOS_DATA || frame_type_subtype == DATA_QOS_NULL)) {
-      proto_item *qos_fields;
-      proto_tree *qos_tree;
-
-      guint16 qos_control, qos_priority, qos_ack_policy;
-
-      qos_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len - 2, 2,
-                                      "QoS parameters");
-      qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters);
-
-      qos_control = tvb_get_letohs(tvb, hdr_len - 2);
-      qos_priority = COOK_QOS_PRIORITY(qos_control);
-      qos_ack_policy = COOK_QOS_ACK_POLICY(qos_control);
-      proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
-                                 hdr_len - 2, 2, qos_priority,
-                                 "Priority: %d (%s) (%s)",
-                                 qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]);
-      proto_tree_add_uint_format (qos_tree, hf_qos_ack_policy, tvb,
-                                 hdr_len - 2, 2, qos_ack_policy,
-                                 "Ack Policy: %d (%sAcknowledge)", 
-                                 qos_ack_policy, qos_ack_policy ? "Do not " : "");
-  }
+
 
   /*
    * Only management and data frames have a body, so we don't have
    * anything more to do for other types of frames.
    */
-  switch (COOK_FRAME_TYPE (fcf))
+  switch (FCF_FRAME_TYPE (fcf))
     {
 
     case MGT_FRAME:
       break;
 
     case DATA_FRAME:
+      if (tree && DATA_FRAME_IS_QOS(frame_type_subtype))
+       {
+
+         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;
+
+         /*
+          * 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, qosoff + 0);
+         qos_priority = QOS_PRIORITY(qos_control);
+         qos_ack_policy = QOS_ACK_POLICY(qos_control);
+         qos_eosp = QOS_EOSP(qos_control);
+         qos_field_content = QOS_FIELD_CONTENT( qos_control);
+
+         proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
+             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,
+             qosoff, 1, qos_eosp);
+
+           if (DATA_FRAME_IS_CF_POLL(frame_type_subtype)) {
+             /* txop limit */
+             proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
+                 qosoff + 1, 1, qos_field_content, "TXOP Limit: %d ", qos_field_content);
+
+           } else {
+             /* qap ps buffer state */
+             proto_item *qos_ps_buf_state_fields;
+             proto_tree *qos_ps_buf_state_tree;
+             guint16 buf_state;
+             guint16 buf_ac;
+             guint16 buf_load;
+
+             buf_state = QOS_PS_BUF_STATE(qos_field_content);
+             buf_ac = QOS_PS_BUF_AC(qos_field_content);  /*access category */
+             buf_load = QOS_PS_BUF_LOAD(qos_field_content);
+
+             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);
+
+/*     FIXME: hf_ values not defined
+             proto_tree_add_boolean (qos_ps_buf_state_tree, hf_qos_buf_state, tvb,
+                 1, 1, buf_state);
+
+             proto_tree_add_uint_format (qos_ps_buf_state_tree, hf_qos_buf_ac, tvb,
+                 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,
+                 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,
+                 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,
+                 qosoff + 1, 1, qos_field_content, "TXOP Limit Requested: %d ", qos_field_content);
+         }
+
+         proto_tree_add_uint (qos_tree, hf_qos_ack_policy, tvb, qosoff, 1,
+             qos_ack_policy);
+
+       } /* end of qos control field */
+
       /*
        * No-data frames don't have a body.
        */
-      switch (frame_type_subtype)
-       {
+      if (DATA_FRAME_IS_NULL(frame_type_subtype))
+       return;
 
-       case DATA_NULL_FUNCTION:
-       case DATA_CF_ACK_NOD:
-       case DATA_CF_POLL_NOD:
-       case DATA_CF_ACK_POLL_NOD:
-       case DATA_QOS_NULL:
-         return;
-       }
-       break;
+      break;
+
+    case CONTROL_FRAME:
+      return;
 
     default:
       return;
     }
 
-  if (IS_WEP(COOK_FLAGS(fcf))) {
+  if (IS_PROTECTED(FCF_FLAGS(fcf))) {
     /*
      * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
      * the data, if we have a matching key.  Otherwise display it as data.
@@ -2196,7 +2933,7 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
     guint8 key, keybyte;
 
     keybyte = tvb_get_guint8(tvb, hdr_len + 3);
-    key = COOK_WEP_KEY(keybyte);
+    key = KEY_OCTET_WEP_KEY(keybyte);
     if ((keybyte & KEY_EXTIV) && (len >= EXTIV_LEN)) {
       /* Extended IV; this frame is likely encrypted with TKIP or CCMP */
       if (tree) {
@@ -2210,15 +2947,15 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
         * determined to be possible only with one of the encryption protocols.
         */
        if (tvb_get_guint8(tvb, hdr_len + 1) & 0x20) {
-         snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
+         g_snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
                   tvb_get_letohl(tvb, hdr_len + 4),
                   tvb_get_guint8(tvb, hdr_len),
                   tvb_get_guint8(tvb, hdr_len + 2));
          proto_tree_add_string(wep_tree, hf_tkip_extiv, tvb, hdr_len,
                                EXTIV_LEN, out_buff);
-       } 
+       }
        if (tvb_get_guint8(tvb, hdr_len + 2) == 0) {
-         snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
+         g_snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
                   tvb_get_letohl(tvb, hdr_len + 4),
                   tvb_get_guint8(tvb, hdr_len + 1),
                   tvb_get_guint8(tvb, hdr_len));
@@ -2244,7 +2981,7 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
        * Also, just pass the data *following* the WEP parameters as the
        * buffer to decrypt.
        */
-      iv = tvb_get_letoh24(tvb, hdr_len);
+      iv = tvb_get_ntoh24(tvb, hdr_len);
       if (tree) {
        proto_item *wep_fields;
 
@@ -2253,6 +2990,14 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
 
        wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
        proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
+       tvb_memcpy(tvb, iv_buff, hdr_len, 3);
+       is_iv_bad = weak_iv(iv_buff);
+       if (is_iv_bad != -1) {
+               proto_tree_add_boolean_format (wep_tree, hf_wep_iv_weak,
+                                              tvb, 0, 0, TRUE,
+                                              "Weak IV for key byte %d",
+                                              is_iv_bad);
+       }
       }
       if (tree)
         proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
@@ -2311,25 +3056,25 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
       next_tvb = tvb_new_subset(tvb, hdr_len + ivlen, len, reported_len);
 
       if (tree && can_decrypt)
-       proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
-                                   hdr_len + ivlen + len, 4, 
+       proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
+                                   hdr_len + ivlen + len, 4,
                                    tvb_get_ntohl(tvb, hdr_len + ivlen + len),
-                                   "WEP ICV: 0x%08x (not verified)", 
+                                   "WEP ICV: 0x%08x (not verified)",
                                    tvb_get_ntohl(tvb, hdr_len + ivlen + len));
 
       if (pinfo->ethertype != ETHERTYPE_CENTRINO_PROMISC)
       {
         /* Some wireless drivers (such as Centrino) WEP payload already decrypted */
         call_dissector(data_handle, next_tvb, pinfo, tree);
-        return;
+        goto end_of_wlan;
       }
     } else {
 
       if (tree)
-       proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
-                                   hdr_len + ivlen + len, 4, 
+       proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
+                                   hdr_len + ivlen + len, 4,
                                    tvb_get_ntohl(tvb, hdr_len + ivlen + len),
-                                   "WEP ICV: 0x%08x (correct)", 
+                                   "WEP ICV: 0x%08x (correct)",
                                    tvb_get_ntohl(tvb, hdr_len + ivlen + len));
 
       add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
@@ -2429,10 +3174,10 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
     next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
     call_dissector(data_handle, next_tvb, pinfo, tree);
     pinfo->fragmented = save_fragmented;
-    return;
+    goto end_of_wlan;
   }
 
-  switch (COOK_FRAME_TYPE (fcf))
+  switch (FCF_FRAME_TYPE (fcf))
     {
 
     case MGT_FRAME:
@@ -2492,7 +3237,7 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
         break;
 
       case ENCAP_ETHERNET:
-        call_dissector(eth_handle, next_tvb, pinfo, tree);
+        call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
         break;
 
       case ENCAP_IPX:
@@ -2502,6 +3247,9 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
       break;
     }
   pinfo->fragmented = save_fragmented;
+
+  end_of_wlan:
+  tap_queue_packet(wlan_tap, pinfo, whdr);
 }
 
 /*
@@ -2511,7 +3259,17 @@ static void
 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);
 }
 
 /*
@@ -2522,7 +3280,7 @@ static void
 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);
 }
 
 /*
@@ -2533,7 +3291,7 @@ dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
 static void
 dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
 {
-  dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE, TRUE);
+  dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, 0, TRUE, FALSE);
 }
 
 /*
@@ -2543,7 +3301,7 @@ dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
 static void
 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
 {
-  dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE, FALSE);
+  dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, 0, FALSE, FALSE);
 }
 
 static void
@@ -2556,6 +3314,9 @@ wlan_defragment_init(void)
 void
 proto_register_ieee80211 (void)
 {
+  int i;
+  GString *key_name, *key_title, *key_desc;
+
   static const value_string frame_type[] = {
     {MGT_FRAME,     "Management frame"},
     {CONTROL_FRAME, "Control frame"},
@@ -2564,10 +3325,14 @@ proto_register_ieee80211 (void)
   };
 
   static const value_string tofrom_ds[] = {
-    {0,                       "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
-    {FLAG_TO_DS,              "Frame is entering DS (To DS: 1  From DS: 0)"},
-    {FLAG_FROM_DS,            "Frame is exiting DS (To DS: 0  From DS: 1)"},
-    {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1  From DS: 1)"},
+    {0,                       "Not leaving DS or network is operating "
+      "in AD-HOC mode (To DS: 0 From DS: 0)"},
+    {FLAG_TO_DS,              "Frame from STA to DS via an AP (To DS: 1 "
+      "From DS: 0)"},
+    {FLAG_FROM_DS,            "Frame from DS to a STA via AP(To DS: 0 "
+      "From DS: 1)"},
+    {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS from one AP to another "
+      "AP (To DS: 1 From DS: 1)"},
     {0, NULL}
   };
 
@@ -2601,9 +3366,9 @@ proto_register_ieee80211 (void)
     "No data buffered"
   };
 
-  static const true_false_string wep_flags = {
-    "WEP is enabled",
-    "WEP is disabled"
+  static const true_false_string protected_flags = {
+    "Data is protected",
+    "Data is not protected"
   };
 
   static const true_false_string order_flags = {
@@ -2647,12 +3412,35 @@ proto_register_ieee80211 (void)
     "DSSS-OFDM modulation not allowed"
   };
 
+  static const true_false_string cf_spec_man_flags = {
+    "dot11SpectrumManagementRequired TRUE",
+    "dot11SpectrumManagementRequired FALSE",
+  };
+
+  static const true_false_string cf_apsd_flags = {
+    "apsd implemented",
+    "apsd not implemented",
+  };
 
+  static const true_false_string cf_del_blk_ack_flags = {
+    "delayed block ack implemented",
+    "delayed block ack not implented",
+  };
+
+  static const true_false_string cf_imm_blk_ack_flags = {
+    "immediate block ack implemented",
+    "immediate block ack not implented",
+  };
   static const true_false_string cf_ibss_flags = {
     "Transmitter belongs to an IBSS",
     "Transmitter belongs to a BSS"
   };
 
+  static const true_false_string eosp_flag = {
+    "End of service period",
+    "Service period"
+  };
+
   static const value_string sta_cf_pollable[] = {
     {0x00, "Station is not CF-Pollable"},
     {0x02, "Station is CF-Pollable, "
@@ -2660,6 +3448,7 @@ proto_register_ieee80211 (void)
     {0x01, "Station is CF-Pollable, "
      "requesting to be placed on the CF-polling list"},
     {0x03, "Station is CF-Pollable, requesting never to be polled"},
+    {0x0200, "QSTA requesting association in QBSS"},
     {0, NULL}
   };
 
@@ -2668,6 +3457,10 @@ proto_register_ieee80211 (void)
     {0x02, "Point coordinator at AP for delivery only (no polling)"},
     {0x01, "Point coordinator at AP for delivery and polling"},
     {0x03, "Reserved"},
+    {0x0200, "QAP (HC) does not use CFP for delivery of unicast data type frames"},
+    {0x0202, "QAP (HC) uses CFP for delivery, but does not send CF-Polls to non-QoS STAs"},
+    {0x0201, "QAP (HC) uses CFP for delivery, and sends CF-Polls to non-QoS STAs"},
+    {0x0203, "Reserved"},
     {0, NULL}
   };
 
@@ -2675,6 +3468,7 @@ proto_register_ieee80211 (void)
   static const value_string auth_alg[] = {
     {0x00, "Open System"},
     {0x01, "Shared key"},
+    {0x80, "Network EAP"},     /* Cisco proprietary? */
     {0, NULL}
   };
 
@@ -2691,7 +3485,11 @@ proto_register_ieee80211 (void)
     {0x07, "Class 3 frame received from nonassociated station"},
     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
     {0x09, "Station requesting (re)association is not authenticated with "
-     "responding station"},
+      "responding station"},
+    {0x0A, "Disassociated because the information in the Power Capability "
+      "element is unacceptable"},
+    {0x0B, "Disassociated because the information in the Supported"
+      "Channels element is unacceptable"},
     {0x0D, "Invalid Information Element"},
     {0x0E, "Michael MIC failure"},
     {0x0F, "4-Way Handshake timeout"},
@@ -2705,6 +3503,18 @@ proto_register_ieee80211 (void)
     {0x16, "Invalid RSN IE Capabilities"},
     {0x17, "IEEE 802.1X Authentication failed"},
     {0x18, "Cipher suite is rejected per security policy"},
+    {0x20, "Disassociated for unspecified, QoS-related reason"},
+    {0x21, "Disassociated because QAP lacks sufficient bandwidth for this QSTA"},
+    {0x22, "Disassociated because of excessive number of frames that need to be "
+      "acknowledged, but are not acknowledged for AP transmissions and/or poor "
+       "channel conditions"},
+    {0x23, "Disassociated because QSTA is transmitting outside the limits of its TXOPs"},
+    {0x24, "Requested from peer QSTA as the QSTA is leaving the QBSS (or resetting)"},
+    {0x25, "Requested from peer QSTA as it does not want to use the mechanism"},
+    {0x26, "Requested from peer QSTA as the QSTA received frames using the mechanism "
+      "for which a set up is required"},
+    {0x27, "Requested from peer QSTA due to time out"},
+    {0x2D, "Peer QSTA does not support the requested cipher suite"},
     {0x00, NULL}
   };
 
@@ -2736,10 +3546,31 @@ proto_register_ieee80211 (void)
      "PBCC encoding"},
     {0x15, "Association denied due to requesting station not supporting "
      "channel agility"},
+    {0x16, "Association request rejected because Spectrum Management"
+      "capability is required"},
+    {0x17, "Association request rejected because the information in the"
+      "Power Capability element is unacceptable"},
+    {0x18, "Association request rejected because the information in the"
+      "Supported Channels element is unacceptable"},
     {0x19, "Association denied due to requesting station not supporting "
      "short slot operation"},
     {0x1A, "Association denied due to requesting station not supporting "
      "DSSS-OFDM operation"},
+    {0x20, "Unspecified, QoS-related failure"},
+    {0x21, "Association denied due to QAP having insufficient bandwidth "
+      "to handle another QSTA"},
+    {0x22, "Association denied due to excessive frame loss rates and/or "
+      "poor conditions on current operating channel"},
+    {0x23, "Association (with QBSS) denied due to requesting station not "
+      "supporting the QoS facility"},
+    {0x24, "Association denied due to requesting station not supporting "
+      "Block Ack"},
+    {0x25, "The request has been declined."},
+    {0x26, "The request has not been successful as one or more parameters "
+      "have invalid values."},
+    {0x27, "The TS has not been created because the request cannot be honored. "
+      "However, a suggested TSPEC is provided so that the initiating QSTA may "
+       "attempt to set another TS with the suggested changes to the TSPEC."},
     {0x28, "Invalid Information Element"},
     {0x29, "Group Cipher is not valid"},
     {0x2A, "Pairwise Cipher is not valid"},
@@ -2747,16 +3578,30 @@ proto_register_ieee80211 (void)
     {0x2C, "Unsupported RSN IE version"},
     {0x2D, "Invalid RSN IE Capabilities"},
     {0x2E, "Cipher suite is rejected per security policy"},
+    {0x2F, "The TS has not been created. However, the HC may be capable of "
+      "creating a TS, in response to a request, after the time indicated in the TS Delay element."},
+    {0x30, "Direct Link is not allowed in the BSS by policy"},
+    {0x31, "Destination STA is not present within this QBSS."},
+    {0x32, "The Destination STA is not a QSTA."},
     {0x00, NULL}
   };
 
   static const value_string category_codes[] = {
-    {0x11, "Management notification frame"},
-    {0x00, NULL}
+    {CAT_SPECTRUM_MGMT, "Spectrum Management"},
+    {CAT_QOS, "QoS"},
+    {CAT_DLS, "DLS"},
+    {CAT_BLOCK_ACK, "Block Ack"},
+    {CAT_MGMT_NOTIFICATION, "Management notification frame"},
+    {0, NULL}
   };
 
-  static const value_string action_codes[] = {
-    {0x00, NULL}
+  static const value_string action_codes[] ={
+    {SM_ACTION_MEASUREMENT_REQUEST, "Measurement Request"},
+    {SM_ACTION_MEASUREMENT_REPORT, "Measurement Report"},
+    {SM_ACTION_TPC_REQUEST, "TPC Request"},
+    {SM_ACTION_TPC_REPORT, "TPC Report"},
+    {SM_ACTION_CHAN_SWITCH_ANNC, "Channel Switch Announcement"},
+    {0, NULL}
   };
 
   static const value_string wme_action_codes[] = {
@@ -2773,6 +3618,14 @@ proto_register_ieee80211 (void)
     {0x00, NULL}
   };
 
+  static const value_string ack_policy[] = {
+    {0x00, "Normal Ack"},
+    {0x02, "No Ack"},
+    {0x01, "No explicit Ack"},
+    {0x03, "Block Ack"},
+    {0x00, NULL}
+  };
+
   static hf_register_info hf[] = {
     {&hf_data_rate,
      {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
@@ -2838,9 +3691,9 @@ proto_register_ieee80211 (void)
      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
       "More data flag", HFILL }},
 
-    {&hf_fc_wep,
-     {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
-      "WEP flag", HFILL }},
+    {&hf_fc_protected,
+     {"Protected flag", "wlan.fc.protected", FT_BOOLEAN, 8, TFS (&protected_flags), FLAG_PROTECTED,
+      "Protected flag", HFILL }},
 
     {&hf_fc_order,
      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
@@ -2890,10 +3743,30 @@ proto_register_ieee80211 (void)
      {"Priority", "wlan.qos.priority", FT_UINT16, BASE_DEC, NULL, 0,
       "802.1D Tag", HFILL }},
 
+    {&hf_qos_eosp,
+     {"EOSP", "wlan.qos.eosp", FT_BOOLEAN, 8, TFS (&eosp_flag), QOS_FLAG_EOSP,
+      "EOSP Field", HFILL }},
+
     {&hf_qos_ack_policy,
-     {"Ack Policy", "wlan.qos.ack", FT_UINT16, BASE_DEC, NULL, 0,
+     {"Ack Policy", "wlan.qos.ack", FT_UINT16, BASE_HEX,  VALS (&ack_policy), 0,
       "Ack Policy", HFILL }},
 
+    {&hf_qos_field_content,
+     {"Content", "wlan.qos.fc_content", FT_UINT16, BASE_DEC, NULL, 0,
+      "Content1", HFILL }},
+
+/*    {&hf_qos_buffer_state,
+     {"QAP PS buffer State", "wlan.qos.ps_buf_state", FT_UINT16, BASE_DEC, NULL, 0,
+      "QAP PS buffer State", HFILL }},
+
+    {&hf_qos_txop_dur_req,
+     {"TXOP Duration Requested", "wlan.qos.txop_dur_req", FT_UINT16, BASE_DEC, NULL, 0,
+      "TXOP Duration Requested", HFILL }},
+
+    {&hf_qos_queue_size,
+     {"Queue Size", "wlan.qos.queue_size", FT_UINT16, BASE_DEC, NULL, 0,
+      "Queue Size", HFILL }},*/
+
     {&hf_fcs,
      {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
       NULL, 0, "FCS", HFILL }},
@@ -2938,6 +3811,10 @@ proto_register_ieee80211 (void)
      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
       "Initialization Vector", HFILL }},
 
+    {&hf_wep_iv_weak,
+     {"Weak IV", "wlan.wep.weakiv", FT_BOOLEAN,BASE_NONE, NULL,0x0,
+       "Weak IV",HFILL}},
+
     {&hf_tkip_extiv,
      {"TKIP Ext. Initialization Vector", "wlan.tkip.extiv", FT_STRING,
       BASE_HEX, NULL, 0, "TKIP Extended Initialization Vector", HFILL }},
@@ -2947,8 +3824,8 @@ proto_register_ieee80211 (void)
       BASE_HEX, NULL, 0, "CCMP Extended Initialization Vector", HFILL }},
 
     {&hf_wep_key,
-     {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
-      "Key", HFILL }},
+     {"Key Index", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
+      "Key Index", HFILL }},
 
     {&hf_wep_icv,
      {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
@@ -3010,12 +3887,12 @@ proto_register_ieee80211 (void)
 
     {&ff_cf_sta_poll,
      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
-      FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C,
+      FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x020C,
       "CF-Poll capabilities for a STA", HFILL }},
 
     {&ff_cf_ap_poll,
      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
-      FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C,
+      FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x020C,
       "CF-Poll capabilities for an AP", HFILL }},
 
     {&ff_cf_privacy,
@@ -3034,16 +3911,35 @@ proto_register_ieee80211 (void)
      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
       FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
 
+    {&ff_cf_spec_man,
+     {"Spectrum Management", "wlan_mgt.fixed.capabilities.spec_man",
+      FT_BOOLEAN, 16, TFS (&cf_spec_man_flags), 0x0100, "Spectrum Management", HFILL }},
+
     {&ff_short_slot_time,
      {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
       FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
       HFILL }},
 
+    {&ff_cf_apsd,
+     {"Automatic Power Save Delivery", "wlan_mgt.fixed.capabilities.apsd",
+      FT_BOOLEAN, 16, TFS (&cf_apsd_flags), 0x0800, "Automatic Power Save "
+       "Delivery", HFILL }},
+
     {&ff_dsss_ofdm,
      {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
       FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
       HFILL }},
 
+    {&ff_cf_del_blk_ack,
+     {"Delayed Block Ack", "wlan_mgt.fixed.capabilities.del_blk_ack",
+      FT_BOOLEAN, 16, TFS (&cf_del_blk_ack_flags), 0x4000, "Delayed Block "
+       "Ack", HFILL }},
+
+    {&ff_cf_imm_blk_ack,
+     {"Immediate Block Ack", "wlan_mgt.fixed.capabilities.imm_blk_ack",
+      FT_BOOLEAN, 16, TFS (&cf_imm_blk_ack_flags), 0x8000, "Immediate Block "
+       "Ack", HFILL }},
+
     {&ff_auth_seq,
      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
@@ -3072,12 +3968,12 @@ proto_register_ieee80211 (void)
 
     {&ff_category_code,
      {"Category code", "wlan_mgt.fixed.category_code",
-      FT_UINT16, BASE_HEX, VALS (&category_codes), 0,
+      FT_UINT16, BASE_DEC, VALS (&category_codes), 0,
       "Management action category", HFILL }},
 
     {&ff_action_code,
      {"Action code", "wlan_mgt.fixed.action_code",
-      FT_UINT16, BASE_HEX, VALS (&action_codes), 0,
+      FT_UINT16, BASE_DEC, VALS (&action_codes), 0,
       "Management action code", HFILL }},
 
     {&ff_dialog_token,
@@ -3107,6 +4003,30 @@ proto_register_ieee80211 (void)
      {"Tag interpretation", "wlan_mgt.tag.interpretation",
       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }},
 
+    {&tag_oui,
+     {"OUI", "wlan_mgt.tag.oui",
+      FT_BYTES, BASE_NONE, NULL, 0, "OUI of vendor specific IE", HFILL }},
+
+    {&tim_length,
+     {"TIM length", "wlan_mgt.tim.length",
+      FT_UINT8, BASE_DEC, NULL, 0,
+      "Traffic Indication Map length", HFILL }},
+
+    {&tim_dtim_count,
+     {"DTIM count", "wlan_mgt.tim.dtim_count",
+      FT_UINT8, BASE_DEC, NULL, 0,
+      "DTIM count", HFILL }},
+
+    {&tim_dtim_period,
+     {"DTIM period", "wlan_mgt.tim.dtim_period",
+      FT_UINT8, BASE_DEC, NULL, 0,
+      "DTIM period", HFILL }},
+
+    {&tim_bmapctl,
+     {"Bitmap control", "wlan_mgt.tim.bmapctl",
+      FT_UINT8, BASE_HEX, NULL, 0,
+      "Bitmap control", HFILL }},
+
     {&rsn_cap,
      {"RSN Capabilities", "wlan_mgt.rsn.capabilities", FT_UINT16, BASE_HEX,
       NULL, 0, "RSN Capability information", HFILL }},
@@ -3132,6 +4052,63 @@ proto_register_ieee80211 (void)
       "wlan_mgt.rsn.capabilities.gtksa_replay_counter",
       FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x0030,
       "RSN GTKSA Replay Counter capabilities", HFILL }},
+
+    {&hf_aironet_ie_type,
+     {"Aironet IE type", "wlan_mgt.aironet.type",
+      FT_UINT8, BASE_DEC, VALS(aironet_ie_type_vals), 0, "", HFILL }},
+
+    {&hf_aironet_ie_version,
+     {"Aironet IE CCX version?", "wlan_mgt.aironet.version",
+      FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+
+    { &hf_aironet_ie_data,
+      { "Aironet IE data", "wlan_mgmt.aironet.data",
+        FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+    {&hf_qbss_version,
+     {"QBSS Version", "wlan_mgt.qbss.version",
+      FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_qbss_scount,
+     {"Station Count", "wlan_mgt.qbss.scount",
+      FT_UINT16, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_qbss_cu,
+     {"Channel Utilization", "wlan_mgt.qbss.cu",
+       FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_qbss_adc,
+     {"Available Admission Capabilities", "wlan_mgt.qbss.adc",
+     FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_qbss2_cu,
+     {"Channel Utilization", "wlan_mgt.qbss2.cu",
+       FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_qbss2_gl,
+     {"G.711 CU Quantum", "wlan_mgt.qbss2.glimit",
+      FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_qbss2_cal,
+     {"Call Admission Limit", "wlan_mgt.qbss2.cal",
+      FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_qbss2_scount,
+     {"Station Count", "wlan_mgt.qbss2.scount",
+      FT_UINT16, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_aironet_ie_qos_unk1,
+     {"Aironet IE QoS unknown1", "wlan_mgt.aironet.qos.unk1",
+      FT_UINT8, BASE_HEX, NULL, 0, "", HFILL }},
+
+    {&hf_aironet_ie_qos_paramset,
+     {"Aironet IE QoS paramset", "wlan_mgt.aironet.qos.paramset",
+      FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+
+    {&hf_aironet_ie_qos_val,
+     {"Aironet IE QoS valueset", "wlan_mgt.aironet.qos.val",
+      FT_BYTES, BASE_NONE, NULL, 0, "", HFILL }},
+
   };
 
   static gint *tree_array[] = {
@@ -3144,20 +4121,15 @@ proto_register_ieee80211 (void)
     &ett_fixed_parameters,
     &ett_tagged_parameters,
     &ett_qos_parameters,
+    &ett_qos_ps_buf_state,
     &ett_wep_parameters,
     &ett_cap_tree,
     &ett_rsn_cap_tree,
+    &ett_80211_mgt_ie,
   };
   module_t *wlan_module;
 
-  static const enum_val_t wep_keys_options[] = {
-    {"0", "0", 0},
-    {"1", "1", 1},
-    {"2", "2", 2},
-    {"3", "3", 3},
-    {"4", "4", 4},
-    {NULL, NULL, -1},
-  };
+  enum_val_t *wep_keys_options = g_malloc(sizeof(enum_val_t) * (MAX_ENCRYPTION_KEYS + 2));
 
 
   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
@@ -3171,8 +4143,11 @@ proto_register_ieee80211 (void)
   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");
+
   /* Register configuration options */
   wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);
   prefs_register_bool_preference(wlan_module, "defragment",
@@ -3191,27 +4166,47 @@ proto_register_ieee80211 (void)
                                 &wlan_ignore_wep);
 
 #ifndef USE_ENV
+
+  for (i = 0; i <= MAX_ENCRYPTION_KEYS; i++) {
+    key_name = g_string_new("");
+    g_string_sprintf(key_name, "%d", i);
+    wep_keys_options[i].name = key_name->str;
+    wep_keys_options[i].description = key_name->str;
+    wep_keys_options[i].value = i;
+    g_string_free(key_name, FALSE);
+  }
+  wep_keys_options[i].name = NULL;
+  wep_keys_options[i].description = NULL;
+  wep_keys_options[i].value = -1;
+
+  key_desc = g_string_new("");
+  g_string_sprintf(key_desc, "How many WEP keys do we have to choose from? (0 to disable, up to %d)", MAX_ENCRYPTION_KEYS);
   prefs_register_enum_preference(wlan_module, "wep_keys",
-                                "WEP key count",
-                                "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
+                                "WEP key count", key_desc->str,
                                 &num_wepkeys, wep_keys_options, FALSE);
-
-  prefs_register_string_preference(wlan_module, "wep_key1",
-                                  "WEP key #1",
-                                  "First WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
-                                  &wep_keystr[0]);
-  prefs_register_string_preference(wlan_module, "wep_key2",
-                                  "WEP key #2",
-                                  "Second WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
-                                  &wep_keystr[1]);
-  prefs_register_string_preference(wlan_module, "wep_key3",
-                                  "WEP key #3",
-                                  "Third WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
-                                  &wep_keystr[2]);
-  prefs_register_string_preference(wlan_module, "wep_key4",
-                                  "WEP key #4",
-                                  "Fourth WEP key (A:B:C:D:E) [40bit] (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
-                                  &wep_keystr[3]);
+  g_string_free(key_desc, FALSE);
+
+  for (i = 0; i < MAX_ENCRYPTION_KEYS; i++) {
+    key_name = g_string_new("");
+    key_title = g_string_new("");
+    key_desc = g_string_new("");
+    wep_keystr[i] = NULL;
+    /* prefs_register_*_preference() expects unique strings, so
+     * we build them using g_string_sprintf and just leave them
+     * allocated. */
+    g_string_sprintf(key_name, "wep_key%d", i + 1);
+    g_string_sprintf(key_title, "WEP key #%d", i + 1);
+    g_string_sprintf(key_desc, "WEP key #%d bytes in hexadecimal (A:B:C:D:E) "
+           "[40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key "
+           "length you're using", i + 1);
+
+    prefs_register_string_preference(wlan_module, key_name->str,
+           key_title->str, key_desc->str, &wep_keystr[i]);
+
+    g_string_free(key_name, FALSE);
+    g_string_free(key_title, FALSE);
+    g_string_free(key_desc, FALSE);
+  }
 #endif
 }
 
@@ -3226,7 +4221,7 @@ proto_reg_handoff_ieee80211(void)
    */
   llc_handle = find_dissector("llc");
   ipx_handle = find_dissector("ipx");
-  eth_handle = find_dissector("eth");
+  eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
   data_handle = find_dissector("data");
 
   ieee80211_handle = find_dissector("wlan");
@@ -3253,7 +4248,7 @@ static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
     return NULL;  /* krap! */
 
   /* try once with the key index in the packet, then look through our list. */
-  for (i = -1; i < (int) num_wepkeys; i++) {
+  for (i = -1; i < num_wepkeys; i++) {
     /* copy the encrypted data over to the tmp buffer */
 #if 0
     printf("trying %d\n", i);
@@ -3295,12 +4290,12 @@ static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
   key[0] = buf[0];
   key[1] = buf[1];
   key[2] = buf[2];
-  keyidx = COOK_WEP_KEY(buf[3]);
+  keyidx = KEY_OCTET_WEP_KEY(buf[3]);
 
   if (key_override >= 0)
     keyidx = key_override;
 
-  if (keyidx >= num_wepkeys)
+  if (keyidx >= (guint)num_wepkeys)
     return -1;
 
   keylen = wep_keylens[keyidx];
@@ -3369,15 +4364,15 @@ static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
 }
 
 static void init_wepkeys(void) {
-  char *tmp;
-  guint i;
+  const char *tmp;
+  int i;
   GByteArray *bytes;
   gboolean res;
 
 #ifdef USE_ENV
-  guint8 buf[128];
+  guint8 *buf;
 
-  tmp = getenv("ETHEREAL_WEPKEYNUM");
+  tmp = getenv("WIRESHARK_WEPKEYNUM");
   if (!tmp) {
     num_wepkeys = 0;
     return;
@@ -3406,7 +4401,8 @@ static void init_wepkeys(void) {
     wep_keylens[i] = 0;
 
 #ifdef USE_ENV
-    sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
+    buf=ep_alloc(128);
+    g_snprintf(buf, 128, "WIRESHARK_WEPKEY%d", i+1);
     tmp = getenv(buf);
 #else
     tmp = wep_keystr[i];
@@ -3448,3 +4444,39 @@ static void init_wepkeys(void) {
   }
   g_byte_array_free(bytes, TRUE);
 }
+/*
+ * This code had been taken from AirSnort crack.c function classify()
+ * Permission granted by snax <at> shmoo dot com
+ * weak_iv - determine which key byte an iv is useful in resolving
+ * parm     - p, pointer to the first byte of an IV
+ * return   -  n - this IV is weak for byte n of a WEP key
+ *            -1 - this IV is not weak for any key bytes
+ *
+ * This function tests for IVs that are known to satisfy the criteria
+ * for a weak IV as specified in FMS section 7.1
+ *
+ */
+static int
+weak_iv(guchar *iv)
+{
+        guchar sum, k;
+
+        if (iv[1] == 255 && iv[0] > 2 && iv[0] < 16) {
+                return iv[0] -3;
+        }
+
+        sum = iv[0] + iv[1];
+        if (sum == 1) {
+                if (iv[2] <= 0x0a) {
+                        return iv[2] +2;
+                }
+                else if (iv[2] == 0xff){
+                        return 0;
+                }
+        }
+        k = 0xfe - iv[2];
+        if (sum == k  && (iv[2] >= 0xf2 && iv[2] <= 0xfe && iv[2] != 0xfd)){
+                return k;
+        }
+        return -1;
+}