Get rid of an unused #define.
[obnox/wireshark/wip.git] / packet-ieee80211.c
index 30e0fe102deb6432c945f8bd56f8e803c0bf0b55..3868ba2b58d861ca91ecd3ab33f14197136b7872 100644 (file)
@@ -3,10 +3,10 @@
  * Copyright 2000, Axis Communications AB 
  * Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com
  *
- * $Id: packet-ieee80211.c,v 1.5 2000/11/30 03:19:27 guy Exp $
+ * $Id: packet-ieee80211.c,v 1.33 2001/06/21 06:59:47 guy Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@unicom.net>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
  * Copied from README.developer
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Credits:
+ * 
+ * The following people helped me by pointing out bugs etc. Thank you!
+ *
+ * Marco Molteni
+ * Lena-Marie Nilsson     
+ * Magnus Hultman-Persson
+ *
  */
 
 #ifdef HAVE_CONFIG_H
 #include <glib.h>
 #include "bitswap.h"
 #include "proto.h"
-#include "etypes.h"
 #include "packet.h"
+#include "resolv.h"
 #include "packet-llc.h"
 #include "packet-ieee80211.h"
+#include "etypes.h"
 
 /* ************************************************************************* */
 /*                          Miscellaneous Constants                          */
 /*  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 & 0x200) >> 8) + ((x & 0x100) >> 8))
-
-#define COOK_FRAGMENT_NUMBER(x) (x & 0x000F)
-#define COOK_SEQUENCE_NUMBER(x) ((x & 0xFFF0) >> 4)
-#define COOK_FLAGS(x)           ((x & 0xFF00) >> 8)
-#define COOK_DS_STATUS(x)       (x & 0x3)
+#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_FLAGS(x)           (((x) & 0xFF00) >> 8)
+#define COOK_DS_STATUS(x)       ((x) & 0x3)
+#define COOK_WEP_IV(x)        ((x) & 0xFFFFFF)
+#define COOK_WEP_KEY(x)       (((x) & 0xC0000000) >> 30)
 #define COL_SHOW_INFO(fd,info) if (check_col(fd,COL_INFO)) \
-col_add_str(fd,COL_INFO,info);
-
-#define IS_TO_DS(x)            ((x & 0x100) >> 8)
-#define IS_FROM_DS(x)          ((x & 0x200) >> 9)
-#define HAVE_FRAGMENTS(x)      ((x & 0x400) >> 10)
-#define IS_RETRY(x)            ((x & 0x800) >> 11)
-#define POWER_MGT_STATUS(x)    ((x & 0x1000))
-#define HAS_MORE_DATA(x)       ((x & 0x2000))
-#define IS_WEP(x)              ((x & 0x4000))
-#define IS_STRICTLY_ORDERED(x) ((x & 0x8000))
-
-#define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
+                               col_add_str(fd,COL_INFO,info);
+#define COL_SHOW_INFO_CONST(fd,info) if (check_col(fd,COL_INFO)) \
+                               col_set_str(fd,COL_INFO,info);
+
+#define IS_TO_DS(x)            ((x) & 0x01)
+#define IS_FROM_DS(x)          ((x) & 0x02)
+#define HAVE_FRAGMENTS(x)      ((x) & 0x04)
+#define IS_RETRY(x)            ((x) & 0x08)
+#define POWER_MGT_STATUS(x)    ((x) & 0x10)
+#define HAS_MORE_DATA(x)       ((x) & 0x20)
+#define IS_WEP(x)              ((x) & 0x40)
+#define IS_STRICTLY_ORDERED(x) ((x) & 0x80)
+
+#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))
@@ -106,7 +120,7 @@ col_add_str(fd,COL_INFO,info);
 #define DATA_SHORT_HDR_LEN     24
 #define DATA_LONG_HDR_LEN      30
 #define MGT_FRAME_HDR_LEN      24      /* Length of Managment frame-headers */
-#define CTLR
+
 #define MGT_ASSOC_REQ        0x00      /* Management - association request        */
 #define MGT_ASSOC_RESP       0x01      /* Management - association response       */
 #define MGT_REASSOC_REQ      0x02      /* Management - reassociation request      */
@@ -129,22 +143,23 @@ col_add_str(fd,COL_INFO,info);
 #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_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_ACK_POLL_NOD 0x26      /* Data - CF ack + CF poll (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_ADDR_T1         0x00
-#define DATA_ADDR_T2         0x01
-#define DATA_ADDR_T3         0x02
-#define DATA_ADDR_T4         0x03
+#define DATA_ADDR_T1         0x0000
+#define DATA_ADDR_T2         0x0100
+#define DATA_ADDR_T3         0x0200
+#define DATA_ADDR_T4         0x0300
 
 
 /* ************************************************************************* */
 /*          Macros used to extract information about fixed fields            */
 /* ************************************************************************* */
-#define ESS_SET(x) ((x & 0x0001))
-#define IBSS_SET(x) ((x & 0x0002))
+#define ESS_SET(x) ((x) & 0x0001)
+#define IBSS_SET(x) ((x) & 0x0002)
 
 
 
@@ -174,12 +189,37 @@ col_add_str(fd,COL_INFO,info);
 #define TAG_IBSS_PARAMETER 0x06
 #define TAG_CHALLENGE_TEXT 0x10
 
-
 /* ************************************************************************* */
-/*                Various constants used in this module                      */
+/*                         Frame types, and their names                      */
 /* ************************************************************************* */
-static const char *capture_proto_name = "IEEE 802.11";
-
+static const value_string frame_type_subtype_vals[] = {
+       {MGT_ASSOC_REQ,        "Association Request"},
+       {MGT_ASSOC_RESP,       "Association Response"},
+       {MGT_REASSOC_REQ,      "Reassociation Request"},
+       {MGT_REASSOC_RESP,     "Reassociation Response"},
+       {MGT_PROBE_REQ,        "Probe Request"},
+       {MGT_PROBE_RESP,       "Probe Response"},
+       {MGT_BEACON,           "Beacon frame"},
+       {MGT_ATIM,             "ATIM"},
+       {MGT_DISASS,           "Dissassociate"},
+       {MGT_AUTHENTICATION,   "Authentication"},
+       {MGT_DEAUTHENTICATION, "Deauthentication"},
+       {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_POLL,         "Data + CF-Poll"},
+       {DATA_CF_ACK_POLL,     "Data + CF-Acknowledgement/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)"},
+       {0,                    NULL}
+};
 
 static int proto_wlan = -1;
 /* ************************************************************************* */
@@ -189,6 +229,7 @@ static int hf_fc_field = -1;
 static int hf_fc_proto_version = -1;
 static int hf_fc_frame_type = -1;
 static int hf_fc_frame_subtype = -1;
+static int hf_fc_frame_type_subtype = -1;
 
 static int hf_fc_flags = -1;
 static int hf_fc_to_ds = -1;
@@ -207,7 +248,7 @@ static int hf_fc_order = -1;
 /*                   Header values for Duration/ID field                     */
 /* ************************************************************************* */
 static int hf_did_duration = -1;
-
+static int hf_assoc_id = -1;
 
 
 /* ************************************************************************* */
@@ -236,25 +277,28 @@ static int hf_fcs = -1;
 /* ************************************************************************* */
 /*                      Fixed fields found in mgt frames                     */
 /* ************************************************************************* */
