Set the svn:eol-style property on all text files to "native", so that
[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$
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 /*
38  * 09/12/2003 - Added dissection of country information tag
39  *
40  * Ritchie<at>tipsybottle.com
41  *
42  * 03/22/2004 - Added dissection of RSN IE
43  * Jouni Malinen <jkmaline@cc.hut.fi>
44  */
45
46 #ifdef HAVE_CONFIG_H
47 # include "config.h"
48 #endif
49
50 #include <stdio.h>
51 #include <stdlib.h>
52
53 #ifdef NEED_SNPRINTF_H
54 # include "snprintf.h"
55 #endif
56
57 #include <string.h>
58 #include <glib.h>
59 #include <epan/bitswap.h>
60 #include <epan/proto.h>
61 #include <epan/packet.h>
62 #include <epan/resolv.h>
63 #include <epan/strutil.h>
64 #include "prefs.h"
65 #include "reassemble.h"
66 #include "packet-ipx.h"
67 #include "packet-llc.h"
68 #include "packet-ieee80211.h"
69 #include "etypes.h"
70 #include "crc32.h"
71
72 /* Defragment fragmented 802.11 datagrams */
73 static gboolean wlan_defragment = TRUE;
74
75 /* Check for the presence of the 802.11 FCS */
76 static gboolean wlan_check_fcs = FALSE;
77
78 /* Ignore the WEP bit; assume packet is decrypted */
79 static gboolean wlan_ignore_wep = FALSE;
80
81 /* Tables for reassembly of fragments. */
82 static GHashTable *wlan_fragment_table = NULL;
83 static GHashTable *wlan_reassembled_table = NULL;
84
85 /* Stuff for the WEP decoder */
86 static guint num_wepkeys = 0;
87 static guint8 **wep_keys = NULL;
88 static int *wep_keylens = NULL;
89 static void init_wepkeys(void);
90 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
91 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
92 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
93
94 /* #define USE_ENV */
95 /* When this is set, an unlimited number of WEP keys can be set in the
96    environment:
97
98    ETHEREAL_WEPKEYNUM=##
99    ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
100    ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
101
102    ... you get the idea.
103
104    otherwise you're limited to specifying four keys in the preference system.
105  */
106
107 #ifndef USE_ENV
108 static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
109 #endif
110
111 /* ************************************************************************* */
112 /*                          Miscellaneous Constants                          */
113 /* ************************************************************************* */
114 #define SHORT_STR 256
115
116 /* ************************************************************************* */
117 /*  Define some very useful macros that are used to analyze frame types etc. */
118 /* ************************************************************************* */
119 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4))      /* Create key to (sub)type */
120 #define COOK_PROT_VERSION(x)  ((x) & 0x3)
121 #define COOK_FRAME_TYPE(x)    (((x) & 0xC) >> 2)
122 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
123 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
124 #define COOK_ASSOC_ID(x)      ((x) & 0x3FFF)
125 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
126 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
127 #define COOK_QOS_PRIORITY(x)    ((x) & 0x0007)
128 #define COOK_QOS_ACK_POLICY(x)  (((x) & 0x0060) >> 5)
129 #define COOK_FLAGS(x)           (((x) & 0xFF00) >> 8)
130 #define COOK_DS_STATUS(x)       ((x) & 0x3)
131 #define COOK_WEP_KEY(x)       (((x) & 0xC0) >> 6)
132
133 #define KEY_EXTIV               0x20
134 #define EXTIV_LEN               8
135
136 #define FLAG_TO_DS              0x01
137 #define FLAG_FROM_DS            0x02
138 #define FLAG_MORE_FRAGMENTS     0x04
139 #define FLAG_RETRY              0x08
140 #define FLAG_POWER_MGT          0x10
141 #define FLAG_MORE_DATA          0x20
142 #define FLAG_WEP                0x40
143 #define FLAG_ORDER              0x80
144
145 #define IS_TO_DS(x)            ((x) & FLAG_TO_DS)
146 #define IS_FROM_DS(x)          ((x) & FLAG_FROM_DS)
147 #define HAVE_FRAGMENTS(x)      ((x) & FLAG_MORE_FRAGMENTS)
148 #define IS_RETRY(x)            ((x) & FLAG_RETRY)
149 #define POWER_MGT_STATUS(x)    ((x) & FLAG_POWER_MGT)
150 #define HAS_MORE_DATA(x)       ((x) & FLAG_MORE_DATA)
151 #define IS_WEP(x)              (!wlan_ignore_wep && ((x) & FLAG_WEP))
152 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
153
154 #define MGT_RESERVED_RANGE(x)  (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
155 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
156 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
157 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
158
159
160 /* ************************************************************************* */
161 /*              Constants used to identify cooked frame types                */
162 /* ************************************************************************* */
163 #define MGT_FRAME            0x00       /* Frame type is management */
164 #define CONTROL_FRAME        0x01       /* Frame type is control */
165 #define DATA_FRAME           0x02       /* Frame type is Data */
166
167 #define DATA_SHORT_HDR_LEN     24
168 #define DATA_LONG_HDR_LEN      30
169 #define MGT_FRAME_HDR_LEN      24       /* Length of Managment frame-headers */
170
171 #define MGT_ASSOC_REQ        0x00       /* Management - association request        */
172 #define MGT_ASSOC_RESP       0x01       /* Management - association response       */
173 #define MGT_REASSOC_REQ      0x02       /* Management - reassociation request      */
174 #define MGT_REASSOC_RESP     0x03       /* Management - reassociation response     */
175 #define MGT_PROBE_REQ        0x04       /* Management - Probe request              */
176 #define MGT_PROBE_RESP       0x05       /* Management - Probe response             */
177 #define MGT_BEACON           0x08       /* Management - Beacon frame               */
178 #define MGT_ATIM             0x09       /* Management - ATIM                       */
179 #define MGT_DISASS           0x0A       /* Management - Disassociation             */
180 #define MGT_AUTHENTICATION   0x0B       /* Management - Authentication             */
181 #define MGT_DEAUTHENTICATION 0x0C       /* Management - Deauthentication           */
182 #define MGT_ACTION           0x0D       /* Management - Action */
183
184 #define CTRL_PS_POLL         0x1A       /* Control - power-save poll               */
185 #define CTRL_RTS             0x1B       /* Control - request to send               */
186 #define CTRL_CTS             0x1C       /* Control - clear to send                 */
187 #define CTRL_ACKNOWLEDGEMENT 0x1D       /* Control - acknowledgement               */
188 #define CTRL_CFP_END         0x1E       /* Control - contention-free period end    */
189 #define CTRL_CFP_ENDACK      0x1F       /* Control - contention-free period end/ack */
190
191 #define DATA                 0x20       /* Data - Data                             */
192 #define DATA_CF_ACK          0x21       /* Data - Data + CF acknowledge            */
193 #define DATA_CF_POLL         0x22       /* Data - Data + CF poll                   */
194 #define DATA_CF_ACK_POLL     0x23       /* Data - Data + CF acknowledge + CF poll  */
195 #define DATA_NULL_FUNCTION   0x24       /* Data - Null function (no data)          */
196 #define DATA_CF_ACK_NOD      0x25       /* Data - CF ack (no data)                 */
197 #define DATA_CF_POLL_NOD     0x26       /* Data - Data + CF poll (No data)         */
198 #define DATA_CF_ACK_POLL_NOD 0x27       /* Data - CF ack + CF poll (no data)       */
199 #define DATA_QOS_DATA        0x28       /* Data - QoS Data                         */
200 #define DATA_QOS_NULL        0x2c       /* Data - QoS Null                         */
201
202 #define DATA_ADDR_T1         0
203 #define DATA_ADDR_T2         (FLAG_FROM_DS << 8)
204 #define DATA_ADDR_T3         (FLAG_TO_DS << 8)
205 #define DATA_ADDR_T4         ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
206
207
208 /* ************************************************************************* */
209 /*          Macros used to extract information about fixed fields            */
210 /* ************************************************************************* */
211 #define ESS_SET(x) ((x) & 0x0001)
212 #define IBSS_SET(x) ((x) & 0x0002)
213
214
215
216 /* ************************************************************************* */
217 /*        Logical field codes (dissector's encoding of fixed fields)         */
218 /* ************************************************************************* */
219 #define FIELD_TIMESTAMP       0x01      /* 64-bit timestamp                       */
220 #define FIELD_BEACON_INTERVAL 0x02      /* 16-bit beacon interval                 */
221 #define FIELD_CAP_INFO        0x03      /* Add capability information tree        */
222 #define FIELD_AUTH_ALG        0x04      /* Authentication algorithm used          */
223 #define FIELD_AUTH_TRANS_SEQ  0x05      /* Authentication sequence number         */
224 #define FIELD_CURRENT_AP_ADDR 0x06
225 #define FIELD_LISTEN_IVAL     0x07
226 #define FIELD_REASON_CODE     0x08
227 #define FIELD_ASSOC_ID        0x09
228 #define FIELD_STATUS_CODE     0x0A
229 #define FIELD_CATEGORY_CODE   0x0B      /* Management action category */
230 #define FIELD_ACTION_CODE     0x0C      /* Management action code */
231 #define FIELD_DIALOG_TOKEN    0x0D      /* Management action dialog token */
232 #define FIELD_WME_ACTION_CODE   0x0E    /* Management notification action code */
233 #define FIELD_WME_DIALOG_TOKEN  0x0F    /* Management notification dialog token */
234 #define FIELD_WME_STATUS_CODE   0x10    /* Management notification setup response status code */
235
236 /* ************************************************************************* */
237 /*        Logical field codes (IEEE 802.11 encoding of tags)                 */
238 /* ************************************************************************* */
239 #define TAG_SSID                 0x00
240 #define TAG_SUPP_RATES           0x01
241 #define TAG_FH_PARAMETER         0x02
242 #define TAG_DS_PARAMETER         0x03
243 #define TAG_CF_PARAMETER         0x04
244 #define TAG_TIM                  0x05
245 #define TAG_IBSS_PARAMETER       0x06
246 #define TAG_COUNTRY_INFO         0x07
247 #define TAG_FH_HOPPING_PARAMETER 0x08
248 #define TAG_FH_HOPPING_TABLE     0x09
249 #define TAG_CHALLENGE_TEXT       0x10
250 #define TAG_ERP_INFO             0x2A
251 #define TAG_ERP_INFO_OLD         0x2F   /* IEEE Std 802.11g/D4.0 */
252 #define TAG_RSN_IE               0x30
253 #define TAG_EXT_SUPP_RATES       0x32
254 #define TAG_VENDOR_SPECIFIC_IE   0xDD
255
256 #define WPA_OUI "\x00\x50\xF2"
257 #define RSN_OUI "\x00\x0F\xAC"
258 #define WME_OUI "\x00\x50\xF2"
259
260 #define PMKID_LEN 16
261
262 /* ************************************************************************* */
263 /*                         Frame types, and their names                      */
264 /* ************************************************************************* */
265 static const value_string frame_type_subtype_vals[] = {
266         {MGT_ASSOC_REQ,        "Association Request"},
267         {MGT_ASSOC_RESP,       "Association Response"},
268         {MGT_REASSOC_REQ,      "Reassociation Request"},
269         {MGT_REASSOC_RESP,     "Reassociation Response"},
270         {MGT_PROBE_REQ,        "Probe Request"},
271         {MGT_PROBE_RESP,       "Probe Response"},
272         {MGT_BEACON,           "Beacon frame"},
273         {MGT_ATIM,             "ATIM"},
274         {MGT_DISASS,           "Dissassociate"},
275         {MGT_AUTHENTICATION,   "Authentication"},
276         {MGT_DEAUTHENTICATION, "Deauthentication"},
277         {MGT_ACTION,           "Action"},
278         {CTRL_PS_POLL,         "Power-Save poll"},
279         {CTRL_RTS,             "Request-to-send"},
280         {CTRL_CTS,             "Clear-to-send"},
281         {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
282         {CTRL_CFP_END,         "CF-End (Control-frame)"},
283         {CTRL_CFP_ENDACK,      "CF-End + CF-Ack (Control-frame)"},
284         {DATA,                 "Data"},
285         {DATA_CF_ACK,          "Data + CF-Acknowledgement"},
286         {DATA_CF_POLL,         "Data + CF-Poll"},
287         {DATA_CF_ACK_POLL,     "Data + CF-Acknowledgement/Poll"},
288         {DATA_NULL_FUNCTION,   "Null function (No data)"},
289         {DATA_CF_ACK_NOD,      "Data + Acknowledgement (No data)"},
290         {DATA_CF_POLL_NOD,     "Data + CF-Poll (No data)"},
291         {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
292         {DATA_QOS_DATA,        "QoS Data"},
293         {DATA_QOS_NULL,        "QoS Null (No data)"},
294         {0,                    NULL}
295 };
296
297 /* ************************************************************************* */
298 /*                             802.1D Tag Names                              */
299 /* ************************************************************************* */
300 static const char *qos_tags[8] = {
301         "Best Effort",
302         "Background",
303         "Spare",
304         "Excellent Effort",
305         "Controlled Load",
306         "Video",
307         "Voice",
308         "Network Control"
309 };
310
311 /* ************************************************************************* */
312 /*                 WME Access Category Names (by 802.1D Tag)                 */
313 /* ************************************************************************* */
314 static const char *qos_acs[8] = {
315         "Best Effort",
316         "Background",
317         "Background",
318         "Video",
319         "Video",
320         "Video",
321         "Voice",
322         "Voice"
323 };
324
325 /* ************************************************************************* */
326 /*                   WME Access Category Names (by WME ACI)                  */
327 /* ************************************************************************* */
328 static const char *wme_acs[4] = {
329         "Best Effort",
330         "Background",
331         "Video",
332         "Voice",
333 };
334
335 static int proto_wlan = -1;
336
337 /* ************************************************************************* */
338 /*                Header field info values for radio information             */
339 /* ************************************************************************* */
340 static int hf_data_rate = -1;
341 static int hf_channel = -1;
342 static int hf_signal_strength = -1;
343
344 /* ************************************************************************* */
345 /*                Header field info values for FC-field                      */
346 /* ************************************************************************* */
347 static int hf_fc_field = -1;
348 static int hf_fc_proto_version = -1;
349 static int hf_fc_frame_type = -1;
350 static int hf_fc_frame_subtype = -1;
351 static int hf_fc_frame_type_subtype = -1;
352
353 static int hf_fc_flags = -1;
354 static int hf_fc_to_ds = -1;
355 static int hf_fc_from_ds = -1;
356 static int hf_fc_data_ds = -1;
357
358 static int hf_fc_more_frag = -1;
359 static int hf_fc_retry = -1;
360 static int hf_fc_pwr_mgt = -1;
361 static int hf_fc_more_data = -1;
362 static int hf_fc_wep = -1;
363 static int hf_fc_order = -1;
364
365
366 /* ************************************************************************* */
367 /*                   Header values for Duration/ID field                     */
368 /* ************************************************************************* */
369 static int hf_did_duration = -1;
370 static int hf_assoc_id = -1;
371
372
373 /* ************************************************************************* */
374 /*         Header values for different address-fields (all 4 of them)        */
375 /* ************************************************************************* */
376 static int hf_addr_da = -1;     /* Destination address subfield */
377 static int hf_addr_sa = -1;     /* Source address subfield */
378 static int hf_addr_ra = -1;     /* Receiver address subfield */
379 static int hf_addr_ta = -1;     /* Transmitter address subfield */
380 static int hf_addr_bssid = -1;  /* address is bssid */
381
382 static int hf_addr = -1;        /* Source or destination address subfield */
383
384
385 /* ************************************************************************* */
386 /*                Header values for QoS control field                        */
387 /* ************************************************************************* */
388 static int hf_qos_priority = -1;
389 static int hf_qos_ack_policy = -1;
390
391 /* ************************************************************************* */
392 /*                Header values for sequence number field                    */
393 /* ************************************************************************* */
394 static int hf_frag_number = -1;
395 static int hf_seq_number = -1;
396
397 /* ************************************************************************* */
398 /*                   Header values for Frame Check field                     */
399 /* ************************************************************************* */
400 static int hf_fcs = -1;
401
402 /* ************************************************************************* */
403 /*                   Header values for reassembly                            */
404 /* ************************************************************************* */
405 static int hf_fragments = -1;
406 static int hf_fragment = -1;
407 static int hf_fragment_overlap = -1;
408 static int hf_fragment_overlap_conflict = -1;
409 static int hf_fragment_multiple_tails = -1;
410 static int hf_fragment_too_long_fragment = -1;
411 static int hf_fragment_error = -1;
412 static int hf_reassembled_in = -1;
413
414
415 static int proto_wlan_mgt = -1;
416 /* ************************************************************************* */
417 /*                      Fixed fields found in mgt frames                     */
418 /* ************************************************************************* */
419 static int ff_auth_alg = -1;    /* Authentication algorithm field            */
420 static int ff_auth_seq = -1;    /* Authentication transaction sequence       */
421 static int ff_current_ap = -1;  /* Current AP MAC address                    */
422 static int ff_listen_ival = -1; /* Listen interval fixed field               */
423 static int ff_timestamp = -1;   /* 64 bit timestamp                          */
424 static int ff_beacon_interval = -1;     /* 16 bit Beacon interval            */
425 static int ff_assoc_id = -1;    /* 16 bit AID field                          */
426 static int ff_reason = -1;      /* 16 bit reason code                        */
427 static int ff_status_code = -1; /* Status code                               */
428 static int ff_category_code = -1;       /* 8 bit Category code */
429 static int ff_action_code = -1;         /* 8 bit Action code */
430 static int ff_dialog_token = -1;        /* 8 bit Dialog token */
431 static int ff_wme_action_code = -1;     /* Management notification action code */
432 static int ff_wme_status_code = -1;     /* Management notification setup response status code */
433
434 /* ************************************************************************* */
435 /*            Flags found in the capability field (fixed field)              */
436 /* ************************************************************************* */
437 static int ff_capture = -1;
438 static int ff_cf_ess = -1;
439 static int ff_cf_ibss = -1;
440 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA            */
441 static int ff_cf_ap_poll = -1;  /* CF pollable status for an AP            */
442 static int ff_cf_privacy = -1;
443 static int ff_cf_preamble = -1;
444 static int ff_cf_pbcc = -1;
445 static int ff_cf_agility = -1;
446 static int ff_short_slot_time = -1;
447 static int ff_dsss_ofdm = -1;
448
449 /* ************************************************************************* */
450 /*                       Tagged value format fields                          */
451 /* ************************************************************************* */
452 static int tag_number = -1;
453 static int tag_length = -1;
454 static int tag_interpretation = -1;
455
456
457
458 static int hf_fixed_parameters = -1;    /* Protocol payload for management frames */
459 static int hf_tagged_parameters = -1;   /* Fixed payload item */
460 static int hf_wep_iv = -1;
461 static int hf_tkip_extiv = -1;
462 static int hf_ccmp_extiv = -1;
463 static int hf_wep_key = -1;
464 static int hf_wep_icv = -1;
465
466
467 static int rsn_cap = -1;
468 static int rsn_cap_preauth = -1;
469 static int rsn_cap_no_pairwise = -1;
470 static int rsn_cap_ptksa_replay_counter = -1;
471 static int rsn_cap_gtksa_replay_counter = -1;
472
473 /* ************************************************************************* */
474 /*                               Protocol trees                              */
475 /* ************************************************************************* */
476 static gint ett_80211 = -1;
477 static gint ett_proto_flags = -1;
478 static gint ett_cap_tree = -1;
479 static gint ett_fc_tree = -1;
480 static gint ett_fragments = -1;
481 static gint ett_fragment = -1;
482
483 static gint ett_80211_mgt = -1;
484 static gint ett_fixed_parameters = -1;
485 static gint ett_tagged_parameters = -1;
486 static gint ett_qos_parameters = -1;
487 static gint ett_wep_parameters = -1;
488
489 static gint ett_rsn_cap_tree = -1;
490
491 static const fragment_items frag_items = {
492         &ett_fragment,
493         &ett_fragments,
494         &hf_fragments,
495         &hf_fragment,
496         &hf_fragment_overlap,
497         &hf_fragment_overlap_conflict,
498         &hf_fragment_multiple_tails,
499         &hf_fragment_too_long_fragment,
500         &hf_fragment_error,
501         &hf_reassembled_in,
502         "fragments"
503 };
504
505 static dissector_handle_t llc_handle;
506 static dissector_handle_t ipx_handle;
507 static dissector_handle_t eth_handle;
508 static dissector_handle_t data_handle;
509
510 /* ************************************************************************* */
511 /*            Return the length of the current header (in bytes)             */
512 /* ************************************************************************* */
513 static int
514 find_header_length (guint16 fcf)
515 {
516   int len;
517
518   switch (COOK_FRAME_TYPE (fcf)) {
519
520   case MGT_FRAME:
521     return MGT_FRAME_HDR_LEN;
522
523   case CONTROL_FRAME:
524     switch (COMPOSE_FRAME_TYPE (fcf)) {
525
526     case CTRL_CTS:
527     case CTRL_ACKNOWLEDGEMENT:
528       return 10;
529
530     case CTRL_RTS:
531     case CTRL_PS_POLL:
532     case CTRL_CFP_END:
533     case CTRL_CFP_ENDACK:
534       return 16;
535     }
536     return 4;   /* XXX */
537
538   case DATA_FRAME:
539     len = (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
540                                                       DATA_SHORT_HDR_LEN;
541     switch (COMPOSE_FRAME_TYPE (fcf)) {
542
543     case DATA_QOS_DATA:
544     case DATA_QOS_NULL:
545       return len + 2;
546
547     default:
548       return len;
549     }
550   default:
551     return 4;   /* XXX */
552   }
553 }
554
555
556 /* ************************************************************************* */
557 /*          This is the capture function used to update packet counts        */
558 /* ************************************************************************* */
559 static void
560 capture_ieee80211_common (const guchar * pd, int offset, int len,
561                           packet_counts * ld, gboolean fixed_length_header)
562 {
563   guint16 fcf, hdr_length;
564
565   if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
566     ld->other++;
567     return;
568   }
569
570   fcf = pletohs (&pd[0]);
571
572   if (IS_WEP(COOK_FLAGS(fcf)))
573     {
574       ld->other++;
575       return;
576     }
577
578   switch (COMPOSE_FRAME_TYPE (fcf))
579     {
580
581     case DATA:                  /* We got a data frame */
582     case DATA_CF_ACK:           /* Data with ACK */
583     case DATA_CF_POLL:
584     case DATA_CF_ACK_POLL:
585     case DATA_QOS_DATA:
586       if (fixed_length_header)
587         hdr_length = DATA_LONG_HDR_LEN;
588       else
589         hdr_length = find_header_length (fcf);
590       /* I guess some bridges take Netware Ethernet_802_3 frames,
591          which are 802.3 frames (with a length field rather than
592          a type field, but with no 802.2 header in the payload),
593          and just stick the payload into an 802.11 frame.  I've seen
594          captures that show frames of that sort.
595
596          This means we have to do the same check for Netware 802.3 -
597          or, if you will, "Netware 802.11" - that we do in the
598          Ethernet dissector, i.e. checking for 0xffff as the first
599          four bytes of the payload and, if we find it, treating it
600          as an IPX frame. */
601       if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
602         ld->other++;
603         return;
604       }
605       if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
606         capture_ipx (ld);
607       }
608       else {
609         capture_llc (pd, offset + hdr_length, len, ld);
610       }
611       break;
612
613     default:
614       ld->other++;
615       break;
616     }
617 }
618
619 /*
620  * Handle 802.11 with a variable-length link-layer header.
621  */
622 void
623 capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
624 {
625   capture_ieee80211_common (pd, offset, len, ld, FALSE);
626 }
627
628 /*
629  * Handle 802.11 with a fixed-length link-layer header (padded to the
630  * maximum length).
631  */
632 void
633 capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
634 {
635   capture_ieee80211_common (pd, offset, len, ld, TRUE);
636 }
637
638
639 /* ************************************************************************* */
640 /*          Add the subtree used to store the fixed parameters               */
641 /* ************************************************************************* */
642 static proto_tree *
643 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
644 {
645   proto_item *fixed_fields;
646   fixed_fields =
647     proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
648                                 size, size, "Fixed parameters (%d bytes)",
649                                 size);
650
651   return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
652 }
653
654
655 /* ************************************************************************* */
656 /*            Add the subtree used to store tagged parameters                */
657 /* ************************************************************************* */
658 static proto_tree *
659 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
660 {
661   proto_item *tagged_fields;
662
663   tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
664                                               tvb,
665                                               start,
666                                               size,
667                                               size,
668                                               "Tagged parameters (%d bytes)",
669                                               size);
670
671   return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
672 }
673
674
675 /* ************************************************************************* */
676 /*              Dissect and add fixed mgmt fields to protocol tree           */
677 /* ************************************************************************* */
678 static void
679 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
680 {
681   const guint8 *dataptr;
682   char out_buff[SHORT_STR];
683   guint16 capability;
684   proto_item *cap_item;
685   static proto_tree *cap_tree;
686   double temp_double;
687
688   switch (lfcode)
689     {
690     case FIELD_TIMESTAMP:
691       dataptr = tvb_get_ptr (tvb, offset, 8);
692       memset (out_buff, 0, SHORT_STR);
693       snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
694                 dataptr[7],
695                 dataptr[6],
696                 dataptr[5],
697                 dataptr[4],
698                 dataptr[3],
699                 dataptr[2],
700                 dataptr[1],
701                 dataptr[0]);
702
703       proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
704       break;
705
706     case FIELD_BEACON_INTERVAL:
707       temp_double = (double) tvb_get_letohs (tvb, offset);
708       temp_double = temp_double * 1024 / 1000000;
709       proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
710                                     temp_double,"Beacon Interval: %f [Seconds]",
711                                     temp_double);
712       break;
713
714
715     case FIELD_CAP_INFO:
716       capability = tvb_get_letohs (tvb, offset);
717
718       cap_item = proto_tree_add_uint_format (tree, ff_capture,
719                                              tvb, offset, 2,
720                                              capability,
721                                              "Capability Information: 0x%04X",
722                                              capability);
723       cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
724       proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
725                               capability);
726       proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
727                               capability);
728       if (ESS_SET (capability) != 0)    /* This is an AP */
729         proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
730                              capability);
731
732       else                      /* This is a STA */
733         proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
734                              capability);
735       proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
736                               capability);
737       proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
738                               capability);
739       proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
740                               capability);
741       proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
742                               capability);
743       proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
744                               capability);
745       proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
746                               capability);
747       break;
748
749     case FIELD_AUTH_ALG:
750       proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
751       break;
752
753     case FIELD_AUTH_TRANS_SEQ:
754       proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
755       break;
756
757     case FIELD_CURRENT_AP_ADDR:
758       proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
759       break;
760
761     case FIELD_LISTEN_IVAL:
762       proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
763       break;
764
765     case FIELD_REASON_CODE:
766       proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
767       break;
768
769     case FIELD_ASSOC_ID:
770       proto_tree_add_uint(tree, ff_assoc_id, tvb, offset, 2, 
771                           COOK_ASSOC_ID(tvb_get_letohs(tvb,offset)));
772       /* proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE); */
773       break;
774
775     case FIELD_STATUS_CODE:
776       proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
777       break;
778
779     case FIELD_CATEGORY_CODE:
780       proto_tree_add_item (tree, ff_category_code, tvb, offset, 1, TRUE);
781       break;
782
783     case FIELD_ACTION_CODE:
784       proto_tree_add_item (tree, ff_action_code, tvb, offset, 1, TRUE);
785       break;
786
787     case FIELD_DIALOG_TOKEN:
788       proto_tree_add_item (tree, ff_dialog_token, tvb, offset, 1, TRUE);
789       break;
790
791     case FIELD_WME_ACTION_CODE:
792       proto_tree_add_item (tree, ff_wme_action_code, tvb, offset, 1, TRUE);
793       break;
794
795     case FIELD_WME_STATUS_CODE:
796       proto_tree_add_item (tree, ff_wme_status_code, tvb, offset, 1, TRUE);
797       break;
798     }
799 }
800
801 static char *wpa_cipher_str[] = 
802 {
803   "NONE",
804   "WEP (40-bit)",
805   "TKIP",
806   "AES (OCB)",
807   "AES (CCM)",
808   "WEP (104-bit)",
809 };
810
811 static char *
812 wpa_cipher_idx2str(guint idx)
813 {
814   if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
815     return wpa_cipher_str[idx];
816   return "UNKNOWN";
817 }
818
819 static char *wpa_keymgmt_str[] = 
820 {
821   "NONE",
822   "WPA",
823   "PSK",
824 };
825
826 static char *
827 wpa_keymgmt_idx2str(guint idx)
828 {
829   if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
830     return wpa_keymgmt_str[idx];
831   return "UNKNOWN";
832 }
833
834 static void 
835 dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
836                 guint32 tag_len, const guint8 *tag_val)
837 {
838       guint32 tag_val_off = 0;
839       char out_buff[SHORT_STR], *pos;
840       guint i;
841         
842       /* Wi-Fi Protected Access (WPA) Information Element */
843       if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
844         snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
845                   tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
846         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
847         offset += 6;
848         tag_val_off += 6;
849         if (tag_val_off + 4 <= tag_len) {
850           /* multicast cipher suite */
851           if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
852             snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s", 
853                       wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
854             proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
855             offset += 4;
856             tag_val_off += 4;
857             /* unicast cipher suites */
858             if (tag_val_off + 2 <= tag_len) {
859               snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
860                         pletohs(tag_val + tag_val_off));
861               proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
862               offset += 2;
863               tag_val_off += 2;
864               i = 1;
865               while (tag_val_off + 4 <= tag_len) {
866                 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
867                   snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s", 
868                             i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
869                   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
870                   offset += 4;
871                   tag_val_off += 4;
872                   i ++;
873                 }
874                 else
875                   break;
876               }
877               /* authenticated key management suites */
878               if (tag_val_off + 2 <= tag_len) {
879                 snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
880                           pletohs(tag_val + tag_val_off));
881                 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
882                 offset += 2;
883                 tag_val_off += 2;
884                 i = 1;
885                 while (tag_val_off + 4 <= tag_len) {
886                   if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
887                     snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s", 
888                               i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
889                     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
890                     offset += 4;
891                     tag_val_off += 4;
892                     i ++;
893                   }
894                   else
895                     break;
896                 }
897               }
898             }
899           }
900         }
901         if (tag_val_off < tag_len)
902           proto_tree_add_string(tree, tag_interpretation, tvb,
903                                  offset, tag_len - tag_val_off, "Not interpreted");
904       } else if (tag_val_off + 7 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x00", 5)) {
905       /* Wireless Multimedia Enhancements (WME) Information Element */
906         snprintf(out_buff, SHORT_STR, "WME IE: type %u, subtype %u, version %u, parameter set %u",
907                  tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
908                  tag_val[tag_val_off + 6]);
909         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
910       } else if (tag_val_off + 24 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x01", 5)) {
911       /* Wireless Multimedia Enhancements (WME) Parameter Element */
912         snprintf(out_buff, SHORT_STR, "WME PE: type %u, subtype %u, version %u, parameter set %u",
913                  tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
914                  tag_val[tag_val_off + 6]);
915         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
916         offset += 8;
917         tag_val_off += 8;
918         for (i = 0; i < 4; i++) {
919           snprintf(out_buff, SHORT_STR, "WME AC Parameters: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
920                    (tag_val[tag_val_off] & 0x60) >> 5,
921                    wme_acs[(tag_val[tag_val_off] & 0x60) >> 5],
922                    (tag_val[tag_val_off] & 0x10) ? "" : "not ",
923                    tag_val[tag_val_off] & 0x0f,
924                    tag_val[tag_val_off + 1] & 0x0f,
925                    (tag_val[tag_val_off + 1] & 0xf0) >> 4,
926                    tvb_get_letohs(tvb, offset + 2));
927           proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
928           offset += 4;
929           tag_val_off += 4;
930         }
931       } else if (tag_val_off + 56 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x02", 5)) {
932       /* Wireless Multimedia Enhancements (WME) TSPEC Element */
933         guint16 ts_info, msdu_size, surplus_bandwidth;
934         const char *direction[] = { "Uplink", "Downlink", "Reserved", "Bi-directional" };
935         const value_string fields[] = {
936           {12, "Minimum Service Interval"},
937           {16, "Maximum Service Interval"},
938           {20, "Inactivity Interval"},
939           {24, "Service Start Time"},
940           {28, "Minimum Data Rate"},
941           {32, "Mean Data Rate"},
942           {36, "Maximum Burst Size"},
943           {40, "Minimum PHY Rate"},
944           {44, "Peak Data Rate"},
945           {48, "Delay Bound"},
946           {0, NULL}
947         };
948         char *field;
949
950         snprintf(out_buff, SHORT_STR, "WME TSPEC: type %u, subtype %u, version %u",
951                  tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5]);
952         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
953         offset += 6;
954         tag_val_off += 6;
955
956         ts_info = tvb_get_letohs(tvb, offset);
957         snprintf(out_buff, SHORT_STR, "WME TS Info: Priority %u (%s) (%s), Contention-based access %sset, %s",
958                  (ts_info >> 11) & 0x7, qos_tags[(ts_info >> 11) & 0x7], qos_acs[(ts_info >> 11) & 0x7],
959                  (ts_info & 0x0080) ? "" : "not ",
960                  direction[(ts_info >> 5) & 0x3]);
961         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
962         offset += 2;
963         tag_val_off += 2;
964
965         msdu_size = tvb_get_letohs(tvb, offset);
966         snprintf(out_buff, SHORT_STR, "WME TSPEC: %s MSDU Size %u",
967                  (msdu_size & 0x8000) ? "Fixed" : "Nominal", msdu_size & 0x7fff);
968         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
969         offset += 2;
970         tag_val_off += 2;
971
972         snprintf(out_buff, SHORT_STR, "WME TSPEC: Maximum MSDU Size %u", tvb_get_letohs(tvb, offset));
973         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
974         offset += 2;
975         tag_val_off += 2;
976
977         while ((field = val_to_str(tag_val_off, fields, NULL))) {
978           snprintf(out_buff, SHORT_STR, "WME TSPEC: %s %u", field, tvb_get_letohl(tvb, offset));
979           proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
980           offset += 4;
981           tag_val_off += 4;
982           if (tag_val_off == 52)
983             break;
984         }
985
986         surplus_bandwidth = tvb_get_letohs(tvb, offset);
987         snprintf(out_buff, SHORT_STR, "WME TSPEC: Surplus Bandwidth Allowance Factor %u.%u",
988                  (surplus_bandwidth >> 13) & 0x7, (surplus_bandwidth & 0x1fff));
989         offset += 2;
990         tag_val_off += 2;
991
992         snprintf(out_buff, SHORT_STR, "WME TSPEC: Medium Time %u", tvb_get_letohs(tvb, offset));
993         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
994         offset += 2;
995         tag_val_off += 2;                
996       } else if (tag_val_off + 4 <= tag_len && !memcmp(tag_val, RSN_OUI"\x04", 4)) {
997         /* IEEE 802.11i / Key Data Encapsulation / Data Type=4 - PMKID.
998          * This is only used within EAPOL-Key frame Key Data. */
999         pos = out_buff;
1000         pos += snprintf(pos, out_buff + SHORT_STR - pos, "RSN PMKID: ");
1001         if (tag_len - 4 != PMKID_LEN) {
1002           pos += snprintf(pos, out_buff + SHORT_STR - pos,
1003                           "(invalid PMKID len=%d, expected 16) ", tag_len - 4);
1004         }
1005         for (i = 0; i < tag_len - 4; i++) {
1006           pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
1007                           tag_val[tag_val_off + 4 + i]);
1008         }
1009         proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1010                               tag_len, out_buff);
1011       } else
1012         proto_tree_add_string(tree, tag_interpretation, 
1013                         tvb, offset, tag_len, "Not interpreted");
1014 }
1015
1016 static void 
1017 dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
1018                guint32 tag_len, const guint8 *tag_val)
1019 {
1020   guint32 tag_val_off = 0;
1021   guint16 rsn_capab;
1022   char out_buff[SHORT_STR];
1023   int i, j, count;
1024   proto_item *cap_item;
1025   proto_tree *cap_tree;
1026
1027   if (tag_val_off + 2 > tag_len) {
1028     proto_tree_add_string(tree, tag_interpretation, tvb, offset, tag_len,
1029                           "Not interpreted");
1030     return;
1031   }
1032
1033   snprintf(out_buff, SHORT_STR, "RSN IE, version %u",
1034            pletohs(&tag_val[tag_val_off]));
1035   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1036
1037   offset += 2;
1038   tag_val_off += 2;
1039
1040   if (tag_val_off + 4 > tag_len)
1041     goto done;
1042
1043   /* multicast cipher suite */
1044   if (!memcmp(&tag_val[tag_val_off], RSN_OUI, 3)) {
1045     snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s", 
1046              wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1047     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1048     offset += 4;
1049     tag_val_off += 4;
1050   }
1051
1052   if (tag_val_off + 2 > tag_len)
1053     goto done;
1054
1055   /* unicast cipher suites */
1056   count = pletohs(tag_val + tag_val_off);
1057   snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", count);
1058   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1059   offset += 2;
1060   tag_val_off += 2;
1061   i = 1;
1062   while (tag_val_off + 4 <= tag_len && i <= count) {
1063     if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
1064       goto done;
1065     snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
1066              i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1067     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1068     offset += 4;
1069     tag_val_off += 4;
1070     i++;
1071   }
1072
1073   if (i <= count || tag_val_off + 2 > tag_len)
1074     goto done;
1075
1076   /* authenticated key management suites */
1077   count = pletohs(tag_val + tag_val_off);
1078   snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", count);
1079   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1080   offset += 2;
1081   tag_val_off += 2;
1082   i = 1;
1083   while (tag_val_off + 4 <= tag_len && i <= count) {
1084     if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
1085       goto done;
1086     snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s", 
1087              i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
1088     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1089     offset += 4;
1090     tag_val_off += 4;
1091     i++;
1092   }
1093
1094   if (i <= count || tag_val_off + 2 > tag_len)
1095     goto done;
1096
1097   rsn_capab = pletohs(&tag_val[tag_val_off]);
1098   snprintf(out_buff, SHORT_STR, "RSN Capabilities 0x%04x", rsn_capab);
1099   cap_item = proto_tree_add_uint_format(tree, rsn_cap, tvb,
1100                                         offset, 2, rsn_capab,
1101                                         "RSN Capabilities: 0x%04X", rsn_capab);
1102   cap_tree = proto_item_add_subtree(cap_item, ett_rsn_cap_tree);
1103   proto_tree_add_boolean(cap_tree, rsn_cap_preauth, tvb, offset, 2,
1104                          rsn_capab);
1105   proto_tree_add_boolean(cap_tree, rsn_cap_no_pairwise, tvb, offset, 2,
1106                          rsn_capab);
1107   proto_tree_add_uint(cap_tree, rsn_cap_ptksa_replay_counter, tvb, offset, 2,
1108                       rsn_capab);
1109   proto_tree_add_uint(cap_tree, rsn_cap_gtksa_replay_counter, tvb, offset, 2,
1110                       rsn_capab);
1111   offset += 2;
1112   tag_val_off += 2;
1113
1114   if (tag_val_off + 2 > tag_len)
1115     goto done;
1116
1117   count = pletohs(tag_val + tag_val_off);
1118   snprintf(out_buff, SHORT_STR, "# of PMKIDs: %u", count);
1119   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1120   offset += 2;
1121   tag_val_off += 2;
1122
1123   /* PMKID List (16 * n octets) */
1124   for (i = 0; i < count; i++) {
1125     char *pos;
1126     if (tag_val_off + PMKID_LEN > tag_len)
1127       goto done;
1128     pos = out_buff;
1129     pos += snprintf(pos, out_buff + SHORT_STR - pos, "PMKID %u: ", i);
1130     for (j = 0; j < PMKID_LEN; j++) {
1131       pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
1132                       tag_val[tag_val_off + j]);
1133     }
1134     proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1135                           PMKID_LEN, out_buff);
1136     offset += PMKID_LEN;
1137     tag_val_off += PMKID_LEN;
1138   }
1139
1140  done:
1141   if (tag_val_off < tag_len)
1142     proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1143                           tag_len - tag_val_off, "Not interpreted");
1144 }
1145
1146 /* ************************************************************************* */
1147 /*           Dissect and add tagged (optional) fields to proto tree          */
1148 /* ************************************************************************* */
1149
1150 static const value_string tag_num_vals[] = {
1151         { TAG_SSID,                 "SSID parameter set" },
1152         { TAG_SUPP_RATES,           "Supported Rates" },
1153         { TAG_FH_PARAMETER,         "FH Parameter set" },
1154         { TAG_DS_PARAMETER,         "DS Parameter set" },
1155         { TAG_CF_PARAMETER,         "CF Parameter set" },
1156         { TAG_TIM,                  "(TIM) Traffic Indication Map" },
1157         { TAG_IBSS_PARAMETER,       "IBSS Parameter set" },
1158         { TAG_COUNTRY_INFO,         "Country Information" },
1159         { TAG_FH_HOPPING_PARAMETER, "Hopping Pattern Parameters" },
1160         { TAG_CHALLENGE_TEXT,       "Challenge text" },
1161         { TAG_ERP_INFO,             "ERP Information" },
1162         { TAG_ERP_INFO_OLD,         "ERP Information" },
1163         { TAG_RSN_IE,               "RSN Information" },
1164         { TAG_EXT_SUPP_RATES,       "Extended Supported Rates" },
1165         { TAG_VENDOR_SPECIFIC_IE,   "Vendor Specific" },
1166         { 0,                        NULL }
1167 };
1168
1169 static const value_string environment_vals[] = {
1170         { 0x20, "Any" },
1171         { 0x4f, "Outdoor" },
1172         { 0x49, "Indoor" },
1173         { 0,    NULL }
1174 };
1175
1176 static int
1177 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
1178 {
1179   const guint8 *tag_data_ptr;
1180   guint32 tag_no, tag_len;
1181   unsigned int i;
1182   int n, ret;
1183   char out_buff[SHORT_STR];
1184
1185
1186   tag_no = tvb_get_guint8(tvb, offset);
1187   proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
1188                               "Tag Number: %u (%s)",
1189                               tag_no,
1190                               val_to_str(tag_no, tag_num_vals,
1191                                          (tag_no >= 17 && tag_no <= 31) ?
1192                                          "Reserved for challenge text" :
1193                                          "Reserved tag number"));
1194
1195   tag_len = tvb_get_guint8(tvb, offset + 1);
1196   proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
1197
1198   tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
1199
1200   switch (tag_no)
1201     {
1202
1203
1204     case TAG_SSID:
1205       memset (out_buff, 0, SHORT_STR);
1206
1207       memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
1208       out_buff[tag_len + 1] = 0;
1209
1210       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1211                              tag_len, out_buff);
1212       break;
1213
1214
1215
1216     case TAG_SUPP_RATES:
1217     case TAG_EXT_SUPP_RATES:
1218       memset (out_buff, 0, SHORT_STR);
1219       strcpy (out_buff, "Supported rates: ");
1220       n = strlen (out_buff);
1221
1222       for (i = 0; i < tag_len && n < SHORT_STR; i++)
1223         {
1224             ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
1225                            (tag_data_ptr[i] & 0x7F) * 0.5,
1226                            (tag_data_ptr[i] & 0x80) ? "(B)" : "");
1227             if (ret == -1 || ret >= SHORT_STR - n) {
1228               /* Some versions of snprintf return -1 if they'd truncate
1229                  the output. Others return <buf_size> or greater.  */
1230               break;
1231             }
1232             n += ret;
1233         }
1234       if (n < SHORT_STR)
1235         snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
1236
1237       out_buff[SHORT_STR-1] = '\0';
1238       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1239                              tag_len, out_buff);
1240       break;
1241
1242
1243
1244     case TAG_FH_PARAMETER:
1245       memset (out_buff, 0, SHORT_STR);
1246
1247       snprintf (out_buff, SHORT_STR,
1248                 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
1249                 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
1250                 tag_data_ptr[3], tag_data_ptr[4]);
1251
1252       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1253                              tag_len, out_buff);
1254       break;
1255
1256
1257
1258     case TAG_DS_PARAMETER:
1259       memset (out_buff, 0, SHORT_STR);
1260
1261       snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
1262       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1263                              tag_len, out_buff);
1264       break;
1265
1266
1267     case TAG_CF_PARAMETER:
1268       memset (out_buff, 0, SHORT_STR);
1269
1270       snprintf (out_buff, SHORT_STR,
1271                 "CFP count %u, CFP period %u, CFP max duration %u, "
1272                 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
1273                 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
1274
1275       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1276                              tag_len, out_buff);
1277       break;
1278
1279
1280     case TAG_TIM:
1281       memset (out_buff, 0, SHORT_STR);
1282       snprintf (out_buff, SHORT_STR,
1283                 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
1284                 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
1285                 tag_data_ptr[2]);
1286       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1287                              tag_len, out_buff);
1288       break;
1289
1290
1291
1292     case TAG_IBSS_PARAMETER:
1293       memset (out_buff, 0, SHORT_STR);
1294       snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
1295                 pletohs (tag_data_ptr));
1296
1297       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1298                              tag_len, out_buff);
1299       break;
1300
1301
1302     case TAG_COUNTRY_INFO:
1303       memset (out_buff, 0, SHORT_STR);
1304
1305       snprintf (out_buff, SHORT_STR, "Country Code: %c%c, %s Environment",
1306                tag_data_ptr[0], tag_data_ptr[1], 
1307                val_to_str(tag_data_ptr[2], environment_vals,"Unknown (0x%02x)"));
1308
1309       n = strlen (out_buff);
1310
1311       for (i = 3; (i + 3) <= tag_len && n < SHORT_STR; i += 3)
1312       { 
1313         ret = snprintf(out_buff + n, SHORT_STR - n,
1314                        ", Start Channel: %u, Channels: %u, Max TX Power: %d dBm",
1315                        tag_data_ptr[i], tag_data_ptr[i + 1],
1316                        (gint)tag_data_ptr[i + 2]);
1317
1318         if (ret == -1 || ret >= SHORT_STR - n) {
1319           /* Some versions of snprintf return -1 if they'd truncate
1320              the output. Others return <buf_size> or greater.  */
1321           break;
1322         }
1323         n += ret;
1324       }
1325
1326       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,tag_len, out_buff);
1327       break;
1328
1329
1330     case TAG_FH_HOPPING_PARAMETER:
1331       memset (out_buff, 0, SHORT_STR);
1332       snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u", 
1333                        tag_data_ptr[0], tag_data_ptr[1]);
1334       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, tag_len, out_buff);
1335                              
1336
1337       break;
1338
1339
1340     case TAG_CHALLENGE_TEXT:
1341       memset (out_buff, 0, SHORT_STR);
1342       snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
1343       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1344                              tag_len, out_buff);
1345
1346       break;
1347
1348
1349
1350     case TAG_ERP_INFO:
1351     case TAG_ERP_INFO_OLD:
1352       memset (out_buff, 0, SHORT_STR);
1353
1354       snprintf (out_buff, SHORT_STR,
1355                 "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)",
1356                 tag_data_ptr[0],
1357                 tag_data_ptr[0] & 0x01 ? "" : "no ",
1358                 tag_data_ptr[0] & 0x02 ? "" : "do not ",
1359                 tag_data_ptr[0] & 0x04 ? "short or long": "long");
1360       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1361                              tag_len, out_buff);
1362
1363       break;
1364
1365     case TAG_VENDOR_SPECIFIC_IE:
1366       dissect_vendor_specific_ie(tree, tvb, offset + 2, tag_len,
1367                                  tag_data_ptr);
1368       break;
1369
1370     case TAG_RSN_IE:
1371       dissect_rsn_ie(tree, tvb, offset + 2, tag_len, tag_data_ptr);
1372       break;
1373
1374
1375     default:
1376       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1377                              tag_len, "Not interpreted");
1378       break;
1379     }
1380
1381   return tag_len + 2;
1382 }
1383
1384 void
1385 ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, proto_tree * tree,
1386        int tagged_parameters_len)
1387 {
1388   int next_len;
1389
1390   while (tagged_parameters_len > 0) {
1391     if ((next_len=add_tagged_field (tree, tvb, offset))==0)
1392       break;
1393     if (next_len > tagged_parameters_len) {
1394       /* XXX - flag this as an error? */
1395       next_len = tagged_parameters_len;
1396     }
1397     offset += next_len;
1398     tagged_parameters_len -= next_len;
1399   }
1400 }
1401
1402 /* ************************************************************************* */
1403 /*                     Dissect 802.11 management frame                       */
1404 /* ************************************************************************* */
1405 static void
1406 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
1407         proto_tree * tree)
1408 {
1409   proto_item *ti = NULL;
1410   proto_tree *mgt_tree;
1411   proto_tree *fixed_tree;
1412   proto_tree *tagged_tree;
1413   int offset;
1414   int tagged_parameter_tree_len;
1415
1416   CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
1417
1418   if (tree)
1419     {
1420       ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
1421       mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
1422
1423       switch (COMPOSE_FRAME_TYPE(fcf))
1424         {
1425
1426         case MGT_ASSOC_REQ:
1427           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
1428           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1429           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1430
1431           offset = 4;   /* Size of fixed fields */
1432           tagged_parameter_tree_len =
1433               tvb_reported_length_remaining(tvb, offset);
1434           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1435                                                    tagged_parameter_tree_len);
1436
1437           ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1438               tagged_parameter_tree_len);
1439           break;
1440
1441
1442         case MGT_ASSOC_RESP:
1443           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1444           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1445           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1446           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1447
1448           offset = 6;   /* Size of fixed fields */
1449
1450           tagged_parameter_tree_len =
1451               tvb_reported_length_remaining(tvb, offset);
1452           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1453                                                    tagged_parameter_tree_len);
1454
1455           ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1456               tagged_parameter_tree_len);
1457           break;
1458
1459
1460         case MGT_REASSOC_REQ:
1461           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1462           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1463           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1464           add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
1465
1466           offset = 10;  /* Size of fixed fields */
1467           tagged_parameter_tree_len =
1468               tvb_reported_length_remaining(tvb, offset);
1469           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1470                                                    tagged_parameter_tree_len);
1471
1472           ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1473               tagged_parameter_tree_len);
1474           break;
1475
1476         case MGT_REASSOC_RESP:
1477           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1478           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1479           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1480           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1481
1482           offset = 6;   /* Size of fixed fields */
1483           tagged_parameter_tree_len =
1484               tvb_reported_length_remaining(tvb, offset);
1485           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1486                                                    tagged_parameter_tree_len);
1487
1488           ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1489               tagged_parameter_tree_len);
1490           break;
1491
1492
1493         case MGT_PROBE_REQ:
1494           offset = 0;
1495           tagged_parameter_tree_len =
1496               tvb_reported_length_remaining(tvb, offset);
1497           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1498                                                    tagged_parameter_tree_len);
1499
1500           ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1501               tagged_parameter_tree_len);
1502           break;
1503
1504
1505         case MGT_PROBE_RESP:
1506           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1507           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1508           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1509           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1510
1511           offset = 12;  /* Size of fixed fields */
1512           tagged_parameter_tree_len =
1513               tvb_reported_length_remaining(tvb, offset);
1514           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1515                                                    tagged_parameter_tree_len);
1516
1517           ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1518               tagged_parameter_tree_len);
1519           break;
1520
1521
1522         case MGT_BEACON:                /* Dissect protocol payload fields  */
1523           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1524
1525           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1526           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1527           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1528
1529           offset = 12;  /* Size of fixed fields */
1530           tagged_parameter_tree_len =
1531               tvb_reported_length_remaining(tvb, offset);
1532           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1533                                                    tagged_parameter_tree_len);
1534
1535           ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1536               tagged_parameter_tree_len);
1537           break;
1538
1539
1540         case MGT_ATIM:
1541           break;
1542
1543
1544         case MGT_DISASS:
1545           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1546           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1547           break;
1548
1549
1550         case MGT_AUTHENTICATION:
1551           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1552           add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
1553           add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
1554           add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
1555
1556           offset = 6;   /* Size of fixed fields */
1557
1558           tagged_parameter_tree_len =
1559                   tvb_reported_length_remaining(tvb, offset);
1560           if (tagged_parameter_tree_len != 0)
1561             {
1562               tagged_tree = get_tagged_parameter_tree (mgt_tree,
1563                                                        tvb,
1564                                                        offset,
1565                                                        tagged_parameter_tree_len);
1566
1567               ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1568                 tagged_parameter_tree_len);
1569             }
1570           break;
1571
1572
1573         case MGT_DEAUTHENTICATION:
1574           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1575           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1576           break;
1577
1578
1579         case MGT_ACTION:
1580           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 3);
1581           add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
1582
1583           switch (tvb_get_guint8(tvb, 0))
1584             {
1585
1586             case 17:    /* Management notification frame */
1587               add_fixed_field (fixed_tree, tvb, 1, FIELD_WME_ACTION_CODE);
1588               add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
1589               add_fixed_field (fixed_tree, tvb, 3, FIELD_WME_STATUS_CODE);
1590
1591               offset = 4;       /* Size of fixed fields */
1592
1593               tagged_parameter_tree_len =
1594                 tvb_reported_length_remaining(tvb, offset);
1595               if (tagged_parameter_tree_len != 0)
1596                 {
1597                   tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1598                                                            tagged_parameter_tree_len);
1599
1600                   ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1601                                                     tagged_parameter_tree_len);
1602                 }
1603               break;
1604
1605             default:    /* Management action frame */
1606               add_fixed_field (fixed_tree, tvb, 1, FIELD_ACTION_CODE);
1607               add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
1608               break;
1609             }
1610           break;
1611         }
1612     }
1613 }
1614
1615 static void
1616 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1617 {
1618   if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1619     col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
1620                     get_ether_name(addr), type);
1621   if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
1622     col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
1623                      ether_to_str(addr), type);
1624 }
1625
1626 static void
1627 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1628 {
1629   if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1630     col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
1631                      get_ether_name(addr), type);
1632   if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
1633     col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
1634                      ether_to_str(addr), type);
1635 }
1636
1637 typedef enum {
1638     ENCAP_802_2,
1639     ENCAP_IPX,
1640     ENCAP_ETHERNET
1641 } encap_t;
1642
1643 /* ************************************************************************* */
1644 /*                          Dissect 802.11 frame                             */
1645 /* ************************************************************************* */
1646 static void
1647 dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
1648                           proto_tree * tree, gboolean fixed_length_header,
1649                           gboolean has_radio_information, gint fcs_len,
1650                           gboolean wlan_broken_fc)
1651 {
1652   guint16 fcf, flags, frame_type_subtype;
1653   guint16 seq_control;
1654   guint32 seq_number, frag_number;
1655   gboolean more_frags;
1656   const guint8 *src = NULL, *dst = NULL;
1657   proto_item *ti = NULL;
1658   proto_item *flag_item;
1659   proto_item *fc_item;
1660   proto_tree *hdr_tree = NULL;
1661   proto_tree *flag_tree;
1662   proto_tree *fc_tree;
1663   guint16 hdr_len;
1664   gboolean has_fcs;
1665   gint len, reported_len, ivlen;
1666   gboolean save_fragmented;
1667   tvbuff_t *volatile next_tvb = NULL;
1668   guint32 addr_type;
1669   volatile encap_t encap_type;
1670   guint8 octet1, octet2;
1671   char out_buff[SHORT_STR];
1672
1673   if (check_col (pinfo->cinfo, COL_PROTOCOL))
1674     col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
1675   if (check_col (pinfo->cinfo, COL_INFO))
1676     col_clear (pinfo->cinfo, COL_INFO);
1677
1678   /* Add the radio information, if present, to the column information */
1679   if (has_radio_information) {
1680     if (check_col(pinfo->cinfo, COL_TX_RATE)) {
1681         col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
1682            pinfo->pseudo_header->ieee_802_11.data_rate / 2,
1683            pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
1684     }
1685     if (check_col(pinfo->cinfo, COL_RSSI)) {
1686       /* XX - this is a percentage, not a dBm or normalized or raw RSSI */
1687       col_add_fstr(pinfo->cinfo, COL_RSSI, "%u",
1688            pinfo->pseudo_header->ieee_802_11.signal_level);
1689     }
1690   }
1691
1692   fcf = tvb_get_letohs (tvb, 0);
1693   if (wlan_broken_fc) {
1694     /* Swap bytes */
1695     fcf = ((fcf & 0xff) << 8) | (((fcf & 0xff00) >> 8) & 0xff);
1696   }
1697   if (fixed_length_header)
1698     hdr_len = DATA_LONG_HDR_LEN;
1699   else
1700     hdr_len = find_header_length (fcf);
1701   frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1702
1703   if (check_col (pinfo->cinfo, COL_INFO))
1704       col_set_str (pinfo->cinfo, COL_INFO,
1705           val_to_str(frame_type_subtype, frame_type_subtype_vals,
1706               "Unrecognized (Reserved frame)"));
1707
1708   flags = COOK_FLAGS (fcf);
1709   more_frags = HAVE_FRAGMENTS (flags);
1710
1711   /* Add the radio information, if present, and the FC to the current tree */
1712   if (tree)
1713     {
1714       ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1715                                            "IEEE 802.11");
1716       hdr_tree = proto_item_add_subtree (ti, ett_80211);
1717
1718       if (has_radio_information) {
1719         proto_tree_add_uint_format(hdr_tree, hf_data_rate,
1720                                    tvb, 0, 0,
1721                                    pinfo->pseudo_header->ieee_802_11.data_rate,
1722                                    "Data Rate: %u.%u Mb/s",
1723                                    pinfo->pseudo_header->ieee_802_11.data_rate / 2,
1724                                    pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
1725
1726         proto_tree_add_uint(hdr_tree, hf_channel,
1727                             tvb, 0, 0,
1728                             pinfo->pseudo_header->ieee_802_11.channel);
1729
1730         proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
1731                                    tvb, 0, 0,
1732                                    pinfo->pseudo_header->ieee_802_11.signal_level,
1733                                    "Signal Strength: %u%%",
1734                                    pinfo->pseudo_header->ieee_802_11.signal_level);
1735       }
1736
1737       proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1738                            tvb, 
1739                            wlan_broken_fc?1:0, 1,
1740                            frame_type_subtype);
1741
1742       fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 
1743                                             0, 2,
1744                                             fcf,
1745                                             "Frame Control: 0x%04X (%s)",
1746                                             fcf, wlan_broken_fc?"Swapped":"Normal");
1747
1748       fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1749
1750
1751       proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 
1752                            wlan_broken_fc?1:0, 1,
1753                            COOK_PROT_VERSION (fcf));
1754
1755       proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 
1756                            wlan_broken_fc?1:0, 1,
1757                            COOK_FRAME_TYPE (fcf));
1758
1759       proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1760                            tvb, 
1761                            wlan_broken_fc?1:0, 1,
1762                            COOK_FRAME_SUBTYPE (fcf));
1763
1764       flag_item =
1765         proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 
1766                                     wlan_broken_fc?0:1, 1,
1767                                     flags, "Flags: 0x%X", flags);
1768
1769       flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1770
1771       proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 
1772                            wlan_broken_fc?0:1, 1,
1773                            COOK_DS_STATUS (flags));
1774       proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1, 
1775                                      flags);
1776       proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1, 
1777                                      flags);
1778
1779       proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 
1780                               wlan_broken_fc?0:1, 1,
1781                               flags);
1782
1783       proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 
1784                               wlan_broken_fc?0:1, 1, flags);
1785
1786       proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 
1787                               wlan_broken_fc?0:1, 1, flags);
1788
1789       proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 
1790                               wlan_broken_fc?0:1, 1,
1791                               flags);
1792
1793       proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb,
1794                               wlan_broken_fc?0:1, 1, flags);
1795
1796       proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 
1797                               wlan_broken_fc?0:1, 1, flags);
1798
1799       if (frame_type_subtype == CTRL_PS_POLL)
1800         proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1801                             COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1802
1803       else
1804           proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1805                                tvb_get_letohs (tvb, 2));
1806     }
1807
1808   /*
1809    * Decode the part of the frame header that isn't the same for all
1810    * frame types.
1811    */
1812   seq_control = 0;
1813   frag_number = 0;
1814   seq_number = 0;
1815
1816   switch (COOK_FRAME_TYPE (fcf))
1817     {
1818
1819     case MGT_FRAME:
1820       /*
1821        * All management frame types have the same header.
1822        */
1823       src = tvb_get_ptr (tvb, 10, 6);
1824       dst = tvb_get_ptr (tvb, 4, 6);
1825
1826       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1827       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1828       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1829       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1830
1831       seq_control = tvb_get_letohs(tvb, 22);
1832       frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1833       seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1834
1835       if (tree)
1836         {
1837           proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1838
1839           proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1840
1841           /* add items for wlan.addr filter */
1842           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1843           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1844
1845           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1846                                 tvb_get_ptr (tvb, 16, 6));
1847
1848           proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1849                                frag_number);
1850
1851           proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1852                                seq_number);
1853         }
1854       break;
1855
1856     case CONTROL_FRAME:
1857       switch (frame_type_subtype)
1858         {
1859
1860         case CTRL_PS_POLL:
1861           src = tvb_get_ptr (tvb, 10, 6);
1862           dst = tvb_get_ptr (tvb, 4, 6);
1863
1864           set_src_addr_cols(pinfo, src, "BSSID");
1865           set_dst_addr_cols(pinfo, dst, "BSSID");
1866
1867           if (tree)
1868             {
1869               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1870
1871               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1872             }
1873           break;
1874
1875
1876         case CTRL_RTS:
1877           src = tvb_get_ptr (tvb, 10, 6);
1878           dst = tvb_get_ptr (tvb, 4, 6);
1879
1880           set_src_addr_cols(pinfo, src, "TA");
1881           set_dst_addr_cols(pinfo, dst, "RA");
1882
1883           if (tree)
1884             {
1885               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1886
1887               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1888             }
1889           break;
1890
1891
1892         case CTRL_CTS:
1893           dst = tvb_get_ptr (tvb, 4, 6);
1894
1895           set_dst_addr_cols(pinfo, dst, "RA");
1896
1897           if (tree)
1898             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1899           break;
1900
1901
1902         case CTRL_ACKNOWLEDGEMENT:
1903           dst = tvb_get_ptr (tvb, 4, 6);
1904
1905           set_dst_addr_cols(pinfo, dst, "RA");
1906
1907           if (tree)
1908             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1909           break;
1910
1911
1912         case CTRL_CFP_END:
1913           src = tvb_get_ptr (tvb, 10, 6);
1914           dst = tvb_get_ptr (tvb, 4, 6);
1915
1916           set_src_addr_cols(pinfo, src, "BSSID");
1917           set_dst_addr_cols(pinfo, dst, "RA");
1918
1919           if (tree)
1920             {
1921               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1922               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1923             }
1924           break;
1925
1926
1927         case CTRL_CFP_ENDACK:
1928           src = tvb_get_ptr (tvb, 10, 6);
1929           dst = tvb_get_ptr (tvb, 4, 6);
1930
1931           set_src_addr_cols(pinfo, src, "BSSID");
1932           set_dst_addr_cols(pinfo, dst, "RA");
1933
1934           if (tree)
1935             {
1936               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1937
1938               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1939             }
1940           break;
1941         }
1942       break;
1943
1944     case DATA_FRAME:
1945       addr_type = COOK_ADDR_SELECTOR (fcf);
1946
1947       /* In order to show src/dst address we must always do the following */
1948       switch (addr_type)
1949         {
1950
1951         case DATA_ADDR_T1:
1952           src = tvb_get_ptr (tvb, 10, 6);
1953           dst = tvb_get_ptr (tvb, 4, 6);
1954           break;
1955
1956
1957         case DATA_ADDR_T2:
1958           src = tvb_get_ptr (tvb, 16, 6);
1959           dst = tvb_get_ptr (tvb, 4, 6);
1960           break;
1961
1962
1963         case DATA_ADDR_T3:
1964           src = tvb_get_ptr (tvb, 10, 6);
1965           dst = tvb_get_ptr (tvb, 16, 6);
1966           break;
1967
1968
1969         case DATA_ADDR_T4:
1970           src = tvb_get_ptr (tvb, 24, 6);
1971           dst = tvb_get_ptr (tvb, 16, 6);
1972           break;
1973         }
1974
1975       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1976       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1977       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1978       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1979
1980       seq_control = tvb_get_letohs(tvb, 22);
1981       frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1982       seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1983
1984       /* Now if we have a tree we start adding stuff */
1985       if (tree)
1986         {
1987
1988
1989           switch (addr_type)
1990             {
1991
1992             case DATA_ADDR_T1:
1993               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1994               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1995               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1996                                     tvb_get_ptr (tvb, 16, 6));
1997               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1998                                    frag_number);
1999               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2000                                    seq_number);
2001
2002               /* add items for wlan.addr filter */
2003               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
2004               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2005               break;
2006
2007
2008             case DATA_ADDR_T2:
2009               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
2010               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
2011                                     tvb_get_ptr (tvb, 10, 6));
2012               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
2013               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2014                                    frag_number);
2015               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2016                                    seq_number);
2017
2018               /* add items for wlan.addr filter */
2019               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
2020               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
2021               break;
2022
2023
2024             case DATA_ADDR_T3:
2025               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
2026                                     tvb_get_ptr (tvb, 4, 6));
2027               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
2028               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
2029
2030               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2031                                    frag_number);
2032               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2033                                    seq_number);
2034
2035               /* add items for wlan.addr filter */
2036               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2037               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
2038               break;
2039
2040
2041             case DATA_ADDR_T4:
2042               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
2043                                     tvb_get_ptr (tvb, 4, 6));
2044               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
2045                                     tvb_get_ptr (tvb, 10, 6));
2046               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
2047               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2048                                    frag_number);
2049               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2050                                    seq_number);
2051               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
2052
2053               /* add items for wlan.addr filter */
2054               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
2055               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
2056               break;
2057             }
2058
2059         }
2060       break;
2061     }
2062
2063   len = tvb_length_remaining(tvb, hdr_len);
2064   reported_len = tvb_reported_length_remaining(tvb, hdr_len);
2065
2066   switch (fcs_len)
2067     {
2068       case 0: /* Definitely has no FCS */
2069         has_fcs = FALSE;
2070         break;
2071
2072       case 4: /* Definitely has an FCS */
2073         has_fcs = TRUE;
2074         break;
2075
2076       default: /* Don't know - use "wlan_check_fcs" */
2077         has_fcs = wlan_check_fcs;
2078         break;
2079     }
2080   if (has_fcs)
2081     {
2082       /*
2083        * Well, this packet should, in theory, have an FCS.
2084        * Do we have the entire packet, and does it have enough data for
2085        * the FCS?
2086        */
2087       if (reported_len < 4)
2088         {
2089           /*
2090            * The packet is claimed not to even have enough data for a 4-byte
2091            * FCS.
2092            * Pretend it doesn't have an FCS.
2093            */
2094           ;
2095         }
2096       else if (len < reported_len)
2097         {
2098           /*
2099            * The packet is claimed to have enough data for a 4-byte FCS, but
2100            * we didn't capture all of the packet.
2101            * Slice off the 4-byte FCS from the reported length, and trim the
2102            * captured length so it's no more than the reported length; that
2103            * will slice off what of the FCS, if any, is in the captured
2104            * length.
2105            */
2106           reported_len -= 4;
2107           if (len > reported_len)
2108             len = reported_len;
2109         }
2110       else
2111         {
2112           /*
2113            * We have the entire packet, and it includes a 4-byte FCS.
2114            * Slice it off, and put it into the tree.
2115            */
2116           len -= 4;
2117           reported_len -= 4;
2118           if (tree)
2119             {
2120               guint32 fcs = crc32_802_tvb(tvb, hdr_len + len);
2121               guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
2122               if (fcs == sent_fcs)
2123                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
2124                         hdr_len + len, 4, sent_fcs,
2125                         "Frame check sequence: 0x%08x (correct)", sent_fcs);
2126               else
2127                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
2128                         hdr_len + len, 4, sent_fcs,
2129                         "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
2130                         sent_fcs, fcs);
2131             }
2132         }
2133     }
2134
2135   if (tree && (frame_type_subtype == DATA_QOS_DATA || frame_type_subtype == DATA_QOS_NULL)) {
2136       proto_item *qos_fields;
2137       proto_tree *qos_tree;
2138
2139       guint16 qos_control, qos_priority, qos_ack_policy;
2140
2141       qos_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len - 2, 2,
2142                                        "QoS parameters");
2143       qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters);
2144
2145       qos_control = tvb_get_letohs(tvb, hdr_len - 2);
2146       qos_priority = COOK_QOS_PRIORITY(qos_control);
2147       qos_ack_policy = COOK_QOS_ACK_POLICY(qos_control);
2148       proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
2149                                   hdr_len - 2, 2, qos_priority,
2150                                   "Priority: %d (%s) (%s)",
2151                                   qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]);
2152       proto_tree_add_uint_format (qos_tree, hf_qos_ack_policy, tvb,
2153                                   hdr_len - 2, 2, qos_ack_policy,
2154                                   "Ack Policy: %d (%sAcknowledge)", 
2155                                   qos_ack_policy, qos_ack_policy ? "Do not " : "");
2156   }
2157
2158   /*
2159    * Only management and data frames have a body, so we don't have
2160    * anything more to do for other types of frames.
2161    */
2162   switch (COOK_FRAME_TYPE (fcf))
2163     {
2164
2165     case MGT_FRAME:
2166       break;
2167
2168     case DATA_FRAME:
2169       /*
2170        * No-data frames don't have a body.
2171        */
2172       switch (frame_type_subtype)
2173         {
2174
2175         case DATA_NULL_FUNCTION:
2176         case DATA_CF_ACK_NOD:
2177         case DATA_CF_POLL_NOD:
2178         case DATA_CF_ACK_POLL_NOD:
2179         case DATA_QOS_NULL:
2180           return;
2181         }
2182         break;
2183
2184     default:
2185       return;
2186     }
2187
2188   if (IS_WEP(COOK_FLAGS(fcf))) {
2189     /*
2190      * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
2191      * the data, if we have a matching key.  Otherwise display it as data.
2192      */
2193     gboolean can_decrypt = FALSE;
2194     proto_tree *wep_tree = NULL;
2195     guint32 iv;
2196     guint8 key, keybyte;
2197
2198     keybyte = tvb_get_guint8(tvb, hdr_len + 3);
2199     key = COOK_WEP_KEY(keybyte);
2200     if ((keybyte & KEY_EXTIV) && (len >= EXTIV_LEN)) {
2201       /* Extended IV; this frame is likely encrypted with TKIP or CCMP */
2202       if (tree) {
2203         proto_item *extiv_fields;
2204
2205         extiv_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 8,
2206                                            "TKIP/CCMP parameters");
2207         wep_tree = proto_item_add_subtree (extiv_fields, ett_wep_parameters);
2208         /* It is unknown whether this is a TKIP or CCMP encrypted packet, so
2209          * display both packet number alternatives unless the ExtIV can be
2210          * determined to be possible only with one of the encryption protocols.
2211          */
2212         if (tvb_get_guint8(tvb, hdr_len + 1) & 0x20) {
2213           snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
2214                    tvb_get_letohl(tvb, hdr_len + 4),
2215                    tvb_get_guint8(tvb, hdr_len),
2216                    tvb_get_guint8(tvb, hdr_len + 2));
2217           proto_tree_add_string(wep_tree, hf_tkip_extiv, tvb, hdr_len,
2218                                 EXTIV_LEN, out_buff);
2219         } 
2220         if (tvb_get_guint8(tvb, hdr_len + 2) == 0) {
2221           snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
2222                    tvb_get_letohl(tvb, hdr_len + 4),
2223                    tvb_get_guint8(tvb, hdr_len + 1),
2224                    tvb_get_guint8(tvb, hdr_len));
2225           proto_tree_add_string(wep_tree, hf_ccmp_extiv, tvb, hdr_len,
2226                                 EXTIV_LEN, out_buff);
2227         }
2228         proto_tree_add_uint(wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
2229       }
2230
2231       /* Subtract out the length of the IV. */
2232       len -= EXTIV_LEN;
2233       reported_len -= EXTIV_LEN;
2234       ivlen = EXTIV_LEN;
2235       /* It is unknown whether this is TKIP or CCMP, so let's not even try to
2236        * parse TKIP Michael MIC+ICV or CCMP MIC. */
2237     } else {
2238       /* No Ext. IV - WEP packet */
2239       /*
2240        * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
2241        * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
2242        * them itself.
2243        *
2244        * Also, just pass the data *following* the WEP parameters as the
2245        * buffer to decrypt.
2246        */
2247       iv = tvb_get_letoh24(tvb, hdr_len);
2248       if (tree) {
2249         proto_item *wep_fields;
2250
2251         wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
2252                                          "WEP parameters");
2253
2254         wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
2255         proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
2256       }
2257       if (tree)
2258         proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
2259
2260       /* Subtract out the length of the IV. */
2261       len -= 4;
2262       reported_len -= 4;
2263       ivlen = 4;
2264
2265       /*
2266        * Well, this packet should, in theory, have an ICV.
2267        * Do we have the entire packet, and does it have enough data for
2268        * the ICV?
2269        */
2270       if (reported_len < 4) {
2271         /*
2272          * The packet is claimed not to even have enough data for a
2273          * 4-byte ICV.
2274          * Pretend it doesn't have an ICV.
2275          */
2276         ;
2277       } else if (len < reported_len) {
2278         /*
2279          * The packet is claimed to have enough data for a 4-byte ICV,
2280          * but we didn't capture all of the packet.
2281          * Slice off the 4-byte ICV from the reported length, and trim
2282          * the captured length so it's no more than the reported length;
2283          * that will slice off what of the ICV, if any, is in the
2284          * captured length.
2285          *
2286          */
2287         reported_len -= 4;
2288         if (len > reported_len)
2289           len = reported_len;
2290       } else {
2291         /*
2292          * We have the entire packet, and it includes a 4-byte ICV.
2293          * Slice it off, and put it into the tree.
2294          *
2295          * We only support decrypting if we have the the ICV.
2296          *
2297          * XXX - the ICV is encrypted; we're putting the encrypted
2298          * value, not the decrypted value, into the tree.
2299          */
2300         len -= 4;
2301         reported_len -= 4;
2302         can_decrypt = TRUE;
2303       }
2304     }
2305
2306     if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
2307       /*
2308        * WEP decode impossible or failed, treat payload as raw data
2309        * and don't attempt fragment reassembly or further dissection.
2310        */
2311       next_tvb = tvb_new_subset(tvb, hdr_len + ivlen, len, reported_len);
2312
2313       if (tree && can_decrypt)
2314         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
2315                                     hdr_len + ivlen + len, 4, 
2316                                     tvb_get_ntohl(tvb, hdr_len + ivlen + len),
2317                                     "WEP ICV: 0x%08x (not verified)", 
2318                                     tvb_get_ntohl(tvb, hdr_len + ivlen + len));
2319
2320       call_dissector(data_handle, next_tvb, pinfo, tree);
2321       return;
2322     } else {
2323
2324       if (tree)
2325         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
2326                                     hdr_len + ivlen + len, 4, 
2327                                     tvb_get_ntohl(tvb, hdr_len + ivlen + len),
2328                                     "WEP ICV: 0x%08x (correct)", 
2329                                     tvb_get_ntohl(tvb, hdr_len + ivlen + len));
2330
2331       add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
2332     }
2333
2334     /*
2335      * WEP decryption successful!
2336      *
2337      * Use the tvbuff we got back from the decryption; the data starts at
2338      * the beginning.  The lengths are already correct for the decoded WEP
2339      * payload.
2340      */
2341     hdr_len = 0;
2342
2343   } else {
2344     /*
2345      * Not a WEP-encrypted frame; just use the data from the tvbuff
2346      * handed to us.
2347      *
2348      * The payload starts at "hdr_len" (i.e., just past the 802.11
2349      * MAC header), the length of data in the tvbuff following the
2350      * 802.11 header is "len", and the length of data in the packet
2351      * following the 802.11 header is "reported_len".
2352      */
2353     next_tvb = tvb;
2354   }
2355
2356   /*
2357    * Do defragmentation if "wlan_defragment" is true, and we have more
2358    * fragments or this isn't the first fragment.
2359    *
2360    * We have to do some special handling to catch frames that
2361    * have the "More Fragments" indicator not set but that
2362    * don't show up as reassembled and don't have any other
2363    * fragments present.  Some networking interfaces appear
2364    * to do reassembly even when you're capturing raw packets
2365    * *and* show the reassembled packet without the "More
2366    * Fragments" indicator set *but* with a non-zero fragment
2367    * number.
2368    *
2369    * "fragment_add_seq_802_11()" handles that; we want to call it
2370    * even if we have a short frame, so that it does those checks - if
2371    * the frame is short, it doesn't do reassembly on it.
2372    *
2373    * (This could get some false positives if we really *did* only
2374    * capture the last fragment of a fragmented packet, but that's
2375    * life.)
2376    */
2377   save_fragmented = pinfo->fragmented;
2378   if (wlan_defragment && (more_frags || frag_number != 0)) {
2379     fragment_data *fd_head;
2380
2381     /*
2382      * If we've already seen this frame, look it up in the
2383      * table of reassembled packets, otherwise add it to
2384      * whatever reassembly is in progress, if any, and see
2385      * if it's done.
2386      */
2387     fd_head = fragment_add_seq_802_11(next_tvb, hdr_len, pinfo, seq_number,
2388                                      wlan_fragment_table,
2389                                      wlan_reassembled_table,
2390                                      frag_number,
2391                                      reported_len,
2392                                      more_frags);
2393     next_tvb = process_reassembled_data(tvb, hdr_len, pinfo,
2394                                         "Reassembled 802.11", fd_head,
2395                                         &frag_items, NULL, hdr_tree);
2396   } else {
2397     /*
2398      * If this is the first fragment, dissect its contents, otherwise
2399      * just show it as a fragment.
2400      */
2401     if (frag_number != 0) {
2402       /* Not the first fragment - don't dissect it. */
2403       next_tvb = NULL;
2404     } else {
2405       /* First fragment, or not fragmented.  Dissect what we have here. */
2406
2407       /* Get a tvbuff for the payload. */
2408       next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
2409
2410       /*
2411        * If this is the first fragment, but not the only fragment,
2412        * tell the next protocol that.
2413        */
2414       if (more_frags)
2415         pinfo->fragmented = TRUE;
2416       else
2417         pinfo->fragmented = FALSE;
2418     }
2419   }
2420
2421   if (next_tvb == NULL) {
2422     /* Just show this as an incomplete fragment. */
2423     if (check_col(pinfo->cinfo, COL_INFO))
2424       col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
2425     next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
2426     call_dissector(data_handle, next_tvb, pinfo, tree);
2427     pinfo->fragmented = save_fragmented;
2428     return;
2429   }
2430
2431   switch (COOK_FRAME_TYPE (fcf))
2432     {
2433
2434     case MGT_FRAME:
2435       dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
2436       break;
2437
2438
2439     case DATA_FRAME:
2440       /* I guess some bridges take Netware Ethernet_802_3 frames,
2441          which are 802.3 frames (with a length field rather than
2442          a type field, but with no 802.2 header in the payload),
2443          and just stick the payload into an 802.11 frame.  I've seen
2444          captures that show frames of that sort.
2445
2446          We also handle some odd form of encapsulation in which a
2447          complete Ethernet frame is encapsulated within an 802.11
2448          data frame, with no 802.2 header.  This has been seen
2449          from some hardware.
2450
2451          So, if the packet doesn't start with 0xaa 0xaa:
2452
2453            we first use the same scheme that linux-wlan-ng does to detect
2454            those encapsulated Ethernet frames, namely looking to see whether
2455            the frame either starts with 6 octets that match the destination
2456            address from the 802.11 header or has 6 octets that match the
2457            source address from the 802.11 header following the first 6 octets,
2458            and, if so, treat it as an encapsulated Ethernet frame;
2459
2460            otherwise, we use the same scheme that we use in the Ethernet
2461            dissector to recognize Netware 802.3 frames, namely checking
2462            whether the packet starts with 0xff 0xff and, if so, treat it
2463            as an encapsulated IPX frame. */
2464       encap_type = ENCAP_802_2;
2465       TRY {
2466         octet1 = tvb_get_guint8(next_tvb, 0);
2467         octet2 = tvb_get_guint8(next_tvb, 1);
2468         if (octet1 != 0xaa || octet2 != 0xaa) {
2469           src = tvb_get_ptr (next_tvb, 6, 6);
2470           dst = tvb_get_ptr (next_tvb, 0, 6);
2471           if (memcmp(src, pinfo->dl_src.data, 6) == 0 ||
2472               memcmp(dst, pinfo->dl_dst.data, 6) == 0)
2473             encap_type = ENCAP_ETHERNET;
2474           else if (octet1 == 0xff && octet2 == 0xff)
2475             encap_type = ENCAP_IPX;
2476         }
2477       }
2478       CATCH2(BoundsError, ReportedBoundsError) {
2479             ; /* do nothing */
2480
2481       }
2482       ENDTRY;
2483
2484       switch (encap_type) {
2485
2486       case ENCAP_802_2:
2487         call_dissector(llc_handle, next_tvb, pinfo, tree);
2488         break;
2489
2490       case ENCAP_ETHERNET:
2491         call_dissector(eth_handle, next_tvb, pinfo, tree);
2492         break;
2493
2494       case ENCAP_IPX:
2495         call_dissector(ipx_handle, next_tvb, pinfo, tree);
2496         break;
2497       }
2498       break;
2499     }
2500   pinfo->fragmented = save_fragmented;
2501 }
2502
2503 /*
2504  * Dissect 802.11 with a variable-length link-layer header.
2505  */
2506 static void
2507 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2508 {
2509   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
2510       pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
2511 }
2512
2513 /*
2514  * Dissect 802.11 with a variable-length link-layer header and a pseudo-
2515  * header containing radio information.
2516  */
2517 static void
2518 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2519 {
2520   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE,
2521      pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
2522 }
2523
2524 /*
2525  * Dissect 802.11 with a variable-length link-layer header and a byte-swapped
2526  * control field (some hardware sends out LWAPP-encapsulated 802.11
2527  * packets with the control field byte swapped).
2528  */
2529 static void
2530 dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2531 {
2532   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE, TRUE);
2533 }
2534
2535 /*
2536  * Dissect 802.11 with a fixed-length link-layer header (padded to the
2537  * maximum length).
2538  */
2539 static void
2540 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2541 {
2542   dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE, FALSE);
2543 }
2544
2545 static void
2546 wlan_defragment_init(void)
2547 {
2548   fragment_table_init(&wlan_fragment_table);
2549   reassembled_table_init(&wlan_reassembled_table);
2550 }
2551
2552 void
2553 proto_register_ieee80211 (void)
2554 {
2555   static const value_string frame_type[] = {
2556     {MGT_FRAME,     "Management frame"},
2557     {CONTROL_FRAME, "Control frame"},
2558     {DATA_FRAME,    "Data frame"},
2559     {0,             NULL}
2560   };
2561
2562   static const value_string tofrom_ds[] = {
2563     {0,                       "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
2564     {FLAG_TO_DS,              "Frame is entering DS (To DS: 1  From DS: 0)"},
2565     {FLAG_FROM_DS,            "Frame is exiting DS (To DS: 0  From DS: 1)"},
2566     {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1  From DS: 1)"},
2567     {0, NULL}
2568   };
2569
2570   static const true_false_string tods_flag = {
2571     "Frame is entering DS",
2572     "Frame is not entering DS"
2573   };
2574
2575   static const true_false_string fromds_flag = {
2576     "Frame is exiting DS",
2577     "Frame is not exiting DS"
2578   };
2579
2580   static const true_false_string more_frags = {
2581     "More fragments follow",
2582     "This is the last fragment"
2583   };
2584
2585   static const true_false_string retry_flags = {
2586     "Frame is being retransmitted",
2587     "Frame is not being retransmitted"
2588   };
2589
2590   static const true_false_string pm_flags = {
2591     "STA will go to sleep",
2592     "STA will stay up"
2593   };
2594
2595   static const true_false_string md_flags = {
2596     "Data is buffered for STA at AP",
2597     "No data buffered"
2598   };
2599
2600   static const true_false_string wep_flags = {
2601     "WEP is enabled",
2602     "WEP is disabled"
2603   };
2604
2605   static const true_false_string order_flags = {
2606     "Strictly ordered",
2607     "Not strictly ordered"
2608   };
2609
2610   static const true_false_string cf_ess_flags = {
2611     "Transmitter is an AP",
2612     "Transmitter is a STA"
2613   };
2614
2615
2616   static const true_false_string cf_privacy_flags = {
2617     "AP/STA can support WEP",
2618     "AP/STA cannot support WEP"
2619   };
2620
2621   static const true_false_string cf_preamble_flags = {
2622     "Short preamble allowed",
2623     "Short preamble not allowed"
2624   };
2625
2626   static const true_false_string cf_pbcc_flags = {
2627     "PBCC modulation allowed",
2628     "PBCC modulation not allowed"
2629   };
2630
2631   static const true_false_string cf_agility_flags = {
2632     "Channel agility in use",
2633     "Channel agility not in use"
2634   };
2635
2636   static const true_false_string short_slot_time_flags = {
2637     "Short slot time in use",
2638     "Short slot time not in use"
2639   };
2640
2641   static const true_false_string dsss_ofdm_flags = {
2642     "DSSS-OFDM modulation allowed",
2643     "DSSS-OFDM modulation not allowed"
2644   };
2645
2646
2647   static const true_false_string cf_ibss_flags = {
2648     "Transmitter belongs to an IBSS",
2649     "Transmitter belongs to a BSS"
2650   };
2651
2652   static const value_string sta_cf_pollable[] = {
2653     {0x00, "Station is not CF-Pollable"},
2654     {0x02, "Station is CF-Pollable, "
2655      "not requesting to be placed on the  CF-polling list"},
2656     {0x01, "Station is CF-Pollable, "
2657      "requesting to be placed on the CF-polling list"},
2658     {0x03, "Station is CF-Pollable, requesting never to be polled"},
2659     {0, NULL}
2660   };
2661
2662   static const value_string ap_cf_pollable[] = {
2663     {0x00, "No point coordinator at AP"},
2664     {0x02, "Point coordinator at AP for delivery only (no polling)"},
2665     {0x01, "Point coordinator at AP for delivery and polling"},
2666     {0x03, "Reserved"},
2667     {0, NULL}
2668   };
2669
2670
2671   static const value_string auth_alg[] = {
2672     {0x00, "Open System"},
2673     {0x01, "Shared key"},
2674     {0, NULL}
2675   };
2676
2677   static const value_string reason_codes[] = {
2678     {0x00, "Reserved"},
2679     {0x01, "Unspecified reason"},
2680     {0x02, "Previous authentication no longer valid"},
2681     {0x03, "Deauthenticated because sending STA is leaving (has left) "
2682      "IBSS or ESS"},
2683     {0x04, "Disassociated due to inactivity"},
2684     {0x05, "Disassociated because AP is unable to handle all currently "
2685      "associated stations"},
2686     {0x06, "Class 2 frame received from nonauthenticated station"},
2687     {0x07, "Class 3 frame received from nonassociated station"},
2688     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
2689     {0x09, "Station requesting (re)association is not authenticated with "
2690      "responding station"},
2691     {0x0D, "Invalid Information Element"},
2692     {0x0E, "Michael MIC failure"},
2693     {0x0F, "4-Way Handshake timeout"},
2694     {0x10, "Group key update timeout"},
2695     {0x11, "Information element in 4-Way Handshake different from "
2696      "(Re)Association Request/Probe Response/Beacon"},
2697     {0x12, "Group Cipher is not valid"},
2698     {0x13, "Pairwise Cipher is not valid"},
2699     {0x14, "AKMP is not valid"},
2700     {0x15, "Unsupported RSN IE version"},
2701     {0x16, "Invalid RSN IE Capabilities"},
2702     {0x17, "IEEE 802.1X Authentication failed"},
2703     {0x18, "Cipher suite is rejected per security policy"},
2704     {0x00, NULL}
2705   };
2706
2707
2708   static const value_string status_codes[] = {
2709     {0x00, "Successful"},
2710     {0x01, "Unspecified failure"},
2711     {0x0A, "Cannot support all requested capabilities in the "
2712      "Capability information field"},
2713     {0x0B, "Reassociation denied due to inability to confirm that "
2714      "association exists"},
2715     {0x0C, "Association denied due to reason outside the scope of this "
2716      "standard"},
2717
2718     {0x0D, "Responding station does not support the specified authentication "
2719      "algorithm"},
2720     {0x0E, "Received an Authentication frame with authentication sequence "
2721      "transaction sequence number out of expected sequence"},
2722     {0x0F, "Authentication rejected because of challenge failure"},
2723     {0x10, "Authentication rejected due to timeout waiting for next "
2724      "frame in sequence"},
2725     {0x11, "Association denied because AP is unable to handle additional "
2726      "associated stations"},
2727     {0x12, "Association denied due to requesting station not supporting all "
2728      "of the datarates in the BSSBasicServiceSet Parameter"},
2729     {0x13, "Association denied due to requesting station not supporting "
2730      "short preamble operation"},
2731     {0x14, "Association denied due to requesting station not supporting "
2732      "PBCC encoding"},
2733     {0x15, "Association denied due to requesting station not supporting "
2734      "channel agility"},
2735     {0x19, "Association denied due to requesting station not supporting "
2736      "short slot operation"},
2737     {0x1A, "Association denied due to requesting station not supporting "
2738      "DSSS-OFDM operation"},
2739     {0x28, "Invalid Information Element"},
2740     {0x29, "Group Cipher is not valid"},
2741     {0x2A, "Pairwise Cipher is not valid"},
2742     {0x2B, "AKMP is not valid"},
2743     {0x2C, "Unsupported RSN IE version"},
2744     {0x2D, "Invalid RSN IE Capabilities"},
2745     {0x2E, "Cipher suite is rejected per security policy"},
2746     {0x00, NULL}
2747   };
2748
2749   static const value_string category_codes[] = {
2750     {0x11, "Management notification frame"},
2751     {0x00, NULL}
2752   };
2753
2754   static const value_string action_codes[] = {
2755     {0x00, NULL}
2756   };
2757
2758   static const value_string wme_action_codes[] = {
2759     {0x00, "Setup request"},
2760     {0x01, "Setup response"},
2761     {0x02, "Teardown"},
2762     {0x00, NULL}
2763   };
2764
2765   static const value_string wme_status_codes[] = {
2766     {0x00, "Admission accepted"},
2767     {0x01, "Invalid parameters"},
2768     {0x03, "Refused"},
2769     {0x00, NULL}
2770   };
2771
2772   static hf_register_info hf[] = {
2773     {&hf_data_rate,
2774      {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2775       "Data rate (.5 Mb/s units)", HFILL }},
2776
2777     {&hf_channel,
2778      {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2779       "Radio channel", HFILL }},
2780
2781     {&hf_signal_strength,
2782      {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2783       "Signal strength (percentage)", HFILL }},
2784
2785     {&hf_fc_field,
2786      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2787       "MAC Frame control", HFILL }},
2788
2789     {&hf_fc_proto_version,
2790      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2791       "MAC Protocol version", HFILL }}, /* 0 */
2792
2793     {&hf_fc_frame_type,
2794      {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2795       "Frame type", HFILL }},
2796
2797     {&hf_fc_frame_subtype,
2798      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2799       "Frame subtype", HFILL }},        /* 2 */
2800
2801     {&hf_fc_frame_type_subtype,
2802      {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2803       "Type and subtype combined", HFILL }},
2804
2805     {&hf_fc_flags,
2806      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2807       "Protocol flags", HFILL }},
2808
2809     {&hf_fc_data_ds,
2810      {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2811       "Data-frame DS-traversal status", HFILL }},       /* 3 */
2812
2813     {&hf_fc_to_ds,
2814      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2815       "To DS flag", HFILL }},           /* 4 */
2816
2817     {&hf_fc_from_ds,
2818      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2819       "From DS flag", HFILL }},         /* 5 */
2820
2821     {&hf_fc_more_frag,
2822      {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2823       "More Fragments flag", HFILL }},  /* 6 */
2824
2825     {&hf_fc_retry,
2826      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2827       "Retransmission flag", HFILL }},
2828
2829     {&hf_fc_pwr_mgt,
2830      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2831       "Power management status", HFILL }},
2832
2833     {&hf_fc_more_data,
2834      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2835       "More data flag", HFILL }},
2836
2837     {&hf_fc_wep,
2838      {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2839       "WEP flag", HFILL }},
2840
2841     {&hf_fc_order,
2842      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2843       "Strictly ordered flag", HFILL }},
2844
2845     {&hf_assoc_id,
2846      {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2847       "Association-ID field", HFILL }},
2848
2849     {&hf_did_duration,
2850      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2851       "Duration field", HFILL }},
2852
2853     {&hf_addr_da,
2854      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2855       "Destination Hardware Address", HFILL }},
2856
2857     {&hf_addr_sa,
2858      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2859       "Source Hardware Address", HFILL }},
2860
2861     { &hf_addr,
2862       {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2863        "Source or Destination Hardware Address", HFILL }},
2864
2865     {&hf_addr_ra,
2866      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2867       "Receiving Station Hardware Address", HFILL }},
2868
2869     {&hf_addr_ta,
2870      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2871       "Transmitting Station Hardware Address", HFILL }},
2872
2873     {&hf_addr_bssid,
2874      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2875       "Basic Service Set ID", HFILL }},
2876
2877     {&hf_frag_number,
2878      {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2879       "Fragment number", HFILL }},
2880
2881     {&hf_seq_number,
2882      {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2883       "Sequence number", HFILL }},
2884
2885     {&hf_qos_priority,
2886      {"Priority", "wlan.qos.priority", FT_UINT16, BASE_DEC, NULL, 0,
2887       "802.1D Tag", HFILL }},
2888
2889     {&hf_qos_ack_policy,
2890      {"Ack Policy", "wlan.qos.ack", FT_UINT16, BASE_DEC, NULL, 0,
2891       "Ack Policy", HFILL }},
2892
2893     {&hf_fcs,
2894      {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
2895       NULL, 0, "FCS", HFILL }},
2896
2897     {&hf_fragment_overlap,
2898       {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2899        NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2900
2901     {&hf_fragment_overlap_conflict,
2902       {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2903        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2904        "Overlapping fragments contained conflicting data", HFILL }},
2905
2906     {&hf_fragment_multiple_tails,
2907       {"Multiple tail fragments found", "wlan.fragment.multipletails",
2908        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2909        "Several tails were found when defragmenting the packet", HFILL }},
2910
2911     {&hf_fragment_too_long_fragment,
2912       {"Fragment too long", "wlan.fragment.toolongfragment",
2913        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2914        "Fragment contained data past end of packet", HFILL }},
2915
2916     {&hf_fragment_error,
2917       {"Defragmentation error", "wlan.fragment.error",
2918        FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2919        "Defragmentation error due to illegal fragments", HFILL }},
2920
2921     {&hf_fragment,
2922       {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2923        "802.11 Fragment", HFILL }},
2924
2925     {&hf_fragments,
2926       {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2927        "802.11 Fragments", HFILL }},
2928
2929     {&hf_reassembled_in,
2930       {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2931        "This 802.11 packet is reassembled in this frame", HFILL }},
2932
2933     {&hf_wep_iv,
2934      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2935       "Initialization Vector", HFILL }},
2936
2937     {&hf_tkip_extiv,
2938      {"TKIP Ext. Initialization Vector", "wlan.tkip.extiv", FT_STRING,
2939       BASE_HEX, NULL, 0, "TKIP Extended Initialization Vector", HFILL }},
2940
2941     {&hf_ccmp_extiv,
2942      {"CCMP Ext. Initialization Vector", "wlan.ccmp.extiv", FT_STRING,
2943       BASE_HEX, NULL, 0, "CCMP Extended Initialization Vector", HFILL }},
2944
2945     {&hf_wep_key,
2946      {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
2947       "Key", HFILL }},
2948
2949     {&hf_wep_icv,
2950      {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
2951       "WEP ICV", HFILL }},
2952   };
2953
2954   static const true_false_string rsn_preauth_flags = {
2955     "Transmitter supports pre-authentication",
2956     "Transmitter does not support pre-authentication"
2957   };
2958
2959   static const true_false_string rsn_no_pairwise_flags = {
2960     "Transmitter cannot support WEP default key 0 simultaneously with "
2961     "Pairwise key",
2962     "Transmitter can support WEP default key 0 simultaneously with "
2963     "Pairwise key"
2964   };
2965
2966   static const value_string rsn_cap_replay_counter[] = {
2967     {0x00, "1 replay counter per PTKSA/GTKSA/STAKeySA"},
2968     {0x01, "2 replay counters per PTKSA/GTKSA/STAKeySA"},
2969     {0x02, "4 replay counters per PTKSA/GTKSA/STAKeySA"},
2970     {0x03, "16 replay counters per PTKSA/GTKSA/STAKeySA"},
2971     {0, NULL}
2972   };
2973
2974   static hf_register_info ff[] = {
2975     {&ff_timestamp,
2976      {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
2977       NULL, 0, "", HFILL }},
2978
2979     {&ff_auth_alg,
2980      {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
2981       FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
2982
2983     {&ff_beacon_interval,
2984      {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
2985       "", HFILL }},
2986
2987     {&hf_fixed_parameters,
2988      {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
2989       "", HFILL }},
2990
2991     {&hf_tagged_parameters,
2992      {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
2993       "", HFILL }},
2994
2995     {&ff_capture,
2996      {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
2997       "Capability information", HFILL }},
2998
2999     {&ff_cf_ess,
3000      {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
3001       FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
3002
3003     {&ff_cf_ibss,
3004      {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
3005       FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
3006
3007     {&ff_cf_sta_poll,
3008      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
3009       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C,
3010       "CF-Poll capabilities for a STA", HFILL }},
3011
3012     {&ff_cf_ap_poll,
3013      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
3014       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C,
3015       "CF-Poll capabilities for an AP", HFILL }},
3016
3017     {&ff_cf_privacy,
3018      {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
3019       FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
3020
3021     {&ff_cf_preamble,
3022      {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
3023       FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
3024
3025     {&ff_cf_pbcc,
3026      {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
3027       FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
3028
3029     {&ff_cf_agility,
3030      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
3031       FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
3032
3033     {&ff_short_slot_time,
3034      {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
3035       FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
3036       HFILL }},
3037
3038     {&ff_dsss_ofdm,
3039      {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
3040       FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
3041       HFILL }},
3042
3043     {&ff_auth_seq,
3044      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
3045       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
3046
3047     {&ff_assoc_id,
3048      {"Association ID", "wlan_mgt.fixed.aid",
3049       FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
3050
3051     {&ff_listen_ival,
3052      {"Listen Interval", "wlan_mgt.fixed.listen_ival",
3053       FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
3054
3055     {&ff_current_ap,
3056      {"Current AP", "wlan_mgt.fixed.current_ap",
3057       FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
3058
3059     {&ff_reason,
3060      {"Reason code", "wlan_mgt.fixed.reason_code",
3061       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
3062       "Reason for unsolicited notification", HFILL }},
3063
3064     {&ff_status_code,
3065      {"Status code", "wlan_mgt.fixed.status_code",
3066       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
3067       "Status of requested event", HFILL }},
3068
3069     {&ff_category_code,
3070      {"Category code", "wlan_mgt.fixed.category_code",
3071       FT_UINT16, BASE_HEX, VALS (&category_codes), 0,
3072       "Management action category", HFILL }},
3073
3074     {&ff_action_code,
3075      {"Action code", "wlan_mgt.fixed.action_code",
3076       FT_UINT16, BASE_HEX, VALS (&action_codes), 0,
3077       "Management action code", HFILL }},
3078
3079     {&ff_dialog_token,
3080      {"Dialog token", "wlan_mgt.fixed.dialog_token",
3081       FT_UINT16, BASE_HEX, NULL, 0, "Management action dialog token", HFILL }},
3082
3083     {&ff_wme_action_code,
3084      {"Action code", "wlan_mgt.fixed.action_code",
3085       FT_UINT16, BASE_HEX, VALS (&wme_action_codes), 0,
3086       "Management notification action code", HFILL }},
3087
3088     {&ff_wme_status_code,
3089      {"Status code", "wlan_mgt.fixed.status_code",
3090       FT_UINT16, BASE_HEX, VALS (&wme_status_codes), 0,
3091       "Management notification setup response status code", HFILL }},
3092
3093     {&tag_number,
3094      {"Tag", "wlan_mgt.tag.number",
3095       FT_UINT8, BASE_DEC, VALS(tag_num_vals), 0,
3096       "Element ID", HFILL }},
3097
3098     {&tag_length,
3099      {"Tag length", "wlan_mgt.tag.length",
3100       FT_UINT8, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
3101
3102     {&tag_interpretation,
3103      {"Tag interpretation", "wlan_mgt.tag.interpretation",
3104       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }},
3105
3106     {&rsn_cap,
3107      {"RSN Capabilities", "wlan_mgt.rsn.capabilities", FT_UINT16, BASE_HEX,
3108       NULL, 0, "RSN Capability information", HFILL }},
3109
3110     {&rsn_cap_preauth,
3111      {"RSN Pre-Auth capabilities", "wlan_mgt.rsn.capabilities.preauth",
3112       FT_BOOLEAN, 16, TFS (&rsn_preauth_flags), 0x0001,
3113       "RSN Pre-Auth capabilities", HFILL }},
3114
3115     {&rsn_cap_no_pairwise,
3116      {"RSN No Pairwise capabilities", "wlan_mgt.rsn.capabilities.no_pairwise",
3117       FT_BOOLEAN, 16, TFS (&rsn_no_pairwise_flags), 0x0002,
3118       "RSN No Pairwise capabilities", HFILL }},
3119
3120     {&rsn_cap_ptksa_replay_counter,
3121      {"RSN PTKSA Replay Counter capabilities",
3122       "wlan_mgt.rsn.capabilities.ptksa_replay_counter",
3123       FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x000C,
3124       "RSN PTKSA Replay Counter capabilities", HFILL }},
3125
3126     {&rsn_cap_gtksa_replay_counter,
3127      {"RSN GTKSA Replay Counter capabilities",
3128       "wlan_mgt.rsn.capabilities.gtksa_replay_counter",
3129       FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x0030,
3130       "RSN GTKSA Replay Counter capabilities", HFILL }},
3131   };
3132
3133   static gint *tree_array[] = {
3134     &ett_80211,
3135     &ett_fc_tree,
3136     &ett_proto_flags,
3137     &ett_fragments,
3138     &ett_fragment,
3139     &ett_80211_mgt,
3140     &ett_fixed_parameters,
3141     &ett_tagged_parameters,
3142     &ett_qos_parameters,
3143     &ett_wep_parameters,
3144     &ett_cap_tree,
3145     &ett_rsn_cap_tree,
3146   };
3147   module_t *wlan_module;
3148
3149   static const enum_val_t wep_keys_options[] = {
3150     {"0", "0", 0},
3151     {"1", "1", 1},
3152     {"2", "2", 2},
3153     {"3", "3", 3},
3154     {"4", "4", 4},
3155     {NULL, NULL, -1},
3156   };
3157
3158
3159   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
3160                                         "IEEE 802.11", "wlan");
3161   proto_register_field_array (proto_wlan, hf, array_length (hf));
3162   proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
3163                                         "802.11 MGT", "wlan_mgt");
3164   proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
3165   proto_register_subtree_array (tree_array, array_length (tree_array));
3166
3167   register_dissector("wlan", dissect_ieee80211, proto_wlan);
3168   register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
3169   register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
3170   register_init_routine(wlan_defragment_init);
3171
3172   /* Register configuration options */
3173   wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);
3174   prefs_register_bool_preference(wlan_module, "defragment",
3175         "Reassemble fragmented 802.11 datagrams",
3176         "Whether fragmented 802.11 datagrams should be reassembled",
3177         &wlan_defragment);
3178
3179   prefs_register_bool_preference(wlan_module, "check_fcs",
3180                                  "Assume packets have FCS",
3181                                  "Some 802.11 cards include the FCS at the end of a packet, others do not.",
3182                                  &wlan_check_fcs);
3183
3184   prefs_register_bool_preference(wlan_module, "ignore_wep",
3185                                  "Ignore the WEP bit",
3186                                  "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
3187                                  &wlan_ignore_wep);
3188
3189 #ifndef USE_ENV
3190   prefs_register_enum_preference(wlan_module, "wep_keys",
3191                                  "WEP key count",
3192                                  "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
3193                                  &num_wepkeys, wep_keys_options, FALSE);
3194
3195   prefs_register_string_preference(wlan_module, "wep_key1",
3196                                    "WEP key #1",
3197                                    "First WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
3198                                    &wep_keystr[0]);
3199   prefs_register_string_preference(wlan_module, "wep_key2",
3200                                    "WEP key #2",
3201                                    "Second WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
3202                                    &wep_keystr[1]);
3203   prefs_register_string_preference(wlan_module, "wep_key3",
3204                                    "WEP key #3",
3205                                    "Third WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
3206                                    &wep_keystr[2]);
3207   prefs_register_string_preference(wlan_module, "wep_key4",
3208                                    "WEP key #4",
3209                                    "Fourth WEP key (A:B:C:D:E) [40bit] (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
3210                                    &wep_keystr[3]);
3211 #endif
3212 }
3213
3214 void
3215 proto_reg_handoff_ieee80211(void)
3216 {
3217   dissector_handle_t ieee80211_handle;
3218   dissector_handle_t ieee80211_radio_handle;
3219
3220   /*
3221    * Get handles for the LLC, IPX and Ethernet  dissectors.
3222    */
3223   llc_handle = find_dissector("llc");
3224   ipx_handle = find_dissector("ipx");
3225   eth_handle = find_dissector("eth");
3226   data_handle = find_dissector("data");
3227
3228   ieee80211_handle = find_dissector("wlan");
3229   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
3230   ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
3231                                                    proto_wlan);
3232   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
3233                 ieee80211_radio_handle);
3234 }
3235
3236 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
3237   const guint8 *enc_data;
3238   guint8 *tmp = NULL;
3239   int i;
3240   tvbuff_t *decr_tvb = NULL;
3241
3242   if (num_wepkeys < 1)
3243     return NULL;
3244
3245   enc_data = tvb_get_ptr(tvb, offset, len);
3246
3247   if ((tmp = g_malloc(len)) == NULL)
3248     return NULL;  /* krap! */
3249
3250   /* try once with the key index in the packet, then look through our list. */
3251   for (i = -1; i < (int) num_wepkeys; i++) {
3252     /* copy the encrypted data over to the tmp buffer */
3253 #if 0
3254     printf("trying %d\n", i);
3255 #endif
3256     memcpy(tmp, enc_data, len);
3257     if (wep_decrypt(tmp, len, i) == 0) {
3258
3259       /* decrypt successful, let's set up a new data tvb. */
3260       decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
3261       tvb_set_free_cb(decr_tvb, g_free);
3262       tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
3263
3264       goto done;
3265     }
3266   }
3267
3268  done:
3269   if ((!decr_tvb) && (tmp))    g_free(tmp);
3270
3271 #if 0
3272   printf("de-wep %p\n", decr_tvb);
3273 #endif
3274
3275   return decr_tvb;
3276 }
3277
3278
3279 /* de-weps the block.  if successful, buf* will point to the data start. */
3280 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
3281   guint32 i, j, k, crc, keylen;
3282   guint8 s[256], key[128], c_crc[4];
3283   guint8 keyidx, *dpos, *cpos;
3284
3285   /* Needs to be at least 8 bytes of payload */
3286   if (len < 8)
3287     return -1;
3288
3289   /* initialize the first bytes of the key from the IV */
3290   key[0] = buf[0];
3291   key[1] = buf[1];
3292   key[2] = buf[2];
3293   keyidx = COOK_WEP_KEY(buf[3]);
3294
3295   if (key_override >= 0)
3296     keyidx = key_override;
3297
3298   if (keyidx >= num_wepkeys)
3299     return -1;
3300
3301   keylen = wep_keylens[keyidx];
3302
3303   if (keylen == 0)
3304     return -1;
3305   if (wep_keys[keyidx] == NULL)
3306     return -1;
3307
3308   keylen+=3;  /* add in ICV bytes */
3309
3310   /* copy the rest of the key over from the designated key */
3311   memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
3312
3313 #if 0
3314   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]);
3315 #endif
3316
3317   /* set up the RC4 state */
3318   for (i = 0; i < 256; i++)
3319     s[i] = i;
3320   j = 0;
3321   for (i = 0; i < 256; i++) {
3322     j = (j + s[i] + key[i % keylen]) & 0xff;
3323     SSWAP(i,j);
3324   }
3325
3326   /* Apply the RC4 to the data, update the CRC32 */
3327   cpos = buf+4;
3328   dpos = buf;
3329   crc = ~0;
3330   i = j = 0;
3331   for (k = 0; k < (len -8); k++) {
3332     i = (i+1) & 0xff;
3333     j = (j+s[i]) & 0xff;
3334     SSWAP(i,j);
3335 #if 0
3336     printf("%d -- %02x ", k, *dpos);
3337 #endif
3338     *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
3339 #if 0
3340     printf("%02x\n", *dpos);
3341 #endif
3342     crc = crc32_ccitt_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
3343   }
3344   crc = ~crc;
3345
3346   /* now let's check the crc */
3347   c_crc[0] = crc;
3348   c_crc[1] = crc >> 8;
3349   c_crc[2] = crc >> 16;
3350   c_crc[3] = crc >> 24;
3351
3352   for (k = 0; k < 4; k++) {
3353     i = (i + 1) & 0xff;
3354     j = (j+s[i]) & 0xff;
3355     SSWAP(i,j);
3356 #if 0
3357     printf("-- %02x %02x\n", *dpos, c_crc[k]);
3358 #endif
3359     if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
3360       return -1; /* ICV mismatch */
3361   }
3362
3363   return 0;
3364 }
3365
3366 static void init_wepkeys(void) {
3367   char *tmp;
3368   guint i;
3369   GByteArray *bytes;
3370   gboolean res;
3371
3372 #ifdef USE_ENV
3373   guint8 buf[128];
3374
3375   tmp = getenv("ETHEREAL_WEPKEYNUM");
3376   if (!tmp) {
3377     num_wepkeys = 0;
3378     return;
3379   }
3380   num_wepkeys = atoi(tmp);
3381 #else
3382   if (num_wepkeys > 4)
3383     num_wepkeys = 4;
3384 #endif
3385
3386   if (num_wepkeys < 1)
3387     return;
3388
3389   if (wep_keys)
3390     g_free(wep_keys);
3391
3392   if (wep_keylens)
3393     g_free(wep_keylens);
3394
3395   wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
3396   wep_keylens = g_malloc(num_wepkeys * sizeof(int));
3397   bytes = g_byte_array_new();
3398
3399   for (i = 0 ; i < num_wepkeys; i++) {
3400     wep_keys[i] = NULL;
3401     wep_keylens[i] = 0;
3402
3403 #ifdef USE_ENV
3404     sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
3405     tmp = getenv(buf);
3406 #else
3407     tmp = wep_keystr[i];
3408 #endif
3409
3410     if (tmp) {
3411 #if 0
3412 #ifdef USE_ENV
3413       printf("%s -- %s\n", buf, tmp);
3414 #else
3415       printf("%d -- %s\n", i+1, tmp);
3416 #endif
3417 #endif
3418
3419       if (wep_keys[i]) {
3420         g_free(wep_keys[i]);
3421       }
3422
3423       res = hex_str_to_bytes(tmp, bytes, FALSE);
3424       if (res && bytes->len > 0) {
3425         if (bytes->len > 32) {
3426           bytes->len = 32;
3427         }
3428         wep_keys[i] = g_malloc(32 * sizeof(guint8));
3429         memset(wep_keys[i], 0, 32 * sizeof(guint8));
3430         memcpy(wep_keys[i], bytes->data, bytes->len * sizeof(guint8));
3431         wep_keylens[i] = bytes->len;
3432 #if 0
3433         printf("%d: %d bytes\n", i, bytes->len);
3434         printf("%d: %s\n", i, bytes_to_str(bytes->data, bytes->len));
3435 #endif
3436       } else {
3437 #if 0
3438         printf("res: %d  bytes->len: %d\n", res, bytes->len);
3439 #endif
3440         g_warning("Could not parse WEP key %d: %s", i + 1, tmp);
3441       }
3442     }
3443   }
3444   g_byte_array_free(bytes, TRUE);
3445 }