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