Ethereal->Wireshark
[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  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
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 #include <string.h>
54 #include <glib.h>
55 #include <epan/bitswap.h>
56 #include <epan/proto.h>
57 #include <epan/packet.h>
58 #include <epan/addr_resolv.h>
59 #include <epan/strutil.h>
60 #include <epan/prefs.h>
61 #include <epan/reassemble.h>
62 #include "packet-ipx.h"
63 #include "packet-llc.h"
64 #include "packet-ieee80211.h"
65 #include <epan/etypes.h>
66 #include <epan/crc32.h>
67 #include <epan/tap.h>
68 #include <epan/emem.h>
69
70 #include <ctype.h>
71 #include "isprint.h"
72
73 #ifndef roundup2
74 #define roundup2(x, y)  (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
75 #endif
76
77 /* Defragment fragmented 802.11 datagrams */
78 static gboolean wlan_defragment = TRUE;
79
80 /* Check for the presence of the 802.11 FCS */
81 static gboolean wlan_check_fcs = FALSE;
82
83 /* Ignore the WEP bit; assume packet is decrypted */
84 static gboolean wlan_ignore_wep = FALSE;
85
86 /* Tables for reassembly of fragments. */
87 static GHashTable *wlan_fragment_table = NULL;
88 static GHashTable *wlan_reassembled_table = NULL;
89
90 /* Stuff for the WEP decoder */
91 static gint num_wepkeys = 0;
92 static guint8 **wep_keys = NULL;
93 static int *wep_keylens = NULL;
94 static void init_wepkeys(void);
95 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
96 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
97 static int weak_iv(guchar *iv);
98 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
99
100 /* #define USE_ENV */
101 /* When this is set, an unlimited number of WEP keys can be set in the
102    environment:
103
104    WIRESHARK_WEPKEYNUM=##
105    WIRESHARK_WEPKEY1=aa:bb:cc:dd:...
106    WIRESHARK_WEPKEY2=aa:bab:cc:dd:ee:...
107
108    ... you get the idea.
109
110    otherwise you're limited to specifying four keys in the preference system.
111  */
112
113 #ifndef USE_ENV
114 static const char *wep_keystr[] = {NULL, NULL, NULL, NULL};
115 #endif
116
117 /* ************************************************************************* */
118 /*                          Miscellaneous Constants                          */
119 /* ************************************************************************* */
120 #define SHORT_STR 256
121
122 /* ************************************************************************* */
123 /*  Define some very useful macros that are used to analyze frame types etc. */
124 /* ************************************************************************* */
125
126 /*
127  * Extract the protocol version from the frame control field
128  */
129 #define FCF_PROT_VERSION(x)  ((x) & 0x3)
130
131 /*
132  * Extract the frame type from the frame control field.
133  */
134 #define FCF_FRAME_TYPE(x)    (((x) & 0xC) >> 2)
135
136 /*
137  * Extract the frame subtype from the frame control field.
138  */
139 #define FCF_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
140
141 /*
142  * Convert the frame type and subtype from the frame control field into
143  * one of the MGT_, CTRL_, or DATA_ values.
144  */
145 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+FCF_FRAME_SUBTYPE(x))   /* Create key to (sub)type */
146
147 /*
148  * The subtype field of a data frame is, in effect, composed of 4 flag
149  * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have
150  * any data), and QoS.
151  */
152 #define DATA_FRAME_IS_CF_ACK(x)  ((x) & 0x01)
153 #define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02)
154 #define DATA_FRAME_IS_NULL(x)    ((x) & 0x04)
155 #define DATA_FRAME_IS_QOS(x)     ((x) & 0x08)
156
157 /*
158  * Extract the flags from the frame control field.
159  */
160 #define FCF_FLAGS(x)           (((x) & 0xFF00) >> 8)
161
162 /*
163  * Bits from the flags field.
164  */
165 #define FLAG_TO_DS              0x01
166 #define FLAG_FROM_DS            0x02
167 #define FLAG_MORE_FRAGMENTS     0x04
168 #define FLAG_RETRY              0x08
169 #define FLAG_POWER_MGT          0x10
170 #define FLAG_MORE_DATA          0x20
171 #define FLAG_PROTECTED          0x40
172 #define FLAG_ORDER              0x80
173
174 /*
175  * Test bits in the flags field.
176  */
177 #define IS_TO_DS(x)            ((x) & FLAG_TO_DS)
178 #define IS_FROM_DS(x)          ((x) & FLAG_FROM_DS)
179 #define HAVE_FRAGMENTS(x)      ((x) & FLAG_MORE_FRAGMENTS)
180 #define IS_RETRY(x)            ((x) & FLAG_RETRY)
181 #define POWER_MGT_STATUS(x)    ((x) & FLAG_POWER_MGT)
182 #define HAS_MORE_DATA(x)       ((x) & FLAG_MORE_DATA)
183 #define IS_PROTECTED(x)        (!wlan_ignore_wep && ((x) & FLAG_PROTECTED))
184 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
185
186 /*
187  * Extract subfields from the flags field.
188  */
189 #define FLAGS_DS_STATUS(x)          ((x) & (FLAG_FROM_DS|FLAG_TO_DS))
190
191 /*
192  * Extract an indication of the types of addresses in a data frame from
193  * the frame control field.
194  */
195 #define FCF_ADDR_SELECTOR(x) ((x) & ((FLAG_TO_DS|FLAG_FROM_DS) << 8))
196
197 #define DATA_ADDR_T1         0
198 #define DATA_ADDR_T2         (FLAG_FROM_DS << 8)
199 #define DATA_ADDR_T3         (FLAG_TO_DS << 8)
200 #define DATA_ADDR_T4         ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
201
202 /*
203  * Extract the fragment number and sequence number from the sequence
204  * control field.
205  */
206 #define SEQCTL_FRAGMENT_NUMBER(x) ((x) & 0x000F)
207 #define SEQCTL_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
208
209 /*
210  * Extract subfields from the QoS control field.
211  */
212 #define QOS_TID(x)            ((x) & 0x000F)
213 #define QOS_PRIORITY(x)       ((x) & 0x0007)
214 #define QOS_EOSP(x)           (((x) & 0x0010) >> 4) /* end of service period */
215 #define QOS_ACK_POLICY(x)     (((x) & 0x0060) >> 5)
216 #define QOS_FIELD_CONTENT(x)  (((x) & 0xFF00) >> 8)
217
218 #define QOS_FLAG_EOSP           0x08
219
220 /*
221  * Extract subfields from the result of QOS_FIELD_CONTENT().
222  */
223 #define QOS_PS_BUF_STATE(x)     (((x) & 0x02) >> 1)
224 #define QOS_PS_BUF_AC(x)        (((x) & 0x0C) >> 2)
225 #define QOS_PS_BUF_LOAD(x)      (((x) & 0xF0) >> 4)
226
227 /*
228  * Extract the association ID from the value in an association ID field.
229  */
230 #define ASSOC_ID(x)             ((x) & 0x3FFF)
231
232 /*
233  * Extract subfields from the key octet in WEP-encrypted frames.
234  */
235 #define KEY_OCTET_WEP_KEY(x)    (((x) & 0xC0) >> 6)
236
237 #define KEY_EXTIV               0x20
238 #define EXTIV_LEN               8
239
240
241 /* ************************************************************************* */
242 /*              Constants used to identify cooked frame types                */
243 /* ************************************************************************* */
244 #define MGT_FRAME            0x00       /* Frame type is management */
245 #define CONTROL_FRAME        0x01       /* Frame type is control */
246 #define DATA_FRAME           0x02       /* Frame type is Data */
247
248 #define DATA_SHORT_HDR_LEN     24
249 #define DATA_LONG_HDR_LEN      30
250 #define MGT_FRAME_HDR_LEN      24       /* Length of Managment frame-headers */
251
252 /*
253  * COMPOSE_FRAME_TYPE() values for management frames.
254  */
255 #define MGT_ASSOC_REQ        0x00       /* association request        */
256 #define MGT_ASSOC_RESP       0x01       /* association response       */
257 #define MGT_REASSOC_REQ      0x02       /* reassociation request      */
258 #define MGT_REASSOC_RESP     0x03       /* reassociation response     */
259 #define MGT_PROBE_REQ        0x04       /* Probe request              */
260 #define MGT_PROBE_RESP       0x05       /* Probe response             */
261 #define MGT_BEACON           0x08       /* Beacon frame               */
262 #define MGT_ATIM             0x09       /* ATIM                       */
263 #define MGT_DISASS           0x0A       /* Disassociation             */
264 #define MGT_AUTHENTICATION   0x0B       /* Authentication             */
265 #define MGT_DEAUTHENTICATION 0x0C       /* Deauthentication           */
266 #define MGT_ACTION           0x0D       /* Action */
267
268 /*
269  * COMPOSE_FRAME_TYPE() values for control frames.
270  */
271 #define CTRL_BLOCK_ACK_REQ   0x18       /* Block ack Request                */
272 #define CTRL_BLOCK_ACK       0x19       /* Block ack                        */
273 #define CTRL_PS_POLL         0x1A       /* power-save poll               */
274 #define CTRL_RTS             0x1B       /* request to send               */
275 #define CTRL_CTS             0x1C       /* clear to send                 */
276 #define CTRL_ACKNOWLEDGEMENT 0x1D       /* acknowledgement               */
277 #define CTRL_CFP_END         0x1E       /* contention-free period end    */
278 #define CTRL_CFP_ENDACK      0x1F       /* contention-free period end/ack */
279
280 /*
281  * COMPOSE_FRAME_TYPE() values for data frames.
282  */
283 #define DATA                        0x20        /* Data                       */
284 #define DATA_CF_ACK                 0x21        /* Data + CF-Ack              */
285 #define DATA_CF_POLL                0x22        /* Data + CF-Poll             */
286 #define DATA_CF_ACK_POLL            0x23        /* Data + CF-Ack + CF-Poll    */
287 #define DATA_NULL_FUNCTION          0x24        /* Null function (no data)    */
288 #define DATA_CF_ACK_NOD             0x25        /* CF-Ack (no data)           */
289 #define DATA_CF_POLL_NOD            0x26        /* CF-Poll (No data)          */
290 #define DATA_CF_ACK_POLL_NOD        0x27        /* CF-Ack + CF-Poll (no data) */
291
292 #define DATA_QOS_DATA               0x28        /* QoS Data                   */
293 #define DATA_QOS_DATA_CF_ACK        0x29        /* QoS Data + CF-Ack          */
294 #define DATA_QOS_DATA_CF_POLL       0x2A        /* QoS Data + CF-Poll             */
295 #define DATA_QOS_DATA_CF_ACK_POLL   0x2B        /* QoS Data + CF-Ack + CF-Poll    */
296 #define DATA_QOS_NULL               0x2C        /* QoS Null                       */
297 #define DATA_QOS_CF_POLL_NOD        0x2E        /* QoS CF-Poll (No Data)                  */
298 #define DATA_QOS_CF_ACK_POLL_NOD    0x2F        /* QoS CF-Ack + CF-Poll (No Data) */
299
300
301 /* ************************************************************************* */
302 /*          Macros used to extract information about fixed fields            */
303 /* ************************************************************************* */
304 #define ESS_SET(x) ((x) & 0x0001)
305 #define IBSS_SET(x) ((x) & 0x0002)
306
307
308
309 /* ************************************************************************* */
310 /*        Logical field codes (dissector's encoding of fixed fields)         */
311 /* ************************************************************************* */
312 #define FIELD_TIMESTAMP       0x01      /* 64-bit timestamp                       */
313 #define FIELD_BEACON_INTERVAL 0x02      /* 16-bit beacon interval                 */
314 #define FIELD_CAP_INFO        0x03      /* Add capability information tree        */
315 #define FIELD_AUTH_ALG        0x04      /* Authentication algorithm used          */
316 #define FIELD_AUTH_TRANS_SEQ  0x05      /* Authentication sequence number         */
317 #define FIELD_CURRENT_AP_ADDR 0x06
318 #define FIELD_LISTEN_IVAL     0x07
319 #define FIELD_REASON_CODE     0x08
320 #define FIELD_ASSOC_ID        0x09
321 #define FIELD_STATUS_CODE     0x0A
322 #define FIELD_CATEGORY_CODE   0x0B      /* Management action category */
323 #define FIELD_ACTION_CODE     0x0C      /* Management action code */
324 #define FIELD_DIALOG_TOKEN    0x0D      /* Management action dialog token */
325 #define FIELD_WME_ACTION_CODE   0x0E    /* Management notification action code */
326 #define FIELD_WME_DIALOG_TOKEN  0x0F    /* Management notification dialog token */
327 #define FIELD_WME_STATUS_CODE   0x10    /* Management notification setup response status code */
328
329 /* ************************************************************************* */
330 /*        Logical field codes (IEEE 802.11 encoding of tags)                 */
331 /* ************************************************************************* */
332 #define TAG_SSID                 0x00
333 #define TAG_SUPP_RATES           0x01
334 #define TAG_FH_PARAMETER         0x02
335 #define TAG_DS_PARAMETER         0x03
336 #define TAG_CF_PARAMETER         0x04
337 #define TAG_TIM                  0x05
338 #define TAG_IBSS_PARAMETER       0x06
339 #define TAG_COUNTRY_INFO         0x07
340 #define TAG_FH_HOPPING_PARAMETER 0x08
341 #define TAG_FH_HOPPING_TABLE     0x09
342 #define TAG_REQUEST              0x0A
343 #define TAG_QBSS_LOAD            0x0B
344 #define TAG_EDCA_PARAM_SET       0x0C
345 #define TAG_TRAF_SPEC            0x0D
346 #define TAG_TRAF_CLASS           0x0E
347 #define TAG_SCHEDULE             0x0F
348 #define TAG_CHALLENGE_TEXT       0x10
349 #define TAG_POWER_CONSTRAINT     0x20
350 #define TAG_POWER_CAPABILITY     0x21
351 #define TAG_TPC_REQUEST          0x22
352 #define TAG_TPC_REPORT           0x23
353 #define TAG_SUPPORTED_CHANNELS   0x24
354 #define TAG_CHANNEL_SWITCH_ANN   0x25
355 #define TAG_MEASURE_REQ          0x26
356 #define TAG_MEASURE_REP          0x27
357 #define TAG_QUIET                0x28
358 #define TAG_IBSS_DFS             0x29
359 #define TAG_ERP_INFO             0x2A
360 #define TAG_TS_DELAY             0x2B
361 #define TAG_TCLAS_PROCESS        0x2C
362 #define TAG_QOS_CAPABILITY       0x2E
363 #define TAG_ERP_INFO_OLD         0x2F   /* IEEE Std 802.11g/D4.0 */
364 #define TAG_RSN_IE               0x30
365 #define TAG_EXT_SUPP_RATES       0x32
366 #define TAG_AGERE_PROPRIETARY    0x80
367 #define TAG_CISCO_UNKNOWN_1      0x85   /* Cisco Compatible eXtensions? */
368 #define TAG_CISCO_UNKNOWN_2      0x88   /* Cisco Compatible eXtensions? */
369 #define TAG_VENDOR_SPECIFIC_IE   0xDD
370 #define TAG_SYMBOL_PROPRIETARY   0xAD
371
372 #define WPA_OUI "\x00\x50\xF2"
373 #define RSN_OUI "\x00\x0F\xAC"
374 #define WME_OUI "\x00\x50\xF2"
375
376 #define PMKID_LEN 16
377
378 /* ************************************************************************* */
379 /*                         Frame types, and their names                      */
380 /* ************************************************************************* */
381 static const value_string frame_type_subtype_vals[] = {
382         {MGT_ASSOC_REQ,        "Association Request"},
383         {MGT_ASSOC_RESP,       "Association Response"},
384         {MGT_REASSOC_REQ,      "Reassociation Request"},
385         {MGT_REASSOC_RESP,     "Reassociation Response"},
386         {MGT_PROBE_REQ,        "Probe Request"},
387         {MGT_PROBE_RESP,       "Probe Response"},
388         {MGT_BEACON,           "Beacon frame"},
389         {MGT_ATIM,             "ATIM"},
390         {MGT_DISASS,           "Dissassociate"},
391         {MGT_AUTHENTICATION,   "Authentication"},
392         {MGT_DEAUTHENTICATION, "Deauthentication"},
393         {MGT_ACTION,           "Action"},
394
395         {CTRL_BLOCK_ACK_REQ,   "802.11 Block Ack Req"},
396         {CTRL_BLOCK_ACK,       "802.11 Block Ack"},
397         {CTRL_PS_POLL,         "Power-Save poll"},
398         {CTRL_RTS,             "Request-to-send"},
399         {CTRL_CTS,             "Clear-to-send"},
400         {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
401         {CTRL_CFP_END,         "CF-End (Control-frame)"},
402         {CTRL_CFP_ENDACK,      "CF-End + CF-Ack (Control-frame)"},
403
404         {DATA,                 "Data"},
405         {DATA_CF_ACK,          "Data + CF-Ack"},
406         {DATA_CF_POLL,         "Data + CF-Poll"},
407         {DATA_CF_ACK_POLL,     "Data + CF-Ack + CF-Poll"},
408         {DATA_NULL_FUNCTION,   "Null function (No data)"},
409         {DATA_CF_ACK_NOD,      "Acknowledgement (No data)"},
410         {DATA_CF_POLL_NOD,     "CF-Poll (No data)"},
411         {DATA_CF_ACK_POLL_NOD, "CF-Ack/Poll (No data)"},
412         {DATA_QOS_DATA,        "QoS Data"},
413         {DATA_QOS_DATA_CF_ACK,  "QoS Data + CF-Acknowledgment"},
414         {DATA_QOS_DATA_CF_POLL, "QoS Data + CF-Poll"},
415         {DATA_QOS_DATA_CF_ACK_POLL, "QoS Data + CF-Ack + CF-Poll"},
416         {DATA_QOS_NULL,        "QoS Null function (No data)"},
417         {DATA_QOS_CF_POLL_NOD,  "QoS CF-Poll (No Data)"},
418         {DATA_QOS_CF_ACK_POLL_NOD,  "QoS CF-Ack + CF-Poll (No data)"},
419         {0,                    NULL}
420 };
421
422 /* ************************************************************************* */
423 /*                             802.1D Tag Names                              */
424 /* ************************************************************************* */
425 static const char *qos_tags[8] = {
426         "Best Effort",
427         "Background",
428         "Spare",
429         "Excellent Effort",
430         "Controlled Load",
431         "Video",
432         "Voice",
433         "Network Control"
434 };
435
436 /* ************************************************************************* */
437 /*                 WME Access Category Names (by 802.1D Tag)                 */
438 /* ************************************************************************* */
439 static const char *qos_acs[8] = {
440         "Best Effort",
441         "Background",
442         "Background",
443         "Video",
444         "Video",
445         "Video",
446         "Voice",
447         "Voice"
448 };
449
450 /* ************************************************************************* */
451 /*                   WME Access Category Names (by WME ACI)                  */
452 /* ************************************************************************* */
453 static const char *wme_acs[4] = {
454         "Best Effort",
455         "Background",
456         "Video",
457         "Voice",
458 };
459
460
461 #define CAT_SPECTRUM_MGMT       0
462 #define CAT_QOS                 1
463 #define CAT_DLS                 2
464 #define CAT_BLOCK_ACK           3
465 #define CAT_MGMT_NOTIFICATION   17
466
467 #define SM_ACTION_MEASUREMENT_REQUEST   0
468 #define SM_ACTION_MEASUREMENT_REPORT    1
469 #define SM_ACTION_TPC_REQUEST           2
470 #define SM_ACTION_TPC_REPORT            3
471 #define SM_ACTION_CHAN_SWITCH_ANNC      4
472
473 static int proto_wlan = -1;
474 static packet_info * g_pinfo;
475
476 /* ************************************************************************* */
477 /*                Header field info values for radio information             */
478 /* ************************************************************************* */
479 static int hf_data_rate = -1;
480 static int hf_channel = -1;
481 static int hf_signal_strength = -1;
482
483 /* ************************************************************************* */
484 /*                Header field info values for FC-field                      */
485 /* ************************************************************************* */
486 static int hf_fc_field = -1;
487 static int hf_fc_proto_version = -1;
488 static int hf_fc_frame_type = -1;
489 static int hf_fc_frame_subtype = -1;
490 static int hf_fc_frame_type_subtype = -1;
491
492 static int hf_fc_flags = -1;
493 static int hf_fc_to_ds = -1;
494 static int hf_fc_from_ds = -1;
495 static int hf_fc_data_ds = -1;
496
497 static int hf_fc_more_frag = -1;
498 static int hf_fc_retry = -1;
499 static int hf_fc_pwr_mgt = -1;
500 static int hf_fc_more_data = -1;
501 static int hf_fc_protected = -1;
502 static int hf_fc_order = -1;
503
504
505 /* ************************************************************************* */
506 /*                   Header values for Duration/ID field                     */
507 /* ************************************************************************* */
508 static int hf_did_duration = -1;
509 static int hf_assoc_id = -1;
510
511
512 /* ************************************************************************* */
513 /*         Header values for different address-fields (all 4 of them)        */
514 /* ************************************************************************* */
515 static int hf_addr_da = -1;     /* Destination address subfield */
516 static int hf_addr_sa = -1;     /* Source address subfield */
517 static int hf_addr_ra = -1;     /* Receiver address subfield */
518 static int hf_addr_ta = -1;     /* Transmitter address subfield */
519 static int hf_addr_bssid = -1;  /* address is bssid */
520
521 static int hf_addr = -1;        /* Source or destination address subfield */
522
523
524 /* ************************************************************************* */
525 /*                Header values for QoS control field                        */
526 /* ************************************************************************* */
527 static int hf_qos_priority = -1;
528 static int hf_qos_ack_policy = -1;
529 static int hf_qos_eosp = -1;
530 static int hf_qos_field_content = -1;
531 /*static int hf_qos_txop_limit = -1;*/
532 /*      FIXME: hf_ values not defined
533 static int hf_qos_buf_state = -1;
534 static int hf_qos_buf_ac = -1;
535 static int hf_qos_buf_load = -1;
536 */
537 /*static int hf_qos_txop_dur_req = -1;
538 static int hf_qos_queue_size = -1;*/
539
540 /* ************************************************************************* */
541 /*                Header values for sequence number field                    */
542 /* ************************************************************************* */
543 static int hf_frag_number = -1;
544 static int hf_seq_number = -1;
545
546 /* ************************************************************************* */
547 /*                   Header values for Frame Check field                     */
548 /* ************************************************************************* */
549 static int hf_fcs = -1;
550
551 /* ************************************************************************* */
552 /*                   Header values for reassembly                            */
553 /* ************************************************************************* */
554 static int hf_fragments = -1;
555 static int hf_fragment = -1;
556 static int hf_fragment_overlap = -1;
557 static int hf_fragment_overlap_conflict = -1;
558 static int hf_fragment_multiple_tails = -1;
559 static int hf_fragment_too_long_fragment = -1;
560 static int hf_fragment_error = -1;
561 static int hf_reassembled_in = -1;
562
563
564 static int proto_wlan_mgt = -1;
565 /* ************************************************************************* */
566 /*                      Fixed fields found in mgt frames                     */
567 /* ************************************************************************* */
568 static int ff_auth_alg = -1;    /* Authentication algorithm field            */
569 static int ff_auth_seq = -1;    /* Authentication transaction sequence       */
570 static int ff_current_ap = -1;  /* Current AP MAC address                    */
571 static int ff_listen_ival = -1; /* Listen interval fixed field               */
572 static int ff_timestamp = -1;   /* 64 bit timestamp                          */
573 static int ff_beacon_interval = -1;     /* 16 bit Beacon interval            */
574 static int ff_assoc_id = -1;    /* 16 bit AID field                          */
575 static int ff_reason = -1;      /* 16 bit reason code                        */
576 static int ff_status_code = -1; /* Status code                               */
577 static int ff_category_code = -1;       /* 8 bit Category code */
578 static int ff_action_code = -1;         /* 8 bit Action code */
579 static int ff_dialog_token = -1;        /* 8 bit Dialog token */
580 static int ff_wme_action_code = -1;     /* Management notification action code */
581 static int ff_wme_status_code = -1;     /* Management notification setup response status code */
582
583 /* ************************************************************************* */
584 /*            Flags found in the capability field (fixed field)              */
585 /* ************************************************************************* */
586 static int ff_capture = -1;
587 static int ff_cf_ess = -1;
588 static int ff_cf_ibss = -1;
589 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA            */
590 static int ff_cf_ap_poll = -1;  /* CF pollable status for an AP            */
591 static int ff_cf_privacy = -1;
592 static int ff_cf_preamble = -1;
593 static int ff_cf_pbcc = -1;
594 static int ff_cf_agility = -1;
595 static int ff_short_slot_time = -1;
596 static int ff_dsss_ofdm = -1;
597 static int ff_cf_spec_man = -1;
598 static int ff_cf_apsd = -1;
599 static int ff_cf_del_blk_ack = -1;
600 static int ff_cf_imm_blk_ack = -1;
601
602 /* ************************************************************************* */
603 /*                       Tagged value format fields                          */
604 /* ************************************************************************* */
605 static int tag_number = -1;
606 static int tag_length = -1;
607 static int tag_interpretation = -1;
608 static int tag_oui = -1;
609
610
611 static int tim_length = -1;
612 static int tim_dtim_count = -1;
613 static int tim_dtim_period = -1;
614 static int tim_bmapctl = -1;
615
616
617 static int hf_fixed_parameters = -1;    /* Protocol payload for management frames */
618 static int hf_tagged_parameters = -1;   /* Fixed payload item */
619 static int hf_wep_iv = -1;
620 static int hf_wep_iv_weak = -1;
621 static int hf_tkip_extiv = -1;
622 static int hf_ccmp_extiv = -1;
623 static int hf_wep_key = -1;
624 static int hf_wep_icv = -1;
625
626
627 static int rsn_cap = -1;
628 static int rsn_cap_preauth = -1;
629 static int rsn_cap_no_pairwise = -1;
630 static int rsn_cap_ptksa_replay_counter = -1;
631 static int rsn_cap_gtksa_replay_counter = -1;
632
633 static int hf_aironet_ie_type = -1;
634 static int hf_aironet_ie_version = -1;
635 static int hf_aironet_ie_data = -1;
636 static int hf_aironet_ie_qos_unk1 = -1;
637 static int hf_aironet_ie_qos_paramset = -1;
638 static int hf_aironet_ie_qos_val = -1;
639
640 /*QBSS - Version 1,2,802.11e*/
641
642 static int hf_qbss2_cal = -1;
643 static int hf_qbss2_gl = -1;
644 static int hf_qbss_cu = -1;
645 static int hf_qbss2_cu = -1;
646 static int hf_qbss_scount = -1;
647 static int hf_qbss2_scount = -1;
648 static int hf_qbss_version = -1;
649 static int hf_qbss_adc = -1;
650
651 /* ************************************************************************* */
652 /*                               Protocol trees                              */
653 /* ************************************************************************* */
654 static gint ett_80211 = -1;
655 static gint ett_proto_flags = -1;
656 static gint ett_cap_tree = -1;
657 static gint ett_fc_tree = -1;
658 static gint ett_fragments = -1;
659 static gint ett_fragment = -1;
660
661 static gint ett_80211_mgt = -1;
662 static gint ett_fixed_parameters = -1;
663 static gint ett_tagged_parameters = -1;
664 static gint ett_qos_parameters = -1;
665 static gint ett_qos_ps_buf_state = -1;
666 static gint ett_wep_parameters = -1;
667
668 static gint ett_rsn_cap_tree = -1;
669
670 static gint ett_80211_mgt_ie = -1;
671
672 static const fragment_items frag_items = {
673         &ett_fragment,
674         &ett_fragments,
675         &hf_fragments,
676         &hf_fragment,
677         &hf_fragment_overlap,
678         &hf_fragment_overlap_conflict,
679         &hf_fragment_multiple_tails,
680         &hf_fragment_too_long_fragment,
681         &hf_fragment_error,
682         &hf_reassembled_in,
683         "fragments"
684 };
685
686 static dissector_handle_t llc_handle;
687 static dissector_handle_t ipx_handle;
688 static dissector_handle_t eth_withoutfcs_handle;
689 static dissector_handle_t data_handle;
690
691 static int wlan_tap = -1;
692
693 /* ************************************************************************* */
694 /*            Return the length of the current header (in bytes)             */
695 /* ************************************************************************* */
696 static int
697 find_header_length (guint16 fcf)
698 {
699   int len;
700
701   switch (FCF_FRAME_TYPE (fcf)) {
702
703   case MGT_FRAME:
704     return MGT_FRAME_HDR_LEN;
705
706   case CONTROL_FRAME:
707     switch (COMPOSE_FRAME_TYPE (fcf)) {
708
709     case CTRL_CTS:
710     case CTRL_ACKNOWLEDGEMENT:
711       return 10;
712
713     case CTRL_RTS:
714     case CTRL_PS_POLL:
715     case CTRL_CFP_END:
716     case CTRL_CFP_ENDACK:
717     case CTRL_BLOCK_ACK_REQ:
718     case CTRL_BLOCK_ACK:
719       return 16;
720     }
721     return 4;   /* XXX */
722
723   case DATA_FRAME:
724     len = (FCF_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
725                                                       DATA_SHORT_HDR_LEN;
726     if (DATA_FRAME_IS_QOS(COMPOSE_FRAME_TYPE(fcf)))
727       return len + 2;
728     else
729       return len;
730
731   default:
732     return 4;   /* XXX */
733   }
734 }
735
736
737 /* ************************************************************************* */
738 /*          This is the capture function used to update packet counts        */
739 /* ************************************************************************* */
740 static void
741 capture_ieee80211_common (const guchar * pd, int offset, int len,
742                           packet_counts * ld, gboolean fixed_length_header,
743                           gboolean datapad)
744 {
745   guint16 fcf, hdr_length;
746
747   if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
748     ld->other++;
749     return;
750   }
751
752   fcf = pletohs (&pd[offset]);
753
754   if (IS_PROTECTED(FCF_FLAGS(fcf)))
755     {
756       ld->other++;
757       return;
758     }
759
760   switch (COMPOSE_FRAME_TYPE (fcf))
761     {
762
763     case DATA:                  /* We got a data frame */
764     case DATA_CF_ACK:           /* Data with ACK */
765     case DATA_CF_POLL:
766     case DATA_CF_ACK_POLL:
767     case DATA_QOS_DATA:
768       if (fixed_length_header)
769         hdr_length = DATA_LONG_HDR_LEN;
770       else
771         hdr_length = find_header_length (fcf);
772       if (datapad)
773         hdr_length = roundup2(hdr_length, 4);
774       /* I guess some bridges take Netware Ethernet_802_3 frames,
775          which are 802.3 frames (with a length field rather than
776          a type field, but with no 802.2 header in the payload),
777          and just stick the payload into an 802.11 frame.  I've seen
778          captures that show frames of that sort.
779
780          This means we have to do the same check for Netware 802.3 -
781          or, if you will, "Netware 802.11" - that we do in the
782          Ethernet dissector, i.e. checking for 0xffff as the first
783          four bytes of the payload and, if we find it, treating it
784          as an IPX frame. */
785       if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
786         ld->other++;
787         return;
788       }
789       if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
790         capture_ipx (ld);
791       }
792       else {
793         capture_llc (pd, offset + hdr_length, len, ld);
794       }
795       break;
796
797     default:
798       ld->other++;
799       break;
800     }
801 }
802
803 /*
804  * Handle 802.11 with a variable-length link-layer header.
805  */
806 void
807 capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
808 {
809   capture_ieee80211_common (pd, offset, len, ld, FALSE, FALSE);
810 }
811
812 /*
813  * Handle 802.11 with a variable-length link-layer header and data padding.
814  */
815 void
816 capture_ieee80211_datapad (const guchar * pd, int offset, int len,
817                            packet_counts * ld)
818 {
819   capture_ieee80211_common (pd, offset, len, ld, FALSE, TRUE);
820 }
821
822 /*
823  * Handle 802.11 with a fixed-length link-layer header (padded to the
824  * maximum length).
825  */
826 void
827 capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
828 {
829   capture_ieee80211_common (pd, offset, len, ld, TRUE, FALSE);
830 }
831
832
833 /* ************************************************************************* */
834 /*          Add the subtree used to store the fixed parameters               */
835 /* ************************************************************************* */
836 static proto_tree *
837 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
838 {
839   proto_item *fixed_fields;
840   fixed_fields =
841     proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
842                                 size, size, "Fixed parameters (%d bytes)",
843                                 size);
844
845   return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
846 }
847
848
849 /* ************************************************************************* */
850 /*            Add the subtree used to store tagged parameters                */
851 /* ************************************************************************* */
852 static proto_tree *
853 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
854 {
855   proto_item *tagged_fields;
856
857   tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
858                                               tvb,
859                                               start,
860                                               size,
861                                               size,
862                                               "Tagged parameters (%d bytes)",
863                                               size);
864
865   return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
866 }
867
868
869 /* ************************************************************************* */
870 /*              Dissect and add fixed mgmt fields to protocol tree           */
871 /* ************************************************************************* */
872 static void
873 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
874 {
875   const guint8 *dataptr;
876   char out_buff[SHORT_STR];
877   guint16 capability;
878   proto_item *cap_item;
879   static proto_tree *cap_tree;
880   double temp_double;
881
882   switch (lfcode)
883     {
884     case FIELD_TIMESTAMP:
885       dataptr = tvb_get_ptr (tvb, offset, 8);
886       memset (out_buff, 0, SHORT_STR);
887       g_snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
888                 dataptr[7],
889                 dataptr[6],
890                 dataptr[5],
891                 dataptr[4],
892                 dataptr[3],
893                 dataptr[2],
894                 dataptr[1],
895                 dataptr[0]);
896
897       proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
898       break;
899
900     case FIELD_BEACON_INTERVAL:
901       capability = tvb_get_letohs (tvb, offset);
902       temp_double = (double)capability;
903       temp_double = temp_double * 1024 / 1000000;
904       proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
905                                     temp_double,"Beacon Interval: %f [Seconds]",
906                                     temp_double);
907       if (check_col (g_pinfo->cinfo, COL_INFO)) {
908           col_append_fstr(g_pinfo->cinfo, COL_INFO, ",BI=%d", capability);
909       }
910       break;
911
912
913     case FIELD_CAP_INFO:
914       capability = tvb_get_letohs (tvb, offset);
915
916       cap_item = proto_tree_add_uint_format (tree, ff_capture,
917                                              tvb, offset, 2,
918                                              capability,
919                                              "Capability Information: 0x%04X",
920                                              capability);
921       cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
922       proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
923                               capability);
924       proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
925                               capability);
926       if (ESS_SET (capability) != 0)    /* This is an AP */
927         proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
928                              capability);
929
930       else                      /* This is a STA */
931         proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
932                              capability);
933       proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
934                               capability);
935       proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
936                               capability);
937       proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
938                               capability);
939       proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
940                               capability);
941       proto_tree_add_boolean (cap_tree, ff_cf_spec_man, tvb, offset, 2,
942                               capability);
943       proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
944                               capability);
945       proto_tree_add_boolean (cap_tree, ff_cf_apsd, tvb, offset, 2,
946                               capability);
947       proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
948                               capability);
949       proto_tree_add_boolean (cap_tree, ff_cf_del_blk_ack, tvb, offset, 2,
950                               capability);
951       proto_tree_add_boolean (cap_tree, ff_cf_imm_blk_ack, tvb, offset, 2,
952                               capability);
953       break;
954
955     case FIELD_AUTH_ALG:
956       proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
957       break;
958
959     case FIELD_AUTH_TRANS_SEQ:
960       proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
961       break;
962
963     case FIELD_CURRENT_AP_ADDR:
964       proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
965       break;
966
967     case FIELD_LISTEN_IVAL:
968       proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
969       break;
970
971     case FIELD_REASON_CODE:
972       proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
973       break;
974
975     case FIELD_ASSOC_ID:
976       proto_tree_add_uint(tree, ff_assoc_id, tvb, offset, 2,
977                           ASSOC_ID(tvb_get_letohs(tvb,offset)));
978       /* proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE); */
979       break;
980
981     case FIELD_STATUS_CODE:
982       proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
983       break;
984
985     case FIELD_CATEGORY_CODE:
986       proto_tree_add_item (tree, ff_category_code, tvb, offset, 1, TRUE);
987       break;
988
989     case FIELD_ACTION_CODE:
990       proto_tree_add_item (tree, ff_action_code, tvb, offset, 1, TRUE);
991       break;
992
993     case FIELD_DIALOG_TOKEN:
994       proto_tree_add_item (tree, ff_dialog_token, tvb, offset, 1, TRUE);
995       break;
996
997     case FIELD_WME_ACTION_CODE:
998       proto_tree_add_item (tree, ff_wme_action_code, tvb, offset, 1, TRUE);
999       break;
1000
1001     case FIELD_WME_STATUS_CODE:
1002       proto_tree_add_item (tree, ff_wme_status_code, tvb, offset, 1, TRUE);
1003       break;
1004     }
1005 }
1006
1007 static const char *wpa_cipher_str[] =
1008 {
1009   "NONE",
1010   "WEP (40-bit)",
1011   "TKIP",
1012   "AES (OCB)",
1013   "AES (CCM)",
1014   "WEP (104-bit)",
1015 };
1016
1017 static const char *
1018 wpa_cipher_idx2str(guint idx)
1019 {
1020   if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
1021     return wpa_cipher_str[idx];
1022   return "UNKNOWN";
1023 }
1024
1025 static const char *wpa_keymgmt_str[] =
1026 {
1027   "NONE",
1028   "WPA",
1029   "PSK",
1030 };
1031
1032 static const char *
1033 wpa_keymgmt_idx2str(guint idx)
1034 {
1035   if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
1036     return wpa_keymgmt_str[idx];
1037   return "UNKNOWN";
1038 }
1039
1040 static void
1041 dissect_vendor_ie_wpawme(proto_tree * ietree, proto_tree * tree, tvbuff_t * tvb,
1042         int offset, guint32 tag_len, const guint8 *tag_val)
1043 {
1044       guint32 tag_val_off = 0;
1045       char out_buff[SHORT_STR];
1046       guint i;
1047
1048       /* Wi-Fi Protected Access (WPA) Information Element */
1049       if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
1050         g_snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
1051                   tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
1052         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
1053         offset += 6;
1054         tag_val_off += 6;
1055         if (tag_val_off + 4 <= tag_len) {
1056           /* multicast cipher suite */
1057           if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
1058             g_snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
1059                       wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1060             proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1061             offset += 4;
1062             tag_val_off += 4;
1063             /* unicast cipher suites */
1064             if (tag_val_off + 2 <= tag_len) {
1065               g_snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
1066                         pletohs(tag_val + tag_val_off));
1067               proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1068               offset += 2;
1069               tag_val_off += 2;
1070               i = 1;
1071               while (tag_val_off + 4 <= tag_len) {
1072                 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
1073                   g_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                 else
1081                   break;
1082               }
1083               /* authenticated key management suites */
1084               if (tag_val_off + 2 <= tag_len) {
1085                 g_snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
1086                           pletohs(tag_val + tag_val_off));
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) {
1092                   if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
1093                     g_snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
1094                               i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
1095                     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1096                     offset += 4;
1097                     tag_val_off += 4;
1098                     i ++;
1099                   }
1100                   else
1101                     break;
1102                 }
1103               }
1104             }
1105           }
1106         }
1107         if (tag_val_off < tag_len)
1108           proto_tree_add_string(tree, tag_interpretation, tvb,
1109                                  offset, tag_len - tag_val_off, "Not interpreted");
1110         proto_item_append_text(ietree, ": WPA");
1111       } else if (tag_val_off + 7 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x00", 5)) {
1112       /* Wireless Multimedia Enhancements (WME) Information Element */
1113         g_snprintf(out_buff, SHORT_STR, "WME IE: type %u, subtype %u, version %u, parameter set %u",
1114                  tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
1115                  tag_val[tag_val_off + 6]);
1116         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
1117         proto_item_append_text(ietree, ": WME");
1118       } else if (tag_val_off + 24 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x01", 5)) {
1119       /* Wireless Multimedia Enhancements (WME) Parameter Element */
1120         g_snprintf(out_buff, SHORT_STR, "WME PE: type %u, subtype %u, version %u, parameter set %u",
1121                  tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
1122                  tag_val[tag_val_off + 6]);
1123         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
1124         offset += 8;
1125         tag_val_off += 8;
1126         for (i = 0; i < 4; i++) {
1127           g_snprintf(out_buff, SHORT_STR, "WME AC Parameters: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
1128                    (tag_val[tag_val_off] & 0x60) >> 5,
1129                    wme_acs[(tag_val[tag_val_off] & 0x60) >> 5],
1130                    (tag_val[tag_val_off] & 0x10) ? "" : "not ",
1131                    tag_val[tag_val_off] & 0x0f,
1132                    tag_val[tag_val_off + 1] & 0x0f,
1133                    (tag_val[tag_val_off + 1] & 0xf0) >> 4,
1134                    tvb_get_letohs(tvb, offset + 2));
1135           proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1136           offset += 4;
1137           tag_val_off += 4;
1138         }
1139         proto_item_append_text(ietree, ": WME");
1140       } else if (tag_val_off + 56 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x02", 5)) {
1141       /* Wireless Multimedia Enhancements (WME) TSPEC Element */
1142         guint16 ts_info, msdu_size, surplus_bandwidth;
1143         const char *direction[] = { "Uplink", "Downlink", "Reserved", "Bi-directional" };
1144         const value_string fields[] = {
1145           {12, "Minimum Service Interval"},
1146           {16, "Maximum Service Interval"},
1147           {20, "Inactivity Interval"},
1148           {24, "Service Start Time"},
1149           {28, "Minimum Data Rate"},
1150           {32, "Mean Data Rate"},
1151           {36, "Maximum Burst Size"},
1152           {40, "Minimum PHY Rate"},
1153           {44, "Peak Data Rate"},
1154           {48, "Delay Bound"},
1155           {0, NULL}
1156         };
1157         const char *field;
1158
1159         g_snprintf(out_buff, SHORT_STR, "WME TSPEC: type %u, subtype %u, version %u",
1160                  tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5]);
1161         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
1162         offset += 6;
1163         tag_val_off += 6;
1164
1165         ts_info = tvb_get_letohs(tvb, offset);
1166         g_snprintf(out_buff, SHORT_STR, "WME TS Info: Priority %u (%s) (%s), Contention-based access %sset, %s",
1167                  (ts_info >> 11) & 0x7, qos_tags[(ts_info >> 11) & 0x7], qos_acs[(ts_info >> 11) & 0x7],
1168                  (ts_info & 0x0080) ? "" : "not ",
1169                  direction[(ts_info >> 5) & 0x3]);
1170         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1171         offset += 2;
1172         tag_val_off += 2;
1173
1174         msdu_size = tvb_get_letohs(tvb, offset);
1175         g_snprintf(out_buff, SHORT_STR, "WME TSPEC: %s MSDU Size %u",
1176                  (msdu_size & 0x8000) ? "Fixed" : "Nominal", msdu_size & 0x7fff);
1177         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1178         offset += 2;
1179         tag_val_off += 2;
1180
1181         g_snprintf(out_buff, SHORT_STR, "WME TSPEC: Maximum MSDU Size %u", tvb_get_letohs(tvb, offset));
1182         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1183         offset += 2;
1184         tag_val_off += 2;
1185
1186         while ((field = val_to_str(tag_val_off, fields, "Unknown"))) {
1187           g_snprintf(out_buff, SHORT_STR, "WME TSPEC: %s %u", field, tvb_get_letohl(tvb, offset));
1188           proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1189           offset += 4;
1190           tag_val_off += 4;
1191           if (tag_val_off == 52)
1192             break;
1193         }
1194
1195         surplus_bandwidth = tvb_get_letohs(tvb, offset);
1196         g_snprintf(out_buff, SHORT_STR, "WME TSPEC: Surplus Bandwidth Allowance Factor %u.%u",
1197                  (surplus_bandwidth >> 13) & 0x7, (surplus_bandwidth & 0x1fff));
1198         offset += 2;
1199         tag_val_off += 2;
1200
1201         g_snprintf(out_buff, SHORT_STR, "WME TSPEC: Medium Time %u", tvb_get_letohs(tvb, offset));
1202         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1203         offset += 2;
1204         tag_val_off += 2;
1205         proto_item_append_text(ietree, ": WME");
1206       }
1207 }
1208
1209 static void
1210 dissect_vendor_ie_rsn(proto_tree * ietree, proto_tree * tree, tvbuff_t * tvb,
1211         int offset, guint32 tag_len, const guint8 *tag_val)
1212 {
1213         guint32 tag_val_off = 0;
1214         char out_buff[SHORT_STR], *pos;
1215         guint i;
1216
1217         if (tag_val_off + 4 <= tag_len && !memcmp(tag_val, RSN_OUI"\x04", 4)) {
1218                 /* IEEE 802.11i / Key Data Encapsulation / Data Type=4 - PMKID.
1219                  * This is only used within EAPOL-Key frame Key Data. */
1220                 pos = out_buff;
1221                 pos += g_snprintf(pos, out_buff + SHORT_STR - pos, "RSN PMKID: ");
1222                 if (tag_len - 4 != PMKID_LEN) {
1223                         pos += g_snprintf(pos, out_buff + SHORT_STR - pos,
1224                                 "(invalid PMKID len=%d, expected 16) ", tag_len - 4);
1225                 }
1226                 for (i = 0; i < tag_len - 4; i++) {
1227                         pos += g_snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
1228                                 tag_val[tag_val_off + 4 + i]);
1229                 }
1230                 proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1231                         tag_len, out_buff);
1232         }
1233         proto_item_append_text(ietree, ": RSN");
1234 }
1235
1236 typedef enum {
1237         AIRONET_IE_VERSION = 3,
1238         AIRONET_IE_QOS,
1239         AIRONET_IE_QBSS_V2 = 14
1240 } aironet_ie_type_t;
1241
1242 static const value_string aironet_ie_type_vals[] = {
1243         { AIRONET_IE_VERSION,   "CCX version"},
1244         { AIRONET_IE_QOS,       "Qos"},
1245         { AIRONET_IE_QBSS_V2,   "QBSS V2 - CCA"},
1246
1247         { 0,                    NULL }
1248 };
1249
1250 static void
1251 dissect_vendor_ie_aironet(proto_item * aironet_item, proto_tree * ietree,
1252         tvbuff_t * tvb, int offset, guint32 tag_len)
1253 {
1254         guint8  type;
1255         int i;
1256         gboolean dont_change = FALSE; /* Don't change the IE item text to default */
1257
1258         type = tvb_get_guint8(tvb, offset);
1259         proto_tree_add_item (ietree, hf_aironet_ie_type, tvb, offset, 1, TRUE);
1260         offset += 1;
1261
1262         switch (type) {
1263         case AIRONET_IE_VERSION:
1264                 proto_tree_add_item (ietree, hf_aironet_ie_version, tvb, offset, 1, TRUE);
1265                 proto_item_append_text(aironet_item, ": Aironet CCX version = %d", 
1266                         tvb_get_guint8(tvb, offset));
1267                 dont_change = TRUE;
1268                 break;
1269         case AIRONET_IE_QOS:
1270                 proto_tree_add_item (ietree, hf_aironet_ie_qos_unk1, tvb, offset, 1, TRUE);
1271                 offset += 1;
1272                 proto_tree_add_item (ietree, hf_aironet_ie_qos_paramset, tvb, offset, 1, TRUE);
1273                 offset += 1;
1274
1275                 /* XXX: just copied over from WME. Maybe "Best Effort" and "Background"
1276                  *      need to be swapped. Also, the "TXOP" may be TXOP - or not.
1277                  */
1278                 for (i = 0; i < 4; i++) {
1279                         guint8 byte1, byte2;
1280                         guint16 txop;
1281                         byte1 = tvb_get_guint8(tvb, offset);
1282                         byte2 = tvb_get_guint8(tvb, offset + 1);
1283                         txop = tvb_get_letohs(tvb, offset + 2);
1284                         proto_tree_add_bytes_format(ietree, hf_aironet_ie_qos_val, tvb, offset, 4,
1285                                 tvb_get_ptr(tvb, offset, 4),
1286                                 "CCX QoS Parameters??: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
1287                                 (byte1 & 0x60) >> 5, wme_acs[(byte1 & 0x60) >> 5],
1288                                 (byte1 & 0x10) ? "" : "not ", byte1 & 0x0f,
1289                                 byte2 & 0x0f, (byte2 & 0xf0) >> 4,
1290                                 txop);
1291                         offset += 4;
1292                 }
1293                 break;
1294         case AIRONET_IE_QBSS_V2:
1295                 /* Extract Values */
1296                 proto_tree_add_item (ietree, hf_qbss2_scount, tvb, offset, 2, TRUE);
1297                 proto_tree_add_item (ietree, hf_qbss2_cu, tvb, offset + 2, 1, FALSE);
1298                 proto_tree_add_item (ietree, hf_qbss2_cal, tvb, offset + 3, 1, FALSE);
1299                 proto_tree_add_item (ietree, hf_qbss2_gl, tvb, offset + 4, 1, FALSE);
1300                 break;
1301         default:
1302                 proto_tree_add_item(ietree, hf_aironet_ie_data, tvb, offset,
1303                         tag_len - 1, FALSE);
1304                 break;
1305         }
1306         if (!dont_change) {
1307                 proto_item_append_text(aironet_item, ": Aironet %s", 
1308                         val_to_str(type, aironet_ie_type_vals, "Unknown"));
1309         }
1310 }
1311
1312 static void
1313 dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
1314                guint32 tag_len, const guint8 *tag_val)
1315 {
1316   guint32 tag_val_off = 0;
1317   guint16 rsn_capab;
1318   char out_buff[SHORT_STR];
1319   int i, j, count;
1320   proto_item *cap_item;
1321   proto_tree *cap_tree;
1322
1323   if (tag_val_off + 2 > tag_len) {
1324     proto_tree_add_string(tree, tag_interpretation, tvb, offset, tag_len,
1325                           "Not interpreted");
1326     return;
1327   }
1328
1329   g_snprintf(out_buff, SHORT_STR, "RSN IE, version %u",
1330            pletohs(&tag_val[tag_val_off]));
1331   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1332
1333   offset += 2;
1334   tag_val_off += 2;
1335
1336   if (tag_val_off + 4 > tag_len)
1337     goto done;
1338
1339   /* multicast cipher suite */
1340   if (!memcmp(&tag_val[tag_val_off], RSN_OUI, 3)) {
1341     g_snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
1342              wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1343     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1344     offset += 4;
1345     tag_val_off += 4;
1346   }
1347
1348   if (tag_val_off + 2 > tag_len)
1349     goto done;
1350
1351   /* unicast cipher suites */
1352   count = pletohs(tag_val + tag_val_off);
1353   g_snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", count);
1354   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1355   offset += 2;
1356   tag_val_off += 2;
1357   i = 1;
1358   while (tag_val_off + 4 <= tag_len && i <= count) {
1359     if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
1360       goto done;
1361     g_snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
1362              i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1363     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1364     offset += 4;
1365     tag_val_off += 4;
1366     i++;
1367   }
1368
1369   if (i <= count || tag_val_off + 2 > tag_len)
1370     goto done;
1371
1372   /* authenticated key management suites */
1373   count = pletohs(tag_val + tag_val_off);
1374   g_snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", count);
1375   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1376   offset += 2;
1377   tag_val_off += 2;
1378   i = 1;
1379   while (tag_val_off + 4 <= tag_len && i <= count) {
1380     if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
1381       goto done;
1382     g_snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
1383              i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
1384     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1385     offset += 4;
1386     tag_val_off += 4;
1387     i++;
1388   }
1389
1390   if (i <= count || tag_val_off + 2 > tag_len)
1391     goto done;
1392
1393   rsn_capab = pletohs(&tag_val[tag_val_off]);
1394   g_snprintf(out_buff, SHORT_STR, "RSN Capabilities 0x%04x", rsn_capab);
1395   cap_item = proto_tree_add_uint_format(tree, rsn_cap, tvb,
1396                                         offset, 2, rsn_capab,
1397                                         "RSN Capabilities: 0x%04X", rsn_capab);
1398   cap_tree = proto_item_add_subtree(cap_item, ett_rsn_cap_tree);
1399   proto_tree_add_boolean(cap_tree, rsn_cap_preauth, tvb, offset, 2,
1400                          rsn_capab);
1401   proto_tree_add_boolean(cap_tree, rsn_cap_no_pairwise, tvb, offset, 2,
1402                          rsn_capab);
1403   proto_tree_add_uint(cap_tree, rsn_cap_ptksa_replay_counter, tvb, offset, 2,
1404                       rsn_capab);
1405   proto_tree_add_uint(cap_tree, rsn_cap_gtksa_replay_counter, tvb, offset, 2,
1406                       rsn_capab);
1407   offset += 2;
1408   tag_val_off += 2;
1409
1410   if (tag_val_off + 2 > tag_len)
1411     goto done;
1412
1413   count = pletohs(tag_val + tag_val_off);
1414   g_snprintf(out_buff, SHORT_STR, "# of PMKIDs: %u", count);
1415   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1416   offset += 2;
1417   tag_val_off += 2;
1418
1419   /* PMKID List (16 * n octets) */
1420   for (i = 0; i < count; i++) {
1421     char *pos;
1422     if (tag_val_off + PMKID_LEN > tag_len)
1423       goto done;
1424     pos = out_buff;
1425     pos += g_snprintf(pos, out_buff + SHORT_STR - pos, "PMKID %u: ", i);
1426     for (j = 0; j < PMKID_LEN; j++) {
1427       pos += g_snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
1428                       tag_val[tag_val_off + j]);
1429     }
1430     proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1431                           PMKID_LEN, out_buff);
1432     offset += PMKID_LEN;
1433     tag_val_off += PMKID_LEN;
1434   }
1435
1436  done:
1437   if (tag_val_off < tag_len)
1438     proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1439                           tag_len - tag_val_off, "Not interpreted");
1440 }
1441
1442 /* ************************************************************************* */
1443 /*           Dissect and add tagged (optional) fields to proto tree          */
1444 /* ************************************************************************* */
1445
1446 static const value_string tag_num_vals[] = {
1447         { TAG_SSID,                 "SSID parameter set" },
1448         { TAG_SUPP_RATES,           "Supported Rates" },
1449         { TAG_FH_PARAMETER,         "FH Parameter set" },
1450         { TAG_DS_PARAMETER,         "DS Parameter set" },
1451         { TAG_CF_PARAMETER,         "CF Parameter set" },
1452         { TAG_TIM,                  "(TIM) Traffic Indication Map" },
1453         { TAG_IBSS_PARAMETER,       "IBSS Parameter set" },
1454         { TAG_COUNTRY_INFO,         "Country Information" },
1455         { TAG_FH_HOPPING_PARAMETER, "Hopping Pattern Parameters" },
1456         { TAG_CHALLENGE_TEXT,       "Challenge text" },
1457         { TAG_ERP_INFO,             "ERP Information" },
1458         { TAG_ERP_INFO_OLD,         "ERP Information" },
1459         { TAG_RSN_IE,               "RSN Information" },
1460         { TAG_EXT_SUPP_RATES,       "Extended Supported Rates" },
1461         { TAG_CISCO_UNKNOWN_1,      "Cisco Unknown 1 + Device Name" },
1462         { TAG_CISCO_UNKNOWN_2,      "Cisco Unknown 2" },
1463         { TAG_VENDOR_SPECIFIC_IE,   "Vendor Specific" },
1464         { TAG_SYMBOL_PROPRIETARY,   "Symbol Proprietary"},
1465         { TAG_AGERE_PROPRIETARY,    "Agere Proprietary"},
1466         { TAG_REQUEST,              "Request"},
1467         { TAG_QBSS_LOAD,            "QBSS Load Element"},
1468         { TAG_EDCA_PARAM_SET,       "EDCA Parameter Set"},
1469         { TAG_TRAF_SPEC,            "Traffic Specification"},
1470         { TAG_TRAF_CLASS,           "Traffic Classification"},
1471         { TAG_SCHEDULE,             "Schedule"},
1472         { TAG_TS_DELAY,             "TS Delay"},
1473         { TAG_TCLAS_PROCESS,        "TCLAS Processing"},
1474         { TAG_QOS_CAPABILITY,       "QoS Capability"},
1475         { TAG_POWER_CONSTRAINT,     "Power Constraint"},
1476         { TAG_POWER_CAPABILITY,     "Power Capability"},
1477         { TAG_TPC_REQUEST,          "TPC Request"},
1478         { TAG_TPC_REPORT,           "TPC Report"},
1479         { TAG_SUPPORTED_CHANNELS,   "Supported Channels"},
1480         { TAG_CHANNEL_SWITCH_ANN,   "Channel Switch Announcement"},
1481         { TAG_MEASURE_REQ,          "Measurement Request"},
1482         { TAG_MEASURE_REP,          "Measurement Report"},
1483         { TAG_QUIET,                "Quiet"},
1484         { TAG_IBSS_DFS,             "IBSS DFS"},
1485         { 0,                        NULL }
1486 };
1487
1488 static const value_string environment_vals[] = {
1489         { 0x20, "Any" },
1490         { 0x4f, "Outdoor" },
1491         { 0x49, "Indoor" },
1492         { 0,    NULL }
1493 };
1494
1495 static int beacon_padding = 0; /* beacon padding bug */
1496 static int
1497 add_tagged_field (packet_info * pinfo, proto_tree * tree, tvbuff_t * tvb, int offset)
1498 {
1499   guint32 oui;
1500   const guint8 *tag_val;
1501   const guint8 *tag_data_ptr;
1502   guint32 tag_no, tag_len;
1503   unsigned int i;
1504   int n, ret;
1505   char out_buff[SHORT_STR];
1506   char print_buff[SHORT_STR];
1507   proto_tree * orig_tree=tree;
1508   proto_item *ti;
1509
1510   tag_no = tvb_get_guint8(tvb, offset);
1511   tag_len = tvb_get_guint8(tvb, offset + 1);
1512
1513   ti=proto_tree_add_text(orig_tree,tvb,offset,tag_len+2,"%s",
1514                          val_to_str(tag_no, tag_num_vals,
1515                          (tag_no >= 17 && tag_no <= 31) ?
1516                          "Reserved for challenge text" : "Reserved tag number" ));
1517   tree=proto_item_add_subtree(ti,ett_80211_mgt_ie);
1518
1519   proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
1520                               "Tag Number: %u (%s)",
1521                               tag_no,
1522                               val_to_str(tag_no, tag_num_vals,
1523                                          (tag_no >= 17 && tag_no <= 31) ?
1524                                          "Reserved for challenge text" :
1525                                          "Reserved tag number"));
1526   proto_tree_add_uint (tree, (tag_no==TAG_TIM ? tim_length : tag_length), tvb, offset + 1, 1, tag_len);
1527
1528   switch (tag_no)
1529     {
1530
1531     case TAG_SSID:
1532       if(beacon_padding == 0) /* padding bug */
1533       {
1534         char *ssid;
1535
1536         ssid = tvb_get_ephemeral_string(tvb, offset + 2, tag_len);
1537         proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1538                                tag_len, ssid);
1539         if (check_col (pinfo->cinfo, COL_INFO)) {
1540           if (tag_len > 0) {
1541             col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID: \"%s\"",
1542                             format_text(ssid, tag_len));
1543           } else {
1544             col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID: Broadcast");
1545           }
1546         }
1547         if (tag_len > 0) {
1548           proto_item_append_text(ti, ": \"%s\"",
1549                                  format_text(ssid, tag_len));
1550         } else {
1551           proto_item_append_text(ti, ": Broadcast");
1552         }
1553         beacon_padding++; /* padding bug */
1554       }
1555       break;
1556
1557     case TAG_SUPP_RATES:
1558     case TAG_EXT_SUPP_RATES:
1559       if (tag_len < 1)
1560       {
1561         proto_tree_add_text (tree, tvb, offset + 2, tag_len,
1562                 "Tag length %u too short, must be > 0", tag_len);
1563         break;
1564        }
1565        tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
1566
1567       tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
1568       for (i = 0, n = 0; i < tag_len && n < SHORT_STR; i++) {
1569         ret = g_snprintf (print_buff + n, SHORT_STR - n, "%2.1f%s ",
1570                         (tag_data_ptr[i] & 0x7F) * 0.5,
1571                         (tag_data_ptr[i] & 0x80) ? "(B)" : "");
1572         if (ret == -1 || ret >= SHORT_STR - n) {
1573           /* Some versions of snprintf return -1 if they'd truncate
1574              the output. Others return <buf_size> or greater.  */
1575           break;
1576         }
1577         n += ret;
1578       }
1579       g_snprintf (out_buff, SHORT_STR, "Supported rates: %s [Mbit/sec]", print_buff);
1580       out_buff[SHORT_STR-1] = '\0';
1581       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1582                              tag_len, out_buff);
1583       proto_item_append_text(ti, ": %s", print_buff);
1584       break;
1585
1586     case TAG_FH_PARAMETER:
1587       if (tag_len < 5)
1588       {
1589         proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 5",
1590                              tag_len);
1591         break;
1592       }
1593       g_snprintf (out_buff, SHORT_STR,
1594                 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, Hop Index %2d",
1595                 tvb_get_letohs(tvb, offset + 2),
1596                 tvb_get_guint8(tvb, offset + 4),
1597                 tvb_get_guint8(tvb, offset + 5),
1598                 tvb_get_guint8(tvb, offset + 6));
1599       out_buff[SHORT_STR-1] = '\0';
1600       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1601                              tag_len, out_buff);
1602       break;
1603
1604     case TAG_DS_PARAMETER:
1605       if (tag_len < 1)
1606       {
1607         proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 1",
1608                              tag_len);
1609         break;
1610       }
1611       g_snprintf (out_buff, SHORT_STR, "Current Channel: %u",
1612                 tvb_get_guint8(tvb, offset + 2));
1613       out_buff[SHORT_STR-1] = '\0';
1614       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1615                              tag_len, out_buff);
1616       proto_item_append_text(ti, ": %s", out_buff);
1617       break;
1618
1619     case TAG_CF_PARAMETER:
1620       if (tag_len < 6)
1621       {
1622         proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 6",
1623                              tag_len);
1624         break;
1625       }
1626       g_snprintf (out_buff, SHORT_STR, "CFP count: %u",
1627                 tvb_get_guint8(tvb, offset + 2));
1628       out_buff[SHORT_STR-1] = '\0';
1629       proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 2,
1630                                    1, out_buff, "%s", out_buff);
1631       g_snprintf (out_buff, SHORT_STR, "CFP period: %u",
1632                 tvb_get_guint8(tvb, offset + 3));
1633       out_buff[SHORT_STR-1] = '\0';
1634       proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 3,
1635                                    1, out_buff, "%s", out_buff);
1636       g_snprintf (out_buff, SHORT_STR, "CFP max duration: %u",
1637                 tvb_get_letohs(tvb, offset + 4));
1638       out_buff[SHORT_STR-1] = '\0';
1639       proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 4,
1640                                    2, out_buff, "%s", out_buff);
1641       g_snprintf (out_buff, SHORT_STR, "CFP Remaining: %u",
1642                 tvb_get_letohs(tvb, offset + 6));
1643       out_buff[SHORT_STR-1] = '\0';
1644       proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 6,
1645                                    2, out_buff, "%s", out_buff);
1646       proto_item_append_text(ti, ": CFP count %u, CFP period %u, CFP max duration %u, "
1647                              "CFP Remaining %u",
1648                              tvb_get_guint8(tvb, offset + 2),
1649                              tvb_get_guint8(tvb, offset + 3),
1650                              tvb_get_letohs(tvb, offset + 4),
1651                              tvb_get_letohs(tvb, offset + 6));
1652       break;
1653
1654     case TAG_TIM:
1655       if (tag_len < 4)
1656       {
1657         proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 4",
1658                              tag_len);
1659         break;
1660       }
1661       {
1662         guint8 bmapctl;
1663         guint8 bmapoff;
1664         guint8 bmaplen;
1665         const guint8* bmap;
1666
1667         proto_tree_add_item(tree, tim_dtim_count, tvb,
1668                             offset + 2, 1, TRUE);
1669         proto_tree_add_item(tree, tim_dtim_period, tvb,
1670                             offset + 3, 1, TRUE);
1671         proto_item_append_text(ti, ": DTIM %u of %u bitmap",
1672                                tvb_get_guint8(tvb, offset + 2),
1673                                tvb_get_guint8(tvb, offset + 3));
1674
1675         bmapctl = tvb_get_guint8(tvb, offset + 4);
1676         bmapoff = bmapctl>>1;
1677         proto_tree_add_uint_format(tree, tim_bmapctl, tvb,
1678                             offset + 4, 1, bmapctl,
1679                             "Bitmap Control: 0x%02X (mcast:%u, bitmap offset %u)",
1680                             bmapctl, bmapctl&1, bmapoff);
1681
1682         bmaplen = tag_len - 3;
1683         bmap = tvb_get_ptr(tvb, offset + 5, bmaplen);
1684         if (bmaplen==1 && 0==bmap[0] && !(bmapctl&1)) {
1685           proto_item_append_text(ti, " empty");
1686         } else {
1687           if (bmapctl&1) {
1688             proto_item_append_text(ti, " mcast");
1689           }
1690         }
1691         if (bmaplen>1 || bmap[0]) {
1692           int len=g_snprintf (out_buff, SHORT_STR,
1693                             "Bitmap: traffic for AID's:");
1694           int i=0;
1695           for (i=0;i<bmaplen*8;i++) {
1696             if (bmap[i/8] & (1<<(i%8))) {
1697               int aid=i+bmapoff*8;
1698               len+=g_snprintf (out_buff+len, SHORT_STR-len," %u", aid);
1699               proto_item_append_text(ti, " %u", aid);
1700               if (len>=SHORT_STR) {
1701                 break;
1702               }
1703             }
1704           }
1705           out_buff[SHORT_STR-1] = '\0';
1706           proto_tree_add_string_format (tree, tag_interpretation, tvb, offset + 5,
1707                bmaplen, out_buff, "%s", out_buff);
1708         }
1709       }
1710       break;
1711
1712     case TAG_IBSS_PARAMETER:
1713       if (tag_len < 2)
1714       {
1715         proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 2",
1716                              tag_len);
1717         break;
1718       }
1719       g_snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
1720                 tvb_get_letohs(tvb, offset + 2));
1721       out_buff[SHORT_STR-1] = '\0';
1722       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1723                              tag_len, out_buff);
1724       proto_item_append_text(ti, ": %s", out_buff);
1725       break;
1726
1727     case TAG_COUNTRY_INFO: /* IEEE 802.11d-2001 and IEEE 802.11j-2004 */
1728       {
1729         char ccode[2+1];
1730
1731         if (tag_len < 3)
1732         {
1733           proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 3",
1734                                tag_len);
1735           break;
1736         }
1737         tvb_memcpy(tvb, ccode, offset + 2, 2);
1738         ccode[2] = '\0';
1739         g_snprintf (out_buff, SHORT_STR, "Country Code: %s, %s Environment",
1740                  format_text(ccode, 2),
1741                  val_to_str(tvb_get_guint8(tvb, offset + 4), environment_vals,"Unknown (0x%02x)"));
1742         out_buff[SHORT_STR-1] = '\0';
1743         proto_item_append_text(ti, ": %s", out_buff);
1744         proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,3, out_buff);
1745
1746         for (i = 3; (i + 3) <= tag_len; i += 3)
1747         {
1748           guint8 val1, val2, val3;
1749           val1 = tvb_get_guint8(tvb, offset + 2 + i);
1750           val2 = tvb_get_guint8(tvb, offset + 3 + i);
1751           val3 = tvb_get_guint8(tvb, offset + 4 + i);
1752
1753           if (val1 <= 200) {  /* 802.11d */
1754             proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 2+i,3, out_buff,
1755                                        "  Start Channel: %u, Channels: %u, Max TX Power: %d dBm",
1756                                        val1, val2, (gint) val3);
1757           } else {  /* 802.11j */
1758             proto_tree_add_string_format(tree, tag_interpretation, tvb, offset + 2+i,3, out_buff,
1759                                        "  Reg Extension Id: %u, Regulatory Class: %u, Coverage Class: %u",
1760                                        val1, val2, val3);
1761           }
1762         }
1763       }
1764       break;
1765
1766     case TAG_QBSS_LOAD:  
1767       if (tag_len < 4 || tag_len >5)
1768       {
1769         proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Wrong QBSS Tag Length %u", tag_len);
1770         break;
1771       }
1772
1773       if (tag_len == 4)
1774       {
1775         /* QBSS Version 1 */
1776         proto_tree_add_string (tree, tag_interpretation, tvb, offset + 1,
1777           tag_len, "Cisco QBSS Version 1 - non CCA");
1778
1779         /* Extract Values */
1780         proto_tree_add_uint (tree, hf_qbss_version, tvb, offset + 2, tag_len, 1);
1781         proto_tree_add_item (tree, hf_qbss_scount, tvb, offset + 2, 2, TRUE);
1782         proto_tree_add_item (tree, hf_qbss_cu, tvb, offset + 4, 1, FALSE);
1783         proto_tree_add_item (tree, hf_qbss_adc, tvb, offset + 5, 1, FALSE);
1784       } 
1785       else if (tag_len == 5)
1786       {
1787          /* QBSS Version 2 */
1788          proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1789            tag_len, "802.11e CCA Version");
1790
1791          /* Extract Values */
1792          proto_tree_add_uint (tree, hf_qbss_version, tvb, offset + 2, tag_len, 2);
1793          proto_tree_add_item (tree, hf_qbss_scount, tvb, offset + 2, 2, TRUE);
1794          proto_tree_add_item (tree, hf_qbss_cu, tvb, offset + 4, 1, FALSE);
1795          proto_tree_add_item (tree, hf_qbss_adc, tvb, offset + 5, 2, FALSE);
1796       }
1797       break;
1798
1799     case TAG_FH_HOPPING_PARAMETER:
1800       if (tag_len < 2)
1801       {
1802         proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 2",
1803                              tag_len);
1804         break;
1805       }
1806       g_snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u",
1807                 tvb_get_guint8(tvb, offset + 2),
1808                 tvb_get_guint8(tvb, offset + 3));
1809       out_buff[SHORT_STR-1] = '\0';
1810       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, tag_len, out_buff);
1811       proto_item_append_text(ti, ": %s", out_buff);
1812       break;
1813
1814     case TAG_CHALLENGE_TEXT:
1815       g_snprintf (out_buff, SHORT_STR, "Challenge text: %s",
1816                 tvb_bytes_to_str(tvb, offset + 2, tag_len));
1817       out_buff[SHORT_STR-1] = '\0';
1818       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1819                              tag_len, out_buff);
1820       break;
1821
1822     case TAG_ERP_INFO:
1823     case TAG_ERP_INFO_OLD:
1824       {
1825         guint8 erp_info;
1826
1827         if (tag_len < 1)
1828         {
1829           proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 1",
1830                                tag_len);
1831           break;
1832         }
1833         erp_info = tvb_get_guint8 (tvb, offset + 2);
1834         g_snprintf (print_buff, SHORT_STR, "%sNon-ERP STAs, %suse protection, %s preambles",
1835                   erp_info & 0x01 ? "" : "no ",
1836                   erp_info & 0x02 ? "" : "do not ",
1837                   erp_info & 0x04 ? "short or long": "long");
1838         print_buff[SHORT_STR-1] = '\0';
1839         g_snprintf (out_buff, SHORT_STR,
1840                   "ERP info: 0x%x (%s)",erp_info,print_buff);
1841         out_buff[SHORT_STR-1] = '\0';
1842         proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1843                                tag_len, out_buff);
1844         proto_item_append_text(ti, ": %s", print_buff);
1845       }
1846       break;
1847
1848     case TAG_CISCO_UNKNOWN_1:
1849       /* The Name of the sending device starts at offset 10 and is up to
1850          15 or 16 bytes in length, \0 padded */
1851       if (tag_len < 26)
1852       {
1853         proto_tree_add_text (tree, tvb, offset + 2, tag_len, "Tag length %u too short, must be >= 26",
1854                              tag_len);
1855         break;
1856       }
1857       g_snprintf (out_buff, SHORT_STR, "%.16s",
1858                 tvb_format_stringzpad(tvb, offset + 12, 16));
1859       out_buff[SHORT_STR-1] = '\0';
1860       proto_tree_add_string_format (tree, tag_interpretation, tvb, offset + 2,
1861                              tag_len, "", "Tag interpretation: Unknown + Name: %s",
1862                              out_buff);
1863       if (check_col (pinfo->cinfo, COL_INFO)) {
1864           col_append_fstr(pinfo->cinfo, COL_INFO, ", Name: \"%s\"", out_buff);
1865       }
1866       break;
1867
1868     case TAG_VENDOR_SPECIFIC_IE:
1869       tvb_ensure_bytes_exist (tvb, offset + 2, tag_len);
1870       if (tag_len >= 3) {
1871                 oui = tvb_get_ntoh24(tvb, offset + 2);
1872                 tag_val = tvb_get_ptr(tvb, offset + 2, tag_len);
1873                 
1874 #define WPAWME_OUI      0x0050F2
1875 #define RSNOUI_VAL      0x000FAC
1876 #define AIRONET_VAL     0x004096
1877
1878                 switch (oui) {
1879                 case WPAWME_OUI:
1880                         dissect_vendor_ie_wpawme(ti, tree, tvb, offset + 2, tag_len, tag_val);
1881                         break;
1882                 case RSNOUI_VAL:
1883                         dissect_vendor_ie_rsn(ti, tree, tvb, offset + 2, tag_len, tag_val);
1884                         break;
1885                 case AIRONET_VAL:
1886                         dissect_vendor_ie_aironet(ti, tree, tvb, offset + 5, tag_len - 3);
1887                         break;
1888                 default:
1889                         proto_tree_add_bytes_format (tree, tag_oui, tvb, offset + 2, 3,
1890                                 "", "Vendor: %s", get_manuf_name(tag_val));
1891                         proto_item_append_text(ti, ": %s", get_manuf_name(tag_val));
1892                         proto_tree_add_string (tree, tag_interpretation, tvb, offset + 5,
1893                                 tag_len - 3, "Not interpreted");
1894                         break;
1895                 }
1896
1897       }
1898       break;
1899
1900     case TAG_RSN_IE:
1901       dissect_rsn_ie(tree, tvb, offset + 2, tag_len,
1902                      tvb_get_ptr (tvb, offset + 2, tag_len));
1903       break;
1904
1905     default:
1906       tvb_ensure_bytes_exist (tvb, offset + 2, tag_len);
1907       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1908                              tag_len, "Not interpreted");
1909       proto_item_append_text(ti, ": Tag %u Len %u", tag_no, tag_len);
1910       break;
1911     }
1912
1913   return tag_len + 2;
1914 }
1915
1916 void
1917 ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, packet_info * pinfo,
1918         proto_tree * tree, int tagged_parameters_len)
1919 {
1920   int next_len;
1921
1922   beacon_padding = 0; /* this is for the beacon padding confused with ssid fix */
1923   while (tagged_parameters_len > 0) {
1924     if ((next_len=add_tagged_field (pinfo, tree, tvb, offset))==0)
1925       break;
1926     if (next_len > tagged_parameters_len) {
1927       /* XXX - flag this as an error? */
1928       next_len = tagged_parameters_len;
1929     }
1930     offset += next_len;
1931     tagged_parameters_len -= next_len;
1932   }
1933 }
1934
1935 /* ************************************************************************* */
1936 /*                     Dissect 802.11 management frame                       */
1937 /* ************************************************************************* */
1938 static void
1939 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
1940         proto_tree * tree)
1941 {
1942       proto_item *ti = NULL;
1943       proto_tree *mgt_tree;
1944       proto_tree *fixed_tree;
1945       proto_tree *tagged_tree;
1946       int offset;
1947       int tagged_parameter_tree_len;
1948
1949       g_pinfo = pinfo;
1950
1951       CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
1952
1953       ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
1954       mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
1955
1956       switch (COMPOSE_FRAME_TYPE(fcf))
1957         {
1958
1959         case MGT_ASSOC_REQ:
1960           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
1961           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1962           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1963           offset = 4;   /* Size of fixed fields */
1964
1965           tagged_parameter_tree_len =
1966               tvb_reported_length_remaining(tvb, offset);
1967           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1968                                                    tagged_parameter_tree_len);
1969           ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1970               tagged_parameter_tree_len);
1971           break;
1972
1973
1974         case MGT_ASSOC_RESP:
1975           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1976           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1977           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1978           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1979           offset = 6;   /* Size of fixed fields */
1980
1981           tagged_parameter_tree_len =
1982               tvb_reported_length_remaining(tvb, offset);
1983           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1984                                                    tagged_parameter_tree_len);
1985           ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1986               tagged_parameter_tree_len);
1987           break;
1988
1989
1990         case MGT_REASSOC_REQ:
1991           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1992           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1993           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1994           add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
1995           offset = 10;  /* Size of fixed fields */
1996
1997           tagged_parameter_tree_len =
1998               tvb_reported_length_remaining(tvb, offset);
1999           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
2000                                                    tagged_parameter_tree_len);
2001           ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
2002               tagged_parameter_tree_len);
2003           break;
2004
2005         case MGT_REASSOC_RESP:
2006           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
2007           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
2008           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
2009           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
2010           offset = 6;   /* Size of fixed fields */
2011
2012           tagged_parameter_tree_len =
2013               tvb_reported_length_remaining(tvb, offset);
2014           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
2015                                                    tagged_parameter_tree_len);
2016           ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
2017               tagged_parameter_tree_len);
2018           break;
2019
2020
2021         case MGT_PROBE_REQ:
2022           offset = 0;
2023           tagged_parameter_tree_len =
2024               tvb_reported_length_remaining(tvb, offset);
2025           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
2026                                                    tagged_parameter_tree_len);
2027           ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
2028               tagged_parameter_tree_len);
2029           break;
2030
2031
2032         case MGT_PROBE_RESP:
2033           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
2034           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
2035           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
2036           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
2037           offset = 12;  /* Size of fixed fields */
2038
2039           tagged_parameter_tree_len =
2040               tvb_reported_length_remaining(tvb, offset);
2041           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
2042                                                    tagged_parameter_tree_len);
2043           ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
2044               tagged_parameter_tree_len);
2045           break;
2046
2047
2048         case MGT_BEACON:                /* Dissect protocol payload fields  */
2049           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
2050           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
2051           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
2052           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
2053           offset = 12;  /* Size of fixed fields */
2054
2055           tagged_parameter_tree_len =
2056               tvb_reported_length_remaining(tvb, offset);
2057           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
2058                                                    tagged_parameter_tree_len);
2059           ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
2060               tagged_parameter_tree_len);
2061           break;
2062
2063
2064         case MGT_ATIM:
2065           break;
2066
2067
2068         case MGT_DISASS:
2069           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
2070           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
2071           break;
2072
2073
2074         case MGT_AUTHENTICATION:
2075           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
2076           add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
2077           add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
2078           add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
2079           offset = 6;   /* Size of fixed fields */
2080
2081           tagged_parameter_tree_len =
2082                   tvb_reported_length_remaining(tvb, offset);
2083           if (tagged_parameter_tree_len != 0)
2084             {
2085               tagged_tree = get_tagged_parameter_tree (mgt_tree,
2086                                                        tvb,
2087                                                        offset,
2088                                                        tagged_parameter_tree_len);
2089               ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
2090                 tagged_parameter_tree_len);
2091             }
2092           break;
2093
2094
2095         case MGT_DEAUTHENTICATION:
2096           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
2097           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
2098           break;
2099
2100
2101         case MGT_ACTION:
2102           switch (tvb_get_guint8(tvb, 0))
2103             {
2104
2105             case CAT_SPECTRUM_MGMT:
2106               switch (tvb_get_guint8(tvb, 1))
2107                 {
2108                 case SM_ACTION_MEASUREMENT_REQUEST:
2109                 case SM_ACTION_MEASUREMENT_REPORT:
2110                 case SM_ACTION_TPC_REQUEST:
2111                 case SM_ACTION_TPC_REPORT:
2112                   fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 3);
2113                   add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
2114                   add_fixed_field (fixed_tree, tvb, 1, FIELD_ACTION_CODE);
2115                   add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
2116                   offset = 3;   /* Size of fixed fields */
2117                   break;
2118
2119                 case SM_ACTION_CHAN_SWITCH_ANNC:
2120                   fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
2121                   add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
2122                   offset = 2;   /* Size of fixed fields */
2123                   break;
2124
2125                 default:
2126                   fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
2127                   add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
2128                   offset = 2;   /* Size of fixed fields */
2129                   break;
2130                 }
2131               break;
2132
2133             case CAT_MGMT_NOTIFICATION: /* Management notification frame */
2134               fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
2135               add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
2136               add_fixed_field (fixed_tree, tvb, 1, FIELD_WME_ACTION_CODE);
2137               add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
2138               add_fixed_field (fixed_tree, tvb, 3, FIELD_WME_STATUS_CODE);
2139               offset = 4;       /* Size of fixed fields */
2140               break;
2141
2142             default:
2143               fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 1);
2144               add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
2145               offset = 1;       /* Size of fixed fields */
2146               break;
2147             }
2148
2149             tagged_parameter_tree_len =
2150               tvb_reported_length_remaining(tvb, offset);
2151             if (tagged_parameter_tree_len != 0)
2152               {
2153                 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
2154                                                          tagged_parameter_tree_len);
2155                 ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
2156                                                   tagged_parameter_tree_len);
2157               }
2158           break;
2159         }
2160 }
2161
2162 static void
2163 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, const char *type)
2164 {
2165   if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
2166     col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
2167                     get_ether_name(addr), type);
2168   if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
2169     col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s",
2170                      ether_to_str(addr));
2171 }
2172
2173 static void
2174 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, const char *type)
2175 {
2176   if (check_col(pinfo->cinfo, COL_RES_DL_DST))
2177     col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
2178                      get_ether_name(addr), type);
2179   if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
2180     col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s",
2181                      ether_to_str(addr));
2182 }
2183
2184 static guint32
2185 crc32_802_tvb_padded(tvbuff_t *tvb, guint hdr_len, guint hdr_size, guint len)
2186 {
2187   guint32 c_crc;
2188
2189   c_crc = crc32_ccitt_tvb(tvb, hdr_len);
2190   c_crc = crc32_ccitt_seed(tvb_get_ptr(tvb, hdr_size, len), len, ~c_crc);
2191
2192   /* Byte reverse. */
2193   c_crc = ((unsigned char)(c_crc>>0)<<24) |
2194     ((unsigned char)(c_crc>>8)<<16) |
2195     ((unsigned char)(c_crc>>16)<<8) |
2196     ((unsigned char)(c_crc>>24)<<0);
2197
2198   return ( c_crc );
2199 }
2200
2201 typedef enum {
2202     ENCAP_802_2,
2203     ENCAP_IPX,
2204     ENCAP_ETHERNET
2205 } encap_t;
2206
2207 /* ************************************************************************* */
2208 /*                          Dissect 802.11 frame                             */
2209 /* ************************************************************************* */
2210 static void
2211 dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
2212                           proto_tree * tree, gboolean fixed_length_header,
2213                           gboolean has_radio_information, gint fcs_len,
2214                           gboolean wlan_broken_fc, gboolean datapad)
2215 {
2216   guint16 fcf, flags, frame_type_subtype;
2217   guint16 seq_control;
2218   guint32 seq_number, frag_number;
2219   gboolean more_frags;
2220   const guint8 *src = NULL;
2221   const guint8 *dst = NULL;
2222   const guint8 *bssid = NULL;
2223   proto_item *ti = NULL;
2224   proto_item *flag_item;
2225   proto_item *fc_item;
2226   proto_tree *hdr_tree = NULL;
2227   proto_tree *flag_tree;
2228   proto_tree *fc_tree;
2229   guint16 hdr_len, ohdr_len;
2230   gboolean has_fcs;
2231   gint len, reported_len, ivlen;
2232   gboolean save_fragmented;
2233   tvbuff_t *volatile next_tvb = NULL;
2234   guint32 addr_type;
2235   volatile encap_t encap_type;
2236   guint8 octet1, octet2;
2237   char out_buff[SHORT_STR];
2238   gint is_iv_bad;
2239   guchar iv_buff[4];
2240   wlan_hdr *volatile whdr;
2241   static wlan_hdr whdrs[4];
2242
2243   whdr= &whdrs[0];
2244
2245   if (check_col (pinfo->cinfo, COL_PROTOCOL))
2246     col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
2247   if (check_col (pinfo->cinfo, COL_INFO))
2248     col_clear (pinfo->cinfo, COL_INFO);
2249
2250   /* Add the radio information, if present, to the column information */
2251   if (has_radio_information) {
2252     if (check_col(pinfo->cinfo, COL_TX_RATE)) {
2253         col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
2254            pinfo->pseudo_header->ieee_802_11.data_rate / 2,
2255            pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
2256     }
2257     if (check_col(pinfo->cinfo, COL_RSSI)) {
2258       /* XX - this is a percentage, not a dBm or normalized or raw RSSI */
2259       col_add_fstr(pinfo->cinfo, COL_RSSI, "%u",
2260            pinfo->pseudo_header->ieee_802_11.signal_level);
2261     }
2262   }
2263
2264   fcf = tvb_get_letohs (tvb, 0);
2265   if (wlan_broken_fc) {
2266     /* Swap bytes */
2267     fcf = ((fcf & 0xff) << 8) | (((fcf & 0xff00) >> 8) & 0xff);
2268   }
2269   if (fixed_length_header)
2270     hdr_len = DATA_LONG_HDR_LEN;
2271   else
2272     hdr_len = find_header_length (fcf);
2273   ohdr_len = hdr_len;
2274   if (datapad)
2275     hdr_len = roundup2(hdr_len, 4);
2276   frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
2277
2278   if (check_col (pinfo->cinfo, COL_INFO))
2279       col_set_str (pinfo->cinfo, COL_INFO,
2280           val_to_str(frame_type_subtype, frame_type_subtype_vals,
2281               "Unrecognized (Reserved frame)"));
2282
2283   flags = FCF_FLAGS (fcf);
2284   more_frags = HAVE_FRAGMENTS (flags);
2285
2286
2287   /* Add the radio information, if present, and the FC to the current tree */
2288   if (tree)
2289     {
2290       ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
2291                                            "IEEE 802.11");
2292       hdr_tree = proto_item_add_subtree (ti, ett_80211);
2293
2294       if (has_radio_information) {
2295         proto_tree_add_uint_format(hdr_tree, hf_data_rate,
2296                                    tvb, 0, 0,
2297                                    pinfo->pseudo_header->ieee_802_11.data_rate,
2298                                    "Data Rate: %u.%u Mb/s",
2299                                    pinfo->pseudo_header->ieee_802_11.data_rate / 2,
2300                                    pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
2301
2302         proto_tree_add_uint(hdr_tree, hf_channel,
2303                             tvb, 0, 0,
2304                             pinfo->pseudo_header->ieee_802_11.channel);
2305
2306         proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
2307                                    tvb, 0, 0,
2308                                    pinfo->pseudo_header->ieee_802_11.signal_level,
2309                                    "Signal Strength: %u%%",
2310                                    pinfo->pseudo_header->ieee_802_11.signal_level);
2311       }
2312
2313       proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
2314                            tvb,
2315                            wlan_broken_fc?1:0, 1,
2316                            frame_type_subtype);
2317
2318       fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb,
2319                                             0, 2,
2320                                             fcf,
2321                                             "Frame Control: 0x%04X (%s)",
2322                                             fcf, wlan_broken_fc?"Swapped":"Normal");
2323
2324       fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
2325
2326
2327       proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb,
2328                            wlan_broken_fc?1:0, 1,
2329                            FCF_PROT_VERSION (fcf));
2330
2331       proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb,
2332                            wlan_broken_fc?1:0, 1,
2333                            FCF_FRAME_TYPE (fcf));
2334
2335       proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
2336                            tvb,
2337                            wlan_broken_fc?1:0, 1,
2338                            FCF_FRAME_SUBTYPE (fcf));
2339
2340       flag_item =
2341         proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb,
2342                                     wlan_broken_fc?0:1, 1,
2343                                     flags, "Flags: 0x%X", flags);
2344
2345       flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
2346
2347       proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb,
2348                            wlan_broken_fc?0:1, 1,
2349                            FLAGS_DS_STATUS (flags));
2350       proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1,
2351                                      flags);
2352       proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1,
2353                                      flags);
2354
2355       proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb,
2356                               wlan_broken_fc?0:1, 1,
2357                               flags);
2358
2359       proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb,
2360                               wlan_broken_fc?0:1, 1, flags);
2361
2362       proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb,
2363                               wlan_broken_fc?0:1, 1, flags);
2364
2365       proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb,
2366                               wlan_broken_fc?0:1, 1,
2367                               flags);
2368
2369       proto_tree_add_boolean (flag_tree, hf_fc_protected, tvb,
2370                               wlan_broken_fc?0:1, 1, flags);
2371
2372       proto_tree_add_boolean (flag_tree, hf_fc_order, tvb,
2373                               wlan_broken_fc?0:1, 1, flags);
2374
2375       if (frame_type_subtype == CTRL_PS_POLL)
2376         proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
2377                             ASSOC_ID(tvb_get_letohs(tvb,2)));
2378
2379       else
2380           proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
2381                                tvb_get_letohs (tvb, 2));
2382     }
2383
2384   /*
2385    * Decode the part of the frame header that isn't the same for all
2386    * frame types.
2387    */
2388   seq_control = 0;
2389   frag_number = 0;
2390   seq_number = 0;
2391
2392   switch (FCF_FRAME_TYPE (fcf))
2393     {
2394
2395     case MGT_FRAME:
2396       /*
2397        * All management frame types have the same header.
2398        */
2399       src = tvb_get_ptr (tvb, 10, 6);
2400       dst = tvb_get_ptr (tvb, 4, 6);
2401
2402       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
2403       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
2404       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
2405       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
2406
2407       /* for tap */
2408       SET_ADDRESS(&whdr->bssid, AT_ETHER, 6, tvb_get_ptr(tvb, 16,6));
2409       SET_ADDRESS(&whdr->src, AT_ETHER, 6, src);
2410       SET_ADDRESS(&whdr->dst, AT_ETHER, 6, dst);
2411       whdr->type = frame_type_subtype;
2412
2413       seq_control = tvb_get_letohs(tvb, 22);
2414       frag_number = SEQCTL_FRAGMENT_NUMBER(seq_control);
2415       seq_number = SEQCTL_SEQUENCE_NUMBER(seq_control);
2416
2417       if (check_col (pinfo->cinfo, COL_INFO))
2418       {
2419         col_append_fstr(pinfo->cinfo, COL_INFO,
2420           ",SN=%d", seq_number);
2421
2422         col_append_fstr(pinfo->cinfo, COL_INFO,
2423           ",FN=%d",frag_number);
2424       }
2425
2426       if (tree)
2427         {
2428           proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
2429
2430           proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
2431
2432           /* add items for wlan.addr filter */
2433           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
2434           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2435
2436           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
2437                                 tvb_get_ptr (tvb, 16, 6));
2438
2439           proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2440                                frag_number);
2441
2442           proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2443                                seq_number);
2444         }
2445       break;
2446
2447     case CONTROL_FRAME:
2448       switch (frame_type_subtype)
2449         {
2450
2451         case CTRL_PS_POLL:
2452           src = tvb_get_ptr (tvb, 10, 6);
2453           dst = tvb_get_ptr (tvb, 4, 6);
2454
2455           set_src_addr_cols(pinfo, src, "BSSID");
2456           set_dst_addr_cols(pinfo, dst, "BSSID");
2457
2458           if (tree)
2459             {
2460               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
2461
2462               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
2463             }
2464           break;
2465
2466
2467         case CTRL_RTS:
2468           src = tvb_get_ptr (tvb, 10, 6);
2469           dst = tvb_get_ptr (tvb, 4, 6);
2470
2471           set_src_addr_cols(pinfo, src, "TA");
2472           set_dst_addr_cols(pinfo, dst, "RA");
2473
2474           if (tree)
2475             {
2476               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
2477
2478               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
2479             }
2480           break;
2481
2482
2483         case CTRL_CTS:
2484           dst = tvb_get_ptr (tvb, 4, 6);
2485
2486           set_dst_addr_cols(pinfo, dst, "RA");
2487
2488           if (tree)
2489             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
2490           break;
2491
2492
2493         case CTRL_ACKNOWLEDGEMENT:
2494           dst = tvb_get_ptr (tvb, 4, 6);
2495
2496           set_dst_addr_cols(pinfo, dst, "RA");
2497
2498           if (tree)
2499             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
2500           break;
2501
2502
2503         case CTRL_CFP_END:
2504           src = tvb_get_ptr (tvb, 10, 6);
2505           dst = tvb_get_ptr (tvb, 4, 6);
2506
2507           set_src_addr_cols(pinfo, src, "BSSID");
2508           set_dst_addr_cols(pinfo, dst, "RA");
2509
2510           if (tree)
2511             {
2512               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
2513               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
2514             }
2515           break;
2516
2517
2518         case CTRL_CFP_ENDACK:
2519           src = tvb_get_ptr (tvb, 10, 6);
2520           dst = tvb_get_ptr (tvb, 4, 6);
2521
2522           set_src_addr_cols(pinfo, src, "BSSID");
2523           set_dst_addr_cols(pinfo, dst, "RA");
2524
2525           if (tree)
2526             {
2527               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
2528
2529               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
2530             }
2531           break;
2532
2533         case CTRL_BLOCK_ACK_REQ:
2534           {
2535             src = tvb_get_ptr (tvb, 10, 6);
2536             dst = tvb_get_ptr (tvb, 4, 6);
2537
2538             set_src_addr_cols(pinfo, src, "TA");
2539             set_dst_addr_cols(pinfo, dst, "RA");
2540
2541             if (tree)
2542             {
2543               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, src);
2544
2545               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, dst);
2546             }
2547           /* TODO BAR */
2548           break;
2549           }
2550
2551         case CTRL_BLOCK_ACK:
2552           {
2553             src = tvb_get_ptr (tvb, 10, 6);
2554             dst = tvb_get_ptr (tvb, 4, 6);
2555
2556             set_src_addr_cols(pinfo, src, "TA");
2557             set_dst_addr_cols(pinfo, dst, "RA");
2558
2559             if (tree)
2560             {
2561               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, src);
2562
2563               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, dst);
2564             }
2565             /* TODO BAR Format */
2566             break;
2567           }
2568         }
2569       break;
2570
2571     case DATA_FRAME:
2572       addr_type = FCF_ADDR_SELECTOR (fcf);
2573
2574       /* In order to show src/dst address we must always do the following */
2575       switch (addr_type)
2576         {
2577
2578         case DATA_ADDR_T1:
2579           src = tvb_get_ptr (tvb, 10, 6);
2580           dst = tvb_get_ptr (tvb, 4, 6);
2581           bssid = tvb_get_ptr (tvb, 16, 6);
2582           break;
2583
2584
2585         case DATA_ADDR_T2:
2586           src = tvb_get_ptr (tvb, 16, 6);
2587           dst = tvb_get_ptr (tvb, 4, 6);
2588           bssid = tvb_get_ptr (tvb, 10, 6);
2589           break;
2590
2591
2592         case DATA_ADDR_T3:
2593           src = tvb_get_ptr (tvb, 10, 6);
2594           dst = tvb_get_ptr (tvb, 16, 6);
2595           bssid = tvb_get_ptr (tvb, 4, 6);
2596           break;
2597
2598
2599         case DATA_ADDR_T4:
2600           src = tvb_get_ptr (tvb, 24, 6);
2601           dst = tvb_get_ptr (tvb, 16, 6);
2602           bssid = tvb_get_ptr (tvb, 16, 6);
2603           break;
2604         }
2605
2606       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
2607       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
2608       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
2609       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
2610
2611       /* for tap */
2612
2613       SET_ADDRESS(&whdr->bssid, AT_ETHER, 6, bssid);
2614       SET_ADDRESS(&whdr->src, AT_ETHER, 6, src);
2615       SET_ADDRESS(&whdr->dst, AT_ETHER, 6, dst);
2616       whdr->type = frame_type_subtype;
2617
2618       seq_control = tvb_get_letohs(tvb, 22);
2619       frag_number = SEQCTL_FRAGMENT_NUMBER(seq_control);
2620       seq_number = SEQCTL_SEQUENCE_NUMBER(seq_control);
2621
2622       if (check_col (pinfo->cinfo, COL_INFO))
2623       {
2624         col_append_fstr(pinfo->cinfo, COL_INFO,
2625           ",SN=%d", seq_number);
2626
2627         col_append_fstr(pinfo->cinfo, COL_INFO,
2628           ",FN=%d",frag_number);
2629       }
2630
2631       /* Now if we have a tree we start adding stuff */
2632       if (tree)
2633         {
2634
2635
2636           switch (addr_type)
2637             {
2638
2639             case DATA_ADDR_T1:
2640               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
2641               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
2642               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
2643                                     tvb_get_ptr (tvb, 16, 6));
2644               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2645                                    frag_number);
2646               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2647                                    seq_number);
2648
2649               /* add items for wlan.addr filter */
2650               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
2651               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2652               break;
2653
2654
2655             case DATA_ADDR_T2:
2656               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
2657               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
2658                                     tvb_get_ptr (tvb, 10, 6));
2659               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
2660               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2661                                    frag_number);
2662               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2663                                    seq_number);
2664
2665               /* add items for wlan.addr filter */
2666               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
2667               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
2668               break;
2669
2670
2671             case DATA_ADDR_T3:
2672               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
2673                                     tvb_get_ptr (tvb, 4, 6));
2674               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
2675               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
2676
2677               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2678                                    frag_number);
2679               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2680                                    seq_number);
2681
2682               /* add items for wlan.addr filter */
2683               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2684               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
2685               break;
2686
2687
2688             case DATA_ADDR_T4:
2689               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
2690                                     tvb_get_ptr (tvb, 4, 6));
2691               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
2692                                     tvb_get_ptr (tvb, 10, 6));
2693               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
2694               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2695                                    frag_number);
2696               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2697                                    seq_number);
2698               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
2699
2700               /* add items for wlan.addr filter */
2701               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
2702               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
2703               break;
2704             }
2705
2706         }
2707       break;
2708     }
2709
2710   len = tvb_length_remaining(tvb, hdr_len);
2711   reported_len = tvb_reported_length_remaining(tvb, hdr_len);
2712
2713   switch (fcs_len)
2714     {
2715       case 0: /* Definitely has no FCS */
2716         has_fcs = FALSE;
2717         break;
2718
2719       case 4: /* Definitely has an FCS */
2720         has_fcs = TRUE;
2721         break;
2722
2723       default: /* Don't know - use "wlan_check_fcs" */
2724         has_fcs = wlan_check_fcs;
2725         break;
2726     }
2727   if (has_fcs)
2728     {
2729       /*
2730        * Well, this packet should, in theory, have an FCS.
2731        * Do we have the entire packet, and does it have enough data for
2732        * the FCS?
2733        */
2734       if (reported_len < 4)
2735         {
2736           /*
2737            * The packet is claimed not to even have enough data for a 4-byte
2738            * FCS.
2739            * Pretend it doesn't have an FCS.
2740            */
2741           ;
2742         }
2743       else if (len < reported_len)
2744         {
2745           /*
2746            * The packet is claimed to have enough data for a 4-byte FCS, but
2747            * we didn't capture all of the packet.
2748            * Slice off the 4-byte FCS from the reported length, and trim the
2749            * captured length so it's no more than the reported length; that
2750            * will slice off what of the FCS, if any, is in the captured
2751            * length.
2752            */
2753           reported_len -= 4;
2754           if (len > reported_len)
2755             len = reported_len;
2756         }
2757       else
2758         {
2759           /*
2760            * We have the entire packet, and it includes a 4-byte FCS.
2761            * Slice it off, and put it into the tree.
2762            */
2763           len -= 4;
2764           reported_len -= 4;
2765           if (tree)
2766             {
2767               guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
2768               guint32 fcs;
2769
2770               if (datapad)
2771                 fcs = crc32_802_tvb_padded(tvb, ohdr_len, hdr_len, len);
2772               else
2773                 fcs = crc32_802_tvb(tvb, hdr_len + len);
2774               if (fcs == sent_fcs)
2775                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
2776                         hdr_len + len, 4, sent_fcs,
2777                         "Frame check sequence: 0x%08x [correct]", sent_fcs);
2778               else
2779                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
2780                         hdr_len + len, 4, sent_fcs,
2781                         "Frame check sequence: 0x%08x [incorrect, should be 0x%08x]",
2782                         sent_fcs, fcs);
2783             }
2784         }
2785     }
2786
2787
2788
2789   /*
2790    * Only management and data frames have a body, so we don't have
2791    * anything more to do for other types of frames.
2792    */
2793   switch (FCF_FRAME_TYPE (fcf))
2794     {
2795
2796     case MGT_FRAME:
2797       break;
2798
2799     case DATA_FRAME:
2800       if (tree && DATA_FRAME_IS_QOS(frame_type_subtype))
2801         {
2802
2803           proto_item *qos_fields;
2804           proto_tree *qos_tree;
2805
2806           guint16 qosoff;
2807           guint16 qos_control;
2808           guint16 qos_priority;
2809           guint16 qos_ack_policy;
2810           guint16 qos_eosp;
2811           guint16 qos_field_content;
2812
2813           /*
2814            * We calculate the offset to the QoS header data as
2815            * an offset relative to the end of the header.  But
2816            * when the header has been padded to align the data
2817            * this must be done relative to true header size, not
2818            * the padded/aligned value.  To simplify this work we
2819            * stash the original header size in ohdr_len instead
2820            * of recalculating it.
2821            */
2822           qosoff = ohdr_len - 2;
2823           qos_fields = proto_tree_add_text(hdr_tree, tvb, qosoff, 2,
2824               "QoS parameters");
2825           qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters);
2826
2827           qos_control = tvb_get_letohs(tvb, qosoff + 0);
2828           qos_priority = QOS_PRIORITY(qos_control);
2829           qos_ack_policy = QOS_ACK_POLICY(qos_control);
2830           qos_eosp = QOS_EOSP(qos_control);
2831           qos_field_content = QOS_FIELD_CONTENT( qos_control);
2832
2833           proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
2834               qosoff, 2, qos_priority,
2835               "Priority: %d (%s) (%s)",
2836               qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]);
2837
2838           if (flags & FLAG_FROM_DS) {
2839             proto_tree_add_boolean (qos_tree, hf_qos_eosp, tvb,
2840               qosoff, 1, qos_eosp);
2841
2842             if (DATA_FRAME_IS_CF_POLL(frame_type_subtype)) {
2843               /* txop limit */
2844               proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
2845                   qosoff + 1, 1, qos_field_content, "TXOP Limit: %d ", qos_field_content);
2846
2847             } else {
2848               /* qap ps buffer state */
2849               proto_item *qos_ps_buf_state_fields;
2850               proto_tree *qos_ps_buf_state_tree;
2851               guint16 buf_state;
2852               guint16 buf_ac;
2853               guint16 buf_load;
2854
2855               buf_state = QOS_PS_BUF_STATE(qos_field_content);
2856               buf_ac = QOS_PS_BUF_AC(qos_field_content);  /*access category */
2857               buf_load = QOS_PS_BUF_LOAD(qos_field_content);
2858
2859               qos_ps_buf_state_fields = proto_tree_add_text(qos_tree, tvb, qosoff + 1, 1,
2860                 "QAP PS Buffer State: 0x%x", qos_field_content);
2861               qos_ps_buf_state_tree = proto_item_add_subtree (qos_ps_buf_state_fields, ett_qos_ps_buf_state);
2862
2863 /*      FIXME: hf_ values not defined
2864               proto_tree_add_boolean (qos_ps_buf_state_tree, hf_qos_buf_state, tvb,
2865                   1, 1, buf_state);
2866
2867               proto_tree_add_uint_format (qos_ps_buf_state_tree, hf_qos_buf_ac, tvb,
2868                   qosoff + 1, 1, buf_ac, "Priority: %d (%s)",
2869                   buf_ac, wme_acs[buf_ac]);
2870
2871               proto_tree_add_uint_format (qos_ps_buf_state_tree, hf_qos_buf_load, tvb,
2872                   qosoff + 1, 1, buf_load, "Buffered load: %d ", (buf_load * 4096));
2873 */
2874
2875             }
2876           } else if (qos_eosp)  {
2877             /* txop limit requested */
2878             proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
2879                   qosoff + 1, 1, qos_field_content, "Queue Size: %d ", (qos_field_content * 254));
2880           } else {
2881             /* queue size */
2882             proto_tree_add_uint_format (qos_tree, hf_qos_field_content, tvb,
2883                   qosoff + 1, 1, qos_field_content, "TXOP Limit Requested: %d ", qos_field_content);
2884           }
2885
2886           proto_tree_add_uint (qos_tree, hf_qos_ack_policy, tvb, qosoff, 1,
2887               qos_ack_policy);
2888
2889         } /* end of qos control field */
2890
2891       /*
2892        * No-data frames don't have a body.
2893        */
2894       if (DATA_FRAME_IS_NULL(frame_type_subtype))
2895         return;
2896
2897       break;
2898
2899     case CONTROL_FRAME:
2900       return;
2901
2902     default:
2903       return;
2904     }
2905
2906   if (IS_PROTECTED(FCF_FLAGS(fcf))) {
2907     /*
2908      * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
2909      * the data, if we have a matching key.  Otherwise display it as data.
2910      */
2911     gboolean can_decrypt = FALSE;
2912     proto_tree *wep_tree = NULL;
2913     guint32 iv;
2914     guint8 key, keybyte;
2915
2916     keybyte = tvb_get_guint8(tvb, hdr_len + 3);
2917     key = KEY_OCTET_WEP_KEY(keybyte);
2918     if ((keybyte & KEY_EXTIV) && (len >= EXTIV_LEN)) {
2919       /* Extended IV; this frame is likely encrypted with TKIP or CCMP */
2920       if (tree) {
2921         proto_item *extiv_fields;
2922
2923         extiv_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 8,
2924                                            "TKIP/CCMP parameters");
2925         wep_tree = proto_item_add_subtree (extiv_fields, ett_wep_parameters);
2926         /* It is unknown whether this is a TKIP or CCMP encrypted packet, so
2927          * display both packet number alternatives unless the ExtIV can be
2928          * determined to be possible only with one of the encryption protocols.
2929          */
2930         if (tvb_get_guint8(tvb, hdr_len + 1) & 0x20) {
2931           g_snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
2932                    tvb_get_letohl(tvb, hdr_len + 4),
2933                    tvb_get_guint8(tvb, hdr_len),
2934                    tvb_get_guint8(tvb, hdr_len + 2));
2935           proto_tree_add_string(wep_tree, hf_tkip_extiv, tvb, hdr_len,
2936                                 EXTIV_LEN, out_buff);
2937         }
2938         if (tvb_get_guint8(tvb, hdr_len + 2) == 0) {
2939           g_snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
2940                    tvb_get_letohl(tvb, hdr_len + 4),
2941                    tvb_get_guint8(tvb, hdr_len + 1),
2942                    tvb_get_guint8(tvb, hdr_len));
2943           proto_tree_add_string(wep_tree, hf_ccmp_extiv, tvb, hdr_len,
2944                                 EXTIV_LEN, out_buff);
2945         }
2946         proto_tree_add_uint(wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
2947       }
2948
2949       /* Subtract out the length of the IV. */
2950       len -= EXTIV_LEN;
2951       reported_len -= EXTIV_LEN;
2952       ivlen = EXTIV_LEN;
2953       /* It is unknown whether this is TKIP or CCMP, so let's not even try to
2954        * parse TKIP Michael MIC+ICV or CCMP MIC. */
2955     } else {
2956       /* No Ext. IV - WEP packet */
2957       /*
2958        * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
2959        * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
2960        * them itself.
2961        *
2962        * Also, just pass the data *following* the WEP parameters as the
2963        * buffer to decrypt.
2964        */
2965       iv = tvb_get_ntoh24(tvb, hdr_len);
2966       if (tree) {
2967         proto_item *wep_fields;
2968
2969         wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
2970                                          "WEP parameters");
2971
2972         wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
2973         proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
2974         tvb_memcpy(tvb, iv_buff, hdr_len, 3);
2975         is_iv_bad = weak_iv(iv_buff);
2976         if (is_iv_bad != -1) {
2977                 proto_tree_add_boolean_format (wep_tree, hf_wep_iv_weak,
2978                                                tvb, 0, 0, TRUE,
2979                                                "Weak IV for key byte %d",
2980                                                is_iv_bad);
2981         }
2982       }
2983       if (tree)
2984         proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
2985
2986       /* Subtract out the length of the IV. */
2987       len -= 4;
2988       reported_len -= 4;
2989       ivlen = 4;
2990
2991       /*
2992        * Well, this packet should, in theory, have an ICV.
2993        * Do we have the entire packet, and does it have enough data for
2994        * the ICV?
2995        */
2996       if (reported_len < 4) {
2997         /*
2998          * The packet is claimed not to even have enough data for a
2999          * 4-byte ICV.
3000          * Pretend it doesn't have an ICV.
3001          */
3002         ;
3003       } else if (len < reported_len) {
3004         /*
3005          * The packet is claimed to have enough data for a 4-byte ICV,
3006          * but we didn't capture all of the packet.
3007          * Slice off the 4-byte ICV from the reported length, and trim
3008          * the captured length so it's no more than the reported length;
3009          * that will slice off what of the ICV, if any, is in the
3010          * captured length.
3011          *
3012          */
3013         reported_len -= 4;
3014         if (len > reported_len)
3015           len = reported_len;
3016       } else {
3017         /*
3018          * We have the entire packet, and it includes a 4-byte ICV.
3019          * Slice it off, and put it into the tree.
3020          *
3021          * We only support decrypting if we have the the ICV.
3022          *
3023          * XXX - the ICV is encrypted; we're putting the encrypted
3024          * value, not the decrypted value, into the tree.
3025          */
3026         len -= 4;
3027         reported_len -= 4;
3028         can_decrypt = TRUE;
3029       }
3030     }
3031
3032     if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
3033       /*
3034        * WEP decode impossible or failed, treat payload as raw data
3035        * and don't attempt fragment reassembly or further dissection.
3036        */
3037       next_tvb = tvb_new_subset(tvb, hdr_len + ivlen, len, reported_len);
3038
3039       if (tree && can_decrypt)
3040         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
3041                                     hdr_len + ivlen + len, 4,
3042                                     tvb_get_ntohl(tvb, hdr_len + ivlen + len),
3043                                     "WEP ICV: 0x%08x (not verified)",
3044                                     tvb_get_ntohl(tvb, hdr_len + ivlen + len));
3045
3046       if (pinfo->ethertype != ETHERTYPE_CENTRINO_PROMISC)
3047       {
3048         /* Some wireless drivers (such as Centrino) WEP payload already decrypted */
3049         call_dissector(data_handle, next_tvb, pinfo, tree);
3050         goto end_of_wlan;
3051       }
3052     } else {
3053
3054       if (tree)
3055         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
3056                                     hdr_len + ivlen + len, 4,
3057                                     tvb_get_ntohl(tvb, hdr_len + ivlen + len),
3058                                     "WEP ICV: 0x%08x (correct)",
3059                                     tvb_get_ntohl(tvb, hdr_len + ivlen + len));
3060
3061       add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
3062     }
3063
3064     /*
3065      * WEP decryption successful!
3066      *
3067      * Use the tvbuff we got back from the decryption; the data starts at
3068      * the beginning.  The lengths are already correct for the decoded WEP
3069      * payload.
3070      */
3071     hdr_len = 0;
3072
3073   } else {
3074     /*
3075      * Not a WEP-encrypted frame; just use the data from the tvbuff
3076      * handed to us.
3077      *
3078      * The payload starts at "hdr_len" (i.e., just past the 802.11
3079      * MAC header), the length of data in the tvbuff following the
3080      * 802.11 header is "len", and the length of data in the packet
3081      * following the 802.11 header is "reported_len".
3082      */
3083     next_tvb = tvb;
3084   }
3085
3086   /*
3087    * Do defragmentation if "wlan_defragment" is true, and we have more
3088    * fragments or this isn't the first fragment.
3089    *
3090    * We have to do some special handling to catch frames that
3091    * have the "More Fragments" indicator not set but that
3092    * don't show up as reassembled and don't have any other
3093    * fragments present.  Some networking interfaces appear
3094    * to do reassembly even when you're capturing raw packets
3095    * *and* show the reassembled packet without the "More
3096    * Fragments" indicator set *but* with a non-zero fragment
3097    * number.
3098    *
3099    * "fragment_add_seq_802_11()" handles that; we want to call it
3100    * even if we have a short frame, so that it does those checks - if
3101    * the frame is short, it doesn't do reassembly on it.
3102    *
3103    * (This could get some false positives if we really *did* only
3104    * capture the last fragment of a fragmented packet, but that's
3105    * life.)
3106    */
3107   save_fragmented = pinfo->fragmented;
3108   if (wlan_defragment && (more_frags || frag_number != 0)) {
3109     fragment_data *fd_head;
3110
3111     /*
3112      * If we've already seen this frame, look it up in the
3113      * table of reassembled packets, otherwise add it to
3114      * whatever reassembly is in progress, if any, and see
3115      * if it's done.
3116      */
3117     fd_head = fragment_add_seq_802_11(next_tvb, hdr_len, pinfo, seq_number,
3118                                      wlan_fragment_table,
3119                                      wlan_reassembled_table,
3120                                      frag_number,
3121                                      reported_len,
3122                                      more_frags);
3123     next_tvb = process_reassembled_data(tvb, hdr_len, pinfo,
3124                                         "Reassembled 802.11", fd_head,
3125                                         &frag_items, NULL, hdr_tree);
3126   } else {
3127     /*
3128      * If this is the first fragment, dissect its contents, otherwise
3129      * just show it as a fragment.
3130      */
3131     if (frag_number != 0) {
3132       /* Not the first fragment - don't dissect it. */
3133       next_tvb = NULL;
3134     } else {
3135       /* First fragment, or not fragmented.  Dissect what we have here. */
3136
3137       /* Get a tvbuff for the payload. */
3138       next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
3139
3140       /*
3141        * If this is the first fragment, but not the only fragment,
3142        * tell the next protocol that.
3143        */
3144       if (more_frags)
3145         pinfo->fragmented = TRUE;
3146       else
3147         pinfo->fragmented = FALSE;
3148     }
3149   }
3150
3151   if (next_tvb == NULL) {
3152     /* Just show this as an incomplete fragment. */
3153     if (check_col(pinfo->cinfo, COL_INFO))
3154       col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
3155     next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
3156     call_dissector(data_handle, next_tvb, pinfo, tree);
3157     pinfo->fragmented = save_fragmented;
3158     goto end_of_wlan;
3159   }
3160
3161   switch (FCF_FRAME_TYPE (fcf))
3162     {
3163
3164     case MGT_FRAME:
3165       dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
3166       break;
3167
3168
3169     case DATA_FRAME:
3170       /* I guess some bridges take Netware Ethernet_802_3 frames,
3171          which are 802.3 frames (with a length field rather than
3172          a type field, but with no 802.2 header in the payload),
3173          and just stick the payload into an 802.11 frame.  I've seen
3174          captures that show frames of that sort.
3175
3176          We also handle some odd form of encapsulation in which a
3177          complete Ethernet frame is encapsulated within an 802.11
3178          data frame, with no 802.2 header.  This has been seen
3179          from some hardware.
3180
3181          So, if the packet doesn't start with 0xaa 0xaa:
3182
3183            we first use the same scheme that linux-wlan-ng does to detect
3184            those encapsulated Ethernet frames, namely looking to see whether
3185            the frame either starts with 6 octets that match the destination
3186            address from the 802.11 header or has 6 octets that match the
3187            source address from the 802.11 header following the first 6 octets,
3188            and, if so, treat it as an encapsulated Ethernet frame;
3189
3190            otherwise, we use the same scheme that we use in the Ethernet
3191            dissector to recognize Netware 802.3 frames, namely checking
3192            whether the packet starts with 0xff 0xff and, if so, treat it
3193            as an encapsulated IPX frame. */
3194       encap_type = ENCAP_802_2;
3195       TRY {
3196         octet1 = tvb_get_guint8(next_tvb, 0);
3197         octet2 = tvb_get_guint8(next_tvb, 1);
3198         if (octet1 != 0xaa || octet2 != 0xaa) {
3199           src = tvb_get_ptr (next_tvb, 6, 6);
3200           dst = tvb_get_ptr (next_tvb, 0, 6);
3201           if (memcmp(src, pinfo->dl_src.data, 6) == 0 ||
3202               memcmp(dst, pinfo->dl_dst.data, 6) == 0)
3203             encap_type = ENCAP_ETHERNET;
3204           else if (octet1 == 0xff && octet2 == 0xff)
3205             encap_type = ENCAP_IPX;
3206         }
3207       }
3208       CATCH2(BoundsError, ReportedBoundsError) {
3209             ; /* do nothing */
3210
3211       }
3212       ENDTRY;
3213
3214       switch (encap_type) {
3215
3216       case ENCAP_802_2:
3217         call_dissector(llc_handle, next_tvb, pinfo, tree);
3218         break;
3219
3220       case ENCAP_ETHERNET:
3221         call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
3222         break;
3223
3224       case ENCAP_IPX:
3225         call_dissector(ipx_handle, next_tvb, pinfo, tree);
3226         break;
3227       }
3228       break;
3229     }
3230   pinfo->fragmented = save_fragmented;
3231
3232   end_of_wlan:
3233   tap_queue_packet(wlan_tap, pinfo, whdr);
3234 }
3235
3236 /*
3237  * Dissect 802.11 with a variable-length link-layer header.
3238  */
3239 static void
3240 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
3241 {
3242   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
3243       pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE);
3244 }
3245
3246 /*
3247  * Dissect 802.11 with a variable-length link-layer header and data padding.
3248  */
3249 static void
3250 dissect_ieee80211_datapad (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
3251 {
3252   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
3253       pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, TRUE);
3254 }
3255
3256 /*
3257  * Dissect 802.11 with a variable-length link-layer header and a pseudo-
3258  * header containing radio information.
3259  */
3260 static void
3261 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
3262 {
3263   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE,
3264      pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE, FALSE);
3265 }
3266
3267 /*
3268  * Dissect 802.11 with a variable-length link-layer header and a byte-swapped
3269  * control field (some hardware sends out LWAPP-encapsulated 802.11
3270  * packets with the control field byte swapped).
3271  */
3272 static void
3273 dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
3274 {
3275   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, 0, TRUE, FALSE);
3276 }
3277
3278 /*
3279  * Dissect 802.11 with a fixed-length link-layer header (padded to the
3280  * maximum length).
3281  */
3282 static void
3283 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
3284 {
3285   dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, 0, FALSE, FALSE);
3286 }
3287
3288 static void
3289 wlan_defragment_init(void)
3290 {
3291   fragment_table_init(&wlan_fragment_table);
3292   reassembled_table_init(&wlan_reassembled_table);
3293 }
3294
3295 void
3296 proto_register_ieee80211 (void)
3297 {
3298   static const value_string frame_type[] = {
3299     {MGT_FRAME,     "Management frame"},
3300     {CONTROL_FRAME, "Control frame"},
3301     {DATA_FRAME,    "Data frame"},
3302     {0,             NULL}
3303   };
3304
3305   static const value_string tofrom_ds[] = {
3306     {0,                       "Not leaving DS or network is operating "
3307       "in AD-HOC mode (To DS: 0 From DS: 0)"},
3308     {FLAG_TO_DS,              "Frame from STA to DS via an AP (To DS: 1 "
3309       "From DS: 0)"},
3310     {FLAG_FROM_DS,            "Frame from DS to a STA via AP(To DS: 0 "
3311       "From DS: 1)"},
3312     {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS from one AP to another "
3313       "AP (To DS: 1 From DS: 1)"},
3314     {0, NULL}
3315   };
3316
3317   static const true_false_string tods_flag = {
3318     "Frame is entering DS",
3319     "Frame is not entering DS"
3320   };
3321
3322   static const true_false_string fromds_flag = {
3323     "Frame is exiting DS",
3324     "Frame is not exiting DS"
3325   };
3326
3327   static const true_false_string more_frags = {
3328     "More fragments follow",
3329     "This is the last fragment"
3330   };
3331
3332   static const true_false_string retry_flags = {
3333     "Frame is being retransmitted",
3334     "Frame is not being retransmitted"
3335   };
3336
3337   static const true_false_string pm_flags = {
3338     "STA will go to sleep",
3339     "STA will stay up"
3340   };
3341
3342   static const true_false_string md_flags = {
3343     "Data is buffered for STA at AP",
3344     "No data buffered"
3345   };
3346
3347   static const true_false_string protected_flags = {
3348     "Data is protected",
3349     "Data is not protected"
3350   };
3351
3352   static const true_false_string order_flags = {
3353     "Strictly ordered",
3354     "Not strictly ordered"
3355   };
3356
3357   static const true_false_string cf_ess_flags = {
3358     "Transmitter is an AP",
3359     "Transmitter is a STA"
3360   };
3361
3362
3363   static const true_false_string cf_privacy_flags = {
3364     "AP/STA can support WEP",
3365     "AP/STA cannot support WEP"
3366   };
3367
3368   static const true_false_string cf_preamble_flags = {
3369     "Short preamble allowed",
3370     "Short preamble not allowed"
3371   };
3372
3373   static const true_false_string cf_pbcc_flags = {
3374     "PBCC modulation allowed",
3375     "PBCC modulation not allowed"
3376   };
3377
3378   static const true_false_string cf_agility_flags = {
3379     "Channel agility in use",
3380     "Channel agility not in use"
3381   };
3382
3383   static const true_false_string short_slot_time_flags = {
3384     "Short slot time in use",
3385     "Short slot time not in use"
3386   };
3387
3388   static const true_false_string dsss_ofdm_flags = {
3389     "DSSS-OFDM modulation allowed",
3390     "DSSS-OFDM modulation not allowed"
3391   };
3392
3393   static const true_false_string cf_spec_man_flags = {
3394     "dot11SpectrumManagementRequired TRUE",
3395     "dot11SpectrumManagementRequired FALSE",
3396   };
3397
3398   static const true_false_string cf_apsd_flags = {
3399     "apsd implemented",
3400     "apsd not implemented",
3401   };
3402
3403   static const true_false_string cf_del_blk_ack_flags = {
3404     "delayed block ack implemented",
3405     "delayed block ack not implented",
3406   };
3407
3408   static const true_false_string cf_imm_blk_ack_flags = {
3409     "immediate block ack implemented",
3410     "immediate block ack not implented",
3411   };
3412   static const true_false_string cf_ibss_flags = {
3413     "Transmitter belongs to an IBSS",
3414     "Transmitter belongs to a BSS"
3415   };
3416
3417   static const true_false_string eosp_flag = {
3418     "End of service period",
3419     "Service period"
3420   };
3421
3422   static const value_string sta_cf_pollable[] = {
3423     {0x00, "Station is not CF-Pollable"},
3424     {0x02, "Station is CF-Pollable, "
3425      "not requesting to be placed on the  CF-polling list"},
3426     {0x01, "Station is CF-Pollable, "
3427      "requesting to be placed on the CF-polling list"},
3428     {0x03, "Station is CF-Pollable, requesting never to be polled"},
3429     {0x0200, "QSTA requesting association in QBSS"},
3430     {0, NULL}
3431   };
3432
3433   static const value_string ap_cf_pollable[] = {
3434     {0x00, "No point coordinator at AP"},
3435     {0x02, "Point coordinator at AP for delivery only (no polling)"},
3436     {0x01, "Point coordinator at AP for delivery and polling"},
3437     {0x03, "Reserved"},
3438     {0x0200, "QAP (HC) does not use CFP for delivery of unicast data type frames"},
3439     {0x0202, "QAP (HC) uses CFP for delivery, but does not send CF-Polls to non-QoS STAs"},
3440     {0x0201, "QAP (HC) uses CFP for delivery, and sends CF-Polls to non-QoS STAs"},
3441     {0x0203, "Reserved"},
3442     {0, NULL}
3443   };
3444
3445
3446   static const value_string auth_alg[] = {
3447     {0x00, "Open System"},
3448     {0x01, "Shared key"},
3449     {0x80, "Network EAP"},      /* Cisco proprietary? */
3450     {0, NULL}
3451   };
3452
3453   static const value_string reason_codes[] = {
3454     {0x00, "Reserved"},
3455     {0x01, "Unspecified reason"},
3456     {0x02, "Previous authentication no longer valid"},
3457     {0x03, "Deauthenticated because sending STA is leaving (has left) "
3458      "IBSS or ESS"},
3459     {0x04, "Disassociated due to inactivity"},
3460     {0x05, "Disassociated because AP is unable to handle all currently "
3461      "associated stations"},
3462     {0x06, "Class 2 frame received from nonauthenticated station"},
3463     {0x07, "Class 3 frame received from nonassociated station"},
3464     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
3465     {0x09, "Station requesting (re)association is not authenticated with "
3466       "responding station"},
3467     {0x0A, "Disassociated because the information in the Power Capability "
3468       "element is unacceptable"},
3469     {0x0B, "Disassociated because the information in the Supported"
3470       "Channels element is unacceptable"},
3471     {0x0D, "Invalid Information Element"},
3472     {0x0E, "Michael MIC failure"},
3473     {0x0F, "4-Way Handshake timeout"},
3474     {0x10, "Group key update timeout"},
3475     {0x11, "Information element in 4-Way Handshake different from "
3476      "(Re)Association Request/Probe Response/Beacon"},
3477     {0x12, "Group Cipher is not valid"},
3478     {0x13, "Pairwise Cipher is not valid"},
3479     {0x14, "AKMP is not valid"},
3480     {0x15, "Unsupported RSN IE version"},
3481     {0x16, "Invalid RSN IE Capabilities"},
3482     {0x17, "IEEE 802.1X Authentication failed"},
3483     {0x18, "Cipher suite is rejected per security policy"},
3484     {0x20, "Disassociated for unspecified, QoS-related reason"},
3485     {0x21, "Disassociated because QAP lacks sufficient bandwidth for this QSTA"},
3486     {0x22, "Disassociated because of excessive number of frames that need to be "
3487       "acknowledged, but are not acknowledged for AP transmissions and/or poor "
3488         "channel conditions"},
3489     {0x23, "Disassociated because QSTA is transmitting outside the limits of its TXOPs"},
3490     {0x24, "Requested from peer QSTA as the QSTA is leaving the QBSS (or resetting)"},
3491     {0x25, "Requested from peer QSTA as it does not want to use the mechanism"},
3492     {0x26, "Requested from peer QSTA as the QSTA received frames using the mechanism "
3493       "for which a set up is required"},
3494     {0x27, "Requested from peer QSTA due to time out"},
3495     {0x2D, "Peer QSTA does not support the requested cipher suite"},
3496     {0x00, NULL}
3497   };
3498
3499
3500   static const value_string status_codes[] = {
3501     {0x00, "Successful"},
3502     {0x01, "Unspecified failure"},
3503     {0x0A, "Cannot support all requested capabilities in the "
3504      "Capability information field"},
3505     {0x0B, "Reassociation denied due to inability to confirm that "
3506      "association exists"},
3507     {0x0C, "Association denied due to reason outside the scope of this "
3508      "standard"},
3509
3510     {0x0D, "Responding station does not support the specified authentication "
3511      "algorithm"},
3512     {0x0E, "Received an Authentication frame with authentication sequence "
3513      "transaction sequence number out of expected sequence"},
3514     {0x0F, "Authentication rejected because of challenge failure"},
3515     {0x10, "Authentication rejected due to timeout waiting for next "
3516      "frame in sequence"},
3517     {0x11, "Association denied because AP is unable to handle additional "
3518      "associated stations"},
3519     {0x12, "Association denied due to requesting station not supporting all "
3520      "of the datarates in the BSSBasicServiceSet Parameter"},
3521     {0x13, "Association denied due to requesting station not supporting "
3522      "short preamble operation"},
3523     {0x14, "Association denied due to requesting station not supporting "
3524      "PBCC encoding"},
3525     {0x15, "Association denied due to requesting station not supporting "
3526      "channel agility"},
3527     {0x16, "Association request rejected because Spectrum Management"
3528       "capability is required"},
3529     {0x17, "Association request rejected because the information in the"
3530       "Power Capability element is unacceptable"},
3531     {0x18, "Association request rejected because the information in the"
3532       "Supported Channels element is unacceptable"},
3533     {0x19, "Association denied due to requesting station not supporting "
3534      "short slot operation"},
3535     {0x1A, "Association denied due to requesting station not supporting "
3536      "DSSS-OFDM operation"},
3537     {0x20, "Unspecified, QoS-related failure"},
3538     {0x21, "Association denied due to QAP having insufficient bandwidth "
3539       "to handle another QSTA"},
3540     {0x22, "Association denied due to excessive frame loss rates and/or "
3541       "poor conditions on current operating channel"},
3542     {0x23, "Association (with QBSS) denied due to requesting station not "
3543       "supporting the QoS facility"},
3544     {0x24, "Association denied due to requesting station not supporting "
3545       "Block Ack"},
3546     {0x25, "The request has been declined."},
3547     {0x26, "The request has not been successful as one or more parameters "
3548       "have invalid values."},
3549     {0x27, "The TS has not been created because the request cannot be honored. "
3550       "However, a suggested TSPEC is provided so that the initiating QSTA may "
3551         "attempt to set another TS with the suggested changes to the TSPEC."},
3552     {0x28, "Invalid Information Element"},
3553     {0x29, "Group Cipher is not valid"},
3554     {0x2A, "Pairwise Cipher is not valid"},
3555     {0x2B, "AKMP is not valid"},
3556     {0x2C, "Unsupported RSN IE version"},
3557     {0x2D, "Invalid RSN IE Capabilities"},
3558     {0x2E, "Cipher suite is rejected per security policy"},
3559     {0x2F, "The TS has not been created. However, the HC may be capable of "
3560       "creating a TS, in response to a request, after the time indicated in the TS Delay element."},
3561     {0x30, "Direct Link is not allowed in the BSS by policy"},
3562     {0x31, "Destination STA is not present within this QBSS."},
3563     {0x32, "The Destination STA is not a QSTA."},
3564     {0x00, NULL}
3565   };
3566
3567   static const value_string category_codes[] = {
3568     {CAT_SPECTRUM_MGMT, "Spectrum Management"},
3569     {CAT_QOS, "QoS"},
3570     {CAT_DLS, "DLS"},
3571     {CAT_BLOCK_ACK, "Block Ack"},
3572     {CAT_MGMT_NOTIFICATION, "Management notification frame"},
3573     {0, NULL}
3574   };
3575
3576   static const value_string action_codes[] ={
3577     {SM_ACTION_MEASUREMENT_REQUEST, "Measurement Request"},
3578     {SM_ACTION_MEASUREMENT_REPORT, "Measurement Report"},
3579     {SM_ACTION_TPC_REQUEST, "TPC Request"},
3580     {SM_ACTION_TPC_REPORT, "TPC Report"},
3581     {SM_ACTION_CHAN_SWITCH_ANNC, "Channel Switch Announcement"},
3582     {0, NULL}
3583   };
3584
3585   static const value_string wme_action_codes[] = {
3586     {0x00, "Setup request"},
3587     {0x01, "Setup response"},
3588     {0x02, "Teardown"},
3589     {0x00, NULL}
3590   };
3591
3592   static const value_string wme_status_codes[] = {
3593     {0x00, "Admission accepted"},
3594     {0x01, "Invalid parameters"},
3595     {0x03, "Refused"},
3596     {0x00, NULL}
3597   };
3598
3599   static const value_string ack_policy[] = {
3600     {0x00, "Normal Ack"},
3601     {0x02, "No Ack"},
3602     {0x01, "No explicit Ack"},
3603     {0x03, "Block Ack"},
3604     {0x00, NULL}
3605   };
3606
3607   static hf_register_info hf[] = {
3608     {&hf_data_rate,
3609      {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
3610       "Data rate (.5 Mb/s units)", HFILL }},
3611
3612     {&hf_channel,
3613      {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
3614       "Radio channel", HFILL }},
3615
3616     {&hf_signal_strength,
3617      {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
3618       "Signal strength (percentage)", HFILL }},
3619
3620     {&hf_fc_field,
3621      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
3622       "MAC Frame control", HFILL }},
3623
3624     {&hf_fc_proto_version,
3625      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
3626       "MAC Protocol version", HFILL }}, /* 0 */
3627
3628     {&hf_fc_frame_type,
3629      {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
3630       "Frame type", HFILL }},
3631
3632     {&hf_fc_frame_subtype,
3633      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
3634       "Frame subtype", HFILL }},        /* 2 */
3635
3636     {&hf_fc_frame_type_subtype,
3637      {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
3638       "Type and subtype combined", HFILL }},
3639
3640     {&hf_fc_flags,
3641      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
3642       "Protocol flags", HFILL }},
3643
3644     {&hf_fc_data_ds,
3645      {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
3646       "Data-frame DS-traversal status", HFILL }},       /* 3 */
3647
3648     {&hf_fc_to_ds,
3649      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
3650       "To DS flag", HFILL }},           /* 4 */
3651
3652     {&hf_fc_from_ds,
3653      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
3654       "From DS flag", HFILL }},         /* 5 */
3655
3656     {&hf_fc_more_frag,
3657      {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
3658       "More Fragments flag", HFILL }},  /* 6 */
3659
3660     {&hf_fc_retry,
3661      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
3662       "Retransmission flag", HFILL }},
3663
3664     {&hf_fc_pwr_mgt,
3665      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
3666       "Power management status", HFILL }},
3667
3668     {&hf_fc_more_data,
3669      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
3670       "More data flag", HFILL }},
3671
3672     {&hf_fc_protected,
3673      {"Protected flag", "wlan.fc.protected", FT_BOOLEAN, 8, TFS (&protected_flags), FLAG_PROTECTED,
3674       "Protected flag", HFILL }},
3675
3676     {&hf_fc_order,
3677      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
3678       "Strictly ordered flag", HFILL }},
3679
3680     {&hf_assoc_id,
3681      {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
3682       "Association-ID field", HFILL }},
3683
3684     {&hf_did_duration,
3685      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
3686       "Duration field", HFILL }},
3687
3688     {&hf_addr_da,
3689      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
3690       "Destination Hardware Address", HFILL }},
3691
3692     {&hf_addr_sa,
3693      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
3694       "Source Hardware Address", HFILL }},
3695
3696     { &hf_addr,
3697       {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
3698        "Source or Destination Hardware Address", HFILL }},
3699
3700     {&hf_addr_ra,
3701      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
3702       "Receiving Station Hardware Address", HFILL }},
3703
3704     {&hf_addr_ta,
3705      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
3706       "Transmitting Station Hardware Address", HFILL }},
3707
3708     {&hf_addr_bssid,
3709      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
3710       "Basic Service Set ID", HFILL }},
3711
3712     {&hf_frag_number,
3713      {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
3714       "Fragment number", HFILL }},
3715
3716     {&hf_seq_number,
3717      {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
3718       "Sequence number", HFILL }},
3719
3720     {&hf_qos_priority,
3721      {"Priority", "wlan.qos.priority", FT_UINT16, BASE_DEC, NULL, 0,
3722       "802.1D Tag", HFILL }},
3723
3724     {&hf_qos_eosp,
3725      {"EOSP", "wlan.qos.eosp", FT_BOOLEAN, 8, TFS (&eosp_flag), QOS_FLAG_EOSP,
3726       "EOSP Field", HFILL }},
3727
3728     {&hf_qos_ack_policy,
3729      {"Ack Policy", "wlan.qos.ack", FT_UINT16, BASE_HEX,  VALS (&ack_policy), 0,
3730       "Ack Policy", HFILL }},
3731
3732     {&hf_qos_field_content,
3733      {"Content", "wlan.qos.fc_content", FT_UINT16, BASE_DEC, NULL, 0,
3734       "Content1", HFILL }},
3735
3736 /*    {&hf_qos_buffer_state,
3737      {"QAP PS buffer State", "wlan.qos.ps_buf_state", FT_UINT16, BASE_DEC, NULL, 0,
3738       "QAP PS buffer State", HFILL }},
3739
3740     {&hf_qos_txop_dur_req,
3741      {"TXOP Duration Requested", "wlan.qos.txop_dur_req", FT_UINT16, BASE_DEC, NULL, 0,
3742       "TXOP Duration Requested", HFILL }},
3743
3744     {&hf_qos_queue_size,
3745      {"Queue Size", "wlan.qos.queue_size", FT_UINT16, BASE_DEC, NULL, 0,
3746       "Queue Size", HFILL }},*/
3747
3748     {&hf_fcs,
3749      {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
3750       NULL, 0, "FCS", HFILL }},
3751
3752     {&hf_fragment_overlap,
3753       {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
3754        NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
3755
3756     {&hf_fragment_overlap_conflict,
3757       {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
3758        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3759        "Overlapping fragments contained conflicting data", HFILL }},
3760
3761     {&hf_fragment_multiple_tails,
3762       {"Multiple tail fragments found", "wlan.fragment.multipletails",
3763        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3764        "Several tails were found when defragmenting the packet", HFILL }},
3765
3766     {&hf_fragment_too_long_fragment,
3767       {"Fragment too long", "wlan.fragment.toolongfragment",
3768        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3769        "Fragment contained data past end of packet", HFILL }},
3770
3771     {&hf_fragment_error,
3772       {"Defragmentation error", "wlan.fragment.error",
3773        FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3774        "Defragmentation error due to illegal fragments", HFILL }},
3775
3776     {&hf_fragment,
3777       {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3778        "802.11 Fragment", HFILL }},
3779
3780     {&hf_fragments,
3781       {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
3782        "802.11 Fragments", HFILL }},
3783
3784     {&hf_reassembled_in,
3785       {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3786        "This 802.11 packet is reassembled in this frame", HFILL }},
3787
3788     {&hf_wep_iv,
3789      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
3790       "Initialization Vector", HFILL }},
3791
3792     {&hf_wep_iv_weak,
3793      {"Weak IV", "wlan.wep.weakiv", FT_BOOLEAN,BASE_NONE, NULL,0x0,
3794        "Weak IV",HFILL}},
3795
3796     {&hf_tkip_extiv,
3797      {"TKIP Ext. Initialization Vector", "wlan.tkip.extiv", FT_STRING,
3798       BASE_HEX, NULL, 0, "TKIP Extended Initialization Vector", HFILL }},
3799
3800     {&hf_ccmp_extiv,
3801      {"CCMP Ext. Initialization Vector", "wlan.ccmp.extiv", FT_STRING,
3802       BASE_HEX, NULL, 0, "CCMP Extended Initialization Vector", HFILL }},
3803
3804     {&hf_wep_key,
3805      {"Key Index", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
3806       "Key Index", HFILL }},
3807
3808     {&hf_wep_icv,
3809      {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
3810       "WEP ICV", HFILL }},
3811   };
3812
3813   static const true_false_string rsn_preauth_flags = {
3814     "Transmitter supports pre-authentication",
3815     "Transmitter does not support pre-authentication"
3816   };
3817
3818   static const true_false_string rsn_no_pairwise_flags = {
3819     "Transmitter cannot support WEP default key 0 simultaneously with "
3820     "Pairwise key",
3821     "Transmitter can support WEP default key 0 simultaneously with "
3822     "Pairwise key"
3823   };
3824
3825   static const value_string rsn_cap_replay_counter[] = {
3826     {0x00, "1 replay counter per PTKSA/GTKSA/STAKeySA"},
3827     {0x01, "2 replay counters per PTKSA/GTKSA/STAKeySA"},
3828     {0x02, "4 replay counters per PTKSA/GTKSA/STAKeySA"},
3829     {0x03, "16 replay counters per PTKSA/GTKSA/STAKeySA"},
3830     {0, NULL}
3831   };
3832
3833   static hf_register_info ff[] = {
3834     {&ff_timestamp,
3835      {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
3836       NULL, 0, "", HFILL }},
3837
3838     {&ff_auth_alg,
3839      {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
3840       FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
3841
3842     {&ff_beacon_interval,
3843      {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
3844       "", HFILL }},
3845
3846     {&hf_fixed_parameters,
3847      {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
3848       "", HFILL }},
3849
3850     {&hf_tagged_parameters,
3851      {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
3852       "", HFILL }},
3853
3854     {&ff_capture,
3855      {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
3856       "Capability information", HFILL }},
3857
3858     {&ff_cf_ess,
3859      {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
3860       FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
3861
3862     {&ff_cf_ibss,
3863      {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
3864       FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
3865
3866     {&ff_cf_sta_poll,
3867      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
3868       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x020C,
3869       "CF-Poll capabilities for a STA", HFILL }},
3870
3871     {&ff_cf_ap_poll,
3872      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
3873       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x020C,
3874       "CF-Poll capabilities for an AP", HFILL }},
3875
3876     {&ff_cf_privacy,
3877      {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
3878       FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
3879
3880     {&ff_cf_preamble,
3881      {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
3882       FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
3883
3884     {&ff_cf_pbcc,
3885      {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
3886       FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
3887
3888     {&ff_cf_agility,
3889      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
3890       FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
3891
3892     {&ff_cf_spec_man,
3893      {"Spectrum Management", "wlan_mgt.fixed.capabilities.spec_man",
3894       FT_BOOLEAN, 16, TFS (&cf_spec_man_flags), 0x0100, "Spectrum Management", HFILL }},
3895
3896     {&ff_short_slot_time,
3897      {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
3898       FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
3899       HFILL }},
3900
3901     {&ff_cf_apsd,
3902      {"Automatic Power Save Delivery", "wlan_mgt.fixed.capabilities.apsd",
3903       FT_BOOLEAN, 16, TFS (&cf_apsd_flags), 0x0800, "Automatic Power Save "
3904         "Delivery", HFILL }},
3905
3906     {&ff_dsss_ofdm,
3907      {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
3908       FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
3909       HFILL }},
3910
3911     {&ff_cf_del_blk_ack,
3912      {"Delayed Block Ack", "wlan_mgt.fixed.capabilities.del_blk_ack",
3913       FT_BOOLEAN, 16, TFS (&cf_del_blk_ack_flags), 0x4000, "Delayed Block "
3914         "Ack", HFILL }},
3915
3916     {&ff_cf_imm_blk_ack,
3917      {"Immediate Block Ack", "wlan_mgt.fixed.capabilities.imm_blk_ack",
3918       FT_BOOLEAN, 16, TFS (&cf_imm_blk_ack_flags), 0x8000, "Immediate Block "
3919         "Ack", HFILL }},
3920
3921     {&ff_auth_seq,
3922      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
3923       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
3924
3925     {&ff_assoc_id,
3926      {"Association ID", "wlan_mgt.fixed.aid",
3927       FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
3928
3929     {&ff_listen_ival,
3930      {"Listen Interval", "wlan_mgt.fixed.listen_ival",
3931       FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
3932
3933     {&ff_current_ap,
3934      {"Current AP", "wlan_mgt.fixed.current_ap",
3935       FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
3936
3937     {&ff_reason,
3938      {"Reason code", "wlan_mgt.fixed.reason_code",
3939       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
3940       "Reason for unsolicited notification", HFILL }},
3941
3942     {&ff_status_code,
3943      {"Status code", "wlan_mgt.fixed.status_code",
3944       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
3945       "Status of requested event", HFILL }},
3946
3947     {&ff_category_code,
3948      {"Category code", "wlan_mgt.fixed.category_code",
3949       FT_UINT16, BASE_DEC, VALS (&category_codes), 0,
3950       "Management action category", HFILL }},
3951
3952     {&ff_action_code,
3953      {"Action code", "wlan_mgt.fixed.action_code",
3954       FT_UINT16, BASE_DEC, VALS (&action_codes), 0,
3955       "Management action code", HFILL }},
3956
3957     {&ff_dialog_token,
3958      {"Dialog token", "wlan_mgt.fixed.dialog_token",
3959       FT_UINT16, BASE_HEX, NULL, 0, "Management action dialog token", HFILL }},
3960
3961     {&ff_wme_action_code,
3962      {"Action code", "wlan_mgt.fixed.action_code",
3963       FT_UINT16, BASE_HEX, VALS (&wme_action_codes), 0,
3964       "Management notification action code", HFILL }},
3965
3966     {&ff_wme_status_code,
3967      {"Status code", "wlan_mgt.fixed.status_code",
3968       FT_UINT16, BASE_HEX, VALS (&wme_status_codes), 0,
3969       "Management notification setup response status code", HFILL }},
3970
3971     {&tag_number,
3972      {"Tag", "wlan_mgt.tag.number",
3973       FT_UINT8, BASE_DEC, VALS(tag_num_vals), 0,
3974       "Element ID", HFILL }},
3975
3976     {&tag_length,
3977      {"Tag length", "wlan_mgt.tag.length",
3978       FT_UINT8, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
3979
3980     {&tag_interpretation,
3981      {"Tag interpretation", "wlan_mgt.tag.interpretation",
3982       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }},
3983
3984     {&tag_oui,
3985      {"OUI", "wlan_mgt.tag.oui",
3986       FT_BYTES, BASE_NONE, NULL, 0, "OUI of vendor specific IE", HFILL }},
3987
3988     {&tim_length,
3989      {"TIM length", "wlan_mgt.tim.length",
3990       FT_UINT8, BASE_DEC, NULL, 0,
3991       "Traffic Indication Map length", HFILL }},
3992
3993     {&tim_dtim_count,
3994      {"DTIM count", "wlan_mgt.tim.dtim_count",
3995       FT_UINT8, BASE_DEC, NULL, 0,
3996       "DTIM count", HFILL }},
3997
3998     {&tim_dtim_period,
3999      {"DTIM period", "wlan_mgt.tim.dtim_period",
4000       FT_UINT8, BASE_DEC, NULL, 0,
4001       "DTIM period", HFILL }},
4002
4003     {&tim_bmapctl,
4004      {"Bitmap control", "wlan_mgt.tim.bmapctl",
4005       FT_UINT8, BASE_HEX, NULL, 0,
4006       "Bitmap control", HFILL }},
4007
4008     {&rsn_cap,
4009      {"RSN Capabilities", "wlan_mgt.rsn.capabilities", FT_UINT16, BASE_HEX,
4010       NULL, 0, "RSN Capability information", HFILL }},
4011
4012     {&rsn_cap_preauth,
4013      {"RSN Pre-Auth capabilities", "wlan_mgt.rsn.capabilities.preauth",
4014       FT_BOOLEAN, 16, TFS (&rsn_preauth_flags), 0x0001,
4015       "RSN Pre-Auth capabilities", HFILL }},
4016
4017     {&rsn_cap_no_pairwise,
4018      {"RSN No Pairwise capabilities", "wlan_mgt.rsn.capabilities.no_pairwise",
4019       FT_BOOLEAN, 16, TFS (&rsn_no_pairwise_flags), 0x0002,
4020       "RSN No Pairwise capabilities", HFILL }},
4021
4022     {&rsn_cap_ptksa_replay_counter,
4023      {"RSN PTKSA Replay Counter capabilities",
4024       "wlan_mgt.rsn.capabilities.ptksa_replay_counter",
4025       FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x000C,
4026       "RSN PTKSA Replay Counter capabilities", HFILL }},
4027
4028     {&rsn_cap_gtksa_replay_counter,
4029      {"RSN GTKSA Replay Counter capabilities",
4030       "wlan_mgt.rsn.capabilities.gtksa_replay_counter",
4031       FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x0030,
4032       "RSN GTKSA Replay Counter capabilities", HFILL }},
4033
4034     {&hf_aironet_ie_type,
4035      {"Aironet IE type", "wlan_mgt.aironet.type",
4036       FT_UINT8, BASE_DEC, VALS(aironet_ie_type_vals), 0, "", HFILL }},
4037
4038     {&hf_aironet_ie_version,
4039      {"Aironet IE CCX version?", "wlan_mgt.aironet.version",
4040       FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
4041
4042     { &hf_aironet_ie_data,
4043       { "Aironet IE data", "wlan_mgmt.aironet.data",
4044         FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
4045         
4046     {&hf_qbss_version,
4047      {"QBSS Version", "wlan_mgt.qbss.version",
4048       FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
4049
4050     {&hf_qbss_scount,
4051      {"Station Count", "wlan_mgt.qbss.scount",
4052       FT_UINT16, BASE_DEC, NULL, 0, "", HFILL }},
4053
4054     {&hf_qbss_cu,
4055      {"Channel Utilization", "wlan_mgt.qbss.cu",
4056        FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
4057                 
4058     {&hf_qbss_adc,
4059      {"Available Admission Capabilities", "wlan_mgt.qbss.adc",
4060      FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
4061
4062     {&hf_qbss2_cu,
4063      {"Channel Utilization", "wlan_mgt.qbss2.cu",
4064        FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
4065
4066     {&hf_qbss2_gl,
4067      {"G.711 CU Quantum", "wlan_mgt.qbss2.glimit",
4068       FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
4069
4070     {&hf_qbss2_cal,
4071      {"Call Admission Limit", "wlan_mgt.qbss2.cal",
4072       FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
4073
4074     {&hf_qbss2_scount,
4075      {"Station Count", "wlan_mgt.qbss2.scount",
4076       FT_UINT16, BASE_DEC, NULL, 0, "", HFILL }},
4077
4078     {&hf_aironet_ie_qos_unk1,
4079      {"Aironet IE QoS unknown1", "wlan_mgt.aironet.qos.unk1",
4080       FT_UINT8, BASE_HEX, NULL, 0, "", HFILL }},
4081
4082     {&hf_aironet_ie_qos_paramset,
4083      {"Aironet IE QoS paramset", "wlan_mgt.aironet.qos.paramset",
4084       FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
4085
4086     {&hf_aironet_ie_qos_val,
4087      {"Aironet IE QoS valueset", "wlan_mgt.aironet.qos.val",
4088       FT_BYTES, BASE_NONE, NULL, 0, "", HFILL }},
4089
4090   };
4091
4092   static gint *tree_array[] = {
4093     &ett_80211,
4094     &ett_fc_tree,
4095     &ett_proto_flags,
4096     &ett_fragments,
4097     &ett_fragment,
4098     &ett_80211_mgt,
4099     &ett_fixed_parameters,
4100     &ett_tagged_parameters,
4101     &ett_qos_parameters,
4102     &ett_qos_ps_buf_state,
4103     &ett_wep_parameters,
4104     &ett_cap_tree,
4105     &ett_rsn_cap_tree,
4106     &ett_80211_mgt_ie,
4107   };
4108   module_t *wlan_module;
4109
4110   static const enum_val_t wep_keys_options[] = {
4111     {"0", "0", 0},
4112     {"1", "1", 1},
4113     {"2", "2", 2},
4114     {"3", "3", 3},
4115     {"4", "4", 4},
4116     {NULL, NULL, -1},
4117   };
4118
4119
4120   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
4121                                         "IEEE 802.11", "wlan");
4122   proto_register_field_array (proto_wlan, hf, array_length (hf));
4123   proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
4124                                         "802.11 MGT", "wlan_mgt");
4125   proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
4126   proto_register_subtree_array (tree_array, array_length (tree_array));
4127
4128   register_dissector("wlan", dissect_ieee80211, proto_wlan);
4129   register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
4130   register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
4131   register_dissector("wlan_datapad", dissect_ieee80211_datapad, proto_wlan);
4132   register_init_routine(wlan_defragment_init);
4133
4134   wlan_tap = register_tap("wlan");
4135
4136   /* Register configuration options */
4137   wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);
4138   prefs_register_bool_preference(wlan_module, "defragment",
4139         "Reassemble fragmented 802.11 datagrams",
4140         "Whether fragmented 802.11 datagrams should be reassembled",
4141         &wlan_defragment);
4142
4143   prefs_register_bool_preference(wlan_module, "check_fcs",
4144                                  "Assume packets have FCS",
4145                                  "Some 802.11 cards include the FCS at the end of a packet, others do not.",
4146                                  &wlan_check_fcs);
4147
4148   prefs_register_bool_preference(wlan_module, "ignore_wep",
4149                                  "Ignore the WEP bit",
4150                                  "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
4151                                  &wlan_ignore_wep);
4152
4153 #ifndef USE_ENV
4154   prefs_register_enum_preference(wlan_module, "wep_keys",
4155                                  "WEP key count",
4156                                  "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
4157                                  &num_wepkeys, wep_keys_options, FALSE);
4158
4159   prefs_register_string_preference(wlan_module, "wep_key1",
4160                                    "WEP key #1",
4161                                    "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",
4162                                    &wep_keystr[0]);
4163   prefs_register_string_preference(wlan_module, "wep_key2",
4164                                    "WEP key #2",
4165                                    "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",
4166                                    &wep_keystr[1]);
4167   prefs_register_string_preference(wlan_module, "wep_key3",
4168                                    "WEP key #3",
4169                                    "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",
4170                                    &wep_keystr[2]);
4171   prefs_register_string_preference(wlan_module, "wep_key4",
4172                                    "WEP key #4",
4173                                    "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",
4174                                    &wep_keystr[3]);
4175 #endif
4176 }
4177
4178 void
4179 proto_reg_handoff_ieee80211(void)
4180 {
4181   dissector_handle_t ieee80211_handle;
4182   dissector_handle_t ieee80211_radio_handle;
4183
4184   /*
4185    * Get handles for the LLC, IPX and Ethernet  dissectors.
4186    */
4187   llc_handle = find_dissector("llc");
4188   ipx_handle = find_dissector("ipx");
4189   eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
4190   data_handle = find_dissector("data");
4191
4192   ieee80211_handle = find_dissector("wlan");
4193   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
4194   ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
4195                                                    proto_wlan);
4196   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
4197                 ieee80211_radio_handle);
4198   dissector_add("ethertype", ETHERTYPE_CENTRINO_PROMISC, ieee80211_handle);
4199 }
4200
4201 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
4202   const guint8 *enc_data;
4203   guint8 *tmp = NULL;
4204   int i;
4205   tvbuff_t *decr_tvb = NULL;
4206
4207   if (num_wepkeys < 1)
4208     return NULL;
4209
4210   enc_data = tvb_get_ptr(tvb, offset, len);
4211
4212   if ((tmp = g_malloc(len)) == NULL)
4213     return NULL;  /* krap! */
4214
4215   /* try once with the key index in the packet, then look through our list. */
4216   for (i = -1; i < num_wepkeys; i++) {
4217     /* copy the encrypted data over to the tmp buffer */
4218 #if 0
4219     printf("trying %d\n", i);
4220 #endif
4221     memcpy(tmp, enc_data, len);
4222     if (wep_decrypt(tmp, len, i) == 0) {
4223
4224       /* decrypt successful, let's set up a new data tvb. */
4225       decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
4226       tvb_set_free_cb(decr_tvb, g_free);
4227       tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
4228
4229       goto done;
4230     }
4231   }
4232
4233  done:
4234   if ((!decr_tvb) && (tmp))    g_free(tmp);
4235
4236 #if 0
4237   printf("de-wep %p\n", decr_tvb);
4238 #endif
4239
4240   return decr_tvb;
4241 }
4242
4243
4244 /* de-weps the block.  if successful, buf* will point to the data start. */
4245 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
4246   guint32 i, j, k, crc, keylen;
4247   guint8 s[256], key[128], c_crc[4];
4248   guint8 keyidx, *dpos, *cpos;
4249
4250   /* Needs to be at least 8 bytes of payload */
4251   if (len < 8)
4252     return -1;
4253
4254   /* initialize the first bytes of the key from the IV */
4255   key[0] = buf[0];
4256   key[1] = buf[1];
4257   key[2] = buf[2];
4258   keyidx = KEY_OCTET_WEP_KEY(buf[3]);
4259
4260   if (key_override >= 0)
4261     keyidx = key_override;
4262
4263   if (keyidx >= (guint)num_wepkeys)
4264     return -1;
4265
4266   keylen = wep_keylens[keyidx];
4267
4268   if (keylen == 0)
4269     return -1;
4270   if (wep_keys[keyidx] == NULL)
4271     return -1;
4272
4273   keylen+=3;  /* add in ICV bytes */
4274
4275   /* copy the rest of the key over from the designated key */
4276   memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
4277
4278 #if 0
4279   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]);
4280 #endif
4281
4282   /* set up the RC4 state */
4283   for (i = 0; i < 256; i++)
4284     s[i] = i;
4285   j = 0;
4286   for (i = 0; i < 256; i++) {
4287     j = (j + s[i] + key[i % keylen]) & 0xff;
4288     SSWAP(i,j);
4289   }
4290
4291   /* Apply the RC4 to the data, update the CRC32 */
4292   cpos = buf+4;
4293   dpos = buf;
4294   crc = ~0;
4295   i = j = 0;
4296   for (k = 0; k < (len -8); k++) {
4297     i = (i+1) & 0xff;
4298     j = (j+s[i]) & 0xff;
4299     SSWAP(i,j);
4300 #if 0
4301     printf("%d -- %02x ", k, *dpos);
4302 #endif
4303     *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
4304 #if 0
4305     printf("%02x\n", *dpos);
4306 #endif
4307     crc = crc32_ccitt_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
4308   }
4309   crc = ~crc;
4310
4311   /* now let's check the crc */
4312   c_crc[0] = crc;
4313   c_crc[1] = crc >> 8;
4314   c_crc[2] = crc >> 16;
4315   c_crc[3] = crc >> 24;
4316
4317   for (k = 0; k < 4; k++) {
4318     i = (i + 1) & 0xff;
4319     j = (j+s[i]) & 0xff;
4320     SSWAP(i,j);
4321 #if 0
4322     printf("-- %02x %02x\n", *dpos, c_crc[k]);
4323 #endif
4324     if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
4325       return -1; /* ICV mismatch */
4326   }
4327
4328   return 0;
4329 }
4330
4331 static void init_wepkeys(void) {
4332   const char *tmp;
4333   int i;
4334   GByteArray *bytes;
4335   gboolean res;
4336
4337 #ifdef USE_ENV
4338   guint8 *buf;
4339
4340   tmp = getenv("WIRESHARK_WEPKEYNUM");
4341   if (!tmp) {
4342     num_wepkeys = 0;
4343     return;
4344   }
4345   num_wepkeys = atoi(tmp);
4346 #else
4347   if (num_wepkeys > 4)
4348     num_wepkeys = 4;
4349 #endif
4350
4351   if (num_wepkeys < 1)
4352     return;
4353
4354   if (wep_keys)
4355     g_free(wep_keys);
4356
4357   if (wep_keylens)
4358     g_free(wep_keylens);
4359
4360   wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
4361   wep_keylens = g_malloc(num_wepkeys * sizeof(int));
4362   bytes = g_byte_array_new();
4363
4364   for (i = 0 ; i < num_wepkeys; i++) {
4365     wep_keys[i] = NULL;
4366     wep_keylens[i] = 0;
4367
4368 #ifdef USE_ENV
4369     buf=ep_alloc(128);
4370     g_snprintf(buf, 128, "WIRESHARK_WEPKEY%d", i+1);
4371     tmp = getenv(buf);
4372 #else
4373     tmp = wep_keystr[i];
4374 #endif
4375
4376     if (tmp) {
4377 #if 0
4378 #ifdef USE_ENV
4379       printf("%s -- %s\n", buf, tmp);
4380 #else
4381       printf("%d -- %s\n", i+1, tmp);
4382 #endif
4383 #endif
4384
4385       if (wep_keys[i]) {
4386         g_free(wep_keys[i]);
4387       }
4388
4389       res = hex_str_to_bytes(tmp, bytes, FALSE);
4390       if (res && bytes->len > 0) {
4391         if (bytes->len > 32) {
4392           bytes->len = 32;
4393         }
4394         wep_keys[i] = g_malloc(32 * sizeof(guint8));
4395         memset(wep_keys[i], 0, 32 * sizeof(guint8));
4396         memcpy(wep_keys[i], bytes->data, bytes->len * sizeof(guint8));
4397         wep_keylens[i] = bytes->len;
4398 #if 0
4399         printf("%d: %d bytes\n", i, bytes->len);
4400         printf("%d: %s\n", i, bytes_to_str(bytes->data, bytes->len));
4401 #endif
4402       } else {
4403 #if 0
4404         printf("res: %d  bytes->len: %d\n", res, bytes->len);
4405 #endif
4406         g_warning("Could not parse WEP key %d: %s", i + 1, tmp);
4407       }
4408     }
4409   }
4410   g_byte_array_free(bytes, TRUE);
4411 }
4412 /*
4413  * This code had been taken from AirSnort crack.c function classify()
4414  * Permission granted by snax <at> shmoo dot com
4415  * weak_iv - determine which key byte an iv is useful in resolving
4416  * parm     - p, pointer to the first byte of an IV
4417  * return   -  n - this IV is weak for byte n of a WEP key
4418  *            -1 - this IV is not weak for any key bytes
4419  *
4420  * This function tests for IVs that are known to satisfy the criteria
4421  * for a weak IV as specified in FMS section 7.1
4422  *
4423  */
4424 static int
4425 weak_iv(guchar *iv)
4426 {
4427         guchar sum, k;
4428
4429         if (iv[1] == 255 && iv[0] > 2 && iv[0] < 16) {
4430                 return iv[0] -3;
4431         }
4432
4433         sum = iv[0] + iv[1];
4434         if (sum == 1) {
4435                 if (iv[2] <= 0x0a) {
4436                         return iv[2] +2;
4437                 }
4438                 else if (iv[2] == 0xff){
4439                         return 0;
4440                 }
4441         }
4442         k = 0xfe - iv[2];
4443         if (sum == k  && (iv[2] >= 0xf2 && iv[2] <= 0xfe && iv[2] != 0xfd)){
4444                 return k;
4445         }
4446         return -1;
4447 }