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