Add in some missing header files.
[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.70 2002/06/22 23:11:36 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from README.developer
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  *
28  * Credits:
29  * 
30  * The following people helped me by pointing out bugs etc. Thank you!
31  *
32  * Marco Molteni
33  * Lena-Marie Nilsson     
34  * Magnus Hultman-Persson
35  */
36
37 #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     guint32 iv;
1569     guint8 key;
1570
1571     /*
1572      * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
1573      * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
1574      * them itself.
1575      *
1576      * Also, just pass the data *following* the WEP parameters as the
1577      * buffer to decrypt.
1578      */
1579     iv = tvb_get_letoh24(tvb, hdr_len);
1580     if (tree) {
1581       proto_item *wep_fields;
1582
1583       wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
1584                                            "WEP parameters");
1585
1586       wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
1587       proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
1588     }
1589     key = COOK_WEP_KEY (tvb_get_guint8 (tvb, hdr_len + 3));
1590     if (tree)
1591       proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
1592
1593     /* Subtract out the length of the IV. */
1594     len -= 4;
1595     reported_len -= 4;
1596
1597     /*
1598      * Well, this packet should, in theory, have an ICV.
1599      * Do we have the entire packet, and does it have enough data for
1600      * the ICV?
1601      */
1602     if (reported_len < 4) {
1603       /*
1604        * The packet is claimed not to even have enough data for a
1605        * 4-byte ICV.
1606        * Pretend it doesn't have an ICV.
1607        */
1608       ;
1609     } else if (len < reported_len) {
1610       /*
1611        * The packet is claimed to have enough data for a 4-byte ICV,
1612        * but we didn't capture all of the packet.
1613        * Slice off the 4-byte ICV from the reported length, and trim
1614        * the captured length so it's no more than the reported length;
1615        * that will slice off what of the ICV, if any, is in the
1616        * captured length.
1617        *
1618        */
1619       reported_len -= 4;
1620       if (len > reported_len)
1621         len = reported_len;
1622     } else {
1623       /*
1624        * We have the entire packet, and it includes a 4-byte ICV.
1625        * Slice it off, and put it into the tree.
1626        *
1627        * We only support decrypting if we have the the ICV.
1628        *
1629        * XXX - the ICV is encrypted; we're putting the encrypted
1630        * value, not the decrypted value, into the tree.
1631        */
1632       len -= 4;
1633       reported_len -= 4;
1634       if (tree)
1635         proto_tree_add_item (wep_tree, hf_wep_icv, tvb, hdr_len + 4 + len, 4,
1636                              FALSE);
1637       can_decrypt = TRUE;
1638     }
1639
1640     if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
1641       /*
1642        * WEP decode impossible or failed, treat payload as raw data
1643        * and don't attempt fragment reassembly or further dissection.
1644        */
1645       next_tvb = tvb_new_subset(tvb, hdr_len + 4, len, reported_len);
1646
1647       call_dissector(data_handle, next_tvb, pinfo, tree);
1648       return; 
1649     } else {
1650       add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
1651     }
1652
1653     /*
1654      * WEP decryption successful!
1655      *
1656      * Use the tvbuff we got back from the decryption; the data starts at
1657      * the beginning.  The lengths are already correct for the decoded WEP
1658      * payload.
1659      */
1660     hdr_len = 0;
1661
1662   } else {
1663     /*
1664      * Not a WEP-encrypted frame; just use the data from the tvbuff
1665      * handed to us.
1666      *
1667      * The payload starts at "hdr_len" (i.e., just past the 802.11
1668      * MAC header), the length of data in the tvbuff following the
1669      * 802.11 header is "len", and the length of data in the packet
1670      * following the 802.11 header is "reported_len".
1671      */
1672     next_tvb = tvb;
1673   }
1674
1675   /*
1676    * Do defragmentation if "wlan_defragment" is true, and we have more
1677    * fragments or this isn't the first fragment.
1678    *
1679    * We have to do some special handling to catch frames that
1680    * have the "More Fragments" indicator not set but that
1681    * don't show up as reassembled and don't have any other
1682    * fragments present.  Some networking interfaces appear
1683    * to do reassembly even when you're capturing raw packets
1684    * *and* show the reassembled packet without the "More
1685    * Fragments" indicator set *but* with a non-zero fragment
1686    * number.
1687    *
1688    * "fragment_add_seq_check()" handles that; we want to call it
1689    * even if we have a short frame, so that it does those checks - if
1690    * the frame is short, it doesn't do reassembly on it.
1691    *
1692    * (This could get some false positives if we really *did* only
1693    * capture the last fragment of a fragmented packet, but that's
1694    * life.)
1695    */
1696   save_fragmented = pinfo->fragmented;
1697   if (wlan_defragment && (more_frags || frag_number != 0)) {
1698     fragment_data *fd_head;
1699
1700     /*
1701      * If we've already seen this frame, look it up in the
1702      * table of reassembled packets, otherwise add it to
1703      * whatever reassembly is in progress, if any, and see
1704      * if it's done.
1705      */
1706     fd_head = fragment_add_seq_check(next_tvb, hdr_len, pinfo, seq_number,
1707                                      wlan_fragment_table,
1708                                      wlan_reassembled_table,
1709                                      frag_number,
1710                                      len,
1711                                      more_frags);
1712     if (fd_head != NULL) {
1713       /*
1714        * Either this is reassembled or it wasn't fragmented
1715        * (see comment above about some networking interfaces).
1716        * In either case, it's now in the table of reassembled
1717        * packets.
1718        *
1719        * If the "fragment_data" structure doesn't have a list of
1720        * fragments, we assume it's a placeholder to mark those
1721        * not-really-fragmented packets, and just treat this as
1722        * a non-fragmented frame.
1723        */
1724       if (fd_head->next != NULL) {
1725         next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
1726         tvb_set_child_real_data_tvbuff(tvb, next_tvb);
1727         add_new_data_source(pinfo, next_tvb, "Reassembled 802.11");
1728
1729         /* Show all fragments. */
1730         show_fragment_seq_tree(fd_head, &frag_items, hdr_tree, pinfo, next_tvb);
1731       } else {
1732         /*
1733          * Not fragmented, really.
1734          * Show it as a regular frame.
1735          */
1736         next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1737       }
1738
1739       /* It's not fragmented. */
1740       pinfo->fragmented = FALSE;
1741     } else {
1742       /* We don't have the complete reassembled payload. */
1743       next_tvb = NULL;
1744     }
1745   } else {
1746     /*
1747      * If this is the first fragment, dissect its contents, otherwise
1748      * just show it as a fragment.
1749      */
1750     if (frag_number != 0) {
1751       /* Not the first fragment - don't dissect it. */
1752       next_tvb = NULL;
1753     } else {
1754       /* First fragment, or not fragmented.  Dissect what we have here. */
1755
1756       /* Get a tvbuff for the payload. */
1757       next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1758
1759       /*
1760        * If this is the first fragment, but not the only fragment,
1761        * tell the next protocol that.
1762        */
1763       if (more_frags)
1764         pinfo->fragmented = TRUE;
1765       else
1766         pinfo->fragmented = FALSE;
1767     }
1768   }
1769
1770   if (next_tvb == NULL) {
1771     /* Just show this as an incomplete fragment. */
1772     if (check_col(pinfo->cinfo, COL_INFO))
1773       col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
1774     next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
1775     call_dissector(data_handle, next_tvb, pinfo, tree);
1776     pinfo->fragmented = save_fragmented;
1777     return;
1778   }  
1779   
1780   switch (COOK_FRAME_TYPE (fcf))
1781     {
1782
1783     case MGT_FRAME:
1784       dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1785       break;
1786
1787
1788     case DATA_FRAME:
1789       /* I guess some bridges take Netware Ethernet_802_3 frames,
1790          which are 802.3 frames (with a length field rather than
1791          a type field, but with no 802.2 header in the payload),
1792          and just stick the payload into an 802.11 frame.  I've seen
1793          captures that show frames of that sort.
1794
1795          This means we have to do the same check for Netware 802.3 -
1796          or, if you will, "Netware 802.11" - that we do in the
1797          Ethernet dissector, i.e. checking for 0xffff as the first
1798          four bytes of the payload and, if we find it, treating it
1799          as an IPX frame. */
1800       is_802_2 = TRUE;
1801       TRY {
1802         if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1803           is_802_2 = FALSE;
1804       }
1805       CATCH2(BoundsError, ReportedBoundsError) {
1806             ; /* do nothing */
1807
1808       }
1809       ENDTRY;
1810
1811       if (is_802_2)
1812         call_dissector(llc_handle, next_tvb, pinfo, tree);
1813       else
1814         call_dissector(ipx_handle, next_tvb, pinfo, tree);
1815       break;
1816     }
1817   pinfo->fragmented = save_fragmented;
1818 }
1819
1820 /*
1821  * Dissect 802.11 with a variable-length link-layer header.
1822  */
1823 static void
1824 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1825 {
1826   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE);
1827 }
1828
1829 /*
1830  * Dissect 802.11 with a variable-length link-layer header and a pseudo-
1831  * header containing radio information.
1832  */
1833 static void
1834 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1835 {
1836   /* These packets do NOT have a FCS present */
1837   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE, TRUE);
1838 }
1839
1840 /*
1841  * Dissect 802.11 with a fixed-length link-layer header (padded to the
1842  * maximum length).
1843  */
1844 static void
1845 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1846 {
1847   dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE);
1848 }
1849
1850 static void
1851 wlan_defragment_init(void)
1852 {
1853   fragment_table_init(&wlan_fragment_table);
1854   reassembled_table_init(&wlan_reassembled_table);
1855 }
1856
1857 void
1858 proto_register_wlan (void)
1859 {
1860   static const value_string frame_type[] = {
1861     {MGT_FRAME,     "Management frame"},
1862     {CONTROL_FRAME, "Control frame"},
1863     {DATA_FRAME,    "Data frame"},
1864     {0,             NULL}
1865   };
1866
1867   static const value_string tofrom_ds[] = {
1868     {0,                       "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
1869     {FLAG_TO_DS,              "Frame is entering DS (To DS: 1  From DS: 0)"},
1870     {FLAG_FROM_DS,            "Frame is exiting DS (To DS: 0  From DS: 1)"},
1871     {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1  From DS: 1)"},
1872     {0, NULL}
1873   };
1874
1875   static const true_false_string tods_flag = {
1876     "TO DS: Should be false",
1877     "Not used"
1878   };
1879
1880   static const true_false_string fromds_flag = {
1881     "FROM DS: Should be false",
1882     "Not used"
1883   };
1884
1885   static const true_false_string more_frags = {
1886     "More fragments follow",
1887     "This is the last fragment"
1888   };
1889
1890   static const true_false_string retry_flags = {
1891     "Frame is being retransmitted",
1892     "Frame is not being retransmitted"
1893   };
1894
1895   static const true_false_string pm_flags = {
1896     "STA will go to sleep",
1897     "STA will stay up"
1898   };
1899
1900   static const true_false_string md_flags = {
1901     "Data is buffered for STA at AP",
1902     "No data buffered"
1903   };
1904
1905   static const true_false_string wep_flags = {
1906     "WEP is enabled",
1907     "WEP is disabled"
1908   };
1909
1910   static const true_false_string order_flags = {
1911     "Strictly ordered",
1912     "Not strictly ordered"
1913   };
1914
1915   static const true_false_string cf_ess_flags = {
1916     "Transmitter is an AP",
1917     "Transmitter is a STA"
1918   };
1919
1920
1921   static const true_false_string cf_privacy_flags = {
1922     "AP/STA can support WEP",
1923     "AP/STA cannot support WEP"
1924   };
1925
1926   static const true_false_string cf_preamble_flags = {
1927     "Short preamble allowed",
1928     "Short preamble not allowed"
1929   };
1930
1931   static const true_false_string cf_pbcc_flags = {
1932     "PBCC modulation allowed",
1933     "PBCC modulation not allowed"
1934   };
1935
1936   static const true_false_string cf_agility_flags = {
1937     "Channel agility in use",
1938     "Channel agility not in use"
1939   };
1940
1941
1942   static const true_false_string cf_ibss_flags = {
1943     "Transmitter belongs to an IBSS",
1944     "Transmitter belongs to a BSS"
1945   };
1946
1947   static const value_string sta_cf_pollable[] = {
1948     {0x00, "Station is not CF-Pollable"},
1949     {0x02, "Station is CF-Pollable, "
1950      "not requesting to be placed on the  CF-polling list"},
1951     {0x01, "Station is CF-Pollable, "
1952      "requesting to be placed on the CF-polling list"},
1953     {0x03, "Station is CF-Pollable, requesting never to be polled"},
1954     {0, NULL}
1955   };
1956
1957   static const value_string ap_cf_pollable[] = {
1958     {0x00, "No point coordinator at AP"},
1959     {0x02, "Point coordinator at AP for delivery only (no polling)"},
1960     {0x01, "Point coordinator at AP for delivery and polling"},
1961     {0x03, "Reserved"},
1962     {0, NULL}
1963   };
1964
1965
1966   static const value_string auth_alg[] = {
1967     {0x00, "Open System"},
1968     {0x01, "Shared key"},
1969     {0, NULL}
1970   };
1971
1972   static const value_string reason_codes[] = {
1973     {0x00, "Reserved"},
1974     {0x01, "Unspecified reason"},
1975     {0x02, "Previous authentication no longer valid"},
1976     {0x03, "Deauthenticated because sending STA is leaving (has left) "
1977      "IBSS or ESS"},
1978     {0x04, "Disassociated due to inactivity"},
1979     {0x05, "Disassociated because AP is unable to handle all currently "
1980      "associated stations"},
1981     {0x06, "Class 2 frame received from nonauthenticated station"},
1982     {0x07, "Class 3 frame received from nonassociated station"},
1983     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1984     {0x09, "Station requesting (re)association is not authenticated with "
1985      "responding station"},
1986     {0x00, NULL}
1987   };
1988
1989
1990   static const value_string status_codes[] = {
1991     {0x00, "Successful"},
1992     {0x01, "Unspecified failure"},
1993     {0x0A, "Cannot support all requested capabilities in the "
1994      "Capability information field"},
1995     {0x0B, "Reassociation denied due to inability to confirm that "
1996      "association exists"},
1997     {0x0C, "Association denied due to reason outside the scope of this "
1998      "standard"},
1999
2000     {0x0D, "Responding station does not support the specified authentication "
2001      "algorithm"},
2002     {0x0E, "Received an Authentication frame with authentication sequence "
2003      "transaction sequence number out of expected sequence"},
2004     {0x0F, "Authentication rejected because of challenge failure"},
2005     {0x10, "Authentication rejected due to timeout waiting for next "
2006      "frame in sequence"},
2007     {0x11, "Association denied because AP is unable to handle additional "
2008      "associated stations"},
2009     {0x12, "Association denied due to requesting station not supporting all "
2010      "of the datarates in the BSSBasicServiceSet Parameter"},
2011     {0x00, NULL}
2012   };
2013
2014   static hf_register_info hf[] = {
2015     {&hf_data_rate,
2016      {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2017       "Data rate (.5 Mb/s units)", HFILL }},
2018
2019     {&hf_channel,
2020      {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2021       "Radio channel", HFILL }},
2022
2023     {&hf_signal_strength,
2024      {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2025       "Signal strength (percentage)", HFILL }},
2026
2027     {&hf_fc_field,
2028      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2029       "MAC Frame control", HFILL }},
2030
2031     {&hf_fc_proto_version,
2032      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2033       "MAC Protocol version", HFILL }}, /* 0 */
2034
2035     {&hf_fc_frame_type,
2036      {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2037       "Frame type", HFILL }},
2038
2039     {&hf_fc_frame_subtype,
2040      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2041       "Frame subtype", HFILL }},        /* 2 */
2042
2043     {&hf_fc_frame_type_subtype,
2044      {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2045       "Type and subtype combined", HFILL }},
2046
2047     {&hf_fc_flags,
2048      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2049       "Protocol flags", HFILL }},
2050
2051     {&hf_fc_data_ds,
2052      {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2053       "Data-frame DS-traversal status", HFILL }},       /* 3 */
2054
2055     {&hf_fc_to_ds,
2056      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2057       "To DS flag", HFILL }},           /* 4 */
2058
2059     {&hf_fc_from_ds,
2060      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2061       "From DS flag", HFILL }},         /* 5 */
2062
2063     {&hf_fc_more_frag,
2064      {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2065       "More Fragments flag", HFILL }},  /* 6 */
2066
2067     {&hf_fc_retry,
2068      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2069       "Retransmission flag", HFILL }},
2070
2071     {&hf_fc_pwr_mgt,
2072      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2073       "Power management status", HFILL }},
2074
2075     {&hf_fc_more_data,
2076      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2077       "More data flag", HFILL }},
2078
2079     {&hf_fc_wep,
2080      {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2081       "WEP flag", HFILL }},
2082
2083     {&hf_fc_order,
2084      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2085       "Strictly ordered flag", HFILL }},
2086
2087     {&hf_assoc_id,
2088      {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2089       "Association-ID field", HFILL }},
2090
2091     {&hf_did_duration,
2092      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2093       "Duration field", HFILL }},
2094
2095     {&hf_addr_da,
2096      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2097       "Destination Hardware Address", HFILL }},
2098
2099     {&hf_addr_sa,
2100      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2101       "Source Hardware Address", HFILL }},
2102
2103     { &hf_addr,
2104       {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2105        "Source or Destination Hardware Address", HFILL }},
2106
2107     {&hf_addr_ra,
2108      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2109       "Receiving Station Hardware Address", HFILL }},
2110
2111     {&hf_addr_ta,
2112      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2113       "Transmitting Station Hardware Address", HFILL }},
2114
2115     {&hf_addr_bssid,
2116      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2117       "Basic Service Set ID", HFILL }},
2118
2119     {&hf_frag_number,
2120      {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2121       "Fragment number", HFILL }},
2122
2123     {&hf_seq_number,
2124      {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2125       "Sequence number", HFILL }},
2126
2127     {&hf_fcs,
2128      {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
2129       NULL, 0, "FCS", HFILL }},
2130
2131     {&hf_fragment_overlap,
2132       {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2133        NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2134
2135     {&hf_fragment_overlap_conflict,
2136       {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2137        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2138        "Overlapping fragments contained conflicting data", HFILL }},
2139
2140     {&hf_fragment_multiple_tails,
2141       {"Multiple tail fragments found", "wlan.fragment.multipletails",
2142        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2143        "Several tails were found when defragmenting the packet", HFILL }},
2144
2145     {&hf_fragment_too_long_fragment,
2146       {"Fragment too long", "wlan.fragment.toolongfragment",
2147        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2148        "Fragment contained data past end of packet", HFILL }},
2149
2150     {&hf_fragment_error,
2151       {"Defragmentation error", "wlan.fragment.error",
2152        FT_NONE, BASE_NONE, NULL, 0x0,
2153        "Defragmentation error due to illegal fragments", HFILL }},
2154
2155     {&hf_fragment,
2156       {"802.11 Fragment", "wlan.fragment", FT_NONE, BASE_NONE, NULL, 0x0,
2157        "802.11 Fragment", HFILL }},
2158
2159     {&hf_fragments,
2160       {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2161        "802.11 Fragments", HFILL }},
2162
2163     {&hf_wep_iv,
2164      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2165       "Initialization Vector", HFILL }},
2166
2167     {&hf_wep_key,
2168      {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
2169       "Key", HFILL }},
2170
2171     {&hf_wep_icv,
2172      {"WEP ICV (not verified)", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
2173       "WEP ICV", HFILL }},
2174   };
2175
2176   static hf_register_info ff[] = {
2177     {&ff_timestamp,
2178      {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
2179       NULL, 0, "", HFILL }},
2180
2181     {&ff_auth_alg,
2182      {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
2183       FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
2184
2185     {&ff_beacon_interval,
2186      {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
2187       "", HFILL }},
2188
2189     {&hf_fixed_parameters,
2190      {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
2191       "", HFILL }},
2192
2193     {&hf_tagged_parameters,
2194      {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
2195       "", HFILL }},
2196
2197     {&ff_capture,
2198      {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
2199       "Capability information", HFILL }},
2200
2201     {&ff_cf_sta_poll,
2202      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
2203       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
2204       "CF-Poll capabilities for a STA", HFILL }},
2205
2206     {&ff_cf_ap_poll,
2207      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
2208       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
2209       "CF-Poll capabilities for an AP", HFILL }},
2210
2211     {&ff_cf_ess,
2212      {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
2213       FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
2214
2215
2216     {&ff_cf_ibss,
2217      {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
2218       FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
2219     {&ff_cf_privacy,
2220      {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
2221       FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
2222
2223     {&ff_cf_preamble,
2224      {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
2225       FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
2226
2227     {&ff_cf_pbcc,
2228      {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
2229       FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
2230
2231     {&ff_cf_agility,
2232      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
2233       FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
2234
2235     {&ff_auth_seq,
2236      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
2237       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
2238
2239     {&ff_assoc_id,
2240      {"Association ID", "wlan_mgt.fixed.aid",
2241       FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
2242
2243     {&ff_listen_ival,
2244      {"Listen Interval", "wlan_mgt.fixed.listen_ival",
2245       FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
2246
2247     {&ff_current_ap,
2248      {"Current AP", "wlan_mgt.fixed.current_ap",
2249       FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
2250
2251     {&ff_reason,
2252      {"Reason code", "wlan_mgt.fixed.reason_code",
2253       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
2254       "Reason for unsolicited notification", HFILL }},
2255
2256     {&ff_status_code,
2257      {"Status code", "wlan_mgt.fixed.status_code",
2258       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
2259       "Status of requested event", HFILL }},
2260
2261     {&tag_number,
2262      {"Tag", "wlan_mgt.tag.number",
2263       FT_UINT16, BASE_DEC, NULL, 0,
2264       "Element ID", HFILL }},
2265
2266     {&tag_length,
2267      {"Tag length", "wlan_mgt.tag.length",
2268       FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
2269
2270     {&tag_interpretation,
2271      {"Tag interpretation", "wlan_mgt.tag.interpretation",
2272       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
2273
2274   };
2275
2276   static gint *tree_array[] = {
2277     &ett_80211,
2278     &ett_fc_tree,
2279     &ett_proto_flags,
2280     &ett_fragments,
2281     &ett_fragment,
2282     &ett_80211_mgt,
2283     &ett_fixed_parameters,
2284     &ett_tagged_parameters,
2285     &ett_wep_parameters,
2286     &ett_cap_tree,
2287   };
2288   module_t *wlan_module;
2289
2290   static const enum_val_t wep_keys_options[] = {
2291     {"0", 0},
2292     {"1", 1},
2293     {"2", 2},
2294     {"3", 3},
2295     {"4", 4},
2296     {NULL, -1},
2297   };
2298
2299
2300   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
2301                                         "IEEE 802.11", "wlan");
2302   proto_register_field_array (proto_wlan, hf, array_length (hf));
2303   proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
2304                                         "802.11 MGT", "wlan_mgt");
2305   proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
2306   proto_register_subtree_array (tree_array, array_length (tree_array));
2307
2308   register_dissector("wlan", dissect_ieee80211, proto_wlan);
2309   register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
2310   register_init_routine(wlan_defragment_init);
2311
2312   /* Register configuration options */
2313   wlan_module = prefs_register_protocol(proto_wlan, NULL);
2314   prefs_register_bool_preference(wlan_module, "defragment",
2315         "Reassemble fragmented 802.11 datagrams",
2316         "Whether fragmented 802.11 datagrams should be reassembled",
2317         &wlan_defragment);
2318
2319   prefs_register_bool_preference(wlan_module, "check_fcs",
2320                                  "Assume packets have FCS",
2321                                  "Some 802.11 cards include the FCS at the end of a packet, others do not.",
2322                                  &wlan_check_fcs);
2323
2324   prefs_register_bool_preference(wlan_module, "ignore_wep",
2325                                  "Ignore the WEP bit",
2326                                  "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
2327                                  &wlan_ignore_wep);
2328
2329 #ifndef USE_ENV
2330   prefs_register_enum_preference(wlan_module, "wep_keys", 
2331                                  "WEP key count",
2332                                  "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
2333                                  &num_wepkeys, wep_keys_options, FALSE);
2334
2335   prefs_register_string_preference(wlan_module, "wep_key1",
2336                                    "WEP key #1",
2337                                    "First WEP key (A:B:C:D:E:F)",
2338                                    &wep_keystr[0]);
2339   prefs_register_string_preference(wlan_module, "wep_key2",
2340                                    "WEP key #2",
2341                                    "Second WEP key (A:B:C:D:E:F)",
2342                                    &wep_keystr[1]);
2343   prefs_register_string_preference(wlan_module, "wep_key3",
2344                                    "WEP key #3",
2345                                    "Third WEP key (A:B:C:D:E:F)",
2346                                    &wep_keystr[2]);
2347   prefs_register_string_preference(wlan_module, "wep_key4",
2348                                    "WEP key #4",
2349                                    "Fourth WEP key (A:B:C:D:E:F)",
2350                                    &wep_keystr[3]);
2351 #endif
2352 }
2353
2354 void
2355 proto_reg_handoff_wlan(void)
2356 {
2357   dissector_handle_t ieee80211_handle;
2358   dissector_handle_t ieee80211_radio_handle;
2359
2360   /*
2361    * Get handles for the LLC and IPX dissectors.
2362    */
2363   llc_handle = find_dissector("llc");
2364   ipx_handle = find_dissector("ipx");
2365   data_handle = find_dissector("data");
2366
2367   ieee80211_handle = find_dissector("wlan");
2368   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
2369   ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
2370                                                    proto_wlan);
2371   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
2372                 ieee80211_radio_handle);
2373 }
2374
2375 static const guint32 wep_crc32_table[256] = {
2376         0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
2377         0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
2378         0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
2379         0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2380         0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
2381         0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
2382         0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
2383         0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2384         0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
2385         0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
2386         0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
2387         0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2388         0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
2389         0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
2390         0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
2391         0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2392         0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
2393         0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
2394         0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
2395         0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2396         0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
2397         0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
2398         0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
2399         0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2400         0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
2401         0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
2402         0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
2403         0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2404         0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
2405         0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
2406         0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
2407         0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2408         0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
2409         0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
2410         0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
2411         0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2412         0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
2413         0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
2414         0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
2415         0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2416         0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
2417         0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
2418         0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
2419         0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2420         0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
2421         0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
2422         0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
2423         0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2424         0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
2425         0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
2426         0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
2427         0x2d02ef8dL
2428 };
2429
2430 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
2431   guint8 *tmp = NULL;
2432   int i;
2433   tvbuff_t *decr_tvb = NULL;
2434
2435   if (num_wepkeys < 1)
2436     return NULL;
2437   if (wep_keylens == NULL)
2438     init_wepkeys();
2439
2440   if ((tmp = g_malloc(len)) == NULL)
2441     return NULL;  /* krap! */
2442   
2443   /* try once with the key index in the packet, then look through our list. */
2444   for (i = -1; i < (int) num_wepkeys; i++) {
2445     /* copy the encrypted data over to the tmp buffer */
2446 #if 0
2447     printf("trying %d\n", i);
2448 #endif
2449     tvb_memcpy(tvb, tmp, offset, len);
2450     if (wep_decrypt(tmp, len, i) == 0) {
2451
2452       /* decrypt successful, let's set up a new data tvb. */
2453       decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
2454       tvb_set_free_cb(decr_tvb, g_free);
2455       tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2456
2457       goto done;
2458     }
2459   }
2460
2461  done:
2462   if ((!decr_tvb) && (tmp))    free(tmp);
2463
2464 #if 0
2465   printf("de-wep %p\n", decr_tvb);
2466 #endif 
2467
2468   return decr_tvb;
2469 }
2470
2471
2472 /* de-weps the block.  if successful, buf* will point to the data start. */
2473 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
2474   guint32 i, j, k, crc, keylen;
2475   guint8 s[256], key[128], c_crc[4];
2476   guint8 keyidx, *dpos, *cpos;
2477
2478   /* Needs to be at least 8 bytes of payload */
2479   if (len < 8)
2480     return -1;
2481
2482   /* initialize the first bytes of the key from the IV */
2483   key[0] = buf[0];
2484   key[1] = buf[1];
2485   key[2] = buf[2];
2486   keyidx = COOK_WEP_KEY(buf[3]);
2487
2488   if (key_override >= 0)
2489     keyidx = key_override;
2490
2491   if (keyidx >= num_wepkeys)
2492     return -1;
2493
2494   keylen = wep_keylens[keyidx];
2495
2496   if (keylen == 0)
2497     return -1;
2498   if (wep_keys[keyidx] == NULL)
2499     return -1;
2500
2501   keylen+=3;  /* add in ICV bytes */
2502
2503   /* copy the rest of the key over from the designated key */
2504   memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
2505
2506 #if 0
2507   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]);
2508 #endif
2509
2510   /* set up the RC4 state */
2511   for (i = 0; i < 256; i++)
2512     s[i] = i;
2513   j = 0;
2514   for (i = 0; i < 256; i++) {
2515     j = (j + s[i] + key[i % keylen]) & 0xff;
2516     SSWAP(i,j);
2517   }
2518
2519   /* Apply the RC4 to the data, update the CRC32 */
2520   cpos = buf+4;
2521   dpos = buf;
2522   crc = ~0;
2523   i = j = 0;
2524   for (k = 0; k < (len -8); k++) {
2525     i = (i+1) & 0xff;
2526     j = (j+s[i]) & 0xff;
2527     SSWAP(i,j);
2528 #if 0
2529     printf("%d -- %02x ", k, *dpos);
2530 #endif
2531     *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
2532 #if 0
2533     printf("%02x\n", *dpos);
2534 #endif
2535     crc = wep_crc32_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
2536   }
2537   crc = ~crc;
2538
2539   /* now let's check the crc */
2540   c_crc[0] = crc;
2541   c_crc[1] = crc >> 8;
2542   c_crc[2] = crc >> 16;
2543   c_crc[3] = crc >> 24;
2544   
2545   for (k = 0; k < 4; k++) {
2546     i = (i + 1) & 0xff;
2547     j = (j+s[i]) & 0xff;
2548     SSWAP(i,j);
2549 #if 0
2550     printf("-- %02x %02x\n", *dpos, c_crc[k]);
2551 #endif
2552     if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
2553       return -1; /* ICV mismatch */
2554   }
2555
2556   return 0;
2557 }
2558
2559 /* XXX need to verify these malloc()s succeed */
2560
2561 static void init_wepkeys(void) {
2562   char *tmp, *tmp2;
2563   guint8 *tmp3;
2564   guint i, j;
2565
2566 #ifdef USE_ENV
2567   guint8 buf[128];
2568
2569   tmp = getenv("ETHEREAL_WEPKEYNUM");
2570   if (!tmp) {
2571     num_wepkeys = 0;
2572     return;
2573   }
2574   num_wepkeys = atoi(tmp);
2575 #else
2576   if (num_wepkeys > 4)
2577     num_wepkeys = 4;
2578 #endif
2579
2580   if (num_wepkeys < 1)
2581     return;
2582
2583   if (wep_keylens != NULL)
2584     return;
2585
2586   wep_keys = malloc(num_wepkeys * sizeof(guint8*));
2587   wep_keylens = malloc(num_wepkeys * sizeof(int));
2588
2589   for (i = 0 ; i < num_wepkeys; i++) {
2590     wep_keys[i] = NULL;
2591     wep_keylens[i] = 0;
2592
2593 #ifdef USE_ENV
2594     sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
2595     tmp = getenv(buf);
2596 #else
2597     tmp = wep_keystr[i];
2598 #endif
2599
2600     if (tmp) {
2601       j = 0;
2602 #if 0
2603 #ifdef USE_ENV
2604       printf("%s -- %s\n", buf, tmp);
2605 #else
2606       printf("%d -- %s\n", i+1, tmp);
2607 #endif
2608 #endif
2609
2610       wep_keys[i] = malloc(32 * sizeof(guint8));
2611       memset(wep_keys[i], 0, 32 * sizeof(guint8));
2612       tmp3 = wep_keys[i];
2613       while ((tmp != NULL) && (*tmp != 0)) {
2614         tmp3[j] = strtoul(tmp, &tmp2, 16) & 0xff;
2615 #if 0
2616         printf("%d %d -- %02x\n", i, j, tmp3[j]);
2617 #endif
2618         tmp = tmp2;
2619         wep_keylens[i]++;
2620
2621         if ((tmp != NULL) && (*tmp == ':'))
2622           tmp++;
2623         j++;
2624       }
2625     }
2626     
2627   }
2628
2629   return;
2630 }