-static int ff_auth_alg = -1;   /* Authentication algorithm field          */
-static int ff_auth_seq = -1;   /* Authentication transaction sequence     */
-static int ff_current_ap = -1; /* Current AP MAC address                  */
-static int ff_listen_ival = -1;        /* Listen interval fixed field             */
-static int ff_timestamp = -1;  /* 64 bit timestamp                        */
-static int ff_beacon_interval = -1;    /* 16 bit Beacon interval                  */
-static int ff_assoc_id = -1;   /* 16 bit AID field                        */
-static int ff_reason = -1;     /* 16 bit reason code                      */
-static int ff_status_code = -1;        /* Status code                             */
+static int ff_auth_alg = -1;   /* Authentication algorithm field            */
+static int ff_auth_seq = -1;   /* Authentication transaction sequence       */
+static int ff_current_ap = -1; /* Current AP MAC address                    */
+static int ff_listen_ival = -1;        /* Listen interval fixed field               */
+static int ff_timestamp = -1;  /* 64 bit timestamp                          */
+static int ff_beacon_interval = -1;    /* 16 bit Beacon interval            */
+static int ff_assoc_id = -1;   /* 16 bit AID field                          */
+static int ff_reason = -1;     /* 16 bit reason code                        */
+static int ff_status_code = -1;        /* Status code                               */
 
 /* ************************************************************************* */
 /*            Flags found in the capability field (fixed field)              */
 /* ************************************************************************* */
 static int ff_capture = -1;
-static int ff_cf_sta_poll = -1;        /* CF pollable status for a STA            */
+static int ff_cf_sta_poll = -1; /* CF pollable status for a STA            */
 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP            */
 static int ff_cf_ess = -1;
 static int ff_cf_ibss = -1;
 static int ff_cf_privacy = -1;
+static int ff_cf_preamble = -1;
+static int ff_cf_pbcc = -1;
+static int ff_cf_agility = -1;
 
 /* ************************************************************************* */
 /*                       Tagged value format fields                          */
@@ -267,6 +311,10 @@ static int tag_interpretation = -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_parameters = -1;
+static int hf_wep_iv = -1;
+static int hf_wep_key = -1;
+static int hf_wep_crc = -1;
 
 /* ************************************************************************* */
 /*                               Protocol trees                              */
@@ -277,17 +325,42 @@ static gint ett_cap_tree = -1;
 static gint ett_fc_tree = -1;
 static gint ett_fixed_parameters = -1;
 static gint ett_tagged_parameters = -1;
+static gint ett_wep_parameters = -1;
+
+static dissector_handle_t llc_handle;
+
 /* ************************************************************************* */
-/*                                                                           */
+/*            Return the length of the current header (in bytes)             */
 /* ************************************************************************* */
-int
-find_header_length (const u_char * pd, int offset)
+static int
+find_header_length (guint16 fcf)
 {
-  guint16 frame_control;
+  switch (COOK_FRAME_TYPE (fcf)) {
+
+  case MGT_FRAME:
+    return MGT_FRAME_HDR_LEN;
 
-  frame_control = pntohs (pd);
-  return ((IS_FROM_DS (frame_control))
-         && (IS_TO_DS (frame_control))) ? 30 : 24;
+  case CONTROL_FRAME:
+    switch (COMPOSE_FRAME_TYPE (fcf)) {
+
+    case CTRL_CTS:
+    case CTRL_ACKNOWLEDGEMENT:
+      return 10;
+
+    case CTRL_RTS:
+    case CTRL_PS_POLL:
+    case CTRL_CFP_END:
+    case CTRL_CFP_ENDACK:
+      return 16;
+    }
+    return 4;  /* XXX */
+
+  case DATA_FRAME:
+    return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
+                                                      DATA_SHORT_HDR_LEN;
+  default:
+    return 4;  /* XXX */
+  }
 }
 
 
@@ -299,31 +372,22 @@ capture_ieee80211 (const u_char * pd, int offset, packet_counts * ld)
 {
   guint16 fcf, hdr_length;
 
-  fcf = pntohs (*((guint *) pd));
-
+  fcf = pletohs (&pd[0]);
 
-  hdr_length = MGT_FRAME_HDR_LEN;      /* Set the header length of the frame */
+  if (IS_WEP(COOK_FLAGS(fcf)))
+    {
+      ld->other++;
+      return;
+    }
 
   switch (COMPOSE_FRAME_TYPE (fcf))
     {
 
     case DATA:                 /* We got a data frame */
-      hdr_length = find_header_length (pd, offset);
-      capture_llc (pd, offset + hdr_length, ld);
-      break;
-
     case DATA_CF_ACK:          /* Data with ACK */
-      hdr_length = find_header_length (pd, offset);
-      capture_llc (pd, offset + hdr_length, ld);
-      break;
-
     case DATA_CF_POLL:
-      hdr_length = find_header_length (pd, offset);
-      capture_llc (pd, offset + hdr_length, ld);
-      break;
-
     case DATA_CF_ACK_POLL:
-      hdr_length = find_header_length (pd, offset);
+      hdr_length = find_header_length (fcf);
       capture_llc (pd, offset + hdr_length, ld);
       break;
 
@@ -371,6 +435,30 @@ get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size
 }
 
 
+/* ************************************************************************* */
+/*            Add the subtree used to store WEP parameters                   */
+/* ************************************************************************* */
+static void
+get_wep_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
+{
+  proto_item *wep_fields;
+  proto_tree *wep_tree;
+  int crc_offset = size - 4;
+
+  wep_fields = proto_tree_add_string_format(tree, hf_wep_parameters, tvb,
+                                           0, 4, 0, "WEP parameters");
+
+  wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
+  proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, start, 3,
+                      COOK_WEP_IV (tvb_get_letohl (tvb, start)));
+
+  proto_tree_add_uint (wep_tree, hf_wep_key, tvb, start + 3, 1,
+                      COOK_WEP_KEY (tvb_get_letohl (tvb, start)));
+
+  if (tvb_bytes_exist(tvb, start + crc_offset, 4))
+    proto_tree_add_uint (wep_tree, hf_wep_crc, tvb, start + crc_offset, 4,
+                        tvb_get_ntohl (tvb, start + crc_offset));
+}
 
 /* ************************************************************************* */
 /*              Dissect and add fixed mgmt fields to protocol tree           */
@@ -378,11 +466,12 @@ get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size
 static void
 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
 {
-  guint8 *dataptr;
+  const guint8 *dataptr;
   char out_buff[SHORT_STR];
-  guint16 *temp16;
+  guint16 capability;
   proto_item *cap_item;
   static proto_tree *cap_tree;
+  double temp_double;
 
   switch (lfcode)
     {
@@ -390,125 +479,83 @@ add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
       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",
-               BIT_SWAP (dataptr[7]),
-               BIT_SWAP (dataptr[6]),
-               BIT_SWAP (dataptr[5]),
-               BIT_SWAP (dataptr[4]),
-               BIT_SWAP (dataptr[3]),
-               BIT_SWAP (dataptr[2]),
-               BIT_SWAP (dataptr[1]),
-               BIT_SWAP (dataptr[0]));
+               dataptr[7],
+               dataptr[6],
+               dataptr[5],
+               dataptr[4],
+               dataptr[3],
+               dataptr[2],
+               dataptr[1],
+               dataptr[0]);
 
       proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
       break;
 
-
     case FIELD_BEACON_INTERVAL:
-      dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_beacon_interval, tvb, offset, 2,
-                          pntohs (temp16));
+      temp_double = (double) tvb_get_letohs (tvb, offset);
+      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);
       break;
 
 
     case FIELD_CAP_INFO:
-      dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[0] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
+      capability = tvb_get_letohs (tvb, offset);
 
       cap_item = proto_tree_add_uint_format (tree, ff_capture, 
                                             tvb, offset, 2,
-                                            pntohs (temp16),
-                                            "Capability Information: %04X",
-                                            pntohs (temp16));
+                                            capability,
+                                            "Capability Information: 0x%04X",
+                                            capability);
       cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
       proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
