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