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