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