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