-                             pntohs (temp16));
+                             capability);
       proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
-                             pntohs (temp16));
+                             capability);
       proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
-                             pntohs (temp16));
-      if (ESS_SET (pntohs (temp16)) != 0)      /* This is an AP */
+                             capability);
+      proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 1,
+                             capability);
+      proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 1,
+                             capability);
+      proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 1,
+                             capability);
+      if (ESS_SET (capability) != 0)   /* This is an AP */
        proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
-                            ((pntohs (temp16) & 0xC) >> 2));
+                            ((capability & 0xC) >> 2));
 
       else                     /* This is a STA */
        proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
-                            ((pntohs (temp16) & 0xC) >> 2));
+                            ((capability & 0xC) >> 2));
       break;
 
-
     case FIELD_AUTH_ALG:
-      dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2,
-                          pntohs (temp16));
+      proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2, TRUE);
       break;
 
-
     case FIELD_AUTH_TRANS_SEQ:
-      dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2,
-                          pntohs (temp16));
+      proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2, TRUE);
       break;
 
-
     case FIELD_CURRENT_AP_ADDR:
-      dataptr = tvb_get_ptr (tvb, offset, 6);
-      memset (out_buff, 0, SHORT_STR);
-      out_buff[0] = BIT_SWAP (dataptr[5]);
-      out_buff[1] = BIT_SWAP (dataptr[4]);
-      out_buff[2] = BIT_SWAP (dataptr[3]);
-      out_buff[3] = BIT_SWAP (dataptr[2]);
-      out_buff[4] = BIT_SWAP (dataptr[1]);
-      out_buff[5] = BIT_SWAP (dataptr[0]);
-
-      proto_tree_add_string (tree, ff_current_ap, tvb, offset, 6, out_buff);
+      proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
       break;
 
-
     case FIELD_LISTEN_IVAL:
-      dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_listen_ival, tvb, offset, 2,
-                          pntohs (temp16));
+      proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
       break;
 
-
     case FIELD_REASON_CODE:
-      dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_reason, tvb, offset, 2, pntohs (temp16));
+      proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
       break;
 
-
     case FIELD_ASSOC_ID:
-      dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_assoc_id, tvb, offset, 2, pntohs (temp16));
+      proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE);
       break;
 
     case FIELD_STATUS_CODE:
-      dataptr = tvb_get_ptr (tvb, offset, 2);
-      out_buff[0] = BIT_SWAP (dataptr[1]);
-      out_buff[1] = BIT_SWAP (dataptr[0]);
-      temp16 = (guint16 *) out_buff;
-      proto_tree_add_uint (tree, ff_status_code, tvb, offset, 2,
-                          pntohs (temp16));
+      proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
       break;
     }
 }
@@ -520,16 +567,15 @@ add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
 static int
 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 {
-  guint8 *tag_info_ptr;
-  guint8 *tag_data_ptr;
+  const guint8 *tag_data_ptr;
   guint32 tag_no, tag_len;
-  int i, n;
+  unsigned int i;
+  int n;
   char out_buff[SHORT_STR];
 
 
-  tag_info_ptr = tvb_get_ptr (tvb, offset, 2);
-  tag_no = tag_info_ptr[0];
-  tag_len = tag_info_ptr[1];
+  tag_no = tvb_get_guint8(tvb, offset);
+  tag_len = tvb_get_guint8(tvb, offset + 1);
 
   tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
 
@@ -537,13 +583,13 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
   if ((tag_no >= 17) && (tag_no <= 31))
     {                          /* Reserved for challenge text */
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (Reserved for challenge text)",
+                                 "Tag Number: %u (Reserved for challenge text)",
                                  tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
                             tag_len, "Not interpreted");
-      return (int) tag_len;
+      return (int) tag_len + 2;
     }
 
   /* Next See if tag is reserved - if true, skip it! */
@@ -551,24 +597,24 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
       || ((tag_no >= 32) && (tag_no <= 255)))
     {
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (Reserved tag number)",
+                                 "Tag Number: %u (Reserved tag number)",
                                  tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
 
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
                             tag_len, "Not interpreted");
-      return (int) tag_len;
+      return (int) tag_len + 2;
     }
 
 
-  switch (tag_info_ptr[0])
+  switch (tag_no)
     {
 
 
     case TAG_SSID:
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (SSID parameter set)",
+                                 "Tag Number: %u (SSID parameter set)",
                                  tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
@@ -586,7 +632,7 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
     case TAG_SUPP_RATES:
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (Supported Rates)", tag_no);
+                                 "Tag Number: %u (Supported Rates)", tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
 
@@ -596,18 +642,9 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
       for (i = 0; i < tag_len; i++)
        {
-
-         if (tag_data_ptr[i] >= 128)
-           {
-             tag_data_ptr[i] -= 128;
-             n += snprintf (out_buff + n, SHORT_STR - n, "%2.1f ", (float)
-                            (((float) tag_data_ptr[i]) * 0.5));
-           }
-
-         else
-           n += snprintf (out_buff + n, SHORT_STR - n, "%2.1f ", (float)
-                          (((float) tag_data_ptr[i]) * 0.5));
-
+           n += snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
+                          (tag_data_ptr[i] & 0x7F) * 0.5,
+                          (tag_data_ptr[i] & 0x80) ? "(B)" : "");
        }
       snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
 
@@ -619,7 +656,7 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
     case TAG_FH_PARAMETER:
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (FH Parameter set)",
+                                 "Tag Number: %u (FH Parameter set)",
                                  tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
@@ -627,7 +664,7 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
       snprintf (out_buff, SHORT_STR,
                "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
-               "Hop Index %2d", pntohs (tag_data_ptr), tag_data_ptr[2],
+               "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
                tag_data_ptr[3], tag_data_ptr[4]);
 
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
@@ -638,13 +675,13 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
     case TAG_DS_PARAMETER:
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (DS Parameter set)",
+                                 "Tag Number: %u (DS Parameter set)",
                                  tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
       memset (out_buff, 0, SHORT_STR);
 
-      snprintf (out_buff, SHORT_STR, "Current Channel: %d", tag_data_ptr[0]);
+      snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
                             tag_len, out_buff);
       break;
@@ -652,16 +689,16 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
     case TAG_CF_PARAMETER:
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (CF Parameter set)",
+                                 "Tag Number: %u (CF Parameter set)",
                                  tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
       memset (out_buff, 0, SHORT_STR);
 
       snprintf (out_buff, SHORT_STR,
-               "CFP count %d, CFP period %d, CFP max duration %d, "
-               "CFP Remaining %d", tag_data_ptr[0], tag_data_ptr[1],
-               pntohs (tag_data_ptr + 2), pntohs (tag_data_ptr + 4));
+               "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);
@@ -670,13 +707,13 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
     case TAG_TIM:
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (CF Parameter set)",
+                                 "Tag Number: %u ((TIM) Traffic Indication Map)",
                                  tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
       memset (out_buff, 0, SHORT_STR);
       snprintf (out_buff, SHORT_STR,
-               "DTIM count %d, DTIM period %d, Bitmap control 0x%X, "
+               "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,
@@ -687,13 +724,13 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
     case TAG_IBSS_PARAMETER:
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (IBSS Parameter set)",
+                                 "Tag Number: %u (IBSS Parameter set)",
                                  tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
       memset (out_buff, 0, SHORT_STR);
       snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
-               pntohs (tag_data_ptr));
+               pletohs (tag_data_ptr));
 
       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
                             tag_len, out_buff);
@@ -703,7 +740,7 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
 
     case TAG_CHALLENGE_TEXT:
       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
