Add in some heuristics to try to detect AIX libpcap format. (This works
[obnox/wireshark/wip.git] / packet-ieee80211.c
1 /* packet-ieee80211.c
2  * Routines for Wireless LAN (IEEE 802.11) dissection
3  * Copyright 2000, Axis Communications AB 
4  * Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com
5  *
6  * $Id: packet-ieee80211.c,v 1.40 2001/09/25 02:21:15 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from README.developer
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  *
28  * Credits:
29  * 
30  * The following people helped me by pointing out bugs etc. Thank you!
31  *
32  * Marco Molteni
33  * Lena-Marie Nilsson     
34  * Magnus Hultman-Persson
35  *
36  */
37
38 #ifdef HAVE_CONFIG_H
39 # include "config.h"
40 #endif
41
42 #include <stdio.h>
43 #include <stdlib.h>
44
45 #ifdef HAVE_SYS_TYPES_H
46 # include <sys/types.h>
47 #endif
48
49 #ifdef HAVE_NETINET_IN_H
50 # include <netinet/in.h>
51 #endif
52
53 #ifdef NEED_SNPRINTF_H
54 # ifdef HAVE_STDARG_H
55 #  include <stdarg.h>
56 # else
57 #  include <varargs.h>
58 # endif
59 # include "snprintf.h"
60 #endif
61
62 #include <string.h>
63 #include <glib.h>
64 #include "bitswap.h"
65 #include "proto.h"
66 #include "packet.h"
67 #include "resolv.h"
68 #include "packet-ipx.h"
69 #include "packet-llc.h"
70 #include "packet-ieee80211.h"
71 #include "etypes.h"
72
73 /* ************************************************************************* */
74 /*                          Miscellaneous Constants                          */
75 /* ************************************************************************* */
76 #define SHORT_STR 256
77
78 /* ************************************************************************* */
79 /*  Define some very useful macros that are used to analyze frame types etc. */
80 /* ************************************************************************* */
81 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4))      /* Create key to (sub)type */
82 #define COOK_PROT_VERSION(x)  ((x) & 0x3)
83 #define COOK_FRAME_TYPE(x)    (((x) & 0xC) >> 2)
84 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
85 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
86 #define COOK_ASSOC_ID(x)      ((x) & 0x3FFF)
87 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
88 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
89 #define COOK_FLAGS(x)           (((x) & 0xFF00) >> 8)
90 #define COOK_DS_STATUS(x)       ((x) & 0x3)
91 #define COOK_WEP_KEY(x)       (((x) & 0xC0) >> 6)
92 #define COL_SHOW_INFO(fd,info) if (check_col(fd,COL_INFO)) \
93                                 col_add_str(fd,COL_INFO,info);
94 #define COL_SHOW_INFO_CONST(fd,info) if (check_col(fd,COL_INFO)) \
95                                 col_set_str(fd,COL_INFO,info);
96
97 #define FLAG_TO_DS              0x01
98 #define FLAG_FROM_DS            0x02
99 #define FLAG_MORE_FRAGMENTS     0x04
100 #define FLAG_RETRY              0x08
101 #define FLAG_POWER_MGT          0x10
102 #define FLAG_MORE_DATA          0x20
103 #define FLAG_WEP                0x40
104 #define FLAG_ORDER              0x80
105
106 #define IS_TO_DS(x)            ((x) & FLAG_TO_DS)
107 #define IS_FROM_DS(x)          ((x) & FLAG_FROM_DS)
108 #define HAVE_FRAGMENTS(x)      ((x) & FLAG_MORE_FRAGMENTS)
109 #define IS_RETRY(x)            ((x) & FLAG_RETRY)
110 #define POWER_MGT_STATUS(x)    ((x) & FLAG_POWER_MGT)
111 #define HAS_MORE_DATA(x)       ((x) & FLAG_MORE_DATA)
112 #define IS_WEP(x)              ((x) & FLAG_WEP)
113 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
114
115 #define MGT_RESERVED_RANGE(x)  (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
116 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
117 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
118 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
119
120
121 /* ************************************************************************* */
122 /*              Constants used to identify cooked frame types                */
123 /* ************************************************************************* */
124 #define MGT_FRAME            0x00       /* Frame type is management */
125 #define CONTROL_FRAME        0x01       /* Frame type is control */
126 #define DATA_FRAME           0x02       /* Frame type is Data */
127
128 #define DATA_SHORT_HDR_LEN     24
129 #define DATA_LONG_HDR_LEN      30
130 #define MGT_FRAME_HDR_LEN      24       /* Length of Managment frame-headers */
131
132 #define MGT_ASSOC_REQ        0x00       /* Management - association request        */
133 #define MGT_ASSOC_RESP       0x01       /* Management - association response       */
134 #define MGT_REASSOC_REQ      0x02       /* Management - reassociation request      */
135 #define MGT_REASSOC_RESP     0x03       /* Management - reassociation response     */
136 #define MGT_PROBE_REQ        0x04       /* Management - Probe request              */
137 #define MGT_PROBE_RESP       0x05       /* Management - Probe response             */
138 #define MGT_BEACON           0x08       /* Management - Beacon frame               */
139 #define MGT_ATIM             0x09       /* Management - ATIM                       */
140 #define MGT_DISASS           0x0A       /* Management - Disassociation             */
141 #define MGT_AUTHENTICATION   0x0B       /* Management - Authentication             */
142 #define MGT_DEAUTHENTICATION 0x0C       /* Management - Deauthentication           */
143
144 #define CTRL_PS_POLL         0x1A       /* Control - power-save poll               */
145 #define CTRL_RTS             0x1B       /* Control - request to send               */
146 #define CTRL_CTS             0x1C       /* Control - clear to send                 */
147 #define CTRL_ACKNOWLEDGEMENT 0x1D       /* Control - acknowledgement               */
148 #define CTRL_CFP_END         0x1E       /* Control - contention-free period end    */
149 #define CTRL_CFP_ENDACK      0x1F       /* Control - contention-free period end/ack */
150
151 #define DATA                 0x20       /* Data - Data                             */
152 #define DATA_CF_ACK          0x21       /* Data - Data + CF acknowledge            */
153 #define DATA_CF_POLL         0x22       /* Data - Data + CF poll                   */
154 #define DATA_CF_ACK_POLL     0x23       /* Data - Data + CF acknowledge + CF poll  */
155 #define DATA_NULL_FUNCTION   0x24       /* Data - Null function (no data)          */
156 #define DATA_CF_ACK_NOD      0x25       /* Data - CF ack (no data)                 */
157 #define DATA_CF_POLL_NOD     0x26       /* Data - Data + CF poll (No data)         */
158 #define DATA_CF_ACK_POLL_NOD 0x27       /* Data - CF ack + CF poll (no data)       */
159
160 #define DATA_ADDR_T1         0
161 #define DATA_ADDR_T2         (FLAG_FROM_DS << 8)
162 #define DATA_ADDR_T3         (FLAG_TO_DS << 8)
163 #define DATA_ADDR_T4         ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
164
165
166 /* ************************************************************************* */
167 /*          Macros used to extract information about fixed fields            */
168 /* ************************************************************************* */
169 #define ESS_SET(x) ((x) & 0x0001)
170 #define IBSS_SET(x) ((x) & 0x0002)
171
172
173
174 /* ************************************************************************* */
175 /*        Logical field codes (dissector's encoding of fixed fields)         */
176 /* ************************************************************************* */
177 #define FIELD_TIMESTAMP       0x01      /* 64-bit timestamp                       */
178 #define FIELD_BEACON_INTERVAL 0x02      /* 16-bit beacon interval                 */
179 #define FIELD_CAP_INFO        0x03      /* Add capability information tree        */
180 #define FIELD_AUTH_ALG        0x04      /* Authentication algorithm used          */
181 #define FIELD_AUTH_TRANS_SEQ  0x05      /* Authentication sequence number         */
182 #define FIELD_CURRENT_AP_ADDR 0x06
183 #define FIELD_LISTEN_IVAL     0x07
184 #define FIELD_REASON_CODE     0x08
185 #define FIELD_ASSOC_ID        0x09
186 #define FIELD_STATUS_CODE     0x0A
187
188 /* ************************************************************************* */
189 /*        Logical field codes (IEEE 802.11 encoding of tags)                 */
190 /* ************************************************************************* */
191 #define TAG_SSID           0x00
192 #define TAG_SUPP_RATES     0x01
193 #define TAG_FH_PARAMETER   0x02
194 #define TAG_DS_PARAMETER   0x03
195 #define TAG_CF_PARAMETER   0x04
196 #define TAG_TIM            0x05
197 #define TAG_IBSS_PARAMETER 0x06
198 #define TAG_CHALLENGE_TEXT 0x10
199
200 /* ************************************************************************* */
201 /*                         Frame types, and their names                      */
202 /* ************************************************************************* */
203 static const value_string frame_type_subtype_vals[] = {
204         {MGT_ASSOC_REQ,        "Association Request"},
205         {MGT_ASSOC_RESP,       "Association Response"},
206         {MGT_REASSOC_REQ,      "Reassociation Request"},
207         {MGT_REASSOC_RESP,     "Reassociation Response"},
208         {MGT_PROBE_REQ,        "Probe Request"},
209         {MGT_PROBE_RESP,       "Probe Response"},
210         {MGT_BEACON,           "Beacon frame"},
211         {MGT_ATIM,             "ATIM"},
212         {MGT_DISASS,           "Dissassociate"},
213         {MGT_AUTHENTICATION,   "Authentication"},
214         {MGT_DEAUTHENTICATION, "Deauthentication"},
215         {CTRL_PS_POLL,         "Power-Save poll"},
216         {CTRL_RTS,             "Request-to-send"},
217         {CTRL_CTS,             "Clear-to-send"},
218         {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
219         {CTRL_CFP_END,         "CF-End (Control-frame)"},
220         {CTRL_CFP_ENDACK,      "CF-End + CF-Ack (Control-frame)"},
221         {DATA,                 "Data"},
222         {DATA_CF_ACK,          "Data + CF-Acknowledgement"},
223         {DATA_CF_POLL,         "Data + CF-Poll"},
224         {DATA_CF_ACK_POLL,     "Data + CF-Acknowledgement/Poll"},
225         {DATA_NULL_FUNCTION,   "Null function (No data)"},
226         {DATA_CF_ACK_NOD,      "Data + Acknowledgement (No data)"},
227         {DATA_CF_POLL_NOD,     "Data + CF-Poll (No data)"},
228         {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
229         {0,                    NULL}
230 };
231
232 static int proto_wlan = -1;
233 /* ************************************************************************* */
234 /*                Header field info values for FC-field                      */
235 /* ************************************************************************* */
236 static int hf_fc_field = -1;
237 static int hf_fc_proto_version = -1;
238 static int hf_fc_frame_type = -1;
239 static int hf_fc_frame_subtype = -1;
240 static int hf_fc_frame_type_subtype = -1;
241
242 static int hf_fc_flags = -1;
243 static int hf_fc_to_ds = -1;
244 static int hf_fc_from_ds = -1;
245 static int hf_fc_data_ds = -1;
246
247 static int hf_fc_more_frag = -1;
248 static int hf_fc_retry = -1;
249 static int hf_fc_pwr_mgt = -1;
250 static int hf_fc_more_data = -1;
251 static int hf_fc_wep = -1;
252 static int hf_fc_order = -1;
253
254
255 /* ************************************************************************* */
256 /*                   Header values for Duration/ID field                     */
257 /* ************************************************************************* */
258 static int hf_did_duration = -1;
259 static int hf_assoc_id = -1;
260
261
262 /* ************************************************************************* */
263 /*         Header values for different address-fields (all 4 of them)        */
264 /* ************************************************************************* */
265 static int hf_addr_da = -1;     /* Destination address subfield */
266 static int hf_addr_sa = -1;     /* Source address subfield */
267 static int hf_addr_ra = -1;     /* Receiver address subfield */
268 static int hf_addr_ta = -1;     /* Transmitter address subfield */
269 static int hf_addr_bssid = -1;  /* address is bssid */
270
271 static int hf_addr = -1;        /* Source or destination address subfield */
272
273
274 /* ************************************************************************* */
275 /*                Header values for sequence number field                    */
276 /* ************************************************************************* */
277 static int hf_frag_number = -1;
278 static int hf_seq_number = -1;
279
280 /* ************************************************************************* */
281 /*                   Header values for Frame Check field                     */
282 /* ************************************************************************* */
283 static int hf_fcs = -1;
284
285
286
287 static int proto_wlan_mgt = -1;
288 /* ************************************************************************* */
289 /*                      Fixed fields found in mgt frames                     */
290 /* ************************************************************************* */
291 static int ff_auth_alg = -1;    /* Authentication algorithm field            */
292 static int ff_auth_seq = -1;    /* Authentication transaction sequence       */
293 static int ff_current_ap = -1;  /* Current AP MAC address                    */
294 static int ff_listen_ival = -1; /* Listen interval fixed field               */
295 static int ff_timestamp = -1;   /* 64 bit timestamp                          */
296 static int ff_beacon_interval = -1;     /* 16 bit Beacon interval            */
297 static int ff_assoc_id = -1;    /* 16 bit AID field                          */
298 static int ff_reason = -1;      /* 16 bit reason code                        */
299 static int ff_status_code = -1; /* Status code                               */
300
301 /* ************************************************************************* */
302 /*            Flags found in the capability field (fixed field)              */
303 /* ************************************************************************* */
304 static int ff_capture = -1;
305 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA            */
306 static int ff_cf_ap_poll = -1;  /* CF pollable status for an AP            */
307 static int ff_cf_ess = -1;
308 static int ff_cf_ibss = -1;
309 static int ff_cf_privacy = -1;
310 static int ff_cf_preamble = -1;
311 static int ff_cf_pbcc = -1;
312 static int ff_cf_agility = -1;
313
314 /* ************************************************************************* */
315 /*                       Tagged value format fields                          */
316 /* ************************************************************************* */
317 static int tag_number = -1;
318 static int tag_length = -1;
319 static int tag_interpretation = -1;
320
321
322
323 static int hf_fixed_parameters = -1;    /* Protocol payload for management frames */
324 static int hf_tagged_parameters = -1;   /* Fixed payload item */
325 static int hf_wep_iv = -1;
326 static int hf_wep_key = -1;
327 static int hf_wep_crc = -1;
328
329 /* ************************************************************************* */
330 /*                               Protocol trees                              */
331 /* ************************************************************************* */
332 static gint ett_80211 = -1;
333 static gint ett_proto_flags = -1;
334 static gint ett_cap_tree = -1;
335 static gint ett_fc_tree = -1;
336
337 static gint ett_80211_mgt = -1;
338 static gint ett_fixed_parameters = -1;
339 static gint ett_tagged_parameters = -1;
340 static gint ett_wep_parameters = -1;
341
342 static dissector_handle_t llc_handle;
343 static dissector_handle_t ipx_handle;
344
345 /* ************************************************************************* */
346 /*            Return the length of the current header (in bytes)             */
347 /* ************************************************************************* */
348 static int
349 find_header_length (guint16 fcf)
350 {
351   switch (COOK_FRAME_TYPE (fcf)) {
352
353   case MGT_FRAME:
354     return MGT_FRAME_HDR_LEN;
355
356   case CONTROL_FRAME:
357     switch (COMPOSE_FRAME_TYPE (fcf)) {
358
359     case CTRL_CTS:
360     case CTRL_ACKNOWLEDGEMENT:
361       return 10;
362
363     case CTRL_RTS:
364     case CTRL_PS_POLL:
365     case CTRL_CFP_END:
366     case CTRL_CFP_ENDACK:
367       return 16;
368     }
369     return 4;   /* XXX */
370
371   case DATA_FRAME:
372     return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
373                                                        DATA_SHORT_HDR_LEN;
374   default:
375     return 4;   /* XXX */
376   }
377 }
378
379
380 /* ************************************************************************* */
381 /*          This is the capture function used to update packet counts        */
382 /* ************************************************************************* */
383 void
384 capture_ieee80211 (const u_char * pd, int offset, packet_counts * ld)
385 {
386   guint16 fcf, hdr_length;
387
388   fcf = pletohs (&pd[0]);
389
390   if (IS_WEP(COOK_FLAGS(fcf)))
391     {
392       ld->other++;
393       return;
394     }
395
396   switch (COMPOSE_FRAME_TYPE (fcf))
397     {
398
399     case DATA:                  /* We got a data frame */
400     case DATA_CF_ACK:           /* Data with ACK */
401     case DATA_CF_POLL:
402     case DATA_CF_ACK_POLL:
403       hdr_length = find_header_length (fcf);
404       /* I guess some bridges take Netware Ethernet_802_3 frames,
405          which are 802.3 frames (with a length field rather than
406          a type field, but with no 802.2 header in the payload),
407          and just stick the payload into an 802.11 frame.  I've seen
408          captures that show frames of that sort.
409
410          This means we have to do the same check for Netware 802.3 -
411          or, if you will, "Netware 802.11" - that we do in the
412          Ethernet dissector, i.e. checking for 0xffff as the first
413          four bytes of the payload and, if we find it, treating it
414          as an IPX frame. */
415       if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
416         capture_ipx (pd, offset + hdr_length, ld);
417       }
418       else {
419         capture_llc (pd, offset + hdr_length, ld);
420       }
421       break;
422
423     default:
424       ld->other++;
425       break;
426     }
427 }
428
429
430
431 /* ************************************************************************* */
432 /*          Add the subtree used to store the fixed parameters               */
433 /* ************************************************************************* */
434 static proto_tree *
435 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
436 {
437   proto_item *fixed_fields;
438   fixed_fields =
439     proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
440                                 size, size, "Fixed parameters (%d bytes)",
441                                 size);
442
443   return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
444 }
445
446
447 /* ************************************************************************* */
448 /*            Add the subtree used to store tagged parameters                */
449 /* ************************************************************************* */
450 static proto_tree *
451 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
452 {
453   proto_item *tagged_fields;
454
455   tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
456                                               tvb,
457                                               start,
458                                               size,
459                                               size,
460                                               "Tagged parameters (%d bytes)",
461                                               size);
462
463   return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
464 }
465
466
467 /* ************************************************************************* */
468 /*            Add the subtree used to store WEP parameters                   */
469 /* ************************************************************************* */
470 static void
471 get_wep_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
472 {
473   proto_item *wep_fields;
474   proto_tree *wep_tree;
475   int crc_offset = size - 4;
476
477   wep_fields = proto_tree_add_text(tree, tvb, start, 4, "WEP parameters");
478
479   wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
480   proto_tree_add_item (wep_tree, hf_wep_iv, tvb, start, 3, TRUE);
481
482   proto_tree_add_uint (wep_tree, hf_wep_key, tvb, start + 3, 1,
483                        COOK_WEP_KEY (tvb_get_guint8 (tvb, start + 3)));
484
485   if (tvb_bytes_exist(tvb, start + crc_offset, 4))
486     proto_tree_add_uint (wep_tree, hf_wep_crc, tvb, start + crc_offset, 4,
487                          tvb_get_ntohl (tvb, start + crc_offset));
488 }
489
490 /* ************************************************************************* */
491 /*              Dissect and add fixed mgmt fields to protocol tree           */
492 /* ************************************************************************* */
493 static void
494 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
495 {
496   const guint8 *dataptr;
497   char out_buff[SHORT_STR];
498   guint16 capability;
499   proto_item *cap_item;
500   static proto_tree *cap_tree;
501   double temp_double;
502
503   switch (lfcode)
504     {
505     case FIELD_TIMESTAMP:
506       dataptr = tvb_get_ptr (tvb, offset, 8);
507       memset (out_buff, 0, SHORT_STR);
508       snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
509                 dataptr[7],
510                 dataptr[6],
511                 dataptr[5],
512                 dataptr[4],
513                 dataptr[3],
514                 dataptr[2],
515                 dataptr[1],
516                 dataptr[0]);
517
518       proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
519       break;
520
521     case FIELD_BEACON_INTERVAL:
522       temp_double = (double) tvb_get_letohs (tvb, offset);
523       temp_double = temp_double * 1024 / 1000000;
524       proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
525                                     temp_double,"Beacon Interval: %f [Seconds]",
526                                     temp_double);
527       break;
528
529
530     case FIELD_CAP_INFO:
531       capability = tvb_get_letohs (tvb, offset);
532
533       cap_item = proto_tree_add_uint_format (tree, ff_capture, 
534                                              tvb, offset, 2,
535                                              capability,
536                                              "Capability Information: 0x%04X",
537                                              capability);
538       cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
539       proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
540                               capability);
541       proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
542                               capability);
543       proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
544                               capability);
545       proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 1,
546                               capability);
547       proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 1,
548                               capability);
549       proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 1,
550                               capability);
551       if (ESS_SET (capability) != 0)    /* This is an AP */
552         proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
553                              ((capability & 0xC) >> 2));
554
555       else                      /* This is a STA */
556         proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
557                              ((capability & 0xC) >> 2));
558       break;
559
560     case FIELD_AUTH_ALG:
561       proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2, TRUE);
562       break;
563
564     case FIELD_AUTH_TRANS_SEQ:
565       proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2, TRUE);
566       break;
567
568     case FIELD_CURRENT_AP_ADDR:
569       proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
570       break;
571
572     case FIELD_LISTEN_IVAL:
573       proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
574       break;
575
576     case FIELD_REASON_CODE:
577       proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
578       break;
579
580     case FIELD_ASSOC_ID:
581       proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE);
582       break;
583
584     case FIELD_STATUS_CODE:
585       proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
586       break;
587     }
588 }
589
590
591 /* ************************************************************************* */
592 /*           Dissect and add tagged (optional) fields to proto tree          */
593 /* ************************************************************************* */
594 static int
595 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
596 {
597   const guint8 *tag_data_ptr;
598   guint32 tag_no, tag_len;
599   unsigned int i;
600   int n, ret;
601   char out_buff[SHORT_STR];
602
603
604   tag_no = tvb_get_guint8(tvb, offset);
605   tag_len = tvb_get_guint8(tvb, offset + 1);
606
607   tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
608
609
610   if ((tag_no >= 17) && (tag_no <= 31))
611     {                           /* Reserved for challenge text */
612       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
613                                   "Tag Number: %u (Reserved for challenge text)",
614                                   tag_no);
615
616       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
617       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
618                              tag_len, "Not interpreted");
619       return (int) tag_len + 2;
620     }
621
622   /* Next See if tag is reserved - if true, skip it! */
623   if (((tag_no >= 7) && (tag_no <= 15))
624       || ((tag_no >= 32) && (tag_no <= 255)))
625     {
626       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
627                                   "Tag Number: %u (Reserved tag number)",
628                                   tag_no);
629
630       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
631
632       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
633                              tag_len, "Not interpreted");
634       return (int) tag_len + 2;
635     }
636
637
638   switch (tag_no)
639     {
640
641
642     case TAG_SSID:
643       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
644                                   "Tag Number: %u (SSID parameter set)",
645                                   tag_no);
646
647       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
648
649       memset (out_buff, 0, SHORT_STR);
650
651       memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
652       out_buff[tag_len + 1] = 0;
653
654       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
655                              tag_len, out_buff);
656       break;
657
658
659
660     case TAG_SUPP_RATES:
661       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
662                                   "Tag Number: %u (Supported Rates)", tag_no);
663
664       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
665
666       memset (out_buff, 0, SHORT_STR);
667       strcpy (out_buff, "Supported rates: ");
668       n = strlen (out_buff);
669
670       for (i = 0; i < tag_len && n < SHORT_STR; i++)
671         {
672             ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
673                            (tag_data_ptr[i] & 0x7F) * 0.5,
674                            (tag_data_ptr[i] & 0x80) ? "(B)" : "");
675             if (ret == -1) {
676               /* Some versions of snprintf return -1 if they'd truncate
677                  the output. */
678               break;
679             }
680             n += ret;
681         }
682       if (n < SHORT_STR)
683         snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
684
685       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
686                              tag_len, out_buff);
687       break;
688
689
690
691     case TAG_FH_PARAMETER:
692       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
693                                   "Tag Number: %u (FH Parameter set)",
694                                   tag_no);
695
696       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
697       memset (out_buff, 0, SHORT_STR);
698
699       snprintf (out_buff, SHORT_STR,
700                 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
701                 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
702                 tag_data_ptr[3], tag_data_ptr[4]);
703
704       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
705                              tag_len, out_buff);
706       break;
707
708
709
710     case TAG_DS_PARAMETER:
711       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
712                                   "Tag Number: %u (DS Parameter set)",
713                                   tag_no);
714
715       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
716       memset (out_buff, 0, SHORT_STR);
717
718       snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
719       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
720                              tag_len, out_buff);
721       break;
722
723
724     case TAG_CF_PARAMETER:
725       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
726                                   "Tag Number: %u (CF Parameter set)",
727                                   tag_no);
728
729       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
730       memset (out_buff, 0, SHORT_STR);
731
732       snprintf (out_buff, SHORT_STR,
733                 "CFP count %u, CFP period %u, CFP max duration %u, "
734                 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
735                 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
736
737       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
738                              tag_len, out_buff);
739       break;
740
741
742     case TAG_TIM:
743       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
744                                   "Tag Number: %u ((TIM) Traffic Indication Map)",
745                                   tag_no);
746
747       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
748       memset (out_buff, 0, SHORT_STR);
749       snprintf (out_buff, SHORT_STR,
750                 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
751                 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
752                 tag_data_ptr[2]);
753       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
754                              tag_len, out_buff);
755       break;
756
757
758
759     case TAG_IBSS_PARAMETER:
760       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
761                                   "Tag Number: %u (IBSS Parameter set)",
762                                   tag_no);
763
764       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
765       memset (out_buff, 0, SHORT_STR);
766       snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
767                 pletohs (tag_data_ptr));
768
769       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
770                              tag_len, out_buff);
771       break;
772
773
774
775     case TAG_CHALLENGE_TEXT:
776       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
777                                   "Tag Number: %u (Challenge text)", tag_no);
778
779       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
780       memset (out_buff, 0, SHORT_STR);
781       snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
782       proto_tree_add_string (tree, tag_interpretation, tvb, offset, tag_len,
783                              out_buff);
784
785       break;
786
787     default:
788       return 0;
789     }
790
791   return tag_len + 2;
792 }
793
794 /* ************************************************************************* */
795 /*                     Dissect 802.11 management frame                       */
796 /* ************************************************************************* */
797 static void
798 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
799         proto_tree * tree)
800 {
801   proto_item *ti = NULL;
802   proto_tree *mgt_tree;
803   proto_tree *fixed_tree;
804   proto_tree *tagged_tree;
805   guint32 next_idx;
806   guint32 next_len;
807   int tagged_parameter_tree_len;
808
809   CHECK_DISPLAY_AS_DATA(proto_wlan_mgt, tvb, pinfo, tree);
810
811   if (tree)
812     {
813       ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, tvb_length(tvb), FALSE);
814       mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
815
816       switch (COMPOSE_FRAME_TYPE(fcf))
817         {
818
819         case MGT_ASSOC_REQ:
820           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
821           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
822           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
823
824           next_idx = 4; /* Size of fixed fields */
825           tagged_parameter_tree_len =
826               tvb_reported_length_remaining(tvb, next_idx + 4);
827           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
828                                                    tagged_parameter_tree_len);
829
830           while (tagged_parameter_tree_len > 0) {
831             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
832               break;
833             next_idx +=next_len;
834             tagged_parameter_tree_len -= next_len;
835           }
836           break;
837
838
839         case MGT_ASSOC_RESP:
840           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
841           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
842           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
843           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
844
845           next_idx = 6; /* Size of fixed fields */
846
847           tagged_parameter_tree_len =
848               tvb_reported_length_remaining(tvb, next_idx + 4);
849           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
850                                                    tagged_parameter_tree_len);
851
852           while (tagged_parameter_tree_len > 0) {
853             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
854               break;
855             next_idx +=next_len;
856             tagged_parameter_tree_len -= next_len;
857           }
858           break;
859
860
861         case MGT_REASSOC_REQ:
862           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
863           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
864           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
865           add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
866
867           next_idx = 10;        /* Size of fixed fields */
868           tagged_parameter_tree_len =
869               tvb_reported_length_remaining(tvb, next_idx + 4);
870           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
871                                                    tagged_parameter_tree_len);
872
873           while (tagged_parameter_tree_len > 0) {
874             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
875               break;
876             next_idx +=next_len;
877             tagged_parameter_tree_len -= next_len;
878           }
879           break;
880
881         case MGT_REASSOC_RESP:
882           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
883           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
884           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
885           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
886
887           next_idx = 6; /* Size of fixed fields */
888           tagged_parameter_tree_len =
889               tvb_reported_length_remaining(tvb, next_idx + 4);
890           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
891                                                    tagged_parameter_tree_len);
892
893           while (tagged_parameter_tree_len > 0) {
894             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
895               break;
896             next_idx +=next_len;
897             tagged_parameter_tree_len -= next_len;
898           }
899           break;
900
901
902         case MGT_PROBE_REQ:
903           next_idx = 0;
904           tagged_parameter_tree_len =
905               tvb_reported_length_remaining(tvb, next_idx + 4);
906           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
907                                                    tagged_parameter_tree_len);
908
909           while (tagged_parameter_tree_len > 0) {
910             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
911               break;
912             next_idx +=next_len;
913             tagged_parameter_tree_len -= next_len;
914           }
915           break;
916
917
918         case MGT_PROBE_RESP:
919           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
920           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
921           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
922           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
923
924           next_idx = 12;        /* Size of fixed fields */
925           tagged_parameter_tree_len =
926               tvb_reported_length_remaining(tvb, next_idx + 4);
927           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
928                                                    tagged_parameter_tree_len);
929
930           while (tagged_parameter_tree_len > 0) {
931             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
932               break;
933             next_idx +=next_len;
934             tagged_parameter_tree_len -= next_len;
935           }
936           break;
937
938
939         case MGT_BEACON:                /* Dissect protocol payload fields  */
940           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
941
942           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
943           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
944           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
945
946           next_idx = 12;        /* Size of fixed fields */
947           tagged_parameter_tree_len =
948               tvb_reported_length_remaining(tvb, next_idx + 4);
949           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
950                                                    tagged_parameter_tree_len);
951
952           while (tagged_parameter_tree_len > 0) {
953             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
954               break;
955             next_idx +=next_len;
956             tagged_parameter_tree_len -= next_len;
957           }
958           break;
959
960
961         case MGT_ATIM:
962           break;
963
964
965         case MGT_DISASS:
966           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
967           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
968           break;
969
970
971         case MGT_AUTHENTICATION:
972           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
973           add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
974           add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
975           add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
976
977           next_idx = 6; /* Size of fixed fields */
978
979           tagged_parameter_tree_len =
980                   tvb_reported_length_remaining(tvb, next_idx + 4);
981           if (tagged_parameter_tree_len != 0)
982             {
983               tagged_tree = get_tagged_parameter_tree (mgt_tree,
984                                                        tvb,
985                                                        next_idx,
986                                                        tagged_parameter_tree_len);
987
988               while (tagged_parameter_tree_len > 0) {
989                 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
990                   break;
991                 next_idx +=next_len;
992                 tagged_parameter_tree_len -= next_len;
993               }
994             }
995           break;
996
997
998         case MGT_DEAUTHENTICATION:
999           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1000           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1001           break;
1002         }
1003     }
1004 }
1005
1006 static void
1007 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1008 {
1009   if (check_col(pinfo->fd, COL_RES_DL_SRC))
1010     col_add_fstr(pinfo->fd, COL_RES_DL_SRC, "%s (%s)",
1011                     get_ether_name(addr), type);
1012   if (check_col(pinfo->fd, COL_UNRES_DL_SRC))
1013     col_add_fstr(pinfo->fd, COL_UNRES_DL_SRC, "%s (%s)",
1014                      ether_to_str(addr), type);
1015 }
1016
1017 static void
1018 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1019 {
1020   if (check_col(pinfo->fd, COL_RES_DL_DST))
1021     col_add_fstr(pinfo->fd, COL_RES_DL_DST, "%s (%s)",
1022                      get_ether_name(addr), type);
1023   if (check_col(pinfo->fd, COL_UNRES_DL_DST))
1024     col_add_fstr(pinfo->fd, COL_UNRES_DL_DST, "%s (%s)",
1025                      ether_to_str(addr), type);
1026 }
1027
1028 /* ************************************************************************* */
1029 /*                          Dissect 802.11 frame                             */
1030 /* ************************************************************************* */
1031 static void
1032 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1033 {
1034   guint16 fcf, flags, frame_type_subtype;
1035   const guint8 *src = NULL, *dst = NULL;
1036   proto_item *ti = NULL;
1037   proto_item *flag_item;
1038   proto_item *fc_item;
1039   proto_tree *hdr_tree = NULL;
1040   proto_tree *flag_tree;
1041   proto_tree *fc_tree;
1042   guint16 hdr_len;
1043   tvbuff_t *next_tvb;
1044   guint32 addr_type;
1045   volatile gboolean is_802_2;
1046
1047   if (check_col (pinfo->fd, COL_PROTOCOL))
1048     col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
1049   if (check_col (pinfo->fd, COL_INFO))
1050     col_clear (pinfo->fd, COL_INFO);
1051
1052   fcf = tvb_get_letohs (tvb, 0);
1053   hdr_len = find_header_length (fcf);
1054   frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1055
1056   COL_SHOW_INFO_CONST (pinfo->fd,
1057       val_to_str(frame_type_subtype, frame_type_subtype_vals,
1058           "Unrecognized (Reserved frame)"));
1059
1060   /* Add the FC to the current tree */
1061   if (tree)
1062     {
1063       ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1064                                            "IEEE 802.11");
1065       hdr_tree = proto_item_add_subtree (ti, ett_80211);
1066
1067       proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1068                            tvb, 0, 1,
1069                            frame_type_subtype);
1070
1071       fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
1072                                             fcf,
1073                                             "Frame Control: 0x%04X",
1074                                             fcf);
1075
1076       fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1077
1078
1079       proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
1080                            COOK_PROT_VERSION (fcf));
1081
1082       proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
1083                            COOK_FRAME_TYPE (fcf));
1084
1085       proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1086                            tvb, 0, 1,
1087                            COOK_FRAME_SUBTYPE (fcf));
1088
1089       flags = COOK_FLAGS (fcf);
1090
1091       flag_item =
1092         proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
1093                                     flags, "Flags: 0x%X", flags);
1094
1095       flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1096
1097       proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
1098                            COOK_DS_STATUS (flags));
1099
1100       proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1101                               flags);
1102
1103       proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1104
1105       proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1106
1107       proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1108                               flags);
1109
1110       proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1111
1112       proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1113
1114       if (frame_type_subtype == CTRL_PS_POLL) 
1115         proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1116                             COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1117      
1118       else
1119           proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1120                                tvb_get_letohs (tvb, 2));
1121     }
1122
1123   /*
1124    * Decode the part of the frame header that isn't the same for all
1125    * frame types.
1126    */
1127   switch (frame_type_subtype)
1128     {
1129
1130     case MGT_ASSOC_REQ:
1131     case MGT_ASSOC_RESP:
1132     case MGT_REASSOC_REQ:
1133     case MGT_REASSOC_RESP:
1134     case MGT_PROBE_REQ:
1135     case MGT_PROBE_RESP:
1136     case MGT_BEACON:
1137     case MGT_ATIM:
1138     case MGT_DISASS:
1139     case MGT_AUTHENTICATION:
1140     case MGT_DEAUTHENTICATION:
1141       /*
1142        * All management frame types have the same header.
1143        */
1144       src = tvb_get_ptr (tvb, 10, 6);
1145       dst = tvb_get_ptr (tvb, 4, 6);
1146
1147       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1148       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1149       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1150       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1151
1152       if (tree)
1153         {
1154           proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1155
1156           proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1157
1158           /* add items for wlan.addr filter */
1159           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1160           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1161
1162           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1163                                 tvb_get_ptr (tvb, 16, 6));
1164
1165           proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1166                                COOK_FRAGMENT_NUMBER (tvb_get_letohs
1167                                                      (tvb, 22)));
1168
1169           proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1170                                COOK_SEQUENCE_NUMBER (tvb_get_letohs
1171                                                      (tvb, 22)));
1172         }
1173       break;
1174
1175
1176     case CTRL_PS_POLL:
1177       src = tvb_get_ptr (tvb, 10, 6);
1178       dst = tvb_get_ptr (tvb, 4, 6);
1179
1180       set_src_addr_cols(pinfo, src, "BSSID");
1181       set_dst_addr_cols(pinfo, dst, "BSSID");
1182
1183       if (tree)
1184         {
1185           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1186
1187           proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1188         }
1189       break;
1190
1191
1192     case CTRL_RTS:
1193       src = tvb_get_ptr (tvb, 10, 6);
1194       dst = tvb_get_ptr (tvb, 4, 6);
1195
1196       set_src_addr_cols(pinfo, src, "TA");
1197       set_dst_addr_cols(pinfo, dst, "RA");
1198
1199       if (tree)
1200         {
1201           proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1202
1203           proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1204         }
1205       break;
1206
1207
1208     case CTRL_CTS:
1209       dst = tvb_get_ptr (tvb, 4, 6);
1210
1211       set_dst_addr_cols(pinfo, dst, "RA");
1212
1213       if (tree)
1214           proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1215       break;
1216
1217
1218     case CTRL_ACKNOWLEDGEMENT:
1219       dst = tvb_get_ptr (tvb, 4, 6);
1220
1221       set_dst_addr_cols(pinfo, dst, "RA");
1222
1223       if (tree)
1224         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1225       break;
1226
1227
1228     case CTRL_CFP_END:
1229       src = tvb_get_ptr (tvb, 10, 6);
1230       dst = tvb_get_ptr (tvb, 4, 6);
1231
1232       set_src_addr_cols(pinfo, src, "BSSID");
1233       set_dst_addr_cols(pinfo, dst, "RA");
1234
1235       if (tree)
1236         {
1237           proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1238           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1239         }
1240       break;
1241
1242
1243     case CTRL_CFP_ENDACK:
1244       src = tvb_get_ptr (tvb, 10, 6);
1245       dst = tvb_get_ptr (tvb, 4, 6);
1246
1247       set_src_addr_cols(pinfo, src, "BSSID");
1248       set_dst_addr_cols(pinfo, dst, "RA");
1249
1250       if (tree)
1251         {
1252           proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1253
1254           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1255         }
1256       break;
1257
1258
1259     case DATA:
1260     case DATA_CF_ACK:
1261     case DATA_CF_POLL:
1262     case DATA_CF_ACK_POLL:
1263       addr_type = COOK_ADDR_SELECTOR (fcf);
1264
1265       /* In order to show src/dst address we must always do the following */
1266       switch (addr_type)
1267         {
1268
1269         case DATA_ADDR_T1:
1270           src = tvb_get_ptr (tvb, 10, 6);
1271           dst = tvb_get_ptr (tvb, 4, 6);
1272           break;
1273
1274
1275         case DATA_ADDR_T2:
1276           src = tvb_get_ptr (tvb, 16, 6);
1277           dst = tvb_get_ptr (tvb, 4, 6);
1278           break;
1279
1280
1281         case DATA_ADDR_T3:
1282           src = tvb_get_ptr (tvb, 10, 6);
1283           dst = tvb_get_ptr (tvb, 16, 6);
1284           break;
1285
1286
1287         case DATA_ADDR_T4:
1288           src = tvb_get_ptr (tvb, 24, 6);
1289           dst = tvb_get_ptr (tvb, 16, 6);
1290           break;
1291         }
1292
1293       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1294       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1295       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1296       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1297
1298       /* Now if we have a tree we start adding stuff */
1299       if (tree)
1300         {
1301
1302
1303           switch (addr_type)
1304             {
1305
1306             case DATA_ADDR_T1:
1307               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1308               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1309               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1310                                     tvb_get_ptr (tvb, 16, 6));
1311               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1312                                    COOK_FRAGMENT_NUMBER (tvb_get_letohs
1313                                                          (tvb, 22)));
1314               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1315                                    COOK_SEQUENCE_NUMBER (tvb_get_letohs
1316                                                          (tvb, 22)));
1317
1318               /* add items for wlan.addr filter */
1319               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1320               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1321               break;
1322               
1323               
1324             case DATA_ADDR_T2:
1325               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1326               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1327                                     tvb_get_ptr (tvb, 10, 6));
1328               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1329               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1330                                    COOK_FRAGMENT_NUMBER (tvb_get_letohs
1331                                                          (tvb, 22)));
1332               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1333                                    COOK_SEQUENCE_NUMBER (tvb_get_letohs
1334                                                          (tvb, 22)));
1335
1336               /* add items for wlan.addr filter */
1337               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1338               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1339               break;
1340    
1341
1342             case DATA_ADDR_T3:
1343               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1344                                     tvb_get_ptr (tvb, 4, 6));
1345               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1346               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1347
1348               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1349                                    COOK_FRAGMENT_NUMBER (tvb_get_letohs
1350                                                          (tvb, 22)));
1351               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1352                                    COOK_SEQUENCE_NUMBER (tvb_get_letohs
1353                                                          (tvb, 22)));
1354
1355               /* add items for wlan.addr filter */
1356               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1357               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1358               break;
1359               
1360
1361             case DATA_ADDR_T4:
1362               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1363                                     tvb_get_ptr (tvb, 4, 6));
1364               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1365                                     tvb_get_ptr (tvb, 10, 6));
1366               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1367               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1368                                    COOK_FRAGMENT_NUMBER (tvb_get_letohs
1369                                                          (tvb, 22)));
1370               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1371                                    COOK_SEQUENCE_NUMBER (tvb_get_letohs
1372                                                          (tvb, 22)));
1373               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1374
1375               /* add items for wlan.addr filter */
1376               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1377               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1378               break;
1379             }
1380
1381         }
1382       break;
1383     }
1384
1385   /*
1386    * Only management and data frames have a body, so we don't have
1387    * anything more to do for other types of frames.
1388    */
1389   switch (COOK_FRAME_TYPE (fcf))
1390     {
1391
1392     case MGT_FRAME:
1393     case DATA_FRAME:
1394       break;
1395
1396     default:
1397       return;
1398     }
1399
1400   /*
1401    * For WEP-encrypted frames, dissect the WEP parameters and
1402    * display the payload as data.
1403    *
1404    * XXX - allow the key to be specified, and, if it is, decrypt
1405    * the payload and dissect it?
1406    */
1407   if (IS_WEP(COOK_FLAGS(fcf)))
1408     {
1409       int pkt_len = tvb_reported_length (tvb);
1410       int cap_len = tvb_length (tvb);
1411
1412       if (tree)
1413         {
1414           get_wep_parameter_tree (tree, tvb, hdr_len, pkt_len);
1415           pkt_len -= hdr_len + 4;
1416           cap_len -= hdr_len + 4;
1417
1418           /*
1419            * OK, pkt_len and cap_len have had the length of the 802.11
1420            * header and WEP parameters subtracted.
1421            *
1422            * If there's anything left:
1423            *
1424            *    if cap_len is greater than or equal to pkt_len (i.e., we
1425            *    captured the entire packet), subtract the length of the
1426            *    WEP CRC from cap_len;
1427            *
1428            *    if cap_len is from 1 to 3 bytes less than pkt_len (i.e.,
1429            *    we captured some but not all of the WEP CRC), subtract
1430            *    the length of the part of the WEP CRC we captured from
1431            *    crc_len;
1432            *
1433            *    otherwise, (i.e., we captured none of the WEP CRC),
1434            *    leave cap_len alone;
1435            *
1436            * and subtract the length of the WEP CRC from pkt_len.
1437            */
1438           if (cap_len >= pkt_len)
1439             cap_len -= 4;
1440           else if ((pkt_len - cap_len) >= 1 && (pkt_len - cap_len) <= 3)
1441             cap_len -= 4 - (pkt_len - cap_len);
1442           pkt_len -= 4;
1443           if (cap_len > 0 && pkt_len > 0)
1444             dissect_data (tvb, hdr_len + 4, pinfo, tree);
1445         }
1446         return;
1447     }
1448
1449   /*
1450    * Now dissect the body of a non-WEP-encrypted frame.
1451    */
1452   next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1453   switch (COOK_FRAME_TYPE (fcf))
1454     {
1455
1456     case MGT_FRAME:
1457       dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1458       break;
1459
1460
1461     case DATA_FRAME:
1462       /* I guess some bridges take Netware Ethernet_802_3 frames,
1463          which are 802.3 frames (with a length field rather than
1464          a type field, but with no 802.2 header in the payload),
1465          and just stick the payload into an 802.11 frame.  I've seen
1466          captures that show frames of that sort.
1467
1468          This means we have to do the same check for Netware 802.3 -
1469          or, if you will, "Netware 802.11" - that we do in the
1470          Ethernet dissector, i.e. checking for 0xffff as the first
1471          four bytes of the payload and, if we find it, treating it
1472          as an IPX frame. */
1473       is_802_2 = TRUE;
1474       TRY {
1475         if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1476           is_802_2 = FALSE;
1477       }
1478       CATCH2(BoundsError, ReportedBoundsError) {
1479             ; /* do nothing */
1480
1481       }
1482       ENDTRY;
1483
1484       if (is_802_2)
1485         call_dissector(llc_handle, next_tvb, pinfo, tree);
1486       else
1487         call_dissector(ipx_handle, next_tvb, pinfo, tree);
1488       break;
1489     }
1490 }
1491
1492 void
1493 proto_register_wlan (void)
1494 {
1495   static const value_string frame_type[] = {
1496     {MGT_FRAME,     "Management frame"},
1497     {CONTROL_FRAME, "Control frame"},
1498     {DATA_FRAME,    "Data frame"},
1499     {0,             NULL}
1500   };
1501
1502   static const value_string tofrom_ds[] = {
1503     {0,                       "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
1504     {FLAG_TO_DS,              "Frame is entering DS (To DS: 1  From DS: 0)"},
1505     {FLAG_FROM_DS,            "Frame is exiting DS (To DS: 0  From DS: 1)"},
1506     {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1  From DS: 1)"},
1507     {0, NULL}
1508   };
1509
1510   static const true_false_string tods_flag = {
1511     "TO DS: Should be false",
1512     "Not used"
1513   };
1514
1515   static const true_false_string fromds_flag = {
1516     "FROM DS: Should be false",
1517     "Not used"
1518   };
1519
1520   static const true_false_string more_frags = {
1521     "MSDU/MMPDU is fragmented",
1522     "No fragments"
1523   };
1524
1525   static const true_false_string retry_flags = {
1526     "Frame is being retransmitted",
1527     "Frame is not being retransmitted"
1528   };
1529
1530   static const true_false_string pm_flags = {
1531     "STA will go to sleep",
1532     "STA will stay up"
1533   };
1534
1535   static const true_false_string md_flags = {
1536     "Data is buffered for STA at AP",
1537     "No data buffered"
1538   };
1539
1540   static const true_false_string wep_flags = {
1541     "WEP is enabled",
1542     "WEP is disabled"
1543   };
1544
1545   static const true_false_string order_flags = {
1546     "Strictly ordered",
1547     "Not strictly ordered"
1548   };
1549
1550   static const true_false_string cf_ess_flags = {
1551     "Transmitter is an AP",
1552     "Transmitter is a STA"
1553   };
1554
1555
1556   static const true_false_string cf_privacy_flags = {
1557     "AP/STA can support WEP",
1558     "AP/STA cannot support WEP"
1559   };
1560
1561   static const true_false_string cf_preamble_flags = {
1562     "Short preamble allowed",
1563     "Short preamble not allowed"
1564   };
1565
1566   static const true_false_string cf_pbcc_flags = {
1567     "PBCC modulation allowed",
1568     "PBCC modulation not allowed"
1569   };
1570
1571   static const true_false_string cf_agility_flags = {
1572     "Channel agility in use",
1573     "Channel agility not in use"
1574   };
1575
1576
1577   static const true_false_string cf_ibss_flags = {
1578     "Transmitter belongs to an IBSS",
1579     "Transmitter belongs to a BSS"
1580   };
1581
1582   static const value_string sta_cf_pollable[] = {
1583     {0x00, "Station is not CF-Pollable"},
1584     {0x02, "Station is CF-Pollable, "
1585      "not requesting to be placed on the  CF-polling list"},
1586     {0x01, "Station is CF-Pollable, "
1587      "requesting to be placed on the CF-polling list"},
1588     {0x03, "Station is CF-Pollable, requesting never to be polled"},
1589     {0, NULL}
1590   };
1591
1592   static const value_string ap_cf_pollable[] = {
1593     {0x00, "No point coordinator at AP"},
1594     {0x02, "Point coordinator at AP for delivery only (no polling)"},
1595     {0x01, "Point coordinator at AP for delivery and polling"},
1596     {0x03, "Reserved"},
1597     {0, NULL}
1598   };
1599
1600
1601   static const value_string auth_alg[] = {
1602     {0x00, "Open System"},
1603     {0x01, "Shared key"},
1604     {0, NULL}
1605   };
1606
1607   static const value_string reason_codes[] = {
1608     {0x00, "Reserved"},
1609     {0x01, "Unspecified reason"},
1610     {0x02, "Previous authentication no longer valid"},
1611     {0x03, "Deauthenticated because sending STA is leaving (has left) "
1612      "IBSS or ESS"},
1613     {0x04, "Disassociated due to inactivity"},
1614     {0x05, "Disassociated because AP is unable to handle all currently "
1615      "associated stations"},
1616     {0x06, "Class 2 frame received from nonauthenticated station"},
1617     {0x07, "Class 3 frame received from nonassociated station"},
1618     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1619     {0x09, "Station requesting (re)association is not authenticated with "
1620      "responding station"},
1621     {0x00, NULL}
1622   };
1623
1624
1625   static const value_string status_codes[] = {
1626     {0x00, "Successful"},
1627     {0x01, "Unspecified failure"},
1628     {0x0A, "Cannot support all requested capabilities in the "
1629      "Capability information field"},
1630     {0x0B, "Reassociation denied due to inability to confirm that "
1631      "association exists"},
1632     {0x0C, "Association denied due to reason outside the scope of this "
1633      "standard"},
1634
1635     {0x0D, "Responding station does not support the specified authentication "
1636      "algorithm"},
1637     {0x0E, "Received an Authentication frame with authentication sequence "
1638      "transaction sequence number out of expected sequence"},
1639     {0x0F, "Authentication rejected because of challenge failure"},
1640     {0x10, "Authentication rejected due to timeout waiting for next "
1641      "frame in sequence"},
1642     {0x11, "Association denied because AP is unable to handle additional "
1643      "associated stations"},
1644     {0x12, "Association denied due to requesting station not supporting all "
1645      "of the datarates in the BSSBasicServiceSet Parameter"},
1646     {0x00, NULL}
1647   };
1648
1649   static hf_register_info hf[] = {
1650     {&hf_fc_field,
1651      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
1652       "MAC Frame control", HFILL }},
1653
1654     {&hf_fc_proto_version,
1655      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
1656       "MAC Protocol version", HFILL }}, /* 0 */
1657
1658     {&hf_fc_frame_type,
1659      {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
1660       "Frame type", HFILL }},
1661
1662     {&hf_fc_frame_subtype,
1663      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
1664       "Frame subtype", HFILL }},        /* 2 */
1665
1666     {&hf_fc_frame_type_subtype,
1667      {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
1668       "Type and subtype combined", HFILL }},
1669
1670     {&hf_fc_flags,
1671      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
1672       "Protocol flags", HFILL }},
1673
1674     {&hf_fc_data_ds,
1675      {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
1676       "Data-frame DS-traversal status", HFILL }},       /* 3 */
1677
1678     {&hf_fc_to_ds,
1679      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
1680       "To DS flag", HFILL }},           /* 4 */
1681
1682     {&hf_fc_from_ds,
1683      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
1684       "From DS flag", HFILL }},         /* 5 */
1685
1686     {&hf_fc_more_frag,
1687      {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
1688       "More Fragments flag", HFILL }},  /* 6 */
1689
1690     {&hf_fc_retry,
1691      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
1692       "Retransmission flag", HFILL }},
1693
1694     {&hf_fc_pwr_mgt,
1695      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
1696       "Power management status", HFILL }},
1697
1698     {&hf_fc_more_data,
1699      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
1700       "More data flag", HFILL }},
1701
1702     {&hf_fc_wep,
1703      {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
1704       "WEP flag", HFILL }},
1705
1706     {&hf_fc_order,
1707      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
1708       "Strictly ordered flag", HFILL }},
1709
1710     {&hf_assoc_id,
1711      {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
1712       "Association-ID field", HFILL }},
1713
1714     {&hf_did_duration,
1715      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
1716       "Duration field", HFILL }},
1717
1718     {&hf_addr_da,
1719      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
1720       "Destination Hardware Address", HFILL }},
1721
1722     {&hf_addr_sa,
1723      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
1724       "Source Hardware Address", HFILL }},
1725
1726     { &hf_addr,
1727       {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
1728        "Source or Destination Hardware Address", HFILL }},
1729
1730     {&hf_addr_ra,
1731      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
1732       "Receiving Station Hardware Address", HFILL }},
1733
1734     {&hf_addr_ta,
1735      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
1736       "Transmitting Station Hardware Address", HFILL }},
1737
1738     {&hf_addr_bssid,
1739      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
1740       "Basic Service Set ID", HFILL }},
1741
1742     {&hf_frag_number,
1743      {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
1744       "Fragment number", HFILL }},
1745
1746     {&hf_seq_number,
1747      {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
1748       "Sequence number", HFILL }},
1749
1750     {&hf_fcs,
1751      {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
1752       NULL, 0, "", HFILL }},
1753
1754     {&hf_wep_iv,
1755      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
1756       "Initialization Vector", HFILL }},
1757
1758     {&hf_wep_key,
1759      {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
1760       "Key", HFILL }},
1761
1762     {&hf_wep_crc,
1763      {"WEP CRC (not verified)", "wlan.wep.crc", FT_UINT32, BASE_HEX, NULL, 0,
1764       "WEP CRC", HFILL }},
1765   };
1766
1767   static hf_register_info ff[] = {
1768     {&ff_timestamp,
1769      {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
1770       NULL, 0, "", HFILL }},
1771
1772     {&ff_auth_alg,
1773      {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
1774       FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
1775
1776     {&ff_beacon_interval,
1777      {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
1778       "", HFILL }},
1779
1780     {&hf_fixed_parameters,
1781      {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
1782       "", HFILL }},
1783
1784     {&hf_tagged_parameters,
1785      {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
1786       "", HFILL }},
1787
1788     {&ff_capture,
1789      {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
1790       "Capability information", HFILL }},
1791
1792     {&ff_cf_sta_poll,
1793      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
1794       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
1795       "CF-Poll capabilities for a STA", HFILL }},
1796
1797     {&ff_cf_ap_poll,
1798      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
1799       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
1800       "CF-Poll capabilities for an AP", HFILL }},
1801
1802     {&ff_cf_ess,
1803      {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
1804       FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
1805
1806
1807     {&ff_cf_ibss,
1808      {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
1809       FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
1810
1811     {&ff_cf_privacy,
1812      {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
1813       FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
1814
1815     {&ff_cf_preamble,
1816      {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
1817       FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
1818
1819     {&ff_cf_pbcc,
1820      {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
1821       FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
1822
1823     {&ff_cf_agility,
1824      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
1825       FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
1826
1827     {&ff_auth_seq,
1828      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
1829       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
1830
1831     {&ff_assoc_id,
1832      {"Association ID", "wlan_mgt.fixed.aid",
1833       FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
1834
1835     {&ff_listen_ival,
1836      {"Listen Interval", "wlan_mgt.fixed.listen_ival",
1837       FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
1838
1839     {&ff_current_ap,
1840      {"Current AP", "wlan_mgt.fixed.current_ap",
1841       FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
1842
1843     {&ff_reason,
1844      {"Reason code", "wlan_mgt.fixed.reason_code",
1845       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
1846       "Reason for unsolicited notification", HFILL }},
1847
1848     {&ff_status_code,
1849      {"Status code", "wlan_mgt.fixed.status_code",
1850       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
1851       "Status of requested event", HFILL }},
1852
1853     {&tag_number,
1854      {"Tag", "wlan_mgt.tag.number",
1855       FT_UINT16, BASE_DEC, NULL, 0,
1856       "Element ID", HFILL }},
1857
1858     {&tag_length,
1859      {"Tag length", "wlan_mgt.tag.length",
1860       FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
1861
1862     {&tag_interpretation,
1863      {"Tag interpretation", "wlan_mgt.tag.interpretation",
1864       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
1865
1866   };
1867
1868   static gint *tree_array[] = {
1869     &ett_80211,
1870     &ett_fc_tree,
1871     &ett_proto_flags,
1872     &ett_80211_mgt,
1873     &ett_fixed_parameters,
1874     &ett_tagged_parameters,
1875     &ett_wep_parameters,
1876     &ett_cap_tree,
1877   };
1878
1879   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
1880                                         "IEEE 802.11", "wlan");
1881   proto_register_field_array (proto_wlan, hf, array_length (hf));
1882   proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
1883                                         "802.11 MGT", "wlan_mgt");
1884   proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
1885   proto_register_subtree_array (tree_array, array_length (tree_array));
1886 }
1887
1888 void
1889 proto_reg_handoff_wlan(void)
1890 {
1891   /*
1892    * Get handles for the LLC and IPX dissectors.
1893    */
1894   llc_handle = find_dissector("llc");
1895   ipx_handle = find_dissector("ipx");
1896
1897   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,
1898                 proto_wlan);
1899 }