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