-                                 "Tag Number: %d (Challenge text)", tag_no);
+                                 "Tag Number: %u (Challenge text)", tag_no);
 
       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
       memset (out_buff, 0, SHORT_STR);
@@ -720,17 +757,37 @@ add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
   return tag_len + 2;
 }
 
+static void
+set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
+{
+  if (check_col(pinfo->fd, COL_RES_DL_SRC))
+    col_add_fstr(pinfo->fd, COL_RES_DL_SRC, "%s (%s)",
+                   get_ether_name(addr), type);
+  if (check_col(pinfo->fd, COL_UNRES_DL_SRC))
+    col_add_fstr(pinfo->fd, COL_UNRES_DL_SRC, "%s (%s)",
+                    ether_to_str(addr), type);
+}
 
+static void
+set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
+{
+  if (check_col(pinfo->fd, COL_RES_DL_DST))
+    col_add_fstr(pinfo->fd, COL_RES_DL_DST, "%s (%s)",
+                    get_ether_name(addr), type);
+  if (check_col(pinfo->fd, COL_UNRES_DL_DST))
+    col_add_fstr(pinfo->fd, COL_UNRES_DL_DST, "%s (%s)",
+                    ether_to_str(addr), type);
+}
 
 /* ************************************************************************* */
 /*                          Dissect 802.11 frame                             */
 /* ************************************************************************* */
-void
+static void
 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
 {
-  guint16 fcf, flags;
-  guint8 *src = NULL, *dst = NULL;
-  proto_item *ti;
+  guint16 fcf, flags, frame_type_subtype;
+  const guint8 *src = NULL, *dst = NULL;
+  proto_item *ti = NULL;
   proto_item *flag_item;
   proto_item *fc_item;
   static proto_tree *hdr_tree;
@@ -742,43 +799,53 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
   tvbuff_t *next_tvb;
   guint32 next_idx;
   guint32 addr_type;
-
-  cap_len = pinfo->captured_len;
-  fcf = tvb_get_letohs (tvb, 0);
-
-  pinfo->current_proto = capture_proto_name;
+  guint32 next_len;
+  int tagged_parameter_tree_len;
 
   if (check_col (pinfo->fd, COL_PROTOCOL))
     col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
+  if (check_col (pinfo->fd, COL_INFO))
+    col_clear (pinfo->fd, COL_INFO);
+
+  cap_len = tvb_length(tvb);
+  fcf = tvb_get_letohs (tvb, 0);
+  hdr_len = find_header_length (fcf);
+  frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
+
+  COL_SHOW_INFO_CONST (pinfo->fd,
+      val_to_str(frame_type_subtype, frame_type_subtype_vals,
+          "Unrecognized (Reserved frame)"));
 
   /* Add the FC to the current tree */
   if (tree)
     {
-      hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
       ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
-                                          "IEEE 802.11 Header");
+                                          "IEEE 802.11");
       hdr_tree = proto_item_add_subtree (ti, ett_80211);
 
-      fc_item =
-       proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
-                                   tvb_get_letohs (tvb, 0),
-                                   "Frame Control: 0x%04X",
-                                   tvb_get_letohs (tvb, 0));
+      proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
+                          tvb, 0, 1,
+                          frame_type_subtype);
+
+      fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
+                                           fcf,
+                                           "Frame Control: 0x%04X",
+                                           fcf);
 
       fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
 
 
       proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
-                          COOK_PROT_VERSION (tvb_get_letohs (tvb, 0)));
+                          COOK_PROT_VERSION (fcf));
 
       proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
-                          COOK_FRAME_TYPE (tvb_get_letohs (tvb, 0)));
+                          COOK_FRAME_TYPE (fcf));
 
       proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
                           tvb, 0, 1,
-                          COOK_FRAME_SUBTYPE (tvb_get_letohs (tvb, 0)));
+                          COOK_FRAME_SUBTYPE (fcf));
 
-      flags = COOK_FLAGS (tvb_get_letohs (tvb, 0));
+      flags = COOK_FLAGS (fcf);
 
       flag_item =
        proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
@@ -789,12 +856,6 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
       proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
                           COOK_DS_STATUS (flags));
 
-      /*      proto_tree_add_boolean(flag_tree,hf_fc_to_ds,tvb,1,1,
-         flags);
-
-         proto_tree_add_boolean(flag_tree,hf_fc_from_ds,tvb,1,1,
-         flags); */
-
       proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
                              flags);
 
@@ -809,45 +870,48 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
 
       proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
 
-      proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
-                          tvb_get_ntohs (tvb, 2));
-
+      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)));
+     
+      else
+         proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
+                              tvb_get_letohs (tvb, 2));
     }
 
-  /* Perform Tasks which are common to a certain frame type */
+  /* Perform tasks which are common to a certain frame type */
   switch (COOK_FRAME_TYPE (fcf))
     {
 
     case MGT_FRAME:            /* All management frames share a common header */
+      /*
+       * Set the top-level item to cover the entire frame.
+       */
+      if (ti != NULL)
+        proto_item_set_len(ti, tvb_length(tvb));
       src = tvb_get_ptr (tvb, 10, 6);
       dst = tvb_get_ptr (tvb, 4, 6);
 
-
-      if (check_col (pinfo->fd, COL_DEF_SRC))
-       col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X",
-                     src[0], src[1], src[2], src[3], src[4], src[5]);
-
-      if (check_col (pinfo->fd, COL_DEF_DST))
-       col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X",
-                     dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+      SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
+      SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
+      SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
+      SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
 
       if (tree)
        {
-         proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
-                               tvb_get_ptr (tvb, 4, 6));
+         proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
 
-         proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
-                               tvb_get_ptr (tvb, 10, 6));
+         proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
 
          proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
                                tvb_get_ptr (tvb, 16, 6));
 
          proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
-                              COOK_FRAGMENT_NUMBER (tvb_get_ntohs
+                              COOK_FRAGMENT_NUMBER (tvb_get_letohs
                                                     (tvb, 22)));
 
          proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
-                              COOK_SEQUENCE_NUMBER (tvb_get_ntohs
+                              COOK_SEQUENCE_NUMBER (tvb_get_letohs
                                                     (tvb, 22)));
          cap_len = cap_len - MGT_FRAME_LEN - 4;
        }
@@ -891,15 +955,10 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
          break;
        }
 
-      if (check_col (pinfo->fd, COL_DEF_SRC))
-       col_add_fstr (pinfo->fd, COL_DEF_SRC,
-                     "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
-                     src[0], src[1], src[2], src[3], src[4], src[5]);
-
-      if (check_col (pinfo->fd, COL_DEF_DST))
-       col_add_fstr (pinfo->fd, COL_DEF_DST,
-                     "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
-                     dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+      SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
+      SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
+      SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
+      SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
 
       /* Now if we have a tree we start adding stuff */
       if (tree)
@@ -910,85 +969,100 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
            {
 
            case DATA_ADDR_T1:
-             proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
-                                   tvb_get_ptr (tvb, 4, 6));
-             proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
-                                   tvb_get_ptr (tvb, 10, 6));
+             proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
+             proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
              proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
                                    tvb_get_ptr (tvb, 16, 6));
+             proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+                                  COOK_FRAGMENT_NUMBER (tvb_get_letohs
+                                                        (tvb, 22)));
+             proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+                                  COOK_SEQUENCE_NUMBER (tvb_get_letohs
+                                                        (tvb, 22)));
              break;
-
-
+             
+             
            case DATA_ADDR_T2:
-             proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
-                                   tvb_get_ptr (tvb, 4, 6));
+             proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
              proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
                                    tvb_get_ptr (tvb, 10, 6));
