Add a "fragment_add_seq_next()" to reassemble fragments that don't have
[obnox/wireshark/wip.git] / packet-ieee80211.c
1 /* packet-ieee80211.c
2  * Routines for Wireless LAN (IEEE 802.11) dissection
3  * Copyright 2000, Axis Communications AB
4  * Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com
5  *
6  * $Id: packet-ieee80211.c,v 1.76 2002/10/24 06:17:34 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
1198       proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1199                               flags);
1200
1201       proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1202
1203       proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1204
1205       proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1206                               flags);
1207
1208       proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1209
1210       proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1211
1212       if (frame_type_subtype == CTRL_PS_POLL)
1213         proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1214                             COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1215
1216       else
1217           proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1218                                tvb_get_letohs (tvb, 2));
1219     }
1220
1221   /*
1222    * Decode the part of the frame header that isn't the same for all
1223    * frame types.
1224    */
1225   seq_control = 0;
1226   frag_number = 0;
1227   seq_number = 0;
1228
1229   switch (COOK_FRAME_TYPE (fcf))
1230     {
1231
1232     case MGT_FRAME:
1233       /*
1234        * All management frame types have the same header.
1235        */
1236       src = tvb_get_ptr (tvb, 10, 6);
1237       dst = tvb_get_ptr (tvb, 4, 6);
1238
1239       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1240       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1241       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1242       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1243
1244       seq_control = tvb_get_letohs(tvb, 22);
1245       frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1246       seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1247
1248       if (tree)
1249         {
1250           proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1251
1252           proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1253
1254           /* add items for wlan.addr filter */
1255           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1256           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1257
1258           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1259                                 tvb_get_ptr (tvb, 16, 6));
1260
1261           proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1262                                frag_number);
1263
1264           proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1265                                seq_number);
1266         }
1267       break;
1268
1269     case CONTROL_FRAME:
1270       switch (frame_type_subtype)
1271         {
1272
1273         case CTRL_PS_POLL:
1274           src = tvb_get_ptr (tvb, 10, 6);
1275           dst = tvb_get_ptr (tvb, 4, 6);
1276
1277           set_src_addr_cols(pinfo, src, "BSSID");
1278           set_dst_addr_cols(pinfo, dst, "BSSID");
1279
1280           if (tree)
1281             {
1282               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1283
1284               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1285             }
1286           break;
1287
1288
1289         case CTRL_RTS:
1290           src = tvb_get_ptr (tvb, 10, 6);
1291           dst = tvb_get_ptr (tvb, 4, 6);
1292
1293           set_src_addr_cols(pinfo, src, "TA");
1294           set_dst_addr_cols(pinfo, dst, "RA");
1295
1296           if (tree)
1297             {
1298               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1299
1300               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1301             }
1302           break;
1303
1304
1305         case CTRL_CTS:
1306           dst = tvb_get_ptr (tvb, 4, 6);
1307
1308           set_dst_addr_cols(pinfo, dst, "RA");
1309
1310           if (tree)
1311             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1312           break;
1313
1314
1315         case CTRL_ACKNOWLEDGEMENT:
1316           dst = tvb_get_ptr (tvb, 4, 6);
1317
1318           set_dst_addr_cols(pinfo, dst, "RA");
1319
1320           if (tree)
1321             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1322           break;
1323
1324
1325         case CTRL_CFP_END:
1326           src = tvb_get_ptr (tvb, 10, 6);
1327           dst = tvb_get_ptr (tvb, 4, 6);
1328
1329           set_src_addr_cols(pinfo, src, "BSSID");
1330           set_dst_addr_cols(pinfo, dst, "RA");
1331
1332           if (tree)
1333             {
1334               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1335               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1336             }
1337           break;
1338
1339
1340         case CTRL_CFP_ENDACK:
1341           src = tvb_get_ptr (tvb, 10, 6);
1342           dst = tvb_get_ptr (tvb, 4, 6);
1343
1344           set_src_addr_cols(pinfo, src, "BSSID");
1345           set_dst_addr_cols(pinfo, dst, "RA");
1346
1347           if (tree)
1348             {
1349               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1350
1351               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1352             }
1353           break;
1354         }
1355       break;
1356
1357     case DATA_FRAME:
1358       addr_type = COOK_ADDR_SELECTOR (fcf);
1359
1360       /* In order to show src/dst address we must always do the following */
1361       switch (addr_type)
1362         {
1363
1364         case DATA_ADDR_T1:
1365           src = tvb_get_ptr (tvb, 10, 6);
1366           dst = tvb_get_ptr (tvb, 4, 6);
1367           break;
1368
1369
1370         case DATA_ADDR_T2:
1371           src = tvb_get_ptr (tvb, 16, 6);
1372           dst = tvb_get_ptr (tvb, 4, 6);
1373           break;
1374
1375
1376         case DATA_ADDR_T3:
1377           src = tvb_get_ptr (tvb, 10, 6);
1378           dst = tvb_get_ptr (tvb, 16, 6);
1379           break;
1380
1381
1382         case DATA_ADDR_T4:
1383           src = tvb_get_ptr (tvb, 24, 6);
1384           dst = tvb_get_ptr (tvb, 16, 6);
1385           break;
1386         }
1387
1388       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1389       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1390       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1391       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1392
1393       seq_control = tvb_get_letohs(tvb, 22);
1394       frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1395       seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1396
1397       /* Now if we have a tree we start adding stuff */
1398       if (tree)
1399         {
1400
1401
1402           switch (addr_type)
1403             {
1404
1405             case DATA_ADDR_T1:
1406               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1407               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1408               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1409                                     tvb_get_ptr (tvb, 16, 6));
1410               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1411                                    frag_number);
1412               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1413                                    seq_number);
1414
1415               /* add items for wlan.addr filter */
1416               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1417               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1418               break;
1419
1420
1421             case DATA_ADDR_T2:
1422               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1423               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1424                                     tvb_get_ptr (tvb, 10, 6));
1425               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1426               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1427                                    frag_number);
1428               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1429                                    seq_number);
1430
1431               /* add items for wlan.addr filter */
1432               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1433               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1434               break;
1435
1436
1437             case DATA_ADDR_T3:
1438               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1439                                     tvb_get_ptr (tvb, 4, 6));
1440               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1441               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1442
1443               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1444                                    frag_number);
1445               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1446                                    seq_number);
1447
1448               /* add items for wlan.addr filter */
1449               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1450               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1451               break;
1452
1453
1454             case DATA_ADDR_T4:
1455               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1456                                     tvb_get_ptr (tvb, 4, 6));
1457               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1458                                     tvb_get_ptr (tvb, 10, 6));
1459               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1460               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1461                                    frag_number);
1462               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1463                                    seq_number);
1464               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1465
1466               /* add items for wlan.addr filter */
1467               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1468               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1469               break;
1470             }
1471
1472         }
1473       break;
1474     }
1475
1476   len = tvb_length_remaining(tvb, hdr_len);
1477   reported_len = tvb_reported_length_remaining(tvb, hdr_len);
1478
1479   if (!has_no_fcs && (wlan_check_fcs))
1480     {
1481       /*
1482        * Well, this packet should, in theory, have an FCS.
1483        * Do we have the entire packet, and does it have enough data for
1484        * the FCS?
1485        */
1486       if (reported_len < 4)
1487         {
1488           /*
1489            * The packet is claimed not to even have enough data for a 4-byte
1490            * FCS.
1491            * Pretend it doesn't have an FCS.
1492            */
1493           ;
1494         }
1495       else if (len < reported_len)
1496         {
1497           /*
1498            * The packet is claimed to have enough data for a 4-byte FCS, but
1499            * we didn't capture all of the packet.
1500            * Slice off the 4-byte FCS from the reported length, and trim the
1501            * captured length so it's no more than the reported length; that
1502            * will slice off what of the FCS, if any, is in the captured
1503            * length.
1504            */
1505           reported_len -= 4;
1506           if (len > reported_len)
1507             len = reported_len;
1508         }
1509       else
1510         {
1511           /*
1512            * We have the entire packet, and it includes a 4-byte FCS.
1513            * Slice it off, and put it into the tree.
1514            */
1515           len -= 4;
1516           reported_len -= 4;
1517           if (tree)
1518             {
1519               guint32 fcs = crc32(tvb_get_ptr(tvb, 0, hdr_len + len), hdr_len + len);
1520               guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
1521               if (fcs == sent_fcs)
1522                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1523                         hdr_len + len, 4, sent_fcs,
1524                         "Frame check sequence: 0x%08x (correct)", sent_fcs);
1525               else
1526                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1527                         hdr_len + len, 4, sent_fcs,
1528                         "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
1529                         sent_fcs, fcs);
1530             }
1531         }
1532     }
1533
1534   /*
1535    * Only management and data frames have a body, so we don't have
1536    * anything more to do for other types of frames.
1537    */
1538   switch (COOK_FRAME_TYPE (fcf))
1539     {
1540
1541     case MGT_FRAME:
1542       break;
1543
1544     case DATA_FRAME:
1545       /*
1546        * No-data frames don't have a body.
1547        */
1548       switch (frame_type_subtype)
1549         {
1550
1551         case DATA_NULL_FUNCTION:
1552         case DATA_CF_ACK_NOD:
1553         case DATA_CF_POLL_NOD:
1554         case DATA_CF_ACK_POLL_NOD:
1555           return;
1556         }
1557         break;
1558
1559     default:
1560       return;
1561     }
1562
1563   if (IS_WEP(COOK_FLAGS(fcf))) {
1564     /*
1565      * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
1566      * the data, if we have a matching key.  Otherwise display it as data.
1567      */
1568     gboolean can_decrypt = FALSE;
1569     proto_tree *wep_tree = NULL;
1570     guint32 iv;
1571     guint8 key;
1572
1573     /*
1574      * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
1575      * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
1576      * them itself.
1577      *
1578      * Also, just pass the data *following* the WEP parameters as the
1579      * buffer to decrypt.
1580      */
1581     iv = tvb_get_letoh24(tvb, hdr_len);
1582     if (tree) {
1583       proto_item *wep_fields;
1584
1585       wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
1586                                            "WEP parameters");
1587
1588       wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
1589       proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
1590     }
1591     key = COOK_WEP_KEY (tvb_get_guint8 (tvb, hdr_len + 3));
1592     if (tree)
1593       proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
1594
1595     /* Subtract out the length of the IV. */
1596     len -= 4;
1597     reported_len -= 4;
1598
1599     /*
1600      * Well, this packet should, in theory, have an ICV.
1601      * Do we have the entire packet, and does it have enough data for
1602      * the ICV?
1603      */
1604     if (reported_len < 4) {
1605       /*
1606        * The packet is claimed not to even have enough data for a
1607        * 4-byte ICV.
1608        * Pretend it doesn't have an ICV.
1609        */
1610       ;
1611     } else if (len < reported_len) {
1612       /*
1613        * The packet is claimed to have enough data for a 4-byte ICV,
1614        * but we didn't capture all of the packet.
1615        * Slice off the 4-byte ICV from the reported length, and trim
1616        * the captured length so it's no more than the reported length;
1617        * that will slice off what of the ICV, if any, is in the
1618        * captured length.
1619        *
1620        */
1621       reported_len -= 4;
1622       if (len > reported_len)
1623         len = reported_len;
1624     } else {
1625       /*
1626        * We have the entire packet, and it includes a 4-byte ICV.
1627        * Slice it off, and put it into the tree.
1628        *
1629        * We only support decrypting if we have the the ICV.
1630        *
1631        * XXX - the ICV is encrypted; we're putting the encrypted
1632        * value, not the decrypted value, into the tree.
1633        */
1634       len -= 4;
1635       reported_len -= 4;
1636       can_decrypt = TRUE;
1637     }
1638
1639     if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
1640       /*
1641        * WEP decode impossible or failed, treat payload as raw data
1642        * and don't attempt fragment reassembly or further dissection.
1643        */
1644       next_tvb = tvb_new_subset(tvb, hdr_len + 4, len, reported_len);
1645
1646       if (tree && can_decrypt)
1647         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
1648                                     hdr_len + 4 + len, 4, 
1649                                     tvb_get_ntohl(tvb, hdr_len + 4 + len),
1650                                     "WEP ICV: 0x%08x (not verified)", 
1651                                     tvb_get_ntohl(tvb, hdr_len + 4 + len));
1652
1653       call_dissector(data_handle, next_tvb, pinfo, tree);
1654       return;
1655     } else {
1656
1657       if (tree)
1658         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
1659                                     hdr_len + 4 + len, 4, 
1660                                     tvb_get_ntohl(tvb, hdr_len + 4 + len),
1661                                     "WEP ICV: 0x%08x (correct)", 
1662                                     tvb_get_ntohl(tvb, hdr_len + 4 + len));
1663
1664       add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
1665     }
1666
1667     /*
1668      * WEP decryption successful!
1669      *
1670      * Use the tvbuff we got back from the decryption; the data starts at
1671      * the beginning.  The lengths are already correct for the decoded WEP
1672      * payload.
1673      */
1674     hdr_len = 0;
1675
1676   } else {
1677     /*
1678      * Not a WEP-encrypted frame; just use the data from the tvbuff
1679      * handed to us.
1680      *
1681      * The payload starts at "hdr_len" (i.e., just past the 802.11
1682      * MAC header), the length of data in the tvbuff following the
1683      * 802.11 header is "len", and the length of data in the packet
1684      * following the 802.11 header is "reported_len".
1685      */
1686     next_tvb = tvb;
1687   }
1688
1689   /*
1690    * Do defragmentation if "wlan_defragment" is true, and we have more
1691    * fragments or this isn't the first fragment.
1692    *
1693    * We have to do some special handling to catch frames that
1694    * have the "More Fragments" indicator not set but that
1695    * don't show up as reassembled and don't have any other
1696    * fragments present.  Some networking interfaces appear
1697    * to do reassembly even when you're capturing raw packets
1698    * *and* show the reassembled packet without the "More
1699    * Fragments" indicator set *but* with a non-zero fragment
1700    * number.
1701    *
1702    * "fragment_add_seq_check()" handles that; we want to call it
1703    * even if we have a short frame, so that it does those checks - if
1704    * the frame is short, it doesn't do reassembly on it.
1705    *
1706    * (This could get some false positives if we really *did* only
1707    * capture the last fragment of a fragmented packet, but that's
1708    * life.)
1709    */
1710   save_fragmented = pinfo->fragmented;
1711   if (wlan_defragment && (more_frags || frag_number != 0)) {
1712     fragment_data *fd_head;
1713
1714     /*
1715      * If we've already seen this frame, look it up in the
1716      * table of reassembled packets, otherwise add it to
1717      * whatever reassembly is in progress, if any, and see
1718      * if it's done.
1719      */
1720     fd_head = fragment_add_seq_check(next_tvb, hdr_len, pinfo, seq_number,
1721                                      wlan_fragment_table,
1722                                      wlan_reassembled_table,
1723                                      frag_number,
1724                                      len,
1725                                      more_frags);
1726     if (fd_head != NULL) {
1727       /*
1728        * Either this is reassembled or it wasn't fragmented
1729        * (see comment above about some networking interfaces).
1730        * In either case, it's now in the table of reassembled
1731        * packets.
1732        *
1733        * If the "fragment_data" structure doesn't have a list of
1734        * fragments, we assume it's a placeholder to mark those
1735        * not-really-fragmented packets, and just treat this as
1736        * a non-fragmented frame.
1737        */
1738       if (fd_head->next != NULL) {
1739         next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
1740         tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1741         add_new_data_source(pinfo, next_tvb, "Reassembled 802.11");
1742
1743         /* Show all fragments. */
1744         show_fragment_seq_tree(fd_head, &frag_items, hdr_tree, pinfo, next_tvb);
1745       } else {
1746         /*
1747          * Not fragmented, really.
1748          * Show it as a regular frame.
1749          */
1750         next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1751       }
1752
1753       /* It's not fragmented. */
1754       pinfo->fragmented = FALSE;
1755     } else {
1756       /* We don't have the complete reassembled payload. */
1757       next_tvb = NULL;
1758     }
1759   } else {
1760     /*
1761      * If this is the first fragment, dissect its contents, otherwise
1762      * just show it as a fragment.
1763      */
1764     if (frag_number != 0) {
1765       /* Not the first fragment - don't dissect it. */
1766       next_tvb = NULL;
1767     } else {
1768       /* First fragment, or not fragmented.  Dissect what we have here. */
1769
1770       /* Get a tvbuff for the payload. */
1771       next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1772
1773       /*
1774        * If this is the first fragment, but not the only fragment,
1775        * tell the next protocol that.
1776        */
1777       if (more_frags)
1778         pinfo->fragmented = TRUE;
1779       else
1780         pinfo->fragmented = FALSE;
1781     }
1782   }
1783
1784   if (next_tvb == NULL) {
1785     /* Just show this as an incomplete fragment. */
1786     if (check_col(pinfo->cinfo, COL_INFO))
1787       col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
1788     next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
1789     call_dissector(data_handle, next_tvb, pinfo, tree);
1790     pinfo->fragmented = save_fragmented;
1791     return;
1792   }
1793
1794   switch (COOK_FRAME_TYPE (fcf))
1795     {
1796
1797     case MGT_FRAME:
1798       dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1799       break;
1800
1801
1802     case DATA_FRAME:
1803       /* I guess some bridges take Netware Ethernet_802_3 frames,
1804          which are 802.3 frames (with a length field rather than
1805          a type field, but with no 802.2 header in the payload),
1806          and just stick the payload into an 802.11 frame.  I've seen
1807          captures that show frames of that sort.
1808
1809          This means we have to do the same check for Netware 802.3 -
1810          or, if you will, "Netware 802.11" - that we do in the
1811          Ethernet dissector, i.e. checking for 0xffff as the first
1812          four bytes of the payload and, if we find it, treating it
1813          as an IPX frame. */
1814       is_802_2 = TRUE;
1815       TRY {
1816         if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1817           is_802_2 = FALSE;
1818       }
1819       CATCH2(BoundsError, ReportedBoundsError) {
1820             ; /* do nothing */
1821
1822       }
1823       ENDTRY;
1824
1825       if (is_802_2)
1826         call_dissector(llc_handle, next_tvb, pinfo, tree);
1827       else
1828         call_dissector(ipx_handle, next_tvb, pinfo, tree);
1829       break;
1830     }
1831   pinfo->fragmented = save_fragmented;
1832 }
1833
1834 /*
1835  * Dissect 802.11 with a variable-length link-layer header.
1836  */
1837 static void
1838 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1839 {
1840   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE);
1841 }
1842
1843 /*
1844  * Dissect 802.11 with a variable-length link-layer header and a pseudo-
1845  * header containing radio information.
1846  */
1847 static void
1848 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1849 {
1850   /* These packets do NOT have a FCS present */
1851   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE, TRUE);
1852 }
1853
1854 /*
1855  * Dissect 802.11 with a fixed-length link-layer header (padded to the
1856  * maximum length).
1857  */
1858 static void
1859 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1860 {
1861   dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE);
1862 }
1863
1864 static void
1865 wlan_defragment_init(void)
1866 {
1867   fragment_table_init(&wlan_fragment_table);
1868   reassembled_table_init(&wlan_reassembled_table);
1869 }
1870
1871 void
1872 proto_register_wlan (void)
1873 {
1874   static const value_string frame_type[] = {
1875     {MGT_FRAME,     "Management frame"},
1876     {CONTROL_FRAME, "Control frame"},
1877     {DATA_FRAME,    "Data frame"},
1878     {0,             NULL}
1879   };
1880
1881   static const value_string tofrom_ds[] = {
1882     {0,                       "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
1883     {FLAG_TO_DS,              "Frame is entering DS (To DS: 1  From DS: 0)"},
1884     {FLAG_FROM_DS,            "Frame is exiting DS (To DS: 0  From DS: 1)"},
1885     {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1  From DS: 1)"},
1886     {0, NULL}
1887   };
1888
1889   static const true_false_string tods_flag = {
1890     "TO DS: Should be false",
1891     "Not used"
1892   };
1893
1894   static const true_false_string fromds_flag = {
1895     "FROM DS: Should be false",
1896     "Not used"
1897   };
1898
1899   static const true_false_string more_frags = {
1900     "More fragments follow",
1901     "This is the last fragment"
1902   };
1903
1904   static const true_false_string retry_flags = {
1905     "Frame is being retransmitted",
1906     "Frame is not being retransmitted"
1907   };
1908
1909   static const true_false_string pm_flags = {
1910     "STA will go to sleep",
1911     "STA will stay up"
1912   };
1913
1914   static const true_false_string md_flags = {
1915     "Data is buffered for STA at AP",
1916     "No data buffered"
1917   };
1918
1919   static const true_false_string wep_flags = {
1920     "WEP is enabled",
1921     "WEP is disabled"
1922   };
1923
1924   static const true_false_string order_flags = {
1925     "Strictly ordered",
1926     "Not strictly ordered"
1927   };
1928
1929   static const true_false_string cf_ess_flags = {
1930     "Transmitter is an AP",
1931     "Transmitter is a STA"
1932   };
1933
1934
1935   static const true_false_string cf_privacy_flags = {
1936     "AP/STA can support WEP",
1937     "AP/STA cannot support WEP"
1938   };
1939
1940   static const true_false_string cf_preamble_flags = {
1941     "Short preamble allowed",
1942     "Short preamble not allowed"
1943   };
1944
1945   static const true_false_string cf_pbcc_flags = {
1946     "PBCC modulation allowed",
1947     "PBCC modulation not allowed"
1948   };
1949
1950   static const true_false_string cf_agility_flags = {
1951     "Channel agility in use",
1952     "Channel agility not in use"
1953   };
1954
1955
1956   static const true_false_string cf_ibss_flags = {
1957     "Transmitter belongs to an IBSS",
1958     "Transmitter belongs to a BSS"
1959   };
1960
1961   static const value_string sta_cf_pollable[] = {
1962     {0x00, "Station is not CF-Pollable"},
1963     {0x02, "Station is CF-Pollable, "
1964      "not requesting to be placed on the  CF-polling list"},
1965     {0x01, "Station is CF-Pollable, "
1966      "requesting to be placed on the CF-polling list"},
1967     {0x03, "Station is CF-Pollable, requesting never to be polled"},
1968     {0, NULL}
1969   };
1970
1971   static const value_string ap_cf_pollable[] = {
1972     {0x00, "No point coordinator at AP"},
1973     {0x02, "Point coordinator at AP for delivery only (no polling)"},
1974     {0x01, "Point coordinator at AP for delivery and polling"},
1975     {0x03, "Reserved"},
1976     {0, NULL}
1977   };
1978
1979
1980   static const value_string auth_alg[] = {
1981     {0x00, "Open System"},
1982     {0x01, "Shared key"},
1983     {0, NULL}
1984   };
1985
1986   static const value_string reason_codes[] = {
1987     {0x00, "Reserved"},
1988     {0x01, "Unspecified reason"},
1989     {0x02, "Previous authentication no longer valid"},
1990     {0x03, "Deauthenticated because sending STA is leaving (has left) "
1991      "IBSS or ESS"},
1992     {0x04, "Disassociated due to inactivity"},
1993     {0x05, "Disassociated because AP is unable to handle all currently "
1994      "associated stations"},
1995     {0x06, "Class 2 frame received from nonauthenticated station"},
1996     {0x07, "Class 3 frame received from nonassociated station"},
1997     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1998     {0x09, "Station requesting (re)association is not authenticated with "
1999      "responding station"},
2000     {0x00, NULL}
2001   };
2002
2003
2004   static const value_string status_codes[] = {
2005     {0x00, "Successful"},
2006     {0x01, "Unspecified failure"},
2007     {0x0A, "Cannot support all requested capabilities in the "
2008      "Capability information field"},
2009     {0x0B, "Reassociation denied due to inability to confirm that "
2010      "association exists"},
2011     {0x0C, "Association denied due to reason outside the scope of this "
2012      "standard"},
2013
2014     {0x0D, "Responding station does not support the specified authentication "
2015      "algorithm"},
2016     {0x0E, "Received an Authentication frame with authentication sequence "
2017      "transaction sequence number out of expected sequence"},
2018     {0x0F, "Authentication rejected because of challenge failure"},
2019     {0x10, "Authentication rejected due to timeout waiting for next "
2020      "frame in sequence"},
2021     {0x11, "Association denied because AP is unable to handle additional "
2022      "associated stations"},
2023     {0x12, "Association denied due to requesting station not supporting all "
2024      "of the datarates in the BSSBasicServiceSet Parameter"},
2025     {0x00, NULL}
2026   };
2027
2028   static hf_register_info hf[] = {
2029     {&hf_data_rate,
2030      {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2031       "Data rate (.5 Mb/s units)", HFILL }},
2032
2033     {&hf_channel,
2034      {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2035       "Radio channel", HFILL }},
2036
2037     {&hf_signal_strength,
2038      {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2039       "Signal strength (percentage)", HFILL }},
2040
2041     {&hf_fc_field,
2042      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2043       "MAC Frame control", HFILL }},
2044
2045     {&hf_fc_proto_version,
2046      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2047       "MAC Protocol version", HFILL }}, /* 0 */
2048
2049     {&hf_fc_frame_type,
2050      {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2051       "Frame type", HFILL }},
2052
2053     {&hf_fc_frame_subtype,
2054      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2055       "Frame subtype", HFILL }},        /* 2 */
2056
2057     {&hf_fc_frame_type_subtype,
2058      {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2059       "Type and subtype combined", HFILL }},
2060
2061     {&hf_fc_flags,
2062      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2063       "Protocol flags", HFILL }},
2064
2065     {&hf_fc_data_ds,
2066      {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2067       "Data-frame DS-traversal status", HFILL }},       /* 3 */
2068
2069     {&hf_fc_to_ds,
2070      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2071       "To DS flag", HFILL }},           /* 4 */
2072
2073     {&hf_fc_from_ds,
2074      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2075       "From DS flag", HFILL }},         /* 5 */
2076
2077     {&hf_fc_more_frag,
2078      {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2079       "More Fragments flag", HFILL }},  /* 6 */
2080
2081     {&hf_fc_retry,
2082      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2083       "Retransmission flag", HFILL }},
2084
2085     {&hf_fc_pwr_mgt,
2086      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2087       "Power management status", HFILL }},
2088
2089     {&hf_fc_more_data,
2090      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2091       "More data flag", HFILL }},
2092
2093     {&hf_fc_wep,
2094      {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2095       "WEP flag", HFILL }},
2096
2097     {&hf_fc_order,
2098      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2099       "Strictly ordered flag", HFILL }},
2100
2101     {&hf_assoc_id,
2102      {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2103       "Association-ID field", HFILL }},
2104
2105     {&hf_did_duration,
2106      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2107       "Duration field", HFILL }},
2108
2109     {&hf_addr_da,
2110      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2111       "Destination Hardware Address", HFILL }},
2112
2113     {&hf_addr_sa,
2114      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2115       "Source Hardware Address", HFILL }},
2116
2117     { &hf_addr,
2118       {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2119        "Source or Destination Hardware Address", HFILL }},
2120
2121     {&hf_addr_ra,
2122      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2123       "Receiving Station Hardware Address", HFILL }},
2124
2125     {&hf_addr_ta,
2126      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2127       "Transmitting Station Hardware Address", HFILL }},
2128
2129     {&hf_addr_bssid,
2130      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2131       "Basic Service Set ID", HFILL }},
2132
2133     {&hf_frag_number,
2134      {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2135       "Fragment number", HFILL }},
2136
2137     {&hf_seq_number,
2138      {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2139       "Sequence number", HFILL }},
2140
2141     {&hf_fcs,
2142      {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
2143       NULL, 0, "FCS", HFILL }},
2144
2145     {&hf_fragment_overlap,
2146       {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2147        NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2148
2149     {&hf_fragment_overlap_conflict,
2150       {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2151        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2152        "Overlapping fragments contained conflicting data", HFILL }},
2153
2154     {&hf_fragment_multiple_tails,
2155       {"Multiple tail fragments found", "wlan.fragment.multipletails",
2156        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2157        "Several tails were found when defragmenting the packet", HFILL }},
2158
2159     {&hf_fragment_too_long_fragment,
2160       {"Fragment too long", "wlan.fragment.toolongfragment",
2161        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2162        "Fragment contained data past end of packet", HFILL }},
2163
2164     {&hf_fragment_error,
2165       {"Defragmentation error", "wlan.fragment.error",
2166        FT_NONE, BASE_NONE, NULL, 0x0,
2167        "Defragmentation error due to illegal fragments", HFILL }},
2168
2169     {&hf_fragment,
2170       {"802.11 Fragment", "wlan.fragment", FT_NONE, BASE_NONE, NULL, 0x0,
2171        "802.11 Fragment", HFILL }},
2172
2173     {&hf_fragments,
2174       {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2175        "802.11 Fragments", HFILL }},
2176
2177     {&hf_wep_iv,
2178      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2179       "Initialization Vector", HFILL }},
2180
2181     {&hf_wep_key,
2182      {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
2183       "Key", HFILL }},
2184
2185     {&hf_wep_icv,
2186      {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
2187       "WEP ICV", HFILL }},
2188   };
2189
2190   static hf_register_info ff[] = {
2191     {&ff_timestamp,
2192      {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
2193       NULL, 0, "", HFILL }},
2194
2195     {&ff_auth_alg,
2196      {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
2197       FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
2198
2199     {&ff_beacon_interval,
2200      {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
2201       "", HFILL }},
2202
2203     {&hf_fixed_parameters,
2204      {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
2205       "", HFILL }},
2206
2207     {&hf_tagged_parameters,
2208      {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
2209       "", HFILL }},
2210
2211     {&ff_capture,
2212      {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
2213       "Capability information", HFILL }},
2214
2215     {&ff_cf_sta_poll,
2216      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
2217       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
2218       "CF-Poll capabilities for a STA", HFILL }},
2219
2220     {&ff_cf_ap_poll,
2221      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
2222       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
2223       "CF-Poll capabilities for an AP", HFILL }},
2224
2225     {&ff_cf_ess,
2226      {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
2227       FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
2228
2229
2230     {&ff_cf_ibss,
2231      {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
2232       FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
2233     {&ff_cf_privacy,
2234      {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
2235       FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
2236
2237     {&ff_cf_preamble,
2238      {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
2239       FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
2240
2241     {&ff_cf_pbcc,
2242      {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
2243       FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
2244
2245     {&ff_cf_agility,
2246      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
2247       FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
2248
2249     {&ff_auth_seq,
2250      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
2251       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
2252
2253     {&ff_assoc_id,
2254      {"Association ID", "wlan_mgt.fixed.aid",
2255       FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
2256
2257     {&ff_listen_ival,
2258      {"Listen Interval", "wlan_mgt.fixed.listen_ival",
2259       FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
2260
2261     {&ff_current_ap,
2262      {"Current AP", "wlan_mgt.fixed.current_ap",
2263       FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
2264
2265     {&ff_reason,
2266      {"Reason code", "wlan_mgt.fixed.reason_code",
2267       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
2268       "Reason for unsolicited notification", HFILL }},
2269
2270     {&ff_status_code,
2271      {"Status code", "wlan_mgt.fixed.status_code",
2272       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
2273       "Status of requested event", HFILL }},
2274
2275     {&tag_number,
2276      {"Tag", "wlan_mgt.tag.number",
2277       FT_UINT16, BASE_DEC, NULL, 0,
2278       "Element ID", HFILL }},
2279
2280     {&tag_length,
2281      {"Tag length", "wlan_mgt.tag.length",
2282       FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
2283
2284     {&tag_interpretation,
2285      {"Tag interpretation", "wlan_mgt.tag.interpretation",
2286       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
2287
2288   };
2289
2290   static gint *tree_array[] = {
2291     &ett_80211,
2292     &ett_fc_tree,
2293     &ett_proto_flags,
2294     &ett_fragments,
2295     &ett_fragment,
2296     &ett_80211_mgt,
2297     &ett_fixed_parameters,
2298     &ett_tagged_parameters,
2299     &ett_wep_parameters,
2300     &ett_cap_tree,
2301   };
2302   module_t *wlan_module;
2303
2304   static const enum_val_t wep_keys_options[] = {
2305     {"0", 0},
2306     {"1", 1},
2307     {"2", 2},
2308     {"3", 3},
2309     {"4", 4},
2310     {NULL, -1},
2311   };
2312
2313
2314   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
2315                                         "IEEE 802.11", "wlan");
2316   proto_register_field_array (proto_wlan, hf, array_length (hf));
2317   proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
2318                                         "802.11 MGT", "wlan_mgt");
2319   proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
2320   proto_register_subtree_array (tree_array, array_length (tree_array));
2321
2322   register_dissector("wlan", dissect_ieee80211, proto_wlan);
2323   register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
2324   register_init_routine(wlan_defragment_init);
2325
2326   /* Register configuration options */
2327   wlan_module = prefs_register_protocol(proto_wlan, NULL);
2328   prefs_register_bool_preference(wlan_module, "defragment",
2329         "Reassemble fragmented 802.11 datagrams",
2330         "Whether fragmented 802.11 datagrams should be reassembled",
2331         &wlan_defragment);
2332
2333   prefs_register_bool_preference(wlan_module, "check_fcs",
2334                                  "Assume packets have FCS",
2335                                  "Some 802.11 cards include the FCS at the end of a packet, others do not.",
2336                                  &wlan_check_fcs);
2337
2338   prefs_register_bool_preference(wlan_module, "ignore_wep",
2339                                  "Ignore the WEP bit",
2340                                  "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
2341                                  &wlan_ignore_wep);
2342
2343 #ifndef USE_ENV
2344   prefs_register_enum_preference(wlan_module, "wep_keys",
2345                                  "WEP key count",
2346                                  "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
2347                                  &num_wepkeys, wep_keys_options, FALSE);
2348
2349   prefs_register_string_preference(wlan_module, "wep_key1",
2350                                    "WEP key #1",
2351                                    "First WEP key (A:B:C:D:E:F)",
2352                                    &wep_keystr[0]);
2353   prefs_register_string_preference(wlan_module, "wep_key2",
2354                                    "WEP key #2",
2355                                    "Second WEP key (A:B:C:D:E:F)",
2356                                    &wep_keystr[1]);
2357   prefs_register_string_preference(wlan_module, "wep_key3",
2358                                    "WEP key #3",
2359                                    "Third WEP key (A:B:C:D:E:F)",
2360                                    &wep_keystr[2]);
2361   prefs_register_string_preference(wlan_module, "wep_key4",
2362                                    "WEP key #4",
2363                                    "Fourth WEP key (A:B:C:D:E:F)",
2364                                    &wep_keystr[3]);
2365 #endif
2366 }
2367
2368 void
2369 proto_reg_handoff_wlan(void)
2370 {
2371   dissector_handle_t ieee80211_handle;
2372   dissector_handle_t ieee80211_radio_handle;
2373
2374   /*
2375    * Get handles for the LLC and IPX dissectors.
2376    */
2377   llc_handle = find_dissector("llc");
2378   ipx_handle = find_dissector("ipx");
2379   data_handle = find_dissector("data");
2380
2381   ieee80211_handle = find_dissector("wlan");
2382   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
2383   ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
2384                                                    proto_wlan);
2385   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
2386                 ieee80211_radio_handle);
2387 }
2388
2389 static const guint32 wep_crc32_table[256] = {
2390         0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
2391         0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
2392         0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
2393         0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2394         0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
2395         0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
2396         0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
2397         0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2398         0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
2399         0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
2400         0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
2401         0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2402         0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
2403         0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
2404         0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
2405         0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2406         0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
2407         0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
2408         0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
2409         0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2410         0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
2411         0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
2412         0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
2413         0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2414         0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
2415         0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
2416         0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
2417         0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2418         0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
2419         0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
2420         0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
2421         0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2422         0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
2423         0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
2424         0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
2425         0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2426         0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
2427         0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
2428         0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
2429         0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2430         0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
2431         0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
2432         0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
2433         0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2434         0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
2435         0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
2436         0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
2437         0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2438         0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
2439         0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
2440         0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
2441         0x2d02ef8dL
2442 };
2443
2444 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
2445   guint8 *tmp = NULL;
2446   int i;
2447   tvbuff_t *decr_tvb = NULL;
2448
2449   if (num_wepkeys < 1)
2450     return NULL;
2451   if (wep_keylens == NULL)
2452     init_wepkeys();
2453
2454   if ((tmp = g_malloc(len)) == NULL)
2455     return NULL;  /* krap! */
2456
2457   /* try once with the key index in the packet, then look through our list. */
2458   for (i = -1; i < (int) num_wepkeys; i++) {
2459     /* copy the encrypted data over to the tmp buffer */
2460 #if 0
2461     printf("trying %d\n", i);
2462 #endif
2463     tvb_memcpy(tvb, tmp, offset, len);
2464     if (wep_decrypt(tmp, len, i) == 0) {
2465
2466       /* decrypt successful, let's set up a new data tvb. */
2467       decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
2468       tvb_set_free_cb(decr_tvb, g_free);
2469       tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2470
2471       goto done;
2472     }
2473   }
2474
2475  done:
2476   if ((!decr_tvb) && (tmp))    free(tmp);
2477
2478 #if 0
2479   printf("de-wep %p\n", decr_tvb);
2480 #endif
2481
2482   return decr_tvb;
2483 }
2484
2485
2486 /* de-weps the block.  if successful, buf* will point to the data start. */
2487 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
2488   guint32 i, j, k, crc, keylen;
2489   guint8 s[256], key[128], c_crc[4];
2490   guint8 keyidx, *dpos, *cpos;
2491
2492   /* Needs to be at least 8 bytes of payload */
2493   if (len < 8)
2494     return -1;
2495
2496   /* initialize the first bytes of the key from the IV */
2497   key[0] = buf[0];
2498   key[1] = buf[1];
2499   key[2] = buf[2];
2500   keyidx = COOK_WEP_KEY(buf[3]);
2501
2502   if (key_override >= 0)
2503     keyidx = key_override;
2504
2505   if (keyidx >= num_wepkeys)
2506     return -1;
2507
2508   keylen = wep_keylens[keyidx];
2509
2510   if (keylen == 0)
2511     return -1;
2512   if (wep_keys[keyidx] == NULL)
2513     return -1;
2514
2515   keylen+=3;  /* add in ICV bytes */
2516
2517   /* copy the rest of the key over from the designated key */
2518   memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
2519
2520 #if 0
2521   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]);
2522 #endif
2523
2524   /* set up the RC4 state */
2525   for (i = 0; i < 256; i++)
2526     s[i] = i;
2527   j = 0;
2528   for (i = 0; i < 256; i++) {
2529     j = (j + s[i] + key[i % keylen]) & 0xff;
2530     SSWAP(i,j);
2531   }
2532
2533   /* Apply the RC4 to the data, update the CRC32 */
2534   cpos = buf+4;
2535   dpos = buf;
2536   crc = ~0;
2537   i = j = 0;
2538   for (k = 0; k < (len -8); k++) {
2539     i = (i+1) & 0xff;
2540     j = (j+s[i]) & 0xff;
2541     SSWAP(i,j);
2542 #if 0
2543     printf("%d -- %02x ", k, *dpos);
2544 #endif
2545     *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
2546 #if 0
2547     printf("%02x\n", *dpos);
2548 #endif
2549     crc = wep_crc32_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
2550   }
2551   crc = ~crc;
2552
2553   /* now let's check the crc */
2554   c_crc[0] = crc;
2555   c_crc[1] = crc >> 8;
2556   c_crc[2] = crc >> 16;
2557   c_crc[3] = crc >> 24;
2558
2559   for (k = 0; k < 4; k++) {
2560     i = (i + 1) & 0xff;
2561     j = (j+s[i]) & 0xff;
2562     SSWAP(i,j);
2563 #if 0
2564     printf("-- %02x %02x\n", *dpos, c_crc[k]);
2565 #endif
2566     if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
2567       return -1; /* ICV mismatch */
2568   }
2569
2570   return 0;
2571 }
2572
2573 /* XXX need to verify these malloc()s succeed */
2574
2575 static void init_wepkeys(void) {
2576   char *tmp, *tmp2;
2577   guint8 *tmp3;
2578   guint i, j;
2579
2580 #ifdef USE_ENV
2581   guint8 buf[128];
2582
2583   tmp = getenv("ETHEREAL_WEPKEYNUM");
2584   if (!tmp) {
2585     num_wepkeys = 0;
2586     return;
2587   }
2588   num_wepkeys = atoi(tmp);
2589 #else
2590   if (num_wepkeys > 4)
2591     num_wepkeys = 4;
2592 #endif
2593
2594   if (num_wepkeys < 1)
2595     return;
2596
2597   if (wep_keylens != NULL)
2598     return;
2599
2600   wep_keys = malloc(num_wepkeys * sizeof(guint8*));
2601   wep_keylens = malloc(num_wepkeys * sizeof(int));
2602
2603   for (i = 0 ; i < num_wepkeys; i++) {
2604     wep_keys[i] = NULL;
2605     wep_keylens[i] = 0;
2606
2607 #ifdef USE_ENV
2608     sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
2609     tmp = getenv(buf);
2610 #else
2611     tmp = wep_keystr[i];
2612 #endif
2613
2614     if (tmp) {
2615       j = 0;
2616 #if 0
2617 #ifdef USE_ENV
2618       printf("%s -- %s\n", buf, tmp);
2619 #else
2620       printf("%d -- %s\n", i+1, tmp);
2621 #endif
2622 #endif
2623
2624       wep_keys[i] = malloc(32 * sizeof(guint8));
2625       memset(wep_keys[i], 0, 32 * sizeof(guint8));
2626       tmp3 = wep_keys[i];
2627       while ((tmp != NULL) && (*tmp != 0)) {
2628         tmp3[j] = strtoul(tmp, &tmp2, 16) & 0xff;
2629 #if 0
2630         printf("%d %d -- %02x\n", i, j, tmp3[j]);
2631 #endif
2632         tmp = tmp2;
2633         wep_keylens[i]++;
2634
2635         if ((tmp != NULL) && (*tmp == ':'))
2636           tmp++;
2637         j++;
2638       }
2639     }
2640
2641   }
2642
2643   return;
2644 }
2645
2646 static guint32
2647 crc32(const unsigned char* buf, unsigned int len)
2648 {
2649   unsigned int i;
2650   guint32 crc32 = 0xFFFFFFFF, c_crc;
2651
2652   for (i = 0; i < len; i++)
2653     crc32 = wep_crc32_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8);
2654
2655   /* Byte reverse. */
2656   c_crc = ((unsigned char)(crc32>>0)<<24) |
2657     ((unsigned char)(crc32>>8)<<16) |
2658     ((unsigned char)(crc32>>16)<<8) |
2659     ((unsigned char)(crc32>>24)<<0);
2660
2661   return ( ~c_crc );
2662 }