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