-             proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6,
-                                   tvb_get_ptr (tvb, 16, 6));
+             proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
+             proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+                                  COOK_FRAGMENT_NUMBER (tvb_get_letohs
+                                                        (tvb, 22)));
+             proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+                                  COOK_SEQUENCE_NUMBER (tvb_get_letohs
+                                                        (tvb, 22)));
              break;
-
+   
 
            case DATA_ADDR_T3:
              proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
                                    tvb_get_ptr (tvb, 4, 6));
-             proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
-                                   tvb_get_ptr (tvb, 10, 6));
-             proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
-                                   tvb_get_ptr (tvb, 16, 6));
+             proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
+             proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
+             proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+                                  COOK_FRAGMENT_NUMBER (tvb_get_letohs
+                                                        (tvb, 22)));
+             proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+                                  COOK_SEQUENCE_NUMBER (tvb_get_letohs
+                                                        (tvb, 22)));
              break;
-
+             
 
            case DATA_ADDR_T4:
              proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
                                    tvb_get_ptr (tvb, 4, 6));
              proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
                                    tvb_get_ptr (tvb, 10, 6));
-             proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
-                                   tvb_get_ptr (tvb, 16, 6));
-             proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6,
-                                   tvb_get_ptr (tvb, 24, 6));
+             proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
+             proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+                                  COOK_FRAGMENT_NUMBER (tvb_get_letohs
+                                                        (tvb, 22)));
+             proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+                                  COOK_SEQUENCE_NUMBER (tvb_get_letohs
+                                                        (tvb, 22)));
+             proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
              break;
-
            }
 
        }
       break;
     }
 
-
-  switch (COMPOSE_FRAME_TYPE (fcf))
+  switch (frame_type_subtype)
     {
 
     case MGT_ASSOC_REQ:
-      COL_SHOW_INFO (pinfo->fd, "Association Request");
       if (tree)
        {
-         fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 4);
+         fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 4);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_HDR_LEN,
                           FIELD_CAP_INFO);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_HDR_LEN + 2,
                           FIELD_LISTEN_IVAL);
 
          next_idx = MGT_FRAME_HDR_LEN + 4;     /* Size of fixed fields */
-         tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
-                                                  pinfo->captured_len - 4 -
-                                                  next_idx);
-
+         tagged_parameter_tree_len =
+             tvb_reported_length_remaining(tvb, next_idx + 4);
+         tagged_tree = get_tagged_parameter_tree (hdr_tree, tvb, next_idx,
+                                                  tagged_parameter_tree_len);
 
-         while (pinfo->captured_len > (next_idx + 4))
-           next_idx += add_tagged_field (tagged_tree, tvb, next_idx);
+         while (tagged_parameter_tree_len > 0) {
+           if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
+             break;
+           next_idx +=next_len;
+           tagged_parameter_tree_len -= next_len;
+         }
        }
       break;
 
 
 
     case MGT_ASSOC_RESP:
-      COL_SHOW_INFO (pinfo->fd, "Association Response");
-
       if (tree)
        {
-         fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 6);
+         fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 6);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
                           FIELD_STATUS_CODE);
@@ -997,21 +1071,25 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
 
          next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
 
-         tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
-                                                  pinfo->captured_len - 4 -
-                                                  next_idx);
-
-         while (pinfo->captured_len > (next_idx + 4))
-           next_idx += add_tagged_field (tagged_tree, tvb, next_idx);
+         tagged_parameter_tree_len =
+             tvb_reported_length_remaining(tvb, next_idx + 4);
+         tagged_tree = get_tagged_parameter_tree (hdr_tree, tvb, next_idx,
+                                                  tagged_parameter_tree_len);
 
+         while (tagged_parameter_tree_len > 0) {
+           if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
+             break;
+           next_idx +=next_len;
+           tagged_parameter_tree_len -= next_len;
+         }
        }
       break;
 
+
     case MGT_REASSOC_REQ:
-      COL_SHOW_INFO (pinfo->fd, "Reassociation Request");
       if (tree)
        {
-         fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 10);
+         fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 10);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
                           FIELD_LISTEN_IVAL);
@@ -1019,20 +1097,24 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
                           FIELD_CURRENT_AP_ADDR);
 
          next_idx = MGT_FRAME_LEN + 10;        /* Size of fixed fields */
-         tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
-                                                  pinfo->captured_len - 4 -
-                                                  next_idx);
+         tagged_parameter_tree_len =
+             tvb_reported_length_remaining(tvb, next_idx + 4);
+         tagged_tree = get_tagged_parameter_tree (hdr_tree, tvb, next_idx,
+                                                  tagged_parameter_tree_len);
 
-         while ((pinfo->captured_len) > (next_idx + 4))
-           next_idx += add_tagged_field (tagged_tree, tvb, next_idx);
+         while (tagged_parameter_tree_len > 0) {
+           if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
+             break;
+           next_idx +=next_len;
+           tagged_parameter_tree_len -= next_len;
+         }
        }
       break;
 
     case MGT_REASSOC_RESP:
-      COL_SHOW_INFO (pinfo->fd, "Reassociation Response");
       if (tree)
        {
-         fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 10);
+         fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 10);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
                           FIELD_STATUS_CODE);
@@ -1040,38 +1122,44 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
                           FIELD_ASSOC_ID);
 
          next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
-         tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
-                                                  pinfo->captured_len - 4 -
-                                                  next_idx);
-
-         while (pinfo->captured_len > (next_idx + 4))
-           next_idx += add_tagged_field (tagged_tree, tvb, next_idx);
-
+         tagged_parameter_tree_len =
+             tvb_reported_length_remaining(tvb, next_idx + 4);
+         tagged_tree = get_tagged_parameter_tree (hdr_tree, tvb, next_idx,
+                                                  tagged_parameter_tree_len);
 
+         while (tagged_parameter_tree_len > 0) {
+           if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
+             break;
+           next_idx +=next_len;
+           tagged_parameter_tree_len -= next_len;
+         }
        }
       break;
 
+
     case MGT_PROBE_REQ:
-      COL_SHOW_INFO (pinfo->fd, "Probe Request");
       if (tree)
        {
          next_idx = MGT_FRAME_LEN;
-         tagged_tree = get_tagged_parameter_tree (tree, tvb, MGT_FRAME_LEN,
-                                                  pinfo->captured_len - 4 -
-                                                  next_idx);
+         tagged_parameter_tree_len =
+             tvb_reported_length_remaining(tvb, next_idx + 4);
+         tagged_tree = get_tagged_parameter_tree (hdr_tree, tvb, next_idx,
+                                                  tagged_parameter_tree_len);
 
-         while (pinfo->captured_len > (next_idx + 4))
-           next_idx += add_tagged_field (tagged_tree, tvb, next_idx);
+         while (tagged_parameter_tree_len > 0) {
+           if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
+             break;
+           next_idx +=next_len;
+           tagged_parameter_tree_len -= next_len;
+         }
        }
       break;
 
 
-
     case MGT_PROBE_RESP:
-      COL_SHOW_INFO (pinfo->fd, "Probe Response");
       if (tree)
        {
-         fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 12);
+         fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 12);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_TIMESTAMP);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 8,
                           FIELD_BEACON_INTERVAL);
@@ -1079,22 +1167,25 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
                           FIELD_CAP_INFO);
 
          next_idx = MGT_FRAME_LEN + 12;        /* Size of fixed fields */
-         tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
-                                                  pinfo->captured_len - 4 -
-                                                  next_idx);
+         tagged_parameter_tree_len =
+             tvb_reported_length_remaining(tvb, next_idx + 4);
+         tagged_tree = get_tagged_parameter_tree (hdr_tree, tvb, next_idx,
+                                                  tagged_parameter_tree_len);
 
