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