From Chris Waters: export "find_dissector_table()" and add
[metze/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.78 2002/11/06 21:49:29 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 #ifdef HAVE_CONFIG_H
38 # include "config.h"
39 #endif
40
41 #include <stdio.h>
42 #include <stdlib.h>
43
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
46 #endif
47
48 #include <string.h>
49 #include <glib.h>
50 #include <epan/bitswap.h>
51 #include <epan/proto.h>
52 #include <epan/packet.h>
53 #include <epan/resolv.h>
54 #include "prefs.h"
55 #include "reassemble.h"
56 #include "packet-ipx.h"
57 #include "packet-llc.h"
58 #include "packet-ieee80211.h"
59 #include "etypes.h"
60
61 /* Defragment fragmented 802.11 datagrams */
62 static gboolean wlan_defragment = TRUE;
63
64 /* Check for the presence of the 802.11 FCS */
65 static gboolean wlan_check_fcs = FALSE;
66
67 /* Ignore the WEP bit; assume packet is decrypted */
68 static gboolean wlan_ignore_wep = FALSE;
69
70 /* Tables for reassembly of fragments. */
71 static GHashTable *wlan_fragment_table = NULL;
72 static GHashTable *wlan_reassembled_table = NULL;
73
74 /* Stuff for the WEP decoder */
75 static guint num_wepkeys = 0;
76 static guint8 **wep_keys = NULL;
77 static int *wep_keylens = NULL;
78 static void init_wepkeys(void);
79 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
80 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
81 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
82
83 /* FCS utility function. */
84 static guint32 crc32(const unsigned char* buf, unsigned int len);
85
86 /* #define USE_ENV */
87 /* When this is set, an unlimited number of WEP keys can be set in the
88    environment:
89
90    ETHEREAL_WEPKEYNUM=##
91    ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
92    ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
93
94    ... you get the idea.
95
96    otherwise you're limited to specifying four keys in the preference system.
97  */
98
99 #ifndef USE_ENV
100 static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
101 #endif
102
103 /* ************************************************************************* */
104 /*                          Miscellaneous Constants                          */
105 /* ************************************************************************* */
106 #define SHORT_STR 256
107
108 /* ************************************************************************* */
109 /*  Define some very useful macros that are used to analyze frame types etc. */
110 /* ************************************************************************* */
111 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4))      /* Create key to (sub)type */
112 #define COOK_PROT_VERSION(x)  ((x) & 0x3)
113 #define COOK_FRAME_TYPE(x)    (((x) & 0xC) >> 2)
114 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
115 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
116 #define COOK_ASSOC_ID(x)      ((x) & 0x3FFF)
117 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
118 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
119 #define COOK_FLAGS(x)           (((x) & 0xFF00) >> 8)
120 #define COOK_DS_STATUS(x)       ((x) & 0x3)
121 #define COOK_WEP_KEY(x)       (((x) & 0xC0) >> 6)
122
123 #define FLAG_TO_DS              0x01
124 #define FLAG_FROM_DS            0x02
125 #define FLAG_MORE_FRAGMENTS     0x04
126 #define FLAG_RETRY              0x08
127 #define FLAG_POWER_MGT          0x10
128 #define FLAG_MORE_DATA          0x20
129 #define FLAG_WEP                0x40
130 #define FLAG_ORDER              0x80
131
132 #define IS_TO_DS(x)            ((x) & FLAG_TO_DS)
133 #define IS_FROM_DS(x)          ((x) & FLAG_FROM_DS)
134 #define HAVE_FRAGMENTS(x)      ((x) & FLAG_MORE_FRAGMENTS)
135 #define IS_RETRY(x)            ((x) & FLAG_RETRY)
136 #define POWER_MGT_STATUS(x)    ((x) & FLAG_POWER_MGT)
137 #define HAS_MORE_DATA(x)       ((x) & FLAG_MORE_DATA)
138 #define IS_WEP(x)              (!wlan_ignore_wep && ((x) & FLAG_WEP))
139 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
140
141 #define MGT_RESERVED_RANGE(x)  (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
142 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
143 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
144 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
145
146
147 /* ************************************************************************* */
148 /*              Constants used to identify cooked frame types                */
149 /* ************************************************************************* */
150 #define MGT_FRAME            0x00       /* Frame type is management */
151 #define CONTROL_FRAME        0x01       /* Frame type is control */
152 #define DATA_FRAME           0x02       /* Frame type is Data */
153
154 #define DATA_SHORT_HDR_LEN     24
155 #define DATA_LONG_HDR_LEN      30
156 #define MGT_FRAME_HDR_LEN      24       /* Length of Managment frame-headers */
157
158 #define MGT_ASSOC_REQ        0x00       /* Management - association request        */
159 #define MGT_ASSOC_RESP       0x01       /* Management - association response       */
160 #define MGT_REASSOC_REQ      0x02       /* Management - reassociation request      */
161 #define MGT_REASSOC_RESP     0x03       /* Management - reassociation response     */
162 #define MGT_PROBE_REQ        0x04       /* Management - Probe request              */
163 #define MGT_PROBE_RESP       0x05       /* Management - Probe response             */
164 #define MGT_BEACON           0x08       /* Management - Beacon frame               */
165 #define MGT_ATIM             0x09       /* Management - ATIM                       */
166 #define MGT_DISASS           0x0A       /* Management - Disassociation             */
167 #define MGT_AUTHENTICATION   0x0B       /* Management - Authentication             */
168 #define MGT_DEAUTHENTICATION 0x0C       /* Management - Deauthentication           */
169
170 #define CTRL_PS_POLL         0x1A       /* Control - power-save poll               */
171 #define CTRL_RTS             0x1B       /* Control - request to send               */
172 #define CTRL_CTS             0x1C       /* Control - clear to send                 */
173 #define CTRL_ACKNOWLEDGEMENT 0x1D       /* Control - acknowledgement               */
174 #define CTRL_CFP_END         0x1E       /* Control - contention-free period end    */
175 #define CTRL_CFP_ENDACK      0x1F       /* Control - contention-free period end/ack */
176
177 #define DATA                 0x20       /* Data - Data                             */
178 #define DATA_CF_ACK          0x21       /* Data - Data + CF acknowledge            */
179 #define DATA_CF_POLL         0x22       /* Data - Data + CF poll                   */
180 #define DATA_CF_ACK_POLL     0x23       /* Data - Data + CF acknowledge + CF poll  */
181 #define DATA_NULL_FUNCTION   0x24       /* Data - Null function (no data)          */
182 #define DATA_CF_ACK_NOD      0x25       /* Data - CF ack (no data)                 */
183 #define DATA_CF_POLL_NOD     0x26       /* Data - Data + CF poll (No data)         */
184 #define DATA_CF_ACK_POLL_NOD 0x27       /* Data - CF ack + CF poll (no data)       */
185
186 #define DATA_ADDR_T1         0
187 #define DATA_ADDR_T2         (FLAG_FROM_DS << 8)
188 #define DATA_ADDR_T3         (FLAG_TO_DS << 8)
189 #define DATA_ADDR_T4         ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
190
191
192 /* ************************************************************************* */
193 /*          Macros used to extract information about fixed fields            */
194 /* ************************************************************************* */
195 #define ESS_SET(x) ((x) & 0x0001)
196 #define IBSS_SET(x) ((x) & 0x0002)
197
198
199
200 /* ************************************************************************* */
201 /*        Logical field codes (dissector's encoding of fixed fields)         */
202 /* ************************************************************************* */
203 #define FIELD_TIMESTAMP       0x01      /* 64-bit timestamp                       */
204 #define FIELD_BEACON_INTERVAL 0x02      /* 16-bit beacon interval                 */
205 #define FIELD_CAP_INFO        0x03      /* Add capability information tree        */
206 #define FIELD_AUTH_ALG        0x04      /* Authentication algorithm used          */
207 #define FIELD_AUTH_TRANS_SEQ  0x05      /* Authentication sequence number         */
208 #define FIELD_CURRENT_AP_ADDR 0x06
209 #define FIELD_LISTEN_IVAL     0x07
210 #define FIELD_REASON_CODE     0x08
211 #define FIELD_ASSOC_ID        0x09
212 #define FIELD_STATUS_CODE     0x0A
213
214 /* ************************************************************************* */
215 /*        Logical field codes (IEEE 802.11 encoding of tags)                 */
216 /* ************************************************************************* */
217 #define TAG_SSID           0x00
218 #define TAG_SUPP_RATES     0x01
219 #define TAG_FH_PARAMETER   0x02
220 #define TAG_DS_PARAMETER   0x03
221 #define TAG_CF_PARAMETER   0x04
222 #define TAG_TIM            0x05
223 #define TAG_IBSS_PARAMETER 0x06
224 #define TAG_CHALLENGE_TEXT 0x10
225
226 /* ************************************************************************* */
227 /*                         Frame types, and their names                      */
228 /* ************************************************************************* */
229 static const value_string frame_type_subtype_vals[] = {
230         {MGT_ASSOC_REQ,        "Association Request"},
231         {MGT_ASSOC_RESP,       "Association Response"},
232         {MGT_REASSOC_REQ,      "Reassociation Request"},
233         {MGT_REASSOC_RESP,     "Reassociation Response"},
234         {MGT_PROBE_REQ,        "Probe Request"},
235         {MGT_PROBE_RESP,       "Probe Response"},
236         {MGT_BEACON,           "Beacon frame"},
237         {MGT_ATIM,             "ATIM"},
238         {MGT_DISASS,           "Dissassociate"},
239         {MGT_AUTHENTICATION,   "Authentication"},
240         {MGT_DEAUTHENTICATION, "Deauthentication"},
241         {CTRL_PS_POLL,         "Power-Save poll"},
242         {CTRL_RTS,             "Request-to-send"},
243         {CTRL_CTS,             "Clear-to-send"},
244         {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
245         {CTRL_CFP_END,         "CF-End (Control-frame)"},
246         {CTRL_CFP_ENDACK,      "CF-End + CF-Ack (Control-frame)"},
247         {DATA,                 "Data"},
248         {DATA_CF_ACK,          "Data + CF-Acknowledgement"},
249         {DATA_CF_POLL,         "Data + CF-Poll"},
250         {DATA_CF_ACK_POLL,     "Data + CF-Acknowledgement/Poll"},
251         {DATA_NULL_FUNCTION,   "Null function (No data)"},
252         {DATA_CF_ACK_NOD,      "Data + Acknowledgement (No data)"},
253         {DATA_CF_POLL_NOD,     "Data + CF-Poll (No data)"},
254         {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
255         {0,                    NULL}
256 };
257
258 static int proto_wlan = -1;
259
260 /* ************************************************************************* */
261 /*                Header field info values for radio information             */
262 /* ************************************************************************* */
263 static int hf_data_rate = -1;
264 static int hf_channel = -1;
265 static int hf_signal_strength = -1;
266
267 /* ************************************************************************* */
268 /*                Header field info values for FC-field                      */
269 /* ************************************************************************* */
270 static int hf_fc_field = -1;
271 static int hf_fc_proto_version = -1;
272 static int hf_fc_frame_type = -1;
273 static int hf_fc_frame_subtype = -1;
274 static int hf_fc_frame_type_subtype = -1;
275
276 static int hf_fc_flags = -1;
277 static int hf_fc_to_ds = -1;
278 static int hf_fc_from_ds = -1;
279 static int hf_fc_data_ds = -1;
280
281 static int hf_fc_more_frag = -1;
282 static int hf_fc_retry = -1;
283 static int hf_fc_pwr_mgt = -1;
284 static int hf_fc_more_data = -1;
285 static int hf_fc_wep = -1;
286 static int hf_fc_order = -1;
287
288
289 /* ************************************************************************* */
290 /*                   Header values for Duration/ID field                     */
291 /* ************************************************************************* */
292 static int hf_did_duration = -1;
293 static int hf_assoc_id = -1;
294
295
296 /* ************************************************************************* */
297 /*         Header values for different address-fields (all 4 of them)        */
298 /* ************************************************************************* */
299 static int hf_addr_da = -1;     /* Destination address subfield */
300 static int hf_addr_sa = -1;     /* Source address subfield */
301 static int hf_addr_ra = -1;     /* Receiver address subfield */
302 static int hf_addr_ta = -1;     /* Transmitter address subfield */
303 static int hf_addr_bssid = -1;  /* address is bssid */
304
305 static int hf_addr = -1;        /* Source or destination address subfield */
306
307
308 /* ************************************************************************* */
309 /*                Header values for sequence number field                    */
310 /* ************************************************************************* */
311 static int hf_frag_number = -1;
312 static int hf_seq_number = -1;
313
314 /* ************************************************************************* */
315 /*                   Header values for Frame Check field                     */
316 /* ************************************************************************* */
317 static int hf_fcs = -1;
318
319 /* ************************************************************************* */
320 /*                   Header values for reassembly                            */
321 /* ************************************************************************* */
322 static int hf_fragments = -1;
323 static int hf_fragment = -1;
324 static int hf_fragment_overlap = -1;
325 static int hf_fragment_overlap_conflict = -1;
326 static int hf_fragment_multiple_tails = -1;
327 static int hf_fragment_too_long_fragment = -1;
328 static int hf_fragment_error = -1;
329
330
331 static int proto_wlan_mgt = -1;
332 /* ************************************************************************* */
333 /*                      Fixed fields found in mgt frames                     */
334 /* ************************************************************************* */
335 static int ff_auth_alg = -1;    /* Authentication algorithm field            */
336 static int ff_auth_seq = -1;    /* Authentication transaction sequence       */
337 static int ff_current_ap = -1;  /* Current AP MAC address                    */
338 static int ff_listen_ival = -1; /* Listen interval fixed field               */
339 static int ff_timestamp = -1;   /* 64 bit timestamp                          */
340 static int ff_beacon_interval = -1;     /* 16 bit Beacon interval            */
341 static int ff_assoc_id = -1;    /* 16 bit AID field                          */
342 static int ff_reason = -1;      /* 16 bit reason code                        */
343 static int ff_status_code = -1; /* Status code                               */
344
345 /* ************************************************************************* */
346 /*            Flags found in the capability field (fixed field)              */
347 /* ************************************************************************* */
348 static int ff_capture = -1;
349 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA            */
350 static int ff_cf_ap_poll = -1;  /* CF pollable status for an AP            */
351 static int ff_cf_ess = -1;
352 static int ff_cf_ibss = -1;
353 static int ff_cf_privacy = -1;
354 static int ff_cf_preamble = -1;
355 static int ff_cf_pbcc = -1;
356 static int ff_cf_agility = -1;
357
358 /* ************************************************************************* */
359 /*                       Tagged value format fields                          */
360 /* ************************************************************************* */
361 static int tag_number = -1;
362 static int tag_length = -1;
363 static int tag_interpretation = -1;
364
365
366
367 static int hf_fixed_parameters = -1;    /* Protocol payload for management frames */
368 static int hf_tagged_parameters = -1;   /* Fixed payload item */
369 static int hf_wep_iv = -1;
370 static int hf_wep_key = -1;
371 static int hf_wep_icv = -1;
372
373 /* ************************************************************************* */
374 /*                               Protocol trees                              */
375 /* ************************************************************************* */
376 static gint ett_80211 = -1;
377 static gint ett_proto_flags = -1;
378 static gint ett_cap_tree = -1;
379 static gint ett_fc_tree = -1;
380 static gint ett_fragments = -1;
381 static gint ett_fragment = -1;
382
383 static gint ett_80211_mgt = -1;
384 static gint ett_fixed_parameters = -1;
385 static gint ett_tagged_parameters = -1;
386 static gint ett_wep_parameters = -1;
387
388 static const fragment_items frag_items = {
389         &ett_fragment,
390         &ett_fragments,
391         &hf_fragments,
392         &hf_fragment,
393         &hf_fragment_overlap,
394         &hf_fragment_overlap_conflict,
395         &hf_fragment_multiple_tails,
396         &hf_fragment_too_long_fragment,
397         &hf_fragment_error,
398         "fragments"
399 };
400
401 static dissector_handle_t llc_handle;
402 static dissector_handle_t ipx_handle;
403 static dissector_handle_t data_handle;
404
405 /* ************************************************************************* */
406 /*            Return the length of the current header (in bytes)             */
407 /* ************************************************************************* */
408 static int
409 find_header_length (guint16 fcf)
410 {
411   switch (COOK_FRAME_TYPE (fcf)) {
412
413   case MGT_FRAME:
414     return MGT_FRAME_HDR_LEN;
415
416   case CONTROL_FRAME:
417     switch (COMPOSE_FRAME_TYPE (fcf)) {
418
419     case CTRL_CTS:
420     case CTRL_ACKNOWLEDGEMENT:
421       return 10;
422
423     case CTRL_RTS:
424     case CTRL_PS_POLL:
425     case CTRL_CFP_END:
426     case CTRL_CFP_ENDACK:
427       return 16;
428     }
429     return 4;   /* XXX */
430
431   case DATA_FRAME:
432     return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
433                                                        DATA_SHORT_HDR_LEN;
434   default:
435     return 4;   /* XXX */
436   }
437 }
438
439
440 /* ************************************************************************* */
441 /*          This is the capture function used to update packet counts        */
442 /* ************************************************************************* */
443 static void
444 capture_ieee80211_common (const guchar * pd, int offset, int len,
445                           packet_counts * ld, gboolean fixed_length_header)
446 {
447   guint16 fcf, hdr_length;
448
449   if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
450     ld->other++;
451     return;
452   }
453
454   fcf = pletohs (&pd[0]);
455
456   if (IS_WEP(COOK_FLAGS(fcf)))
457     {
458       ld->other++;
459       return;
460     }
461
462   switch (COMPOSE_FRAME_TYPE (fcf))
463     {
464
465     case DATA:                  /* We got a data frame */
466     case DATA_CF_ACK:           /* Data with ACK */
467     case DATA_CF_POLL:
468     case DATA_CF_ACK_POLL:
469       if (fixed_length_header)
470         hdr_length = DATA_LONG_HDR_LEN;
471       else
472         hdr_length = find_header_length (fcf);
473       /* I guess some bridges take Netware Ethernet_802_3 frames,
474          which are 802.3 frames (with a length field rather than
475          a type field, but with no 802.2 header in the payload),
476          and just stick the payload into an 802.11 frame.  I've seen
477          captures that show frames of that sort.
478
479          This means we have to do the same check for Netware 802.3 -
480          or, if you will, "Netware 802.11" - that we do in the
481          Ethernet dissector, i.e. checking for 0xffff as the first
482          four bytes of the payload and, if we find it, treating it
483          as an IPX frame. */
484       if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
485         ld->other++;
486         return;
487       }
488       if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
489         capture_ipx (ld);
490       }
491       else {
492         capture_llc (pd, offset + hdr_length, len, ld);
493       }
494       break;
495
496     default:
497       ld->other++;
498       break;
499     }
500 }
501
502 /*
503  * Handle 802.11 with a variable-length link-layer header.
504  */
505 void
506 capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
507 {
508   capture_ieee80211_common (pd, offset, len, ld, FALSE);
509 }
510
511 /*
512  * Handle 802.11 with a fixed-length link-layer header (padded to the
513  * maximum length).
514  */
515 void
516 capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
517 {
518   capture_ieee80211_common (pd, offset, len, ld, TRUE);
519 }
520
521
522 /* ************************************************************************* */
523 /*          Add the subtree used to store the fixed parameters               */
524 /* ************************************************************************* */
525 static proto_tree *
526 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
527 {
528   proto_item *fixed_fields;
529   fixed_fields =
530     proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
531                                 size, size, "Fixed parameters (%d bytes)",
532                                 size);
533
534   return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
535 }
536
537
538 /* ************************************************************************* */
539 /*            Add the subtree used to store tagged parameters                */
540 /* ************************************************************************* */
541 static proto_tree *
542 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
543 {
544   proto_item *tagged_fields;
545
546   tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
547                                               tvb,
548                                               start,
549                                               size,
550                                               size,
551                                               "Tagged parameters (%d bytes)",
552                                               size);
553
554   return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
555 }
556
557
558 /* ************************************************************************* */
559 /*              Dissect and add fixed mgmt fields to protocol tree           */
560 /* ************************************************************************* */
561 static void
562 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
563 {
564   const guint8 *dataptr;
565   char out_buff[SHORT_STR];
566   guint16 capability;
567   proto_item *cap_item;
568   static proto_tree *cap_tree;
569   double temp_double;
570
571   switch (lfcode)
572     {
573     case FIELD_TIMESTAMP:
574       dataptr = tvb_get_ptr (tvb, offset, 8);
575       memset (out_buff, 0, SHORT_STR);
576       snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
577                 dataptr[7],
578                 dataptr[6],
579                 dataptr[5],
580                 dataptr[4],
581                 dataptr[3],
582                 dataptr[2],
583                 dataptr[1],
584                 dataptr[0]);
585
586       proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
587       break;
588
589     case FIELD_BEACON_INTERVAL:
590       temp_double = (double) tvb_get_letohs (tvb, offset);
591       temp_double = temp_double * 1024 / 1000000;
592       proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
593                                     temp_double,"Beacon Interval: %f [Seconds]",
594                                     temp_double);
595       break;
596
597
598     case FIELD_CAP_INFO:
599       capability = tvb_get_letohs (tvb, offset);
600
601       cap_item = proto_tree_add_uint_format (tree, ff_capture,
602                                              tvb, offset, 2,
603                                              capability,
604                                              "Capability Information: 0x%04X",
605                                              capability);
606       cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
607       proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
608                               capability);
609       proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
610                               capability);
611       proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
612                               capability);
613       proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 1,
614                               capability);
615       proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 1,
616                               capability);
617       proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 1,
618                               capability);
619       if (ESS_SET (capability) != 0)    /* This is an AP */
620         proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
621                              ((capability & 0xC) >> 2));
622
623       else                      /* This is a STA */
624         proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
625                              ((capability & 0xC) >> 2));
626       break;
627
628     case FIELD_AUTH_ALG:
629       proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
630       break;
631
632     case FIELD_AUTH_TRANS_SEQ:
633       proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
634       break;
635
636     case FIELD_CURRENT_AP_ADDR:
637       proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
638       break;
639
640     case FIELD_LISTEN_IVAL:
641       proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
642       break;
643
644     case FIELD_REASON_CODE:
645       proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
646       break;
647
648     case FIELD_ASSOC_ID:
649       proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE);
650       break;
651
652     case FIELD_STATUS_CODE:
653       proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
654       break;
655     }
656 }
657
658
659 /* ************************************************************************* */
660 /*           Dissect and add tagged (optional) fields to proto tree          */
661 /* ************************************************************************* */
662 static int
663 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
664 {
665   const guint8 *tag_data_ptr;
666   guint32 tag_no, tag_len;
667   unsigned int i;
668   int n, ret;
669   char out_buff[SHORT_STR];
670
671
672   tag_no = tvb_get_guint8(tvb, offset);
673   tag_len = tvb_get_guint8(tvb, offset + 1);
674
675   tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
676
677
678   if ((tag_no >= 17) && (tag_no <= 31))
679     {                           /* Reserved for challenge text */
680       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
681                                   "Tag Number: %u (Reserved for challenge text)",
682                                   tag_no);
683
684       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
685       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
686                              tag_len, "Not interpreted");
687       return (int) tag_len + 2;
688     }
689
690   /* Next See if tag is reserved - if true, skip it! */
691   if (((tag_no >= 7) && (tag_no <= 15))
692       || ((tag_no >= 32) && (tag_no <= 255)))
693     {
694       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
695                                   "Tag Number: %u (Reserved tag number)",
696                                   tag_no);
697
698       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
699
700       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
701                              tag_len, "Not interpreted");
702       return (int) tag_len + 2;
703     }
704
705
706   switch (tag_no)
707     {
708
709
710     case TAG_SSID:
711       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
712                                   "Tag Number: %u (SSID parameter set)",
713                                   tag_no);
714
715       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
716
717       memset (out_buff, 0, SHORT_STR);
718
719       memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
720       out_buff[tag_len + 1] = 0;
721
722       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
723                              tag_len, out_buff);
724       break;
725
726
727
728     case TAG_SUPP_RATES:
729       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
730                                   "Tag Number: %u (Supported Rates)", tag_no);
731
732       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
733
734       memset (out_buff, 0, SHORT_STR);
735       strcpy (out_buff, "Supported rates: ");
736       n = strlen (out_buff);
737
738       for (i = 0; i < tag_len && n < SHORT_STR; i++)
739         {
740             ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
741                            (tag_data_ptr[i] & 0x7F) * 0.5,
742                            (tag_data_ptr[i] & 0x80) ? "(B)" : "");
743             if (ret == -1) {
744               /* Some versions of snprintf return -1 if they'd truncate
745                  the output. */
746               break;
747             }
748             n += ret;
749         }
750       if (n < SHORT_STR)
751         snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
752
753       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
754                              tag_len, out_buff);
755       break;
756
757
758
759     case TAG_FH_PARAMETER:
760       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
761                                   "Tag Number: %u (FH Parameter set)",
762                                   tag_no);
763
764       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
765       memset (out_buff, 0, SHORT_STR);
766
767       snprintf (out_buff, SHORT_STR,
768                 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
769                 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
770                 tag_data_ptr[3], tag_data_ptr[4]);
771
772       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
773                              tag_len, out_buff);
774       break;
775
776
777
778     case TAG_DS_PARAMETER:
779       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
780                                   "Tag Number: %u (DS Parameter set)",
781                                   tag_no);
782
783       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
784       memset (out_buff, 0, SHORT_STR);
785
786       snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
787       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
788                              tag_len, out_buff);
789       break;
790
791
792     case TAG_CF_PARAMETER:
793       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
794                                   "Tag Number: %u (CF Parameter set)",
795                                   tag_no);
796
797       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
798       memset (out_buff, 0, SHORT_STR);
799
800       snprintf (out_buff, SHORT_STR,
801                 "CFP count %u, CFP period %u, CFP max duration %u, "
802                 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
803                 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
804
805       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
806                              tag_len, out_buff);
807       break;
808
809
810     case TAG_TIM:
811       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
812                                   "Tag Number: %u ((TIM) Traffic Indication Map)",
813                                   tag_no);
814
815       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
816       memset (out_buff, 0, SHORT_STR);
817       snprintf (out_buff, SHORT_STR,
818                 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
819                 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
820                 tag_data_ptr[2]);
821       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
822                              tag_len, out_buff);
823       break;
824
825
826
827     case TAG_IBSS_PARAMETER:
828       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
829                                   "Tag Number: %u (IBSS Parameter set)",
830                                   tag_no);
831
832       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
833       memset (out_buff, 0, SHORT_STR);
834       snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
835                 pletohs (tag_data_ptr));
836
837       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
838                              tag_len, out_buff);
839       break;
840
841
842
843     case TAG_CHALLENGE_TEXT:
844       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
845                                   "Tag Number: %u (Challenge text)", tag_no);
846
847       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
848       memset (out_buff, 0, SHORT_STR);
849       snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
850       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
851                              tag_len, out_buff);
852
853       break;
854
855     default:
856       return 0;
857     }
858
859   return tag_len + 2;
860 }
861
862 /* ************************************************************************* */
863 /*                     Dissect 802.11 management frame                       */
864 /* ************************************************************************* */
865 static void
866 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
867         proto_tree * tree)
868 {
869   proto_item *ti = NULL;
870   proto_tree *mgt_tree;
871   proto_tree *fixed_tree;
872   proto_tree *tagged_tree;
873   guint32 next_idx;
874   guint32 next_len;
875   int tagged_parameter_tree_len;
876
877   CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
878
879   if (tree)
880     {
881       ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
882       mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
883
884       switch (COMPOSE_FRAME_TYPE(fcf))
885         {
886
887         case MGT_ASSOC_REQ:
888           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
889           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
890           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
891
892           next_idx = 4; /* Size of fixed fields */
893           tagged_parameter_tree_len =
894               tvb_reported_length_remaining(tvb, next_idx);
895           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
896                                                    tagged_parameter_tree_len);
897
898           while (tagged_parameter_tree_len > 0) {
899             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
900               break;
901             next_idx +=next_len;
902             tagged_parameter_tree_len -= next_len;
903           }
904           break;
905
906
907         case MGT_ASSOC_RESP:
908           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
909           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
910           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
911           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
912
913           next_idx = 6; /* Size of fixed fields */
914
915           tagged_parameter_tree_len =
916               tvb_reported_length_remaining(tvb, next_idx);
917           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
918                                                    tagged_parameter_tree_len);
919
920           while (tagged_parameter_tree_len > 0) {
921             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
922               break;
923             next_idx +=next_len;
924             tagged_parameter_tree_len -= next_len;
925           }
926           break;
927
928
929         case MGT_REASSOC_REQ:
930           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
931           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
932           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
933           add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
934
935           next_idx = 10;        /* Size of fixed fields */
936           tagged_parameter_tree_len =
937               tvb_reported_length_remaining(tvb, next_idx);
938           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
939                                                    tagged_parameter_tree_len);
940
941           while (tagged_parameter_tree_len > 0) {
942             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
943               break;
944             next_idx +=next_len;
945             tagged_parameter_tree_len -= next_len;
946           }
947           break;
948
949         case MGT_REASSOC_RESP:
950           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
951           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
952           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
953           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
954
955           next_idx = 6; /* Size of fixed fields */
956           tagged_parameter_tree_len =
957               tvb_reported_length_remaining(tvb, next_idx);
958           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
959                                                    tagged_parameter_tree_len);
960
961           while (tagged_parameter_tree_len > 0) {
962             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
963               break;
964             next_idx +=next_len;
965             tagged_parameter_tree_len -= next_len;
966           }
967           break;
968
969
970         case MGT_PROBE_REQ:
971           next_idx = 0;
972           tagged_parameter_tree_len =
973               tvb_reported_length_remaining(tvb, next_idx);
974           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
975                                                    tagged_parameter_tree_len);
976
977           while (tagged_parameter_tree_len > 0) {
978             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
979               break;
980             next_idx +=next_len;
981             tagged_parameter_tree_len -= next_len;
982           }
983           break;
984
985
986         case MGT_PROBE_RESP:
987           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
988           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
989           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
990           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
991
992           next_idx = 12;        /* Size of fixed fields */
993           tagged_parameter_tree_len =
994               tvb_reported_length_remaining(tvb, next_idx);
995           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
996                                                    tagged_parameter_tree_len);
997
998           while (tagged_parameter_tree_len > 0) {
999             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1000               break;
1001             next_idx +=next_len;
1002             tagged_parameter_tree_len -= next_len;
1003           }
1004           break;
1005
1006
1007         case MGT_BEACON:                /* Dissect protocol payload fields  */
1008           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1009
1010           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1011           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1012           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1013
1014           next_idx = 12;        /* Size of fixed fields */
1015           tagged_parameter_tree_len =
1016               tvb_reported_length_remaining(tvb, next_idx);
1017           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1018                                                    tagged_parameter_tree_len);
1019
1020           while (tagged_parameter_tree_len > 0) {
1021             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1022               break;
1023             next_idx +=next_len;
1024             tagged_parameter_tree_len -= next_len;
1025           }
1026           break;
1027
1028
1029         case MGT_ATIM:
1030           break;
1031
1032
1033         case MGT_DISASS:
1034           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1035           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1036           break;
1037
1038
1039         case MGT_AUTHENTICATION:
1040           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1041           add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
1042           add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
1043           add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
1044
1045           next_idx = 6; /* Size of fixed fields */
1046
1047           tagged_parameter_tree_len =
1048                   tvb_reported_length_remaining(tvb, next_idx);
1049           if (tagged_parameter_tree_len != 0)
1050             {
1051               tagged_tree = get_tagged_parameter_tree (mgt_tree,
1052                                                        tvb,
1053                                                        next_idx,
1054                                                        tagged_parameter_tree_len);
1055
1056               while (tagged_parameter_tree_len > 0) {
1057                 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1058                   break;
1059                 next_idx +=next_len;
1060                 tagged_parameter_tree_len -= next_len;
1061               }
1062             }
1063           break;
1064
1065
1066         case MGT_DEAUTHENTICATION:
1067           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1068           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1069           break;
1070         }
1071     }
1072 }
1073
1074 static void
1075 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1076 {
1077   if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1078     col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
1079                     get_ether_name(addr), type);
1080   if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
1081     col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
1082                      ether_to_str(addr), type);
1083 }
1084
1085 static void
1086 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1087 {
1088   if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1089     col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
1090                      get_ether_name(addr), type);
1091   if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
1092     col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
1093                      ether_to_str(addr), type);
1094 }
1095
1096 /* ************************************************************************* */
1097 /*                          Dissect 802.11 frame                             */
1098 /* ************************************************************************* */
1099 static void
1100 dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
1101                           proto_tree * tree, gboolean fixed_length_header,
1102                           gboolean has_radio_information, gboolean has_no_fcs)
1103 {
1104   guint16 fcf, flags, frame_type_subtype;
1105   guint16 seq_control;
1106   guint32 seq_number, frag_number;
1107   gboolean more_frags;
1108   const guint8 *src = NULL, *dst = NULL;
1109   proto_item *ti = NULL;
1110   proto_item *flag_item;
1111   proto_item *fc_item;
1112   proto_tree *hdr_tree = NULL;
1113   proto_tree *flag_tree;
1114   proto_tree *fc_tree;
1115   guint16 hdr_len;
1116   gint len, reported_len;
1117   gboolean save_fragmented;
1118   tvbuff_t *volatile next_tvb = NULL;
1119   guint32 addr_type;
1120   volatile gboolean is_802_2;
1121
1122   if (check_col (pinfo->cinfo, COL_PROTOCOL))
1123     col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
1124   if (check_col (pinfo->cinfo, COL_INFO))
1125     col_clear (pinfo->cinfo, COL_INFO);
1126
1127   fcf = tvb_get_letohs (tvb, 0);
1128   if (fixed_length_header)
1129     hdr_len = DATA_LONG_HDR_LEN;
1130   else
1131     hdr_len = find_header_length (fcf);
1132   frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1133
1134   if (check_col (pinfo->cinfo, COL_INFO))
1135       col_set_str (pinfo->cinfo, COL_INFO,
1136           val_to_str(frame_type_subtype, frame_type_subtype_vals,
1137               "Unrecognized (Reserved frame)"));
1138
1139   flags = COOK_FLAGS (fcf);
1140   more_frags = HAVE_FRAGMENTS (flags);
1141
1142   /* Add the radio information, if present, and the FC to the current tree */
1143   if (tree)
1144     {
1145       ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1146                                            "IEEE 802.11");
1147       hdr_tree = proto_item_add_subtree (ti, ett_80211);
1148
1149       if (has_radio_information) {
1150         proto_tree_add_uint_format(hdr_tree, hf_data_rate,
1151                                    tvb, 0, 0,
1152                                    pinfo->pseudo_header->ieee_802_11.data_rate,
1153                                    "Data Rate: %g mb/s",
1154                                    .5*pinfo->pseudo_header->ieee_802_11.data_rate);
1155
1156         proto_tree_add_uint(hdr_tree, hf_channel,
1157                             tvb, 0, 0,
1158                             pinfo->pseudo_header->ieee_802_11.channel);
1159
1160         proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
1161                                    tvb, 0, 0,
1162                                    pinfo->pseudo_header->ieee_802_11.signal_level,
1163                                    "Signal Strength: %u%%",
1164                                    pinfo->pseudo_header->ieee_802_11.signal_level);
1165       }
1166
1167       proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1168                            tvb, 0, 1,
1169                            frame_type_subtype);
1170
1171       fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
1172                                             fcf,
1173                                             "Frame Control: 0x%04X",
1174                                             fcf);
1175
1176       fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1177
1178
1179       proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
1180                            COOK_PROT_VERSION (fcf));
1181
1182       proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
1183                            COOK_FRAME_TYPE (fcf));
1184
1185       proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1186                            tvb, 0, 1,
1187                            COOK_FRAME_SUBTYPE (fcf));
1188
1189       flag_item =
1190         proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
1191                                     flags, "Flags: 0x%X", flags);
1192
1193       flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1194
1195       proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
1196                            COOK_DS_STATUS (flags));
1197       proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1, 
1198                                      flags);
1199       proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1, 
1200                                      flags);
1201
1202       proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1203                               flags);
1204
1205       proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1206
1207       proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1208
1209       proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1210                               flags);
1211
1212       proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1213
1214       proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1215
1216       if (frame_type_subtype == CTRL_PS_POLL)
1217         proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1218                             COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1219
1220       else
1221           proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1222                                tvb_get_letohs (tvb, 2));
1223     }
1224
1225   /*
1226    * Decode the part of the frame header that isn't the same for all
1227    * frame types.
1228    */
1229   seq_control = 0;
1230   frag_number = 0;
1231   seq_number = 0;
1232
1233   switch (COOK_FRAME_TYPE (fcf))
1234     {
1235
1236     case MGT_FRAME:
1237       /*
1238        * All management frame types have the same header.
1239        */
1240       src = tvb_get_ptr (tvb, 10, 6);
1241       dst = tvb_get_ptr (tvb, 4, 6);
1242
1243       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1244       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1245       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1246       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1247
1248       seq_control = tvb_get_letohs(tvb, 22);
1249       frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1250       seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1251
1252       if (tree)
1253         {
1254           proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1255
1256           proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1257
1258           /* add items for wlan.addr filter */
1259           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1260           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1261
1262           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1263                                 tvb_get_ptr (tvb, 16, 6));
1264
1265           proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1266                                frag_number);
1267
1268           proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1269                                seq_number);
1270         }
1271       break;
1272
1273     case CONTROL_FRAME:
1274       switch (frame_type_subtype)
1275         {
1276
1277         case CTRL_PS_POLL:
1278           src = tvb_get_ptr (tvb, 10, 6);
1279           dst = tvb_get_ptr (tvb, 4, 6);
1280
1281           set_src_addr_cols(pinfo, src, "BSSID");
1282           set_dst_addr_cols(pinfo, dst, "BSSID");
1283
1284           if (tree)
1285             {
1286               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1287
1288               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1289             }
1290           break;
1291
1292
1293         case CTRL_RTS:
1294           src = tvb_get_ptr (tvb, 10, 6);
1295           dst = tvb_get_ptr (tvb, 4, 6);
1296
1297           set_src_addr_cols(pinfo, src, "TA");
1298           set_dst_addr_cols(pinfo, dst, "RA");
1299
1300           if (tree)
1301             {
1302               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1303
1304               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1305             }
1306           break;
1307
1308
1309         case CTRL_CTS:
1310           dst = tvb_get_ptr (tvb, 4, 6);
1311
1312           set_dst_addr_cols(pinfo, dst, "RA");
1313
1314           if (tree)
1315             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1316           break;
1317
1318
1319         case CTRL_ACKNOWLEDGEMENT:
1320           dst = tvb_get_ptr (tvb, 4, 6);
1321
1322           set_dst_addr_cols(pinfo, dst, "RA");
1323
1324           if (tree)
1325             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1326           break;
1327
1328
1329         case CTRL_CFP_END:
1330           src = tvb_get_ptr (tvb, 10, 6);
1331           dst = tvb_get_ptr (tvb, 4, 6);
1332
1333           set_src_addr_cols(pinfo, src, "BSSID");
1334           set_dst_addr_cols(pinfo, dst, "RA");
1335
1336           if (tree)
1337             {
1338               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1339               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1340             }
1341           break;
1342
1343
1344         case CTRL_CFP_ENDACK:
1345           src = tvb_get_ptr (tvb, 10, 6);
1346           dst = tvb_get_ptr (tvb, 4, 6);
1347
1348           set_src_addr_cols(pinfo, src, "BSSID");
1349           set_dst_addr_cols(pinfo, dst, "RA");
1350
1351           if (tree)
1352             {
1353               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1354
1355               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1356             }
1357           break;
1358         }
1359       break;
1360
1361     case DATA_FRAME:
1362       addr_type = COOK_ADDR_SELECTOR (fcf);
1363
1364       /* In order to show src/dst address we must always do the following */
1365       switch (addr_type)
1366         {
1367
1368         case DATA_ADDR_T1:
1369           src = tvb_get_ptr (tvb, 10, 6);
1370           dst = tvb_get_ptr (tvb, 4, 6);
1371           break;
1372
1373
1374         case DATA_ADDR_T2:
1375           src = tvb_get_ptr (tvb, 16, 6);
1376           dst = tvb_get_ptr (tvb, 4, 6);
1377           break;
1378
1379
1380         case DATA_ADDR_T3:
1381           src = tvb_get_ptr (tvb, 10, 6);
1382           dst = tvb_get_ptr (tvb, 16, 6);
1383           break;
1384
1385
1386         case DATA_ADDR_T4:
1387           src = tvb_get_ptr (tvb, 24, 6);
1388           dst = tvb_get_ptr (tvb, 16, 6);
1389           break;
1390         }
1391
1392       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1393       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1394       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1395       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1396
1397       seq_control = tvb_get_letohs(tvb, 22);
1398       frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1399       seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1400
1401       /* Now if we have a tree we start adding stuff */
1402       if (tree)
1403         {
1404
1405
1406           switch (addr_type)
1407             {
1408
1409             case DATA_ADDR_T1:
1410               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1411               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1412               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1413                                     tvb_get_ptr (tvb, 16, 6));
1414               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1415                                    frag_number);
1416               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1417                                    seq_number);
1418
1419               /* add items for wlan.addr filter */
1420               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1421               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1422               break;
1423
1424
1425             case DATA_ADDR_T2:
1426               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1427               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1428                                     tvb_get_ptr (tvb, 10, 6));
1429               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1430               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1431                                    frag_number);
1432               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1433                                    seq_number);
1434
1435               /* add items for wlan.addr filter */
1436               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1437               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1438               break;
1439
1440
1441             case DATA_ADDR_T3:
1442               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1443                                     tvb_get_ptr (tvb, 4, 6));
1444               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1445               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1446
1447               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1448                                    frag_number);
1449               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1450                                    seq_number);
1451
1452               /* add items for wlan.addr filter */
1453               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1454               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1455               break;
1456
1457
1458             case DATA_ADDR_T4:
1459               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1460                                     tvb_get_ptr (tvb, 4, 6));
1461               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1462                                     tvb_get_ptr (tvb, 10, 6));
1463               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1464               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1465                                    frag_number);
1466               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1467                                    seq_number);
1468               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1469
1470               /* add items for wlan.addr filter */
1471               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1472               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1473               break;
1474             }
1475
1476         }
1477       break;
1478     }
1479
1480   len = tvb_length_remaining(tvb, hdr_len);
1481   reported_len = tvb_reported_length_remaining(tvb, hdr_len);
1482
1483   if (!has_no_fcs && (wlan_check_fcs))
1484     {
1485       /*
1486        * Well, this packet should, in theory, have an FCS.
1487        * Do we have the entire packet, and does it have enough data for
1488        * the FCS?
1489        */
1490       if (reported_len < 4)
1491         {
1492           /*
1493            * The packet is claimed not to even have enough data for a 4-byte
1494            * FCS.
1495            * Pretend it doesn't have an FCS.
1496            */
1497           ;
1498         }
1499       else if (len < reported_len)
1500         {
1501           /*
1502            * The packet is claimed to have enough data for a 4-byte FCS, but
1503            * we didn't capture all of the packet.
1504            * Slice off the 4-byte FCS from the reported length, and trim the
1505            * captured length so it's no more than the reported length; that
1506            * will slice off what of the FCS, if any, is in the captured
1507            * length.
1508            */
1509           reported_len -= 4;
1510           if (len > reported_len)
1511             len = reported_len;
1512         }
1513       else
1514         {
1515           /*
1516            * We have the entire packet, and it includes a 4-byte FCS.
1517            * Slice it off, and put it into the tree.
1518            */
1519           len -= 4;
1520           reported_len -= 4;
1521           if (tree)
1522             {
1523               guint32 fcs = crc32(tvb_get_ptr(tvb, 0, hdr_len + len), hdr_len + len);
1524               guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
1525               if (fcs == sent_fcs)
1526                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1527                         hdr_len + len, 4, sent_fcs,
1528                         "Frame check sequence: 0x%08x (correct)", sent_fcs);
1529               else
1530                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1531                         hdr_len + len, 4, sent_fcs,
1532                         "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
1533                         sent_fcs, fcs);
1534             }
1535         }
1536     }
1537
1538   /*
1539    * Only management and data frames have a body, so we don't have
1540    * anything more to do for other types of frames.
1541    */
1542   switch (COOK_FRAME_TYPE (fcf))
1543     {
1544
1545     case MGT_FRAME:
1546       break;
1547
1548     case DATA_FRAME:
1549       /*
1550        * No-data frames don't have a body.
1551        */
1552       switch (frame_type_subtype)
1553         {
1554
1555         case DATA_NULL_FUNCTION:
1556         case DATA_CF_ACK_NOD:
1557         case DATA_CF_POLL_NOD:
1558         case DATA_CF_ACK_POLL_NOD:
1559           return;
1560         }
1561         break;
1562
1563     default:
1564       return;
1565     }
1566
1567   if (IS_WEP(COOK_FLAGS(fcf))) {
1568     /*
1569      * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
1570      * the data, if we have a matching key.  Otherwise display it as data.
1571      */
1572     gboolean can_decrypt = FALSE;
1573     proto_tree *wep_tree = NULL;
1574     guint32 iv;
1575     guint8 key;
1576
1577     /*
1578      * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
1579      * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
1580      * them itself.
1581      *
1582      * Also, just pass the data *following* the WEP parameters as the
1583      * buffer to decrypt.
1584      */
1585     iv = tvb_get_letoh24(tvb, hdr_len);
1586     if (tree) {
1587       proto_item *wep_fields;
1588
1589       wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
1590                                            "WEP parameters");
1591
1592       wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
1593       proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
1594     }
1595     key = COOK_WEP_KEY (tvb_get_guint8 (tvb, hdr_len + 3));
1596     if (tree)
1597       proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
1598
1599     /* Subtract out the length of the IV. */
1600     len -= 4;
1601     reported_len -= 4;
1602
1603     /*
1604      * Well, this packet should, in theory, have an ICV.
1605      * Do we have the entire packet, and does it have enough data for
1606      * the ICV?
1607      */
1608     if (reported_len < 4) {
1609       /*
1610        * The packet is claimed not to even have enough data for a
1611        * 4-byte ICV.
1612        * Pretend it doesn't have an ICV.
1613        */
1614       ;
1615     } else if (len < reported_len) {
1616       /*
1617        * The packet is claimed to have enough data for a 4-byte ICV,
1618        * but we didn't capture all of the packet.
1619        * Slice off the 4-byte ICV from the reported length, and trim
1620        * the captured length so it's no more than the reported length;
1621        * that will slice off what of the ICV, if any, is in the
1622        * captured length.
1623        *
1624        */
1625       reported_len -= 4;
1626       if (len > reported_len)
1627         len = reported_len;
1628     } else {
1629       /*
1630        * We have the entire packet, and it includes a 4-byte ICV.
1631        * Slice it off, and put it into the tree.
1632        *
1633        * We only support decrypting if we have the the ICV.
1634        *
1635        * XXX - the ICV is encrypted; we're putting the encrypted
1636        * value, not the decrypted value, into the tree.
1637        */
1638       len -= 4;
1639       reported_len -= 4;
1640       can_decrypt = TRUE;
1641     }
1642
1643     if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
1644       /*
1645        * WEP decode impossible or failed, treat payload as raw data
1646        * and don't attempt fragment reassembly or further dissection.
1647        */
1648       next_tvb = tvb_new_subset(tvb, hdr_len + 4, len, reported_len);
1649
1650       if (tree && can_decrypt)
1651         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
1652                                     hdr_len + 4 + len, 4, 
1653                                     tvb_get_ntohl(tvb, hdr_len + 4 + len),
1654                                     "WEP ICV: 0x%08x (not verified)", 
1655                                     tvb_get_ntohl(tvb, hdr_len + 4 + len));
1656
1657       call_dissector(data_handle, next_tvb, pinfo, tree);
1658       return;
1659     } else {
1660
1661       if (tree)
1662         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
1663                                     hdr_len + 4 + len, 4, 
1664                                     tvb_get_ntohl(tvb, hdr_len + 4 + len),
1665                                     "WEP ICV: 0x%08x (correct)", 
1666                                     tvb_get_ntohl(tvb, hdr_len + 4 + len));
1667
1668       add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
1669     }
1670
1671     /*
1672      * WEP decryption successful!
1673      *
1674      * Use the tvbuff we got back from the decryption; the data starts at
1675      * the beginning.  The lengths are already correct for the decoded WEP
1676      * payload.
1677      */
1678     hdr_len = 0;
1679
1680   } else {
1681     /*
1682      * Not a WEP-encrypted frame; just use the data from the tvbuff
1683      * handed to us.
1684      *
1685      * The payload starts at "hdr_len" (i.e., just past the 802.11
1686      * MAC header), the length of data in the tvbuff following the
1687      * 802.11 header is "len", and the length of data in the packet
1688      * following the 802.11 header is "reported_len".
1689      */
1690     next_tvb = tvb;
1691   }
1692
1693   /*
1694    * Do defragmentation if "wlan_defragment" is true, and we have more
1695    * fragments or this isn't the first fragment.
1696    *
1697    * We have to do some special handling to catch frames that
1698    * have the "More Fragments" indicator not set but that
1699    * don't show up as reassembled and don't have any other
1700    * fragments present.  Some networking interfaces appear
1701    * to do reassembly even when you're capturing raw packets
1702    * *and* show the reassembled packet without the "More
1703    * Fragments" indicator set *but* with a non-zero fragment
1704    * number.
1705    *
1706    * "fragment_add_seq_check()" handles that; we want to call it
1707    * even if we have a short frame, so that it does those checks - if
1708    * the frame is short, it doesn't do reassembly on it.
1709    *
1710    * (This could get some false positives if we really *did* only
1711    * capture the last fragment of a fragmented packet, but that's
1712    * life.)
1713    */
1714   save_fragmented = pinfo->fragmented;
1715   if (wlan_defragment && (more_frags || frag_number != 0)) {
1716     fragment_data *fd_head;
1717
1718     /*
1719      * If we've already seen this frame, look it up in the
1720      * table of reassembled packets, otherwise add it to
1721      * whatever reassembly is in progress, if any, and see
1722      * if it's done.
1723      */
1724     fd_head = fragment_add_seq_check(next_tvb, hdr_len, pinfo, seq_number,
1725                                      wlan_fragment_table,
1726                                      wlan_reassembled_table,
1727                                      frag_number,
1728                                      len,
1729                                      more_frags);
1730     if (fd_head != NULL) {
1731       /*
1732        * Either this is reassembled or it wasn't fragmented
1733        * (see comment above about some networking interfaces).
1734        * In either case, it's now in the table of reassembled
1735        * packets.
1736        *
1737        * If the "fragment_data" structure doesn't have a list of
1738        * fragments, we assume it's a placeholder to mark those
1739        * not-really-fragmented packets, and just treat this as
1740        * a non-fragmented frame.
1741        */
1742       if (fd_head->next != NULL) {
1743         next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
1744         tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1745         add_new_data_source(pinfo, next_tvb, "Reassembled 802.11");
1746
1747         /* Show all fragments. */
1748         show_fragment_seq_tree(fd_head, &frag_items, hdr_tree, pinfo, next_tvb);
1749       } else {
1750         /*
1751          * Not fragmented, really.
1752          * Show it as a regular frame.
1753          */
1754         next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1755       }
1756
1757       /* It's not fragmented. */
1758       pinfo->fragmented = FALSE;
1759     } else {
1760       /* We don't have the complete reassembled payload. */
1761       next_tvb = NULL;
1762     }
1763   } else {
1764     /*
1765      * If this is the first fragment, dissect its contents, otherwise
1766      * just show it as a fragment.
1767      */
1768     if (frag_number != 0) {
1769       /* Not the first fragment - don't dissect it. */
1770       next_tvb = NULL;
1771     } else {
1772       /* First fragment, or not fragmented.  Dissect what we have here. */
1773
1774       /* Get a tvbuff for the payload. */
1775       next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1776
1777       /*
1778        * If this is the first fragment, but not the only fragment,
1779        * tell the next protocol that.
1780        */
1781       if (more_frags)
1782         pinfo->fragmented = TRUE;
1783       else
1784         pinfo->fragmented = FALSE;
1785     }
1786   }
1787
1788   if (next_tvb == NULL) {
1789     /* Just show this as an incomplete fragment. */
1790     if (check_col(pinfo->cinfo, COL_INFO))
1791       col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
1792     next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
1793     call_dissector(data_handle, next_tvb, pinfo, tree);
1794     pinfo->fragmented = save_fragmented;
1795     return;
1796   }
1797
1798   switch (COOK_FRAME_TYPE (fcf))
1799     {
1800
1801     case MGT_FRAME:
1802       dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1803       break;
1804
1805
1806     case DATA_FRAME:
1807       /* I guess some bridges take Netware Ethernet_802_3 frames,
1808          which are 802.3 frames (with a length field rather than
1809          a type field, but with no 802.2 header in the payload),
1810          and just stick the payload into an 802.11 frame.  I've seen
1811          captures that show frames of that sort.
1812
1813          This means we have to do the same check for Netware 802.3 -
1814          or, if you will, "Netware 802.11" - that we do in the
1815          Ethernet dissector, i.e. checking for 0xffff as the first
1816          four bytes of the payload and, if we find it, treating it
1817          as an IPX frame. */
1818       is_802_2 = TRUE;
1819       TRY {
1820         if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1821           is_802_2 = FALSE;
1822       }
1823       CATCH2(BoundsError, ReportedBoundsError) {
1824             ; /* do nothing */
1825
1826       }
1827       ENDTRY;
1828
1829       if (is_802_2)
1830         call_dissector(llc_handle, next_tvb, pinfo, tree);
1831       else
1832         call_dissector(ipx_handle, next_tvb, pinfo, tree);
1833       break;
1834     }
1835   pinfo->fragmented = save_fragmented;
1836 }
1837
1838 /*
1839  * Dissect 802.11 with a variable-length link-layer header.
1840  */
1841 static void
1842 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1843 {
1844   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE);
1845 }
1846
1847 /*
1848  * Dissect 802.11 with a variable-length link-layer header and a pseudo-
1849  * header containing radio information.
1850  */
1851 static void
1852 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1853 {
1854   /* These packets do NOT have a FCS present */
1855   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE, TRUE);
1856 }
1857
1858 /*
1859  * Dissect 802.11 with a fixed-length link-layer header (padded to the
1860  * maximum length).
1861  */
1862 static void
1863 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1864 {
1865   dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE);
1866 }
1867
1868 static void
1869 wlan_defragment_init(void)
1870 {
1871   fragment_table_init(&wlan_fragment_table);
1872   reassembled_table_init(&wlan_reassembled_table);
1873 }
1874
1875 void
1876 proto_register_ieee80211 (void)
1877 {
1878   static const value_string frame_type[] = {
1879     {MGT_FRAME,     "Management frame"},
1880     {CONTROL_FRAME, "Control frame"},
1881     {DATA_FRAME,    "Data frame"},
1882     {0,             NULL}
1883   };
1884
1885   static const value_string tofrom_ds[] = {
1886     {0,                       "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
1887     {FLAG_TO_DS,              "Frame is entering DS (To DS: 1  From DS: 0)"},
1888     {FLAG_FROM_DS,            "Frame is exiting DS (To DS: 0  From DS: 1)"},
1889     {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1  From DS: 1)"},
1890     {0, NULL}
1891   };
1892
1893   static const true_false_string tods_flag = {
1894     "Frame is entering DS",
1895     "Frame is not entering DS"
1896   };
1897
1898   static const true_false_string fromds_flag = {
1899     "Frame is exiting DS",
1900     "Frame is not exiting DS"
1901   };
1902
1903   static const true_false_string more_frags = {
1904     "More fragments follow",
1905     "This is the last fragment"
1906   };
1907
1908   static const true_false_string retry_flags = {
1909     "Frame is being retransmitted",
1910     "Frame is not being retransmitted"
1911   };
1912
1913   static const true_false_string pm_flags = {
1914     "STA will go to sleep",
1915     "STA will stay up"
1916   };
1917
1918   static const true_false_string md_flags = {
1919     "Data is buffered for STA at AP",
1920     "No data buffered"
1921   };
1922
1923   static const true_false_string wep_flags = {
1924     "WEP is enabled",
1925     "WEP is disabled"
1926   };
1927
1928   static const true_false_string order_flags = {
1929     "Strictly ordered",
1930     "Not strictly ordered"
1931   };
1932
1933   static const true_false_string cf_ess_flags = {
1934     "Transmitter is an AP",
1935     "Transmitter is a STA"
1936   };
1937
1938
1939   static const true_false_string cf_privacy_flags = {
1940     "AP/STA can support WEP",
1941     "AP/STA cannot support WEP"
1942   };
1943
1944   static const true_false_string cf_preamble_flags = {
1945     "Short preamble allowed",
1946     "Short preamble not allowed"
1947   };
1948
1949   static const true_false_string cf_pbcc_flags = {
1950     "PBCC modulation allowed",
1951     "PBCC modulation not allowed"
1952   };
1953
1954   static const true_false_string cf_agility_flags = {
1955     "Channel agility in use",
1956     "Channel agility not in use"
1957   };
1958
1959
1960   static const true_false_string cf_ibss_flags = {
1961     "Transmitter belongs to an IBSS",
1962     "Transmitter belongs to a BSS"
1963   };
1964
1965   static const value_string sta_cf_pollable[] = {
1966     {0x00, "Station is not CF-Pollable"},
1967     {0x02, "Station is CF-Pollable, "
1968      "not requesting to be placed on the  CF-polling list"},
1969     {0x01, "Station is CF-Pollable, "
1970      "requesting to be placed on the CF-polling list"},
1971     {0x03, "Station is CF-Pollable, requesting never to be polled"},
1972     {0, NULL}
1973   };
1974
1975   static const value_string ap_cf_pollable[] = {
1976     {0x00, "No point coordinator at AP"},
1977     {0x02, "Point coordinator at AP for delivery only (no polling)"},
1978     {0x01, "Point coordinator at AP for delivery and polling"},
1979     {0x03, "Reserved"},
1980     {0, NULL}
1981   };
1982
1983
1984   static const value_string auth_alg[] = {
1985     {0x00, "Open System"},
1986     {0x01, "Shared key"},
1987     {0, NULL}
1988   };
1989
1990   static const value_string reason_codes[] = {
1991     {0x00, "Reserved"},
1992     {0x01, "Unspecified reason"},
1993     {0x02, "Previous authentication no longer valid"},
1994     {0x03, "Deauthenticated because sending STA is leaving (has left) "
1995      "IBSS or ESS"},
1996     {0x04, "Disassociated due to inactivity"},
1997     {0x05, "Disassociated because AP is unable to handle all currently "
1998      "associated stations"},
1999     {0x06, "Class 2 frame received from nonauthenticated station"},
2000     {0x07, "Class 3 frame received from nonassociated station"},
2001     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
2002     {0x09, "Station requesting (re)association is not authenticated with "
2003      "responding station"},
2004     {0x00, NULL}
2005   };
2006
2007
2008   static const value_string status_codes[] = {
2009     {0x00, "Successful"},
2010     {0x01, "Unspecified failure"},
2011     {0x0A, "Cannot support all requested capabilities in the "
2012      "Capability information field"},
2013     {0x0B, "Reassociation denied due to inability to confirm that "
2014      "association exists"},
2015     {0x0C, "Association denied due to reason outside the scope of this "
2016      "standard"},
2017
2018     {0x0D, "Responding station does not support the specified authentication "
2019      "algorithm"},
2020     {0x0E, "Received an Authentication frame with authentication sequence "
2021      "transaction sequence number out of expected sequence"},
2022     {0x0F, "Authentication rejected because of challenge failure"},
2023     {0x10, "Authentication rejected due to timeout waiting for next "
2024      "frame in sequence"},
2025     {0x11, "Association denied because AP is unable to handle additional "
2026      "associated stations"},
2027     {0x12, "Association denied due to requesting station not supporting all "
2028      "of the datarates in the BSSBasicServiceSet Parameter"},
2029     {0x00, NULL}
2030   };
2031
2032   static hf_register_info hf[] = {
2033     {&hf_data_rate,
2034      {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2035       "Data rate (.5 Mb/s units)", HFILL }},
2036
2037     {&hf_channel,
2038      {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2039       "Radio channel", HFILL }},
2040
2041     {&hf_signal_strength,
2042      {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2043       "Signal strength (percentage)", HFILL }},
2044
2045     {&hf_fc_field,
2046      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2047       "MAC Frame control", HFILL }},
2048
2049     {&hf_fc_proto_version,
2050      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2051       "MAC Protocol version", HFILL }}, /* 0 */
2052
2053     {&hf_fc_frame_type,
2054      {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2055       "Frame type", HFILL }},
2056
2057     {&hf_fc_frame_subtype,
2058      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2059       "Frame subtype", HFILL }},        /* 2 */
2060
2061     {&hf_fc_frame_type_subtype,
2062      {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2063       "Type and subtype combined", HFILL }},
2064
2065     {&hf_fc_flags,
2066      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2067       "Protocol flags", HFILL }},
2068
2069     {&hf_fc_data_ds,
2070      {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2071       "Data-frame DS-traversal status", HFILL }},       /* 3 */
2072
2073     {&hf_fc_to_ds,
2074      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2075       "To DS flag", HFILL }},           /* 4 */
2076
2077     {&hf_fc_from_ds,
2078      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2079       "From DS flag", HFILL }},         /* 5 */
2080
2081     {&hf_fc_more_frag,
2082      {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2083       "More Fragments flag", HFILL }},  /* 6 */
2084
2085     {&hf_fc_retry,
2086      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2087       "Retransmission flag", HFILL }},
2088
2089     {&hf_fc_pwr_mgt,
2090      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2091       "Power management status", HFILL }},
2092
2093     {&hf_fc_more_data,
2094      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2095       "More data flag", HFILL }},
2096
2097     {&hf_fc_wep,
2098      {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2099       "WEP flag", HFILL }},
2100
2101     {&hf_fc_order,
2102      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2103       "Strictly ordered flag", HFILL }},
2104
2105     {&hf_assoc_id,
2106      {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2107       "Association-ID field", HFILL }},
2108
2109     {&hf_did_duration,
2110      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2111       "Duration field", HFILL }},
2112
2113     {&hf_addr_da,
2114      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2115       "Destination Hardware Address", HFILL }},
2116
2117     {&hf_addr_sa,
2118      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2119       "Source Hardware Address", HFILL }},
2120
2121     { &hf_addr,
2122       {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2123        "Source or Destination Hardware Address", HFILL }},
2124
2125     {&hf_addr_ra,
2126      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2127       "Receiving Station Hardware Address", HFILL }},
2128
2129     {&hf_addr_ta,
2130      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2131       "Transmitting Station Hardware Address", HFILL }},
2132
2133     {&hf_addr_bssid,
2134      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2135       "Basic Service Set ID", HFILL }},
2136
2137     {&hf_frag_number,
2138      {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2139       "Fragment number", HFILL }},
2140
2141     {&hf_seq_number,
2142      {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2143       "Sequence number", HFILL }},
2144
2145     {&hf_fcs,
2146      {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
2147       NULL, 0, "FCS", HFILL }},
2148
2149     {&hf_fragment_overlap,
2150       {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2151        NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2152
2153     {&hf_fragment_overlap_conflict,
2154       {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2155        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2156        "Overlapping fragments contained conflicting data", HFILL }},
2157
2158     {&hf_fragment_multiple_tails,
2159       {"Multiple tail fragments found", "wlan.fragment.multipletails",
2160        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2161        "Several tails were found when defragmenting the packet", HFILL }},
2162
2163     {&hf_fragment_too_long_fragment,
2164       {"Fragment too long", "wlan.fragment.toolongfragment",
2165        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2166        "Fragment contained data past end of packet", HFILL }},
2167
2168     {&hf_fragment_error,
2169       {"Defragmentation error", "wlan.fragment.error",
2170        FT_NONE, BASE_NONE, NULL, 0x0,
2171        "Defragmentation error due to illegal fragments", HFILL }},
2172
2173     {&hf_fragment,
2174       {"802.11 Fragment", "wlan.fragment", FT_NONE, BASE_NONE, NULL, 0x0,
2175        "802.11 Fragment", HFILL }},
2176
2177     {&hf_fragments,
2178       {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2179        "802.11 Fragments", HFILL }},
2180
2181     {&hf_wep_iv,
2182      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2183       "Initialization Vector", HFILL }},
2184
2185     {&hf_wep_key,
2186      {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
2187       "Key", HFILL }},
2188
2189     {&hf_wep_icv,
2190      {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
2191       "WEP ICV", HFILL }},
2192   };
2193
2194   static hf_register_info ff[] = {
2195     {&ff_timestamp,
2196      {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
2197       NULL, 0, "", HFILL }},
2198
2199     {&ff_auth_alg,
2200      {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
2201       FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
2202
2203     {&ff_beacon_interval,
2204      {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
2205       "", HFILL }},
2206
2207     {&hf_fixed_parameters,
2208      {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
2209       "", HFILL }},
2210
2211     {&hf_tagged_parameters,
2212      {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
2213       "", HFILL }},
2214
2215     {&ff_capture,
2216      {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
2217       "Capability information", HFILL }},
2218
2219     {&ff_cf_sta_poll,
2220      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
2221       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
2222       "CF-Poll capabilities for a STA", HFILL }},
2223
2224     {&ff_cf_ap_poll,
2225      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
2226       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
2227       "CF-Poll capabilities for an AP", HFILL }},
2228
2229     {&ff_cf_ess,
2230      {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
2231       FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
2232
2233
2234     {&ff_cf_ibss,
2235      {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
2236       FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
2237     {&ff_cf_privacy,
2238      {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
2239       FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
2240
2241     {&ff_cf_preamble,
2242      {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
2243       FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
2244
2245     {&ff_cf_pbcc,
2246      {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
2247       FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
2248
2249     {&ff_cf_agility,
2250      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
2251       FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
2252
2253     {&ff_auth_seq,
2254      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
2255       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
2256
2257     {&ff_assoc_id,
2258      {"Association ID", "wlan_mgt.fixed.aid",
2259       FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
2260
2261     {&ff_listen_ival,
2262      {"Listen Interval", "wlan_mgt.fixed.listen_ival",
2263       FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
2264
2265     {&ff_current_ap,
2266      {"Current AP", "wlan_mgt.fixed.current_ap",
2267       FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
2268
2269     {&ff_reason,
2270      {"Reason code", "wlan_mgt.fixed.reason_code",
2271       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
2272       "Reason for unsolicited notification", HFILL }},
2273
2274     {&ff_status_code,
2275      {"Status code", "wlan_mgt.fixed.status_code",
2276       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
2277       "Status of requested event", HFILL }},
2278
2279     {&tag_number,
2280      {"Tag", "wlan_mgt.tag.number",
2281       FT_UINT16, BASE_DEC, NULL, 0,
2282       "Element ID", HFILL }},
2283
2284     {&tag_length,
2285      {"Tag length", "wlan_mgt.tag.length",
2286       FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
2287
2288     {&tag_interpretation,
2289      {"Tag interpretation", "wlan_mgt.tag.interpretation",
2290       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
2291
2292   };
2293
2294   static gint *tree_array[] = {
2295     &ett_80211,
2296     &ett_fc_tree,
2297     &ett_proto_flags,
2298     &ett_fragments,
2299     &ett_fragment,
2300     &ett_80211_mgt,
2301     &ett_fixed_parameters,
2302     &ett_tagged_parameters,
2303     &ett_wep_parameters,
2304     &ett_cap_tree,
2305   };
2306   module_t *wlan_module;
2307
2308   static const enum_val_t wep_keys_options[] = {
2309     {"0", 0},
2310     {"1", 1},
2311     {"2", 2},
2312     {"3", 3},
2313     {"4", 4},
2314     {NULL, -1},
2315   };
2316
2317
2318   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
2319                                         "IEEE 802.11", "wlan");
2320   proto_register_field_array (proto_wlan, hf, array_length (hf));
2321   proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
2322                                         "802.11 MGT", "wlan_mgt");
2323   proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
2324   proto_register_subtree_array (tree_array, array_length (tree_array));
2325
2326   register_dissector("wlan", dissect_ieee80211, proto_wlan);
2327   register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
2328   register_init_routine(wlan_defragment_init);
2329
2330   /* Register configuration options */
2331   wlan_module = prefs_register_protocol(proto_wlan, NULL);
2332   prefs_register_bool_preference(wlan_module, "defragment",
2333         "Reassemble fragmented 802.11 datagrams",
2334         "Whether fragmented 802.11 datagrams should be reassembled",
2335         &wlan_defragment);
2336
2337   prefs_register_bool_preference(wlan_module, "check_fcs",
2338                                  "Assume packets have FCS",
2339                                  "Some 802.11 cards include the FCS at the end of a packet, others do not.",
2340                                  &wlan_check_fcs);
2341
2342   prefs_register_bool_preference(wlan_module, "ignore_wep",
2343                                  "Ignore the WEP bit",
2344                                  "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
2345                                  &wlan_ignore_wep);
2346
2347 #ifndef USE_ENV
2348   prefs_register_enum_preference(wlan_module, "wep_keys",
2349                                  "WEP key count",
2350                                  "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
2351                                  &num_wepkeys, wep_keys_options, FALSE);
2352
2353   prefs_register_string_preference(wlan_module, "wep_key1",
2354                                    "WEP key #1",
2355                                    "First WEP key (A:B:C:D:E:F)",
2356                                    &wep_keystr[0]);
2357   prefs_register_string_preference(wlan_module, "wep_key2",
2358                                    "WEP key #2",
2359                                    "Second WEP key (A:B:C:D:E:F)",
2360                                    &wep_keystr[1]);
2361   prefs_register_string_preference(wlan_module, "wep_key3",
2362                                    "WEP key #3",
2363                                    "Third WEP key (A:B:C:D:E:F)",
2364                                    &wep_keystr[2]);
2365   prefs_register_string_preference(wlan_module, "wep_key4",
2366                                    "WEP key #4",
2367                                    "Fourth WEP key (A:B:C:D:E:F)",
2368                                    &wep_keystr[3]);
2369 #endif
2370 }
2371
2372 void
2373 proto_reg_handoff_ieee80211(void)
2374 {
2375   dissector_handle_t ieee80211_handle;
2376   dissector_handle_t ieee80211_radio_handle;
2377
2378   /*
2379    * Get handles for the LLC and IPX dissectors.
2380    */
2381   llc_handle = find_dissector("llc");
2382   ipx_handle = find_dissector("ipx");
2383   data_handle = find_dissector("data");
2384
2385   ieee80211_handle = find_dissector("wlan");
2386   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
2387   ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
2388                                                    proto_wlan);
2389   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
2390                 ieee80211_radio_handle);
2391 }
2392
2393 static const guint32 wep_crc32_table[256] = {
2394         0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
2395         0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
2396         0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
2397         0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2398         0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
2399         0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
2400         0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
2401         0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2402         0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
2403         0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
2404         0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
2405         0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2406         0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
2407         0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
2408         0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
2409         0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2410         0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
2411         0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
2412         0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
2413         0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2414         0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
2415         0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
2416         0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
2417         0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2418         0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
2419         0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
2420         0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
2421         0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2422         0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
2423         0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
2424         0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
2425         0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2426         0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
2427         0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
2428         0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
2429         0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2430         0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
2431         0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
2432         0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
2433         0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2434         0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
2435         0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
2436         0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
2437         0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2438         0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
2439         0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
2440         0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
2441         0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2442         0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
2443         0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
2444         0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
2445         0x2d02ef8dL
2446 };
2447
2448 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
2449   guint8 *tmp = NULL;
2450   int i;
2451   tvbuff_t *decr_tvb = NULL;
2452
2453   if (num_wepkeys < 1)
2454     return NULL;
2455   if (wep_keylens == NULL)
2456     init_wepkeys();
2457
2458   if ((tmp = g_malloc(len)) == NULL)
2459     return NULL;  /* krap! */
2460
2461   /* try once with the key index in the packet, then look through our list. */
2462   for (i = -1; i < (int) num_wepkeys; i++) {
2463     /* copy the encrypted data over to the tmp buffer */
2464 #if 0
2465     printf("trying %d\n", i);
2466 #endif
2467     tvb_memcpy(tvb, tmp, offset, len);
2468     if (wep_decrypt(tmp, len, i) == 0) {
2469
2470       /* decrypt successful, let's set up a new data tvb. */
2471       decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
2472       tvb_set_free_cb(decr_tvb, g_free);
2473       tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2474
2475       goto done;
2476     }
2477   }
2478
2479  done:
2480   if ((!decr_tvb) && (tmp))    free(tmp);
2481
2482 #if 0
2483   printf("de-wep %p\n", decr_tvb);
2484 #endif
2485
2486   return decr_tvb;
2487 }
2488
2489
2490 /* de-weps the block.  if successful, buf* will point to the data start. */
2491 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
2492   guint32 i, j, k, crc, keylen;
2493   guint8 s[256], key[128], c_crc[4];
2494   guint8 keyidx, *dpos, *cpos;
2495
2496   /* Needs to be at least 8 bytes of payload */
2497   if (len < 8)
2498     return -1;
2499
2500   /* initialize the first bytes of the key from the IV */
2501   key[0] = buf[0];
2502   key[1] = buf[1];
2503   key[2] = buf[2];
2504   keyidx = COOK_WEP_KEY(buf[3]);
2505
2506   if (key_override >= 0)
2507     keyidx = key_override;
2508
2509   if (keyidx >= num_wepkeys)
2510     return -1;
2511
2512   keylen = wep_keylens[keyidx];
2513
2514   if (keylen == 0)
2515     return -1;
2516   if (wep_keys[keyidx] == NULL)
2517     return -1;
2518
2519   keylen+=3;  /* add in ICV bytes */
2520
2521   /* copy the rest of the key over from the designated key */
2522   memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
2523
2524 #if 0
2525   printf("%d: %02x %02x %02x (%d %d) %02x:%02x:%02x:%02x:%02x\n", len, key[0], key[1], key[2], keyidx, keylen, key[3], key[4], key[5], key[6], key[7]);
2526 #endif
2527
2528   /* set up the RC4 state */
2529   for (i = 0; i < 256; i++)
2530     s[i] = i;
2531   j = 0;
2532   for (i = 0; i < 256; i++) {
2533     j = (j + s[i] + key[i % keylen]) & 0xff;
2534     SSWAP(i,j);
2535   }
2536
2537   /* Apply the RC4 to the data, update the CRC32 */
2538   cpos = buf+4;
2539   dpos = buf;
2540   crc = ~0;
2541   i = j = 0;
2542   for (k = 0; k < (len -8); k++) {
2543     i = (i+1) & 0xff;
2544     j = (j+s[i]) & 0xff;
2545     SSWAP(i,j);
2546 #if 0
2547     printf("%d -- %02x ", k, *dpos);
2548 #endif
2549     *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
2550 #if 0
2551     printf("%02x\n", *dpos);
2552 #endif
2553     crc = wep_crc32_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
2554   }
2555   crc = ~crc;
2556
2557   /* now let's check the crc */
2558   c_crc[0] = crc;
2559   c_crc[1] = crc >> 8;
2560   c_crc[2] = crc >> 16;
2561   c_crc[3] = crc >> 24;
2562
2563   for (k = 0; k < 4; k++) {
2564     i = (i + 1) & 0xff;
2565     j = (j+s[i]) & 0xff;
2566     SSWAP(i,j);
2567 #if 0
2568     printf("-- %02x %02x\n", *dpos, c_crc[k]);
2569 #endif
2570     if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
2571       return -1; /* ICV mismatch */
2572   }
2573
2574   return 0;
2575 }
2576
2577 /* XXX need to verify these malloc()s succeed */
2578
2579 static void init_wepkeys(void) {
2580   char *tmp, *tmp2;
2581   guint8 *tmp3;
2582   guint i, j;
2583
2584 #ifdef USE_ENV
2585   guint8 buf[128];
2586
2587   tmp = getenv("ETHEREAL_WEPKEYNUM");
2588   if (!tmp) {
2589     num_wepkeys = 0;
2590     return;
2591   }
2592   num_wepkeys = atoi(tmp);
2593 #else
2594   if (num_wepkeys > 4)
2595     num_wepkeys = 4;
2596 #endif
2597
2598   if (num_wepkeys < 1)
2599     return;
2600
2601   if (wep_keylens != NULL)
2602     return;
2603
2604   wep_keys = malloc(num_wepkeys * sizeof(guint8*));
2605   wep_keylens = malloc(num_wepkeys * sizeof(int));
2606
2607   for (i = 0 ; i < num_wepkeys; i++) {
2608     wep_keys[i] = NULL;
2609     wep_keylens[i] = 0;
2610
2611 #ifdef USE_ENV
2612     sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
2613     tmp = getenv(buf);
2614 #else
2615     tmp = wep_keystr[i];
2616 #endif
2617
2618     if (tmp) {
2619       j = 0;
2620 #if 0
2621 #ifdef USE_ENV
2622       printf("%s -- %s\n", buf, tmp);
2623 #else
2624       printf("%d -- %s\n", i+1, tmp);
2625 #endif
2626 #endif
2627
2628       wep_keys[i] = malloc(32 * sizeof(guint8));
2629       memset(wep_keys[i], 0, 32 * sizeof(guint8));
2630       tmp3 = wep_keys[i];
2631       while ((tmp != NULL) && (*tmp != 0)) {
2632         tmp3[j] = strtoul(tmp, &tmp2, 16) & 0xff;
2633 #if 0
2634         printf("%d %d -- %02x\n", i, j, tmp3[j]);
2635 #endif
2636         tmp = tmp2;
2637         wep_keylens[i]++;
2638
2639         if ((tmp != NULL) && (*tmp == ':'))
2640           tmp++;
2641         j++;
2642       }
2643     }
2644
2645   }
2646
2647   return;
2648 }
2649
2650 static guint32
2651 crc32(const unsigned char* buf, unsigned int len)
2652 {
2653   unsigned int i;
2654   guint32 crc32 = 0xFFFFFFFF, c_crc;
2655
2656   for (i = 0; i < len; i++)
2657     crc32 = wep_crc32_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8);
2658
2659   /* Byte reverse. */
2660   c_crc = ((unsigned char)(crc32>>0)<<24) |
2661     ((unsigned char)(crc32>>8)<<16) |
2662     ((unsigned char)(crc32>>16)<<8) |
2663     ((unsigned char)(crc32>>24)<<0);
2664
2665   return ( ~c_crc );
2666 }