-         while ((pinfo->captured_len) > (next_idx + 4))
-           next_idx += add_tagged_field (tagged_tree, tvb, next_idx);
+         while (tagged_parameter_tree_len > 0) {
+           if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
+             break;
+           next_idx +=next_len;
+           tagged_parameter_tree_len -= next_len;
+         }
        }
       break;
 
 
     case MGT_BEACON:           /* Dissect protocol payload fields  */
-      COL_SHOW_INFO (pinfo->fd, "Beacon frame");
-
       if (tree)
        {
-         fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 12);
+         fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 12);
 
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_TIMESTAMP);
 
@@ -1104,64 +1195,83 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
                           FIELD_CAP_INFO);
 
          next_idx = MGT_FRAME_LEN + 12;        /* Size of fixed fields */
-         tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
-                                                  pinfo->captured_len - 4 -
-                                                  next_idx);
-
-         while (pinfo->captured_len > (next_idx + 4))
-           next_idx += add_tagged_field (tagged_tree, tvb, next_idx);
+         tagged_parameter_tree_len =
+             tvb_reported_length_remaining(tvb, next_idx + 4);
+         tagged_tree = get_tagged_parameter_tree (hdr_tree, tvb, next_idx,
+                                                  tagged_parameter_tree_len);
 
+         while (tagged_parameter_tree_len > 0) {
+           if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
+             break;
+           next_idx +=next_len;
+           tagged_parameter_tree_len -= next_len;
+         }
        }
       break;
 
 
-
     case MGT_ATIM:
-      COL_SHOW_INFO (pinfo->fd, "ATIM");
       if (tree)
        {
        }
       break;
 
     case MGT_DISASS:
-      COL_SHOW_INFO (pinfo->fd, "Dissassociate");
       if (tree)
        {
-         fixed_tree =
-           get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, cap_len);
+         fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, cap_len);
          add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_REASON_CODE);
        }
       break;
 
     case MGT_AUTHENTICATION:
-      COL_SHOW_INFO (pinfo->fd, "Authentication");
-      if (tree)
+      if (IS_WEP(COOK_FLAGS(fcf)))
        {
-         fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 6);
-         add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_AUTH_ALG);
-         add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
-                          FIELD_AUTH_TRANS_SEQ);
-         add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
-                          FIELD_STATUS_CODE);
-
-         next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
-
-         if ((pinfo->captured_len - next_idx - 4) != 0)
+         int pkt_len = tvb_reported_length (tvb);
+         int cap_len = tvb_length (tvb);
+
+         if (tree)
+           get_wep_parameter_tree (tree, tvb, MGT_FRAME_LEN, pkt_len);
+         pkt_len = MAX (pkt_len - 8 - MGT_FRAME_LEN, 0);
+         cap_len = MIN (pkt_len, MAX (cap_len - 8 - MGT_FRAME_LEN, 0));
+         next_tvb = tvb_new_subset (tvb, MGT_FRAME_LEN + 4, cap_len, pkt_len);
+         dissect_data (next_tvb, 0, pinfo, tree);
+       }
+      else
+       {
+         if (tree)
            {
-             tagged_tree = get_tagged_parameter_tree (tree,
-                                                      tvb,
-                                                      next_idx,
-                                                      pinfo->captured_len -
-                                                      next_idx - 4);
-
-             while ((pinfo->captured_len) > (next_idx - 4))
-               next_idx += add_tagged_field (tagged_tree, tvb, next_idx);
+             fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 6);
+             add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_AUTH_ALG);
+             add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
+                              FIELD_AUTH_TRANS_SEQ);
+             add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
+                              FIELD_STATUS_CODE);
+
+             next_idx = MGT_FRAME_LEN + 6;     /* Size of fixed fields */
+
+             tagged_parameter_tree_len =
+                 tvb_reported_length_remaining(tvb, next_idx + 4);
+             if (tagged_parameter_tree_len != 0)
+               {
+                 tagged_tree = get_tagged_parameter_tree (hdr_tree,
+                                                          tvb,
+                                                          next_idx,
+                                                          tagged_parameter_tree_len);
+
+                 while (tagged_parameter_tree_len > 0) {
+                   if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
+                     break;
+                   next_idx +=next_len;
+                   tagged_parameter_tree_len -= next_len;
+                 }
+               }
            }
        }
       break;
 
+
     case MGT_DEAUTHENTICATION:
-      COL_SHOW_INFO (pinfo->fd, "Deauthentication");
       if (tree)
        {
          fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 2);
@@ -1170,234 +1280,109 @@ dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
       break;
 
 
-
     case CTRL_PS_POLL:
-      COL_SHOW_INFO (pinfo->fd, "Power-Save poll");
-
       src = tvb_get_ptr (tvb, 10, 6);
       dst = tvb_get_ptr (tvb, 4, 6);
 
-
-      if (check_col (pinfo->fd, COL_DEF_SRC))
-       col_add_fstr (pinfo->fd, COL_DEF_SRC,
-                     "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (BSSID)",
-                     src[0], src[1], src[2], src[3], src[4], src[5]);
-
-      if (check_col (pinfo->fd, COL_DEF_DST))
-       col_add_fstr (pinfo->fd, COL_DEF_DST,
-                     "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (TA)",
-                     dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+      set_src_addr_cols(pinfo, src, "BSSID");
+      set_dst_addr_cols(pinfo, dst, "BSSID");
 
       if (tree)
        {
-         proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
-                               tvb_get_ptr (tvb, 4, 6));
-
-         proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
-                               tvb_get_ptr (tvb, 10, 6));
+         proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
 
+         proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
        }
       break;
 
 
-
     case CTRL_RTS:
-      COL_SHOW_INFO (pinfo->fd, "Request-to-send");
       src = tvb_get_ptr (tvb, 10, 6);
       dst = tvb_get_ptr (tvb, 4, 6);
 
-
-      if (check_col (pinfo->fd, COL_DEF_SRC))
-       col_add_fstr (pinfo->fd, COL_DEF_SRC,
-                     "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (TA)",
-                     src[0], src[1], src[2], src[3], src[4], src[5]);
-
-      if (check_col (pinfo->fd, COL_DEF_DST))
-       col_add_fstr (pinfo->fd, COL_DEF_DST,
-                     "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
-                     dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+      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,
-                               tvb_get_ptr (tvb, 4, 6));
-
-         proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
-                               tvb_get_ptr (tvb, 10, 6));
+         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
 
+         proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
        }
       break;
 
 
-
     case CTRL_CTS:
-      COL_SHOW_INFO (pinfo->fd, "Clear-to-send");
-
       dst = tvb_get_ptr (tvb, 4, 6);
 
-      if (check_col (pinfo->fd, COL_DEF_DST))
-       col_add_fstr (pinfo->fd, COL_DEF_DST,
-                     "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
-                     dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+      set_dst_addr_cols(pinfo, dst, "RA");
 
       if (tree)
-       {
-         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
-                               tvb_get_ptr (tvb, 4, 6));
-
-       }
+         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
       break;
 
 
-
     case CTRL_ACKNOWLEDGEMENT:
-      COL_SHOW_INFO (pinfo->fd, "Acknowledgement");
-
       dst = tvb_get_ptr (tvb, 4, 6);
 
-      if (check_col (pinfo->fd, COL_DEF_DST))
-       col_add_fstr (pinfo->fd, COL_DEF_DST,
-                     "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
-                     dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+      set_dst_addr_cols(pinfo, dst, "RA");
 
       if (tree)
-       proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
-                             tvb_get_ptr (tvb, 4, 6));
+       proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
       break;
 
 
-
     case CTRL_CFP_END:
-      COL_SHOW_INFO (pinfo->fd, "CF-End (Control-frame)");
-
       src = tvb_get_ptr (tvb, 10, 6);
       dst = tvb_get_ptr (tvb, 4, 6);
 
-
-      if (check_col (pinfo->fd, COL_DEF_SRC))
-       col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X (BSSID)",
-                     src[0], src[1], src[2], src[3], src[4], src[5]);
-
-      if (check_col (pinfo->fd, COL_DEF_DST))
-       col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X (RA)",
-                     dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+      set_src_addr_cols(pinfo, src, "BSSID");
+      set_dst_addr_cols(pinfo, dst, "RA");
 
       if (tree)
        {
-         proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
-                              tvb_get_ntohs (tvb, 2));
-
-         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
-                               tvb_get_ptr (tvb, 4, 6));
-
-         proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
-                               tvb_get_ptr (tvb, 10, 6));
-
+         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
+         proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
        }
       break;
 
 
-
     case CTRL_CFP_ENDACK:
-      COL_SHOW_INFO (pinfo->fd, "CF-End + CF-Ack (Control-frame)");
-
       src = tvb_get_ptr (tvb, 10, 6);
       dst = tvb_get_ptr (tvb, 4, 6);
 
-      if (check_col (pinfo->fd, COL_DEF_SRC))
-       col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X (BSSID)",
-                     src[0], src[1], src[2], src[3], src[4], src[5]);
-
-      if (check_col (pinfo->fd, COL_DEF_DST))
-       col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X (RA)",
-                     dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+      set_src_addr_cols(pinfo, src, "BSSID");
+      set_dst_addr_cols(pinfo, dst, "RA");
 
       if (tree)
        {
-         proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
-                              tvb_get_ntohs (tvb, 2));
-
-         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
-                               tvb_get_ptr (tvb, 4, 6));
-
-         proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
-                               tvb_get_ptr (tvb, 10, 6));
+         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
 
+         proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
        }
       break;
 
 
-
     case DATA:
-      COL_SHOW_INFO (pinfo->fd, "Data");
-      if (tree)
-       {
-         hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
-
-         next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
-         dissect_llc (next_tvb, pinfo, tree);
-
-       }
-      break;
-
-
-
     case DATA_CF_ACK:
-      COL_SHOW_INFO (pinfo->fd, "Data + CF-Acknowledgement");
-      if (tree)
-       {
-         hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
-
-         next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
-         dissect_llc (next_tvb, pinfo, tree);
-       }
-      break;
-
-
-
     case DATA_CF_POLL:
-      COL_SHOW_INFO (pinfo->fd, "Data + CF-Poll");
-      if (tree)
-       {
-         hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
-         next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
-         dissect_llc (next_tvb, pinfo, tree);
-       }
-      break;
-
-
-
     case DATA_CF_ACK_POLL:
-      COL_SHOW_INFO (pinfo->fd, "Data + CF-Acknowledgement/Poll");
-      if (tree)
+      next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
+
+      if (IS_WEP(COOK_FLAGS(fcf)))
        {
-         hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
-         next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
-         dissect_llc (next_tvb, pinfo, tree);
+         int pkt_len = tvb_reported_length (next_tvb);
+         int cap_len = tvb_length (next_tvb);
+
+         if (tree)
+           get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
+         pkt_len = MAX (pkt_len - 8, 0);
+         cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
+         next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
+         dissect_data (next_tvb, 0, pinfo, tree);
        }
-      break;
-
-
-
-    case DATA_NULL_FUNCTION:
-      COL_SHOW_INFO (pinfo->fd, "Null function (No data)");
-      break;
-
-
-    case DATA_CF_ACK_NOD:
-      COL_SHOW_INFO (pinfo->fd, "Data + Acknowledgement(No data)");
-      break;
-
-
-
-    case DATA_CF_ACK_POLL_NOD:
-      COL_SHOW_INFO (pinfo->fd, "Data + CF-Acknowledgement/Poll (No data)");
-      break;
-
-
-
-    default:
-      COL_SHOW_INFO (pinfo->fd, "Unrecognized (Reserved frame)");
+      else
+       call_dissector (llc_handle, next_tvb, pinfo, tree);
       break;
     }
 }
@@ -1407,10 +1392,17 @@ void
 proto_register_wlan (void)
 {
 
+  static const value_string frame_type[] = {
+    {MGT_FRAME,     "Management frame"},
+    {CONTROL_FRAME, "Control frame"},
+    {DATA_FRAME,    "Data frame"},
+    {0,             NULL}
+  };
+
   static const value_string tofrom_ds[] = {
-    {0, "Network operating in AD-HOC mode ( To DS: 0  From DS: 0)"},
+    {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
     {1, "Frame is exiting DS (To DS: 0  From DS: 1)"},
-    {2, "Frame is entering DS (To DS: 0  From DS: 1)"},
+    {2, "Frame is entering DS (To DS: 1  From DS: 0)"},
     {3, "Frame part of WDS (To DS: 1  From DS: 1)"},
     {0, NULL}
   };
@@ -1451,8 +1443,8 @@ proto_register_wlan (void)
   };
 
   static const true_false_string order_flags = {
-    "",
-    ""
+    "Strictly ordered",
+    "Not strictly ordered"
   };
 
   static const true_false_string cf_ess_flags = {
@@ -1466,6 +1458,21 @@ proto_register_wlan (void)
     "AP/STA cannot support WEP"
   };
 
+  static const true_false_string cf_preamble_flags = {
+    "Short preamble allowed",
+    "Short preamble not allowed"
+  };
+
+  static const true_false_string cf_pbcc_flags = {
+    "PBCC modulation allowed",
+    "PBCC modulation not allowed"
+  };
+
+  static const true_false_string cf_agility_flags = {
+    "Channel agility in use",
+    "Channel agility not in use"
+  };
+
 
   static const true_false_string cf_ibss_flags = {
     "Transmitter belongs to an IBSS",
@@ -1544,182 +1551,217 @@ proto_register_wlan (void)
   static hf_register_info hf[] = {
     {&hf_fc_field,
      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
-      "MAC Frame control"}},
+      "MAC Frame control", HFILL }},
 
     {&hf_fc_proto_version,
      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
-      "MAC Protocol version"}},        /* 0 */
+      "MAC Protocol version", HFILL }},        /* 0 */
 
     {&hf_fc_frame_type,
-     {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, NULL, 0,
-      "Frame type"}},
+     {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
+      "Frame type", HFILL }},
 
     {&hf_fc_frame_subtype,
      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
-      "Frame subtype"}},       /* 2 */
+      "Frame subtype", HFILL }},       /* 2 */
+
+    {&hf_fc_frame_type_subtype,
+     {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
+      "Type and subtype combined", HFILL }},
 
     {&hf_fc_flags,
      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
-      "Protocol flags"}},
+      "Protocol flags", HFILL }},
 
     {&hf_fc_data_ds,
-     {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, TFS (&tofrom_ds), 0,
-      "Data-frame DS-traversal status"}},      /* 3 */
+     {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
+      "Data-frame DS-traversal status", HFILL }},      /* 3 */
 
     {&hf_fc_to_ds,
      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), 0x1,
-      "To DS flag"}},          /* 4 */
+      "To DS flag", HFILL }},          /* 4 */
 
     {&hf_fc_from_ds,
      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), 0x2,
-      "From DS flag"}},                /* 5 */
+      "From DS flag", HFILL }},                /* 5 */
 
     {&hf_fc_more_frag,
      {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), 0x4,
-      "More Fragments flag"}}, /* 6 */
+      "More Fragments flag", HFILL }}, /* 6 */
 
     {&hf_fc_retry,
      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), 0x8,
-      "Retransmission flag"}},
+      "Retransmission flag", HFILL }},
 
     {&hf_fc_pwr_mgt,
      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), 0x10,
-      "Power management status"}},
+      "Power management status", HFILL }},
 
     {&hf_fc_more_data,
      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), 0x20,
-      "More data flag"}},
+      "More data flag", HFILL }},
 
     {&hf_fc_wep,
      {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), 0x40,
-      "WEP flag"}},
+      "WEP flag", HFILL }},
 
     {&hf_fc_order,
      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), 0x80,
-      "Strictly ordered flag"}},
+      "Strictly ordered flag", HFILL }},
+
+    {&hf_assoc_id,
+     {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
+      "Association-ID field", HFILL }},
 
     {&hf_did_duration,
      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
-      "Duration field"}},
+      "Duration field", HFILL }},
 
     {&hf_addr_da,
      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
-      "Destination Hardware address"}},
+      "Destination Hardware address", HFILL }},
 
     {&hf_addr_sa,
      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
-      "Source Hardware address"}},
+      "Source Hardware address", HFILL }},
 
     {&hf_addr_ra,
      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
-      "Receiving Station Hardware Address"}},
+      "Receiving Station Hardware Address", HFILL }},
 
     {&hf_addr_ta,
      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
-      "Transmitting Station Hardware Address"}},
+      "Transmitting Station Hardware Address", HFILL }},
 
     {&hf_addr_bssid,
      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
-      "Basic Service Set ID"}},
+      "Basic Service Set ID", HFILL }},
 
     {&hf_frag_number,
-     {"Fragment number", "wlan.frag", FT_UINT16, BASE_HEX, NULL, 0,
-      "Fragment number"}},
+     {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
+      "Fragment number", HFILL }},
 
     {&hf_seq_number,
-     {"Sequence number", "wlan.seq", FT_UINT16, BASE_HEX, NULL, 0,
-      "Fragment number"}},
+     {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
+      "Sequence number", HFILL }},
 
     {&hf_fcs,
      {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
-      NULL, 0, ""}},
+      NULL, 0, "", HFILL }},
 
     {&ff_timestamp,
      {"Timestamp", "wlan.fixed.timestamp", FT_STRING, BASE_NONE,
-      NULL, 0, ""}},
+      NULL, 0, "", HFILL }},
 
     {&ff_auth_alg,
      {"Authentication Algorithm", "wlan.fixed.auth.alg",
-      FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, ""}},
+      FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
 
     {&ff_beacon_interval,
-     {"Beacon Interval", "wlan.fixed.beacon", FT_UINT16, BASE_DEC, NULL, 0,
-      ""}},
+     {"Beacon Interval", "wlan.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
+      "", HFILL }},
 
     {&hf_fixed_parameters,
      {"Fixed parameters", "wlan.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
-      ""}},
+      "", HFILL }},
 
     {&hf_tagged_parameters,
      {"Tagged parameters", "wlan.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
-      ""}},
+      "", HFILL }},
+
+    {&hf_wep_parameters,
+     {"WEP parameters", "wlan.wep.all", FT_STRING, BASE_NONE, NULL, 0,
+      "", HFILL }},
+
+    {&hf_wep_iv,
+     {"Initialization Vector", "wlan.wep.iv", FT_UINT32, BASE_HEX, NULL, 0,
+      "Initialization Vector", HFILL }},
+
+    {&hf_wep_key,
+     {"Key", "wlan.wep.key", FT_UINT32, BASE_DEC, NULL, 0,
+      "Key", HFILL }},
+
+    {&hf_wep_crc,
+     {"WEP CRC (not verified)", "wlan.wep.crc", FT_UINT32, BASE_HEX, NULL, 0,
+      "WEP CRC", HFILL }},
 
     {&ff_capture,
      {"Capabilities", "wlan.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
-      "Capability information"}},
+      "Capability information", HFILL }},
 
     {&ff_cf_sta_poll,
      {"CFP participation capabilities", "wlan.fixed.capabilities.cfpoll.sta",
       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
-      "CF-Poll capabilities for a STA"}},
+      "CF-Poll capabilities for a STA", HFILL }},
 
     {&ff_cf_ap_poll,
      {"CFP participation capabilities", "wlan.fixed.capabilities.cfpoll.ap",
       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
-      "CF-Poll capabilities for an AP"}},
+      "CF-Poll capabilities for an AP", HFILL }},
 
     {&ff_cf_ess,
      {"ESS capabilities", "wlan.fixed.capabilities.ess",
-      FT_BOOLEAN, 1, TFS (&cf_ess_flags), 0x0001, "ESS capabilities"}},
+      FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
 
 
     {&ff_cf_ibss,
      {"IBSS status", "wlan.fixed.capabilities.ibss",
-      FT_BOOLEAN, 1, TFS (&cf_ibss_flags), 0x0002, "IBSS participation"}},
+      FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
 
     {&ff_cf_privacy,
      {"Privacy", "wlan.fixed.capabilities.privacy",
-      FT_BOOLEAN, 1, TFS (&cf_privacy_flags), 0x0010, "WEP support"}},
+      FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
 
+    {&ff_cf_preamble,
+     {"Short Preamble", "wlan.fixed.capabilities.preamble",
+      FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
+
+    {&ff_cf_pbcc,
+     {"PBCC", "wlan.fixed.capabilities.pbcc",
+      FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
+
+    {&ff_cf_agility,
+     {"Channel Agility", "wlan.fixed.capabilities.agility",
+      FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
 
     {&ff_auth_seq,
      {"Authentication SEQ", "wlan.fixed.auth_seq",
-      FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number"}},
+      FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
 
     {&ff_assoc_id,
      {"Association ID", "wlan.fixed.aid",
-      FT_UINT16, BASE_HEX, NULL, 0, "Association ID"}},
+      FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
 
     {&ff_listen_ival,
      {"Listen Interval", "wlan.fixed.listen_ival",
-      FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval"}},
+      FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
 
     {&ff_current_ap,
      {"Current AP", "wlan.fixed.current_ap",
-      FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP"}},
+      FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
 
     {&ff_reason,
      {"Reason code", "wlan.fixed.reason_code",
       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
-      "Reason for unsolicited notification"}},
+      "Reason for unsolicited notification", HFILL }},
 
     {&ff_status_code,
      {"Status code", "wlan.fixed.status_code",
       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
-      "Status of requested event"}},
+      "Status of requested event", HFILL }},
 
     {&tag_number,
      {"Tag", "wlan.tag.number",
       FT_UINT16, BASE_DEC, NULL, 0,
-      "Element ID"}},
+      "Element ID", HFILL }},
 
     {&tag_length,
      {"Tag length", "wlan.tag.length",
-      FT_UINT16, BASE_DEC, NULL, 0, "Length of tag"}},
+      FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
 
     {&tag_interpretation,
      {"Tag interpretation", "wlan.tag.interpretation",
-      FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag"}}
+      FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
 
 
   };
@@ -1730,10 +1772,12 @@ proto_register_wlan (void)
     &ett_proto_flags,
     &ett_fixed_parameters,
     &ett_tagged_parameters,
+    &ett_wep_parameters,
     &ett_cap_tree,
   };
 
-  proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN", "wlan");
+  proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
+                                       "IEEE 802.11", "wlan");
   proto_register_field_array (proto_wlan, hf, array_length (hf));
   proto_register_subtree_array (tree_array, array_length (tree_array));
 }
@@ -1741,5 +1785,11 @@ proto_register_wlan (void)
 void
 proto_reg_handoff_wlan(void)
 {
-       dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211);
+  /*
+   * Get a handle for the LLC dissector.
+   */
+  llc_handle = find_dissector("llc");
+
+  dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,
+               proto_wlan);
 }