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