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