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