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