The data in a tagged field can be up to 255 bytes (the length is an
[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.39 2001/09/25 00:34:24 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;
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; i++)
671         {
672             n += 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         }
676       snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
677
678       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
679                              tag_len, out_buff);
680       break;
681
682
683
684     case TAG_FH_PARAMETER:
685       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
686                                   "Tag Number: %u (FH Parameter set)",
687                                   tag_no);
688
689       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
690       memset (out_buff, 0, SHORT_STR);
691
692       snprintf (out_buff, SHORT_STR,
693                 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
694                 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
695                 tag_data_ptr[3], tag_data_ptr[4]);
696
697       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
698                              tag_len, out_buff);
699       break;
700
701
702
703     case TAG_DS_PARAMETER:
704       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
705                                   "Tag Number: %u (DS Parameter set)",
706                                   tag_no);
707
708       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
709       memset (out_buff, 0, SHORT_STR);
710
711       snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
712       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
713                              tag_len, out_buff);
714       break;
715
716
717     case TAG_CF_PARAMETER:
718       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
719                                   "Tag Number: %u (CF Parameter set)",
720                                   tag_no);
721
722       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
723       memset (out_buff, 0, SHORT_STR);
724
725       snprintf (out_buff, SHORT_STR,
726                 "CFP count %u, CFP period %u, CFP max duration %u, "
727                 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
728                 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
729
730       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
731                              tag_len, out_buff);
732       break;
733
734
735     case TAG_TIM:
736       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
737                                   "Tag Number: %u ((TIM) Traffic Indication Map)",
738                                   tag_no);
739
740       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
741       memset (out_buff, 0, SHORT_STR);
742       snprintf (out_buff, SHORT_STR,
743                 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
744                 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
745                 tag_data_ptr[2]);
746       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
747                              tag_len, out_buff);
748       break;
749
750
751
752     case TAG_IBSS_PARAMETER:
753       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
754                                   "Tag Number: %u (IBSS Parameter set)",
755                                   tag_no);
756
757       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
758       memset (out_buff, 0, SHORT_STR);
759       snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
760                 pletohs (tag_data_ptr));
761
762       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
763                              tag_len, out_buff);
764       break;
765
766
767
768     case TAG_CHALLENGE_TEXT:
769       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
770                                   "Tag Number: %u (Challenge text)", tag_no);
771
772       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
773       memset (out_buff, 0, SHORT_STR);
774       snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
775       proto_tree_add_string (tree, tag_interpretation, tvb, offset, tag_len,
776                              out_buff);
777
778       break;
779
780     default:
781       return 0;
782     }
783
784   return tag_len + 2;
785 }
786
787 /* ************************************************************************* */
788 /*                     Dissect 802.11 management frame                       */
789 /* ************************************************************************* */
790 static void
791 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
792         proto_tree * tree)
793 {
794   proto_item *ti = NULL;
795   proto_tree *mgt_tree;
796   proto_tree *fixed_tree;
797   proto_tree *tagged_tree;
798   guint32 next_idx;
799   guint32 next_len;
800   int tagged_parameter_tree_len;
801
802   CHECK_DISPLAY_AS_DATA(proto_wlan_mgt, tvb, pinfo, tree);
803
804   if (tree)
805     {
806       ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, tvb_length(tvb), FALSE);
807       mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
808
809       switch (COMPOSE_FRAME_TYPE(fcf))
810         {
811
812         case MGT_ASSOC_REQ:
813           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
814           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
815           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
816
817           next_idx = 4; /* Size of fixed fields */
818           tagged_parameter_tree_len =
819               tvb_reported_length_remaining(tvb, next_idx + 4);
820           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
821                                                    tagged_parameter_tree_len);
822
823           while (tagged_parameter_tree_len > 0) {
824             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
825               break;
826             next_idx +=next_len;
827             tagged_parameter_tree_len -= next_len;
828           }
829           break;
830
831
832         case MGT_ASSOC_RESP:
833           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
834           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
835           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
836           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
837
838           next_idx = 6; /* Size of fixed fields */
839
840           tagged_parameter_tree_len =
841               tvb_reported_length_remaining(tvb, next_idx + 4);
842           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
843                                                    tagged_parameter_tree_len);
844
845           while (tagged_parameter_tree_len > 0) {
846             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
847               break;
848             next_idx +=next_len;
849             tagged_parameter_tree_len -= next_len;
850           }
851           break;
852
853
854         case MGT_REASSOC_REQ:
855           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
856           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
857           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
858           add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
859
860           next_idx = 10;        /* Size of fixed fields */
861           tagged_parameter_tree_len =
862               tvb_reported_length_remaining(tvb, next_idx + 4);
863           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
864                                                    tagged_parameter_tree_len);
865
866           while (tagged_parameter_tree_len > 0) {
867             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
868               break;
869             next_idx +=next_len;
870             tagged_parameter_tree_len -= next_len;
871           }
872           break;
873
874         case MGT_REASSOC_RESP:
875           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
876           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
877           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
878           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
879
880           next_idx = 6; /* Size of fixed fields */
881           tagged_parameter_tree_len =
882               tvb_reported_length_remaining(tvb, next_idx + 4);
883           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
884                                                    tagged_parameter_tree_len);
885
886           while (tagged_parameter_tree_len > 0) {
887             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
888               break;
889             next_idx +=next_len;
890             tagged_parameter_tree_len -= next_len;
891           }
892           break;
893
894
895         case MGT_PROBE_REQ:
896           next_idx = 0;
897           tagged_parameter_tree_len =
898               tvb_reported_length_remaining(tvb, next_idx + 4);
899           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
900                                                    tagged_parameter_tree_len);
901
902           while (tagged_parameter_tree_len > 0) {
903             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
904               break;
905             next_idx +=next_len;
906             tagged_parameter_tree_len -= next_len;
907           }
908           break;
909
910
911         case MGT_PROBE_RESP:
912           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
913           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
914           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
915           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
916
917           next_idx = 12;        /* Size of fixed fields */
918           tagged_parameter_tree_len =
919               tvb_reported_length_remaining(tvb, next_idx + 4);
920           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
921                                                    tagged_parameter_tree_len);
922
923           while (tagged_parameter_tree_len > 0) {
924             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
925               break;
926             next_idx +=next_len;
927             tagged_parameter_tree_len -= next_len;
928           }
929           break;
930
931
932         case MGT_BEACON:                /* Dissect protocol payload fields  */
933           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
934
935           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
936           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
937           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
938
939           next_idx = 12;        /* Size of fixed fields */
940           tagged_parameter_tree_len =
941               tvb_reported_length_remaining(tvb, next_idx + 4);
942           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
943                                                    tagged_parameter_tree_len);
944
945           while (tagged_parameter_tree_len > 0) {
946             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
947               break;
948             next_idx +=next_len;
949             tagged_parameter_tree_len -= next_len;
950           }
951           break;
952
953
954         case MGT_ATIM:
955           break;
956
957
958         case MGT_DISASS:
959           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
960           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
961           break;
962
963
964         case MGT_AUTHENTICATION:
965           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
966           add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
967           add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
968           add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
969
970           next_idx = 6; /* Size of fixed fields */
971
972           tagged_parameter_tree_len =
973                   tvb_reported_length_remaining(tvb, next_idx + 4);
974           if (tagged_parameter_tree_len != 0)
975             {
976               tagged_tree = get_tagged_parameter_tree (mgt_tree,
977                                                        tvb,
978                                                        next_idx,
979                                                        tagged_parameter_tree_len);
980
981               while (tagged_parameter_tree_len > 0) {
982                 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
983                   break;
984                 next_idx +=next_len;
985                 tagged_parameter_tree_len -= next_len;
986               }
987             }
988           break;
989
990
991         case MGT_DEAUTHENTICATION:
992           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
993           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
994           break;
995         }
996     }
997 }
998
999 static void
1000 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1001 {
1002   if (check_col(pinfo->fd, COL_RES_DL_SRC))
1003     col_add_fstr(pinfo->fd, COL_RES_DL_SRC, "%s (%s)",
1004                     get_ether_name(addr), type);
1005   if (check_col(pinfo->fd, COL_UNRES_DL_SRC))
1006     col_add_fstr(pinfo->fd, COL_UNRES_DL_SRC, "%s (%s)",
1007                      ether_to_str(addr), type);
1008 }
1009
1010 static void
1011 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1012 {
1013   if (check_col(pinfo->fd, COL_RES_DL_DST))
1014     col_add_fstr(pinfo->fd, COL_RES_DL_DST, "%s (%s)",
1015                      get_ether_name(addr), type);
1016   if (check_col(pinfo->fd, COL_UNRES_DL_DST))
1017     col_add_fstr(pinfo->fd, COL_UNRES_DL_DST, "%s (%s)",
1018                      ether_to_str(addr), type);
1019 }
1020
1021 /* ************************************************************************* */
1022 /*                          Dissect 802.11 frame                             */
1023 /* ************************************************************************* */
1024 static void
1025 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1026 {
1027   guint16 fcf, flags, frame_type_subtype;
1028   const guint8 *src = NULL, *dst = NULL;
1029   proto_item *ti = NULL;
1030   proto_item *flag_item;
1031   proto_item *fc_item;
1032   proto_tree *hdr_tree = NULL;
1033   proto_tree *flag_tree;
1034   proto_tree *fc_tree;
1035   guint16 hdr_len;
1036   tvbuff_t *next_tvb;
1037   guint32 addr_type;
1038   volatile gboolean is_802_2;
1039
1040   if (check_col (pinfo->fd, COL_PROTOCOL))
1041     col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
1042   if (check_col (pinfo->fd, COL_INFO))
1043     col_clear (pinfo->fd, COL_INFO);
1044
1045   fcf = tvb_get_letohs (tvb, 0);
1046   hdr_len = find_header_length (fcf);
1047   frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1048
1049   COL_SHOW_INFO_CONST (pinfo->fd,
1050       val_to_str(frame_type_subtype, frame_type_subtype_vals,
1051           "Unrecognized (Reserved frame)"));
1052
1053   /* Add the FC to the current tree */
1054   if (tree)
1055     {
1056       ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1057                                            "IEEE 802.11");
1058       hdr_tree = proto_item_add_subtree (ti, ett_80211);
1059
1060       proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1061                            tvb, 0, 1,
1062                            frame_type_subtype);
1063
1064       fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
1065                                             fcf,
1066                                             "Frame Control: 0x%04X",
1067                                             fcf);
1068
1069       fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1070
1071
1072       proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
1073                            COOK_PROT_VERSION (fcf));
1074
1075       proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
1076                            COOK_FRAME_TYPE (fcf));
1077
1078       proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1079                            tvb, 0, 1,
1080                            COOK_FRAME_SUBTYPE (fcf));
1081
1082       flags = COOK_FLAGS (fcf);
1083
1084       flag_item =
1085         proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
1086                                     flags, "Flags: 0x%X", flags);
1087
1088       flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1089
1090       proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
1091                            COOK_DS_STATUS (flags));
1092
1093       proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1094                               flags);
1095
1096       proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1097
1098       proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1099
1100       proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1101                               flags);
1102
1103       proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1104
1105       proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1106
1107       if (frame_type_subtype == CTRL_PS_POLL) 
1108         proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1109                             COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1110      
1111       else
1112           proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1113                                tvb_get_letohs (tvb, 2));
1114     }
1115
1116   /*
1117    * Decode the part of the frame header that isn't the same for all
1118    * frame types.
1119    */
1120   switch (frame_type_subtype)
1121     {
1122
1123     case MGT_ASSOC_REQ:
1124     case MGT_ASSOC_RESP:
1125     case MGT_REASSOC_REQ:
1126     case MGT_REASSOC_RESP:
1127     case MGT_PROBE_REQ:
1128     case MGT_PROBE_RESP:
1129     case MGT_BEACON:
1130     case MGT_ATIM:
1131     case MGT_DISASS:
1132     case MGT_AUTHENTICATION:
1133     case MGT_DEAUTHENTICATION:
1134       /*
1135        * All management frame types have the same header.
1136        */
1137       src = tvb_get_ptr (tvb, 10, 6);
1138       dst = tvb_get_ptr (tvb, 4, 6);
1139
1140       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1141       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1142       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1143       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1144
1145       if (tree)
1146         {
1147           proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1148
1149           proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1150
1151           /* add items for wlan.addr filter */
1152           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1153           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1154
1155           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1156                                 tvb_get_ptr (tvb, 16, 6));
1157
1158           proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1159                                COOK_FRAGMENT_NUMBER (tvb_get_letohs
1160                                                      (tvb, 22)));
1161
1162           proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1163                                COOK_SEQUENCE_NUMBER (tvb_get_letohs
1164                                                      (tvb, 22)));
1165         }
1166       break;
1167
1168
1169     case CTRL_PS_POLL:
1170       src = tvb_get_ptr (tvb, 10, 6);
1171       dst = tvb_get_ptr (tvb, 4, 6);
1172
1173       set_src_addr_cols(pinfo, src, "BSSID");
1174       set_dst_addr_cols(pinfo, dst, "BSSID");
1175
1176       if (tree)
1177         {
1178           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1179
1180           proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1181         }
1182       break;
1183
1184
1185     case CTRL_RTS:
1186       src = tvb_get_ptr (tvb, 10, 6);
1187       dst = tvb_get_ptr (tvb, 4, 6);
1188
1189       set_src_addr_cols(pinfo, src, "TA");
1190       set_dst_addr_cols(pinfo, dst, "RA");
1191
1192       if (tree)
1193         {
1194           proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1195
1196           proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1197         }
1198       break;
1199
1200
1201     case CTRL_CTS:
1202       dst = tvb_get_ptr (tvb, 4, 6);
1203
1204       set_dst_addr_cols(pinfo, dst, "RA");
1205
1206       if (tree)
1207           proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1208       break;
1209
1210
1211     case CTRL_ACKNOWLEDGEMENT:
1212       dst = tvb_get_ptr (tvb, 4, 6);
1213
1214       set_dst_addr_cols(pinfo, dst, "RA");
1215
1216       if (tree)
1217         proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1218       break;
1219
1220
1221     case CTRL_CFP_END:
1222       src = tvb_get_ptr (tvb, 10, 6);
1223       dst = tvb_get_ptr (tvb, 4, 6);
1224
1225       set_src_addr_cols(pinfo, src, "BSSID");
1226       set_dst_addr_cols(pinfo, dst, "RA");
1227
1228       if (tree)
1229         {
1230           proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1231           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1232         }
1233       break;
1234
1235
1236     case CTRL_CFP_ENDACK:
1237       src = tvb_get_ptr (tvb, 10, 6);
1238       dst = tvb_get_ptr (tvb, 4, 6);
1239
1240       set_src_addr_cols(pinfo, src, "BSSID");
1241       set_dst_addr_cols(pinfo, dst, "RA");
1242
1243       if (tree)
1244         {
1245           proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1246
1247           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1248         }
1249       break;
1250
1251
1252     case DATA:
1253     case DATA_CF_ACK:
1254     case DATA_CF_POLL:
1255     case DATA_CF_ACK_POLL:
1256       addr_type = COOK_ADDR_SELECTOR (fcf);
1257
1258       /* In order to show src/dst address we must always do the following */
1259       switch (addr_type)
1260         {
1261
1262         case DATA_ADDR_T1:
1263           src = tvb_get_ptr (tvb, 10, 6);
1264           dst = tvb_get_ptr (tvb, 4, 6);
1265           break;
1266
1267
1268         case DATA_ADDR_T2:
1269           src = tvb_get_ptr (tvb, 16, 6);
1270           dst = tvb_get_ptr (tvb, 4, 6);
1271           break;
1272
1273
1274         case DATA_ADDR_T3:
1275           src = tvb_get_ptr (tvb, 10, 6);
1276           dst = tvb_get_ptr (tvb, 16, 6);
1277           break;
1278
1279
1280         case DATA_ADDR_T4:
1281           src = tvb_get_ptr (tvb, 24, 6);
1282           dst = tvb_get_ptr (tvb, 16, 6);
1283           break;
1284         }
1285
1286       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1287       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1288       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1289       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1290
1291       /* Now if we have a tree we start adding stuff */
1292       if (tree)
1293         {
1294
1295
1296           switch (addr_type)
1297             {
1298
1299             case DATA_ADDR_T1:
1300               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1301               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1302               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1303                                     tvb_get_ptr (tvb, 16, 6));
1304               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1305                                    COOK_FRAGMENT_NUMBER (tvb_get_letohs
1306                                                          (tvb, 22)));
1307               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1308                                    COOK_SEQUENCE_NUMBER (tvb_get_letohs
1309                                                          (tvb, 22)));
1310
1311               /* add items for wlan.addr filter */
1312               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1313               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1314               break;
1315               
1316               
1317             case DATA_ADDR_T2:
1318               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1319               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1320                                     tvb_get_ptr (tvb, 10, 6));
1321               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1322               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1323                                    COOK_FRAGMENT_NUMBER (tvb_get_letohs
1324                                                          (tvb, 22)));
1325               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1326                                    COOK_SEQUENCE_NUMBER (tvb_get_letohs
1327                                                          (tvb, 22)));
1328
1329               /* add items for wlan.addr filter */
1330               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1331               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1332               break;
1333    
1334
1335             case DATA_ADDR_T3:
1336               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1337                                     tvb_get_ptr (tvb, 4, 6));
1338               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1339               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1340
1341               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1342                                    COOK_FRAGMENT_NUMBER (tvb_get_letohs
1343                                                          (tvb, 22)));
1344               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1345                                    COOK_SEQUENCE_NUMBER (tvb_get_letohs
1346                                                          (tvb, 22)));
1347
1348               /* add items for wlan.addr filter */
1349               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1350               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1351               break;
1352               
1353
1354             case DATA_ADDR_T4:
1355               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1356                                     tvb_get_ptr (tvb, 4, 6));
1357               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1358                                     tvb_get_ptr (tvb, 10, 6));
1359               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1360               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1361                                    COOK_FRAGMENT_NUMBER (tvb_get_letohs
1362                                                          (tvb, 22)));
1363               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1364                                    COOK_SEQUENCE_NUMBER (tvb_get_letohs
1365                                                          (tvb, 22)));
1366               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1367
1368               /* add items for wlan.addr filter */
1369               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1370               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1371               break;
1372             }
1373
1374         }
1375       break;
1376     }
1377
1378   /*
1379    * Only management and data frames have a body, so we don't have
1380    * anything more to do for other types of frames.
1381    */
1382   switch (COOK_FRAME_TYPE (fcf))
1383     {
1384
1385     case MGT_FRAME:
1386     case DATA_FRAME:
1387       break;
1388
1389     default:
1390       return;
1391     }
1392
1393   /*
1394    * For WEP-encrypted frames, dissect the WEP parameters and
1395    * display the payload as data.
1396    *
1397    * XXX - allow the key to be specified, and, if it is, decrypt
1398    * the payload and dissect it?
1399    */
1400   if (IS_WEP(COOK_FLAGS(fcf)))
1401     {
1402       int pkt_len = tvb_reported_length (tvb);
1403       int cap_len = tvb_length (tvb);
1404
1405       if (tree)
1406         {
1407           get_wep_parameter_tree (tree, tvb, hdr_len, pkt_len);
1408           pkt_len -= hdr_len + 4;
1409           cap_len -= hdr_len + 4;
1410
1411           /*
1412            * OK, pkt_len and cap_len have had the length of the 802.11
1413            * header and WEP parameters subtracted.
1414            *
1415            * If there's anything left:
1416            *
1417            *    if cap_len is greater than or equal to pkt_len (i.e., we
1418            *    captured the entire packet), subtract the length of the
1419            *    WEP CRC from cap_len;
1420            *
1421            *    if cap_len is from 1 to 3 bytes less than pkt_len (i.e.,
1422            *    we captured some but not all of the WEP CRC), subtract
1423            *    the length of the part of the WEP CRC we captured from
1424            *    crc_len;
1425            *
1426            *    otherwise, (i.e., we captured none of the WEP CRC),
1427            *    leave cap_len alone;
1428            *
1429            * and subtract the length of the WEP CRC from pkt_len.
1430            */
1431           if (cap_len >= pkt_len)
1432             cap_len -= 4;
1433           else if ((pkt_len - cap_len) >= 1 && (pkt_len - cap_len) <= 3)
1434             cap_len -= 4 - (pkt_len - cap_len);
1435           pkt_len -= 4;
1436           if (cap_len > 0 && pkt_len > 0)
1437             dissect_data (tvb, hdr_len + 4, pinfo, tree);
1438         }
1439         return;
1440     }
1441
1442   /*
1443    * Now dissect the body of a non-WEP-encrypted frame.
1444    */
1445   next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1446   switch (COOK_FRAME_TYPE (fcf))
1447     {
1448
1449     case MGT_FRAME:
1450       dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1451       break;
1452
1453
1454     case DATA_FRAME:
1455       /* I guess some bridges take Netware Ethernet_802_3 frames,
1456          which are 802.3 frames (with a length field rather than
1457          a type field, but with no 802.2 header in the payload),
1458          and just stick the payload into an 802.11 frame.  I've seen
1459          captures that show frames of that sort.
1460
1461          This means we have to do the same check for Netware 802.3 -
1462          or, if you will, "Netware 802.11" - that we do in the
1463          Ethernet dissector, i.e. checking for 0xffff as the first
1464          four bytes of the payload and, if we find it, treating it
1465          as an IPX frame. */
1466       is_802_2 = TRUE;
1467       TRY {
1468         if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1469           is_802_2 = FALSE;
1470       }
1471       CATCH2(BoundsError, ReportedBoundsError) {
1472             ; /* do nothing */
1473
1474       }
1475       ENDTRY;
1476
1477       if (is_802_2)
1478         call_dissector(llc_handle, next_tvb, pinfo, tree);
1479       else
1480         call_dissector(ipx_handle, next_tvb, pinfo, tree);
1481       break;
1482     }
1483 }
1484
1485 void
1486 proto_register_wlan (void)
1487 {
1488   static const value_string frame_type[] = {
1489     {MGT_FRAME,     "Management frame"},
1490     {CONTROL_FRAME, "Control frame"},
1491     {DATA_FRAME,    "Data frame"},
1492     {0,             NULL}
1493   };
1494
1495   static const value_string tofrom_ds[] = {
1496     {0,                       "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
1497     {FLAG_TO_DS,              "Frame is entering DS (To DS: 1  From DS: 0)"},
1498     {FLAG_FROM_DS,            "Frame is exiting DS (To DS: 0  From DS: 1)"},
1499     {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1  From DS: 1)"},
1500     {0, NULL}
1501   };
1502
1503   static const true_false_string tods_flag = {
1504     "TO DS: Should be false",
1505     "Not used"
1506   };
1507
1508   static const true_false_string fromds_flag = {
1509     "FROM DS: Should be false",
1510     "Not used"
1511   };
1512
1513   static const true_false_string more_frags = {
1514     "MSDU/MMPDU is fragmented",
1515     "No fragments"
1516   };
1517
1518   static const true_false_string retry_flags = {
1519     "Frame is being retransmitted",
1520     "Frame is not being retransmitted"
1521   };
1522
1523   static const true_false_string pm_flags = {
1524     "STA will go to sleep",
1525     "STA will stay up"
1526   };
1527
1528   static const true_false_string md_flags = {
1529     "Data is buffered for STA at AP",
1530     "No data buffered"
1531   };
1532
1533   static const true_false_string wep_flags = {
1534     "WEP is enabled",
1535     "WEP is disabled"
1536   };
1537
1538   static const true_false_string order_flags = {
1539     "Strictly ordered",
1540     "Not strictly ordered"
1541   };
1542
1543   static const true_false_string cf_ess_flags = {
1544     "Transmitter is an AP",
1545     "Transmitter is a STA"
1546   };
1547
1548
1549   static const true_false_string cf_privacy_flags = {
1550     "AP/STA can support WEP",
1551     "AP/STA cannot support WEP"
1552   };
1553
1554   static const true_false_string cf_preamble_flags = {
1555     "Short preamble allowed",
1556     "Short preamble not allowed"
1557   };
1558
1559   static const true_false_string cf_pbcc_flags = {
1560     "PBCC modulation allowed",
1561     "PBCC modulation not allowed"
1562   };
1563
1564   static const true_false_string cf_agility_flags = {
1565     "Channel agility in use",
1566     "Channel agility not in use"
1567   };
1568
1569
1570   static const true_false_string cf_ibss_flags = {
1571     "Transmitter belongs to an IBSS",
1572     "Transmitter belongs to a BSS"
1573   };
1574
1575   static const value_string sta_cf_pollable[] = {
1576     {0x00, "Station is not CF-Pollable"},
1577     {0x02, "Station is CF-Pollable, "
1578      "not requesting to be placed on the  CF-polling list"},
1579     {0x01, "Station is CF-Pollable, "
1580      "requesting to be placed on the CF-polling list"},
1581     {0x03, "Station is CF-Pollable, requesting never to be polled"},
1582     {0, NULL}
1583   };
1584
1585   static const value_string ap_cf_pollable[] = {
1586     {0x00, "No point coordinator at AP"},
1587     {0x02, "Point coordinator at AP for delivery only (no polling)"},
1588     {0x01, "Point coordinator at AP for delivery and polling"},
1589     {0x03, "Reserved"},
1590     {0, NULL}
1591   };
1592
1593
1594   static const value_string auth_alg[] = {
1595     {0x00, "Open System"},
1596     {0x01, "Shared key"},
1597     {0, NULL}
1598   };
1599
1600   static const value_string reason_codes[] = {
1601     {0x00, "Reserved"},
1602     {0x01, "Unspecified reason"},
1603     {0x02, "Previous authentication no longer valid"},
1604     {0x03, "Deauthenticated because sending STA is leaving (has left) "
1605      "IBSS or ESS"},
1606     {0x04, "Disassociated due to inactivity"},
1607     {0x05, "Disassociated because AP is unable to handle all currently "
1608      "associated stations"},
1609     {0x06, "Class 2 frame received from nonauthenticated station"},
1610     {0x07, "Class 3 frame received from nonassociated station"},
1611     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1612     {0x09, "Station requesting (re)association is not authenticated with "
1613      "responding station"},
1614     {0x00, NULL}
1615   };
1616
1617
1618   static const value_string status_codes[] = {
1619     {0x00, "Successful"},
1620     {0x01, "Unspecified failure"},
1621     {0x0A, "Cannot support all requested capabilities in the "
1622      "Capability information field"},
1623     {0x0B, "Reassociation denied due to inability to confirm that "
1624      "association exists"},
1625     {0x0C, "Association denied due to reason outside the scope of this "
1626      "standard"},
1627
1628     {0x0D, "Responding station does not support the specified authentication "
1629      "algorithm"},
1630     {0x0E, "Received an Authentication frame with authentication sequence "
1631      "transaction sequence number out of expected sequence"},
1632     {0x0F, "Authentication rejected because of challenge failure"},
1633     {0x10, "Authentication rejected due to timeout waiting for next "
1634      "frame in sequence"},
1635     {0x11, "Association denied because AP is unable to handle additional "
1636      "associated stations"},
1637     {0x12, "Association denied due to requesting station not supporting all "
1638      "of the datarates in the BSSBasicServiceSet Parameter"},
1639     {0x00, NULL}
1640   };
1641
1642   static hf_register_info hf[] = {
1643     {&hf_fc_field,
1644      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
1645       "MAC Frame control", HFILL }},
1646
1647     {&hf_fc_proto_version,
1648      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
1649       "MAC Protocol version", HFILL }}, /* 0 */
1650
1651     {&hf_fc_frame_type,
1652      {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
1653       "Frame type", HFILL }},
1654
1655     {&hf_fc_frame_subtype,
1656      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
1657       "Frame subtype", HFILL }},        /* 2 */
1658
1659     {&hf_fc_frame_type_subtype,
1660      {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
1661       "Type and subtype combined", HFILL }},
1662
1663     {&hf_fc_flags,
1664      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
1665       "Protocol flags", HFILL }},
1666
1667     {&hf_fc_data_ds,
1668      {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
1669       "Data-frame DS-traversal status", HFILL }},       /* 3 */
1670
1671     {&hf_fc_to_ds,
1672      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
1673       "To DS flag", HFILL }},           /* 4 */
1674
1675     {&hf_fc_from_ds,
1676      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
1677       "From DS flag", HFILL }},         /* 5 */
1678
1679     {&hf_fc_more_frag,
1680      {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
1681       "More Fragments flag", HFILL }},  /* 6 */
1682
1683     {&hf_fc_retry,
1684      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
1685       "Retransmission flag", HFILL }},
1686
1687     {&hf_fc_pwr_mgt,
1688      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
1689       "Power management status", HFILL }},
1690
1691     {&hf_fc_more_data,
1692      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
1693       "More data flag", HFILL }},
1694
1695     {&hf_fc_wep,
1696      {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
1697       "WEP flag", HFILL }},
1698
1699     {&hf_fc_order,
1700      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
1701       "Strictly ordered flag", HFILL }},
1702
1703     {&hf_assoc_id,
1704      {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
1705       "Association-ID field", HFILL }},
1706
1707     {&hf_did_duration,
1708      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
1709       "Duration field", HFILL }},
1710
1711     {&hf_addr_da,
1712      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
1713       "Destination Hardware Address", HFILL }},
1714
1715     {&hf_addr_sa,
1716      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
1717       "Source Hardware Address", HFILL }},
1718
1719     { &hf_addr,
1720       {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
1721        "Source or Destination Hardware Address", HFILL }},
1722
1723     {&hf_addr_ra,
1724      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
1725       "Receiving Station Hardware Address", HFILL }},
1726
1727     {&hf_addr_ta,
1728      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
1729       "Transmitting Station Hardware Address", HFILL }},
1730
1731     {&hf_addr_bssid,
1732      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
1733       "Basic Service Set ID", HFILL }},
1734
1735     {&hf_frag_number,
1736      {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
1737       "Fragment number", HFILL }},
1738
1739     {&hf_seq_number,
1740      {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
1741       "Sequence number", HFILL }},
1742
1743     {&hf_fcs,
1744      {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
1745       NULL, 0, "", HFILL }},
1746
1747     {&hf_wep_iv,
1748      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
1749       "Initialization Vector", HFILL }},
1750
1751     {&hf_wep_key,
1752      {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
1753       "Key", HFILL }},
1754
1755     {&hf_wep_crc,
1756      {"WEP CRC (not verified)", "wlan.wep.crc", FT_UINT32, BASE_HEX, NULL, 0,
1757       "WEP CRC", HFILL }},
1758   };
1759
1760   static hf_register_info ff[] = {
1761     {&ff_timestamp,
1762      {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
1763       NULL, 0, "", HFILL }},
1764
1765     {&ff_auth_alg,
1766      {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
1767       FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
1768
1769     {&ff_beacon_interval,
1770      {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
1771       "", HFILL }},
1772
1773     {&hf_fixed_parameters,
1774      {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
1775       "", HFILL }},
1776
1777     {&hf_tagged_parameters,
1778      {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
1779       "", HFILL }},
1780
1781     {&ff_capture,
1782      {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
1783       "Capability information", HFILL }},
1784
1785     {&ff_cf_sta_poll,
1786      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
1787       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
1788       "CF-Poll capabilities for a STA", HFILL }},
1789
1790     {&ff_cf_ap_poll,
1791      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
1792       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
1793       "CF-Poll capabilities for an AP", HFILL }},
1794
1795     {&ff_cf_ess,
1796      {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
1797       FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
1798
1799
1800     {&ff_cf_ibss,
1801      {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
1802       FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
1803
1804     {&ff_cf_privacy,
1805      {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
1806       FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
1807
1808     {&ff_cf_preamble,
1809      {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
1810       FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
1811
1812     {&ff_cf_pbcc,
1813      {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
1814       FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
1815
1816     {&ff_cf_agility,
1817      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
1818       FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
1819
1820     {&ff_auth_seq,
1821      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
1822       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
1823
1824     {&ff_assoc_id,
1825      {"Association ID", "wlan_mgt.fixed.aid",
1826       FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
1827
1828     {&ff_listen_ival,
1829      {"Listen Interval", "wlan_mgt.fixed.listen_ival",
1830       FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
1831
1832     {&ff_current_ap,
1833      {"Current AP", "wlan_mgt.fixed.current_ap",
1834       FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
1835
1836     {&ff_reason,
1837      {"Reason code", "wlan_mgt.fixed.reason_code",
1838       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
1839       "Reason for unsolicited notification", HFILL }},
1840
1841     {&ff_status_code,
1842      {"Status code", "wlan_mgt.fixed.status_code",
1843       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
1844       "Status of requested event", HFILL }},
1845
1846     {&tag_number,
1847      {"Tag", "wlan_mgt.tag.number",
1848       FT_UINT16, BASE_DEC, NULL, 0,
1849       "Element ID", HFILL }},
1850
1851     {&tag_length,
1852      {"Tag length", "wlan_mgt.tag.length",
1853       FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
1854
1855     {&tag_interpretation,
1856      {"Tag interpretation", "wlan_mgt.tag.interpretation",
1857       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
1858
1859   };
1860
1861   static gint *tree_array[] = {
1862     &ett_80211,
1863     &ett_fc_tree,
1864     &ett_proto_flags,
1865     &ett_80211_mgt,
1866     &ett_fixed_parameters,
1867     &ett_tagged_parameters,
1868     &ett_wep_parameters,
1869     &ett_cap_tree,
1870   };
1871
1872   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
1873                                         "IEEE 802.11", "wlan");
1874   proto_register_field_array (proto_wlan, hf, array_length (hf));
1875   proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
1876                                         "802.11 MGT", "wlan_mgt");
1877   proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
1878   proto_register_subtree_array (tree_array, array_length (tree_array));
1879 }
1880
1881 void
1882 proto_reg_handoff_wlan(void)
1883 {
1884   /*
1885    * Get handles for the LLC and IPX dissectors.
1886    */
1887   llc_handle = find_dissector("llc");
1888   ipx_handle = find_dissector("ipx");
1889
1890   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,
1891                 proto_wlan);
1892 }