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
6 * $Id: packet-ieee80211.c,v 1.101 2003/09/24 23:35:39 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * Copied from README.developer
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.
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.
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.
30 * The following people helped me by pointing out bugs etc. Thank you!
34 * Magnus Hultman-Persson
38 * 09/12/2003 - Added dissection of country information tag
40 * Ritchie<at>tipsybottle.com
50 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
56 #include <epan/bitswap.h>
57 #include <epan/proto.h>
58 #include <epan/packet.h>
59 #include <epan/resolv.h>
61 #include "reassemble.h"
62 #include "packet-ipx.h"
63 #include "packet-llc.h"
64 #include "packet-ieee80211.h"
68 /* Defragment fragmented 802.11 datagrams */
69 static gboolean wlan_defragment = TRUE;
71 /* Check for the presence of the 802.11 FCS */
72 static gboolean wlan_check_fcs = FALSE;
74 /* Ignore the WEP bit; assume packet is decrypted */
75 static gboolean wlan_ignore_wep = FALSE;
77 /* Tables for reassembly of fragments. */
78 static GHashTable *wlan_fragment_table = NULL;
79 static GHashTable *wlan_reassembled_table = NULL;
81 /* Stuff for the WEP decoder */
82 static guint num_wepkeys = 0;
83 static guint8 **wep_keys = NULL;
84 static int *wep_keylens = NULL;
85 static void init_wepkeys(void);
86 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
87 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
88 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
91 /* When this is set, an unlimited number of WEP keys can be set in the
95 ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
96 ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
100 otherwise you're limited to specifying four keys in the preference system.
104 static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
107 /* ************************************************************************* */
108 /* Miscellaneous Constants */
109 /* ************************************************************************* */
110 #define SHORT_STR 256
112 /* ************************************************************************* */
113 /* Define some very useful macros that are used to analyze frame types etc. */
114 /* ************************************************************************* */
115 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */
116 #define COOK_PROT_VERSION(x) ((x) & 0x3)
117 #define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2)
118 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
119 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
120 #define COOK_ASSOC_ID(x) ((x) & 0x3FFF)
121 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
122 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
123 #define COOK_FLAGS(x) (((x) & 0xFF00) >> 8)
124 #define COOK_DS_STATUS(x) ((x) & 0x3)
125 #define COOK_WEP_KEY(x) (((x) & 0xC0) >> 6)
127 #define FLAG_TO_DS 0x01
128 #define FLAG_FROM_DS 0x02
129 #define FLAG_MORE_FRAGMENTS 0x04
130 #define FLAG_RETRY 0x08
131 #define FLAG_POWER_MGT 0x10
132 #define FLAG_MORE_DATA 0x20
133 #define FLAG_WEP 0x40
134 #define FLAG_ORDER 0x80
136 #define IS_TO_DS(x) ((x) & FLAG_TO_DS)
137 #define IS_FROM_DS(x) ((x) & FLAG_FROM_DS)
138 #define HAVE_FRAGMENTS(x) ((x) & FLAG_MORE_FRAGMENTS)
139 #define IS_RETRY(x) ((x) & FLAG_RETRY)
140 #define POWER_MGT_STATUS(x) ((x) & FLAG_POWER_MGT)
141 #define HAS_MORE_DATA(x) ((x) & FLAG_MORE_DATA)
142 #define IS_WEP(x) (!wlan_ignore_wep && ((x) & FLAG_WEP))
143 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
145 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
146 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
147 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
148 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
151 /* ************************************************************************* */
152 /* Constants used to identify cooked frame types */
153 /* ************************************************************************* */
154 #define MGT_FRAME 0x00 /* Frame type is management */
155 #define CONTROL_FRAME 0x01 /* Frame type is control */
156 #define DATA_FRAME 0x02 /* Frame type is Data */
158 #define DATA_SHORT_HDR_LEN 24
159 #define DATA_LONG_HDR_LEN 30
160 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
162 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
163 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
164 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
165 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
166 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
167 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
168 #define MGT_BEACON 0x08 /* Management - Beacon frame */
169 #define MGT_ATIM 0x09 /* Management - ATIM */
170 #define MGT_DISASS 0x0A /* Management - Disassociation */
171 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
172 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
174 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
175 #define CTRL_RTS 0x1B /* Control - request to send */
176 #define CTRL_CTS 0x1C /* Control - clear to send */
177 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
178 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
179 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
181 #define DATA 0x20 /* Data - Data */
182 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
183 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
184 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
185 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
186 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
187 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
188 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
190 #define DATA_ADDR_T1 0
191 #define DATA_ADDR_T2 (FLAG_FROM_DS << 8)
192 #define DATA_ADDR_T3 (FLAG_TO_DS << 8)
193 #define DATA_ADDR_T4 ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
196 /* ************************************************************************* */
197 /* Macros used to extract information about fixed fields */
198 /* ************************************************************************* */
199 #define ESS_SET(x) ((x) & 0x0001)
200 #define IBSS_SET(x) ((x) & 0x0002)
204 /* ************************************************************************* */
205 /* Logical field codes (dissector's encoding of fixed fields) */
206 /* ************************************************************************* */
207 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
208 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
209 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
210 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
211 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
212 #define FIELD_CURRENT_AP_ADDR 0x06
213 #define FIELD_LISTEN_IVAL 0x07
214 #define FIELD_REASON_CODE 0x08
215 #define FIELD_ASSOC_ID 0x09
216 #define FIELD_STATUS_CODE 0x0A
218 /* ************************************************************************* */
219 /* Logical field codes (IEEE 802.11 encoding of tags) */
220 /* ************************************************************************* */
221 #define TAG_SSID 0x00
222 #define TAG_SUPP_RATES 0x01
223 #define TAG_FH_PARAMETER 0x02
224 #define TAG_DS_PARAMETER 0x03
225 #define TAG_CF_PARAMETER 0x04
227 #define TAG_IBSS_PARAMETER 0x06
228 #define TAG_COUNTRY_INFO 0x07
229 #define TAG_FH_HOPPING_PARAMETER 0x08
230 #define TAG_FH_HOPPING_TABLE 0x09
231 #define TAG_CHALLENGE_TEXT 0x10
232 #define TAG_ERP_INFO 0x2A
233 #define TAG_ERP_INFO_OLD 0x2F /* IEEE Std 802.11g/D4.0 */
234 #define TAG_EXT_SUPP_RATES 0x32
235 #define TAG_VENDOR_SPECIFIC_IE 0xDD
237 #define WPA_OUI "\x00\x50\xF2"
239 /* ************************************************************************* */
240 /* Frame types, and their names */
241 /* ************************************************************************* */
242 static const value_string frame_type_subtype_vals[] = {
243 {MGT_ASSOC_REQ, "Association Request"},
244 {MGT_ASSOC_RESP, "Association Response"},
245 {MGT_REASSOC_REQ, "Reassociation Request"},
246 {MGT_REASSOC_RESP, "Reassociation Response"},
247 {MGT_PROBE_REQ, "Probe Request"},
248 {MGT_PROBE_RESP, "Probe Response"},
249 {MGT_BEACON, "Beacon frame"},
251 {MGT_DISASS, "Dissassociate"},
252 {MGT_AUTHENTICATION, "Authentication"},
253 {MGT_DEAUTHENTICATION, "Deauthentication"},
254 {CTRL_PS_POLL, "Power-Save poll"},
255 {CTRL_RTS, "Request-to-send"},
256 {CTRL_CTS, "Clear-to-send"},
257 {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
258 {CTRL_CFP_END, "CF-End (Control-frame)"},
259 {CTRL_CFP_ENDACK, "CF-End + CF-Ack (Control-frame)"},
261 {DATA_CF_ACK, "Data + CF-Acknowledgement"},
262 {DATA_CF_POLL, "Data + CF-Poll"},
263 {DATA_CF_ACK_POLL, "Data + CF-Acknowledgement/Poll"},
264 {DATA_NULL_FUNCTION, "Null function (No data)"},
265 {DATA_CF_ACK_NOD, "Data + Acknowledgement (No data)"},
266 {DATA_CF_POLL_NOD, "Data + CF-Poll (No data)"},
267 {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
271 static int proto_wlan = -1;
273 /* ************************************************************************* */
274 /* Header field info values for radio information */
275 /* ************************************************************************* */
276 static int hf_data_rate = -1;
277 static int hf_channel = -1;
278 static int hf_signal_strength = -1;
280 /* ************************************************************************* */
281 /* Header field info values for FC-field */
282 /* ************************************************************************* */
283 static int hf_fc_field = -1;
284 static int hf_fc_proto_version = -1;
285 static int hf_fc_frame_type = -1;
286 static int hf_fc_frame_subtype = -1;
287 static int hf_fc_frame_type_subtype = -1;
289 static int hf_fc_flags = -1;
290 static int hf_fc_to_ds = -1;
291 static int hf_fc_from_ds = -1;
292 static int hf_fc_data_ds = -1;
294 static int hf_fc_more_frag = -1;
295 static int hf_fc_retry = -1;
296 static int hf_fc_pwr_mgt = -1;
297 static int hf_fc_more_data = -1;
298 static int hf_fc_wep = -1;
299 static int hf_fc_order = -1;
302 /* ************************************************************************* */
303 /* Header values for Duration/ID field */
304 /* ************************************************************************* */
305 static int hf_did_duration = -1;
306 static int hf_assoc_id = -1;
309 /* ************************************************************************* */
310 /* Header values for different address-fields (all 4 of them) */
311 /* ************************************************************************* */
312 static int hf_addr_da = -1; /* Destination address subfield */
313 static int hf_addr_sa = -1; /* Source address subfield */
314 static int hf_addr_ra = -1; /* Receiver address subfield */
315 static int hf_addr_ta = -1; /* Transmitter address subfield */
316 static int hf_addr_bssid = -1; /* address is bssid */
318 static int hf_addr = -1; /* Source or destination address subfield */
321 /* ************************************************************************* */
322 /* Header values for sequence number field */
323 /* ************************************************************************* */
324 static int hf_frag_number = -1;
325 static int hf_seq_number = -1;
327 /* ************************************************************************* */
328 /* Header values for Frame Check field */
329 /* ************************************************************************* */
330 static int hf_fcs = -1;
332 /* ************************************************************************* */
333 /* Header values for reassembly */
334 /* ************************************************************************* */
335 static int hf_fragments = -1;
336 static int hf_fragment = -1;
337 static int hf_fragment_overlap = -1;
338 static int hf_fragment_overlap_conflict = -1;
339 static int hf_fragment_multiple_tails = -1;
340 static int hf_fragment_too_long_fragment = -1;
341 static int hf_fragment_error = -1;
342 static int hf_reassembled_in = -1;
345 static int proto_wlan_mgt = -1;
346 /* ************************************************************************* */
347 /* Fixed fields found in mgt frames */
348 /* ************************************************************************* */
349 static int ff_auth_alg = -1; /* Authentication algorithm field */
350 static int ff_auth_seq = -1; /* Authentication transaction sequence */
351 static int ff_current_ap = -1; /* Current AP MAC address */
352 static int ff_listen_ival = -1; /* Listen interval fixed field */
353 static int ff_timestamp = -1; /* 64 bit timestamp */
354 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
355 static int ff_assoc_id = -1; /* 16 bit AID field */
356 static int ff_reason = -1; /* 16 bit reason code */
357 static int ff_status_code = -1; /* Status code */
359 /* ************************************************************************* */
360 /* Flags found in the capability field (fixed field) */
361 /* ************************************************************************* */
362 static int ff_capture = -1;
363 static int ff_cf_ess = -1;
364 static int ff_cf_ibss = -1;
365 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
366 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
367 static int ff_cf_privacy = -1;
368 static int ff_cf_preamble = -1;
369 static int ff_cf_pbcc = -1;
370 static int ff_cf_agility = -1;
371 static int ff_short_slot_time = -1;
372 static int ff_dsss_ofdm = -1;
374 /* ************************************************************************* */
375 /* Tagged value format fields */
376 /* ************************************************************************* */
377 static int tag_number = -1;
378 static int tag_length = -1;
379 static int tag_interpretation = -1;
383 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
384 static int hf_tagged_parameters = -1; /* Fixed payload item */
385 static int hf_wep_iv = -1;
386 static int hf_wep_key = -1;
387 static int hf_wep_icv = -1;
389 /* ************************************************************************* */
391 /* ************************************************************************* */
392 static gint ett_80211 = -1;
393 static gint ett_proto_flags = -1;
394 static gint ett_cap_tree = -1;
395 static gint ett_fc_tree = -1;
396 static gint ett_fragments = -1;
397 static gint ett_fragment = -1;
399 static gint ett_80211_mgt = -1;
400 static gint ett_fixed_parameters = -1;
401 static gint ett_tagged_parameters = -1;
402 static gint ett_wep_parameters = -1;
404 static const fragment_items frag_items = {
409 &hf_fragment_overlap,
410 &hf_fragment_overlap_conflict,
411 &hf_fragment_multiple_tails,
412 &hf_fragment_too_long_fragment,
418 static dissector_handle_t llc_handle;
419 static dissector_handle_t ipx_handle;
420 static dissector_handle_t data_handle;
422 /* ************************************************************************* */
423 /* Return the length of the current header (in bytes) */
424 /* ************************************************************************* */
426 find_header_length (guint16 fcf)
428 switch (COOK_FRAME_TYPE (fcf)) {
431 return MGT_FRAME_HDR_LEN;
434 switch (COMPOSE_FRAME_TYPE (fcf)) {
437 case CTRL_ACKNOWLEDGEMENT:
443 case CTRL_CFP_ENDACK:
449 return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
457 /* ************************************************************************* */
458 /* This is the capture function used to update packet counts */
459 /* ************************************************************************* */
461 capture_ieee80211_common (const guchar * pd, int offset, int len,
462 packet_counts * ld, gboolean fixed_length_header)
464 guint16 fcf, hdr_length;
466 if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
471 fcf = pletohs (&pd[0]);
473 if (IS_WEP(COOK_FLAGS(fcf)))
479 switch (COMPOSE_FRAME_TYPE (fcf))
482 case DATA: /* We got a data frame */
483 case DATA_CF_ACK: /* Data with ACK */
485 case DATA_CF_ACK_POLL:
486 if (fixed_length_header)
487 hdr_length = DATA_LONG_HDR_LEN;
489 hdr_length = find_header_length (fcf);
490 /* I guess some bridges take Netware Ethernet_802_3 frames,
491 which are 802.3 frames (with a length field rather than
492 a type field, but with no 802.2 header in the payload),
493 and just stick the payload into an 802.11 frame. I've seen
494 captures that show frames of that sort.
496 This means we have to do the same check for Netware 802.3 -
497 or, if you will, "Netware 802.11" - that we do in the
498 Ethernet dissector, i.e. checking for 0xffff as the first
499 four bytes of the payload and, if we find it, treating it
501 if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
505 if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
509 capture_llc (pd, offset + hdr_length, len, ld);
520 * Handle 802.11 with a variable-length link-layer header.
523 capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
525 capture_ieee80211_common (pd, offset, len, ld, FALSE);
529 * Handle 802.11 with a fixed-length link-layer header (padded to the
533 capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
535 capture_ieee80211_common (pd, offset, len, ld, TRUE);
539 /* ************************************************************************* */
540 /* Add the subtree used to store the fixed parameters */
541 /* ************************************************************************* */
543 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
545 proto_item *fixed_fields;
547 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
548 size, size, "Fixed parameters (%d bytes)",
551 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
555 /* ************************************************************************* */
556 /* Add the subtree used to store tagged parameters */
557 /* ************************************************************************* */
559 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
561 proto_item *tagged_fields;
563 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
568 "Tagged parameters (%d bytes)",
571 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
575 /* ************************************************************************* */
576 /* Dissect and add fixed mgmt fields to protocol tree */
577 /* ************************************************************************* */
579 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
581 const guint8 *dataptr;
582 char out_buff[SHORT_STR];
584 proto_item *cap_item;
585 static proto_tree *cap_tree;
590 case FIELD_TIMESTAMP:
591 dataptr = tvb_get_ptr (tvb, offset, 8);
592 memset (out_buff, 0, SHORT_STR);
593 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
603 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
606 case FIELD_BEACON_INTERVAL:
607 temp_double = (double) tvb_get_letohs (tvb, offset);
608 temp_double = temp_double * 1024 / 1000000;
609 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
610 temp_double,"Beacon Interval: %f [Seconds]",
616 capability = tvb_get_letohs (tvb, offset);
618 cap_item = proto_tree_add_uint_format (tree, ff_capture,
621 "Capability Information: 0x%04X",
623 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
624 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
626 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
628 if (ESS_SET (capability) != 0) /* This is an AP */
629 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
632 else /* This is a STA */
633 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
635 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
637 proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
639 proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
641 proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
643 proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
645 proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
650 proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
653 case FIELD_AUTH_TRANS_SEQ:
654 proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
657 case FIELD_CURRENT_AP_ADDR:
658 proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
661 case FIELD_LISTEN_IVAL:
662 proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
665 case FIELD_REASON_CODE:
666 proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
670 proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE);
673 case FIELD_STATUS_CODE:
674 proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
679 static char *wpa_cipher_str[] =
690 wpa_cipher_idx2str(guint idx)
692 if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
693 return wpa_cipher_str[idx];
697 static char *wpa_keymgmt_str[] =
705 wpa_keymgmt_idx2str(guint idx)
707 if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
708 return wpa_keymgmt_str[idx];
713 dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
714 guint32 tag_len, const guint8 *tag_val)
716 guint32 tag_val_off = 0;
717 char out_buff[SHORT_STR];
720 if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
721 snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
722 tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
723 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
726 if (tag_val_off + 4 <= tag_len) {
727 /* multicast cipher suite */
728 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
729 snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
730 wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
731 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
734 /* unicast cipher suites */
735 if (tag_val_off + 2 <= tag_len) {
736 snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
737 pletohs(tag_val + tag_val_off));
738 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
742 while (tag_val_off + 4 <= tag_len) {
743 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
744 snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
745 i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
746 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
754 /* authenticated key management suites */
755 if (tag_val_off + 2 <= tag_len) {
756 snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
757 pletohs(tag_val + tag_val_off));
758 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
762 while (tag_val_off + 4 <= tag_len) {
763 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
764 snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
765 i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
766 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
778 if (tag_val_off < tag_len)
779 proto_tree_add_string(tree, tag_interpretation, tvb,
780 offset, tag_len - tag_val_off, "Not interpreted");
783 proto_tree_add_string(tree, tag_interpretation,
784 tvb, offset, tag_len, "Not interpreted");
787 /* ************************************************************************* */
788 /* Dissect and add tagged (optional) fields to proto tree */
789 /* ************************************************************************* */
791 static const value_string tag_num_vals[] = {
792 { TAG_SSID, "SSID parameter set" },
793 { TAG_SUPP_RATES, "Supported Rates" },
794 { TAG_FH_PARAMETER, "FH Parameter set" },
795 { TAG_DS_PARAMETER, "DS Parameter set" },
796 { TAG_CF_PARAMETER, "CF Parameter set" },
797 { TAG_TIM, "(TIM) Traffic Indication Map" },
798 { TAG_IBSS_PARAMETER, "IBSS Parameter set" },
799 { TAG_COUNTRY_INFO, "Country Information" },
800 { TAG_FH_HOPPING_PARAMETER, "Hopping Pattern Parameters" },
801 { TAG_CHALLENGE_TEXT, "Challenge text" },
802 { TAG_ERP_INFO, "ERP Information" },
803 { TAG_ERP_INFO_OLD, "ERP Information" },
804 { TAG_EXT_SUPP_RATES, "Extended Supported Rates" },
805 { TAG_VENDOR_SPECIFIC_IE, "Vendor Specific" },
809 static const value_string environment_vals[] = {
817 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
819 const guint8 *tag_data_ptr;
820 guint32 tag_no, tag_len;
823 char out_buff[SHORT_STR];
826 tag_no = tvb_get_guint8(tvb, offset);
827 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
828 "Tag Number: %u (%s)",
830 val_to_str(tag_no, tag_num_vals,
831 (tag_no >= 17 && tag_no <= 31) ?
832 "Reserved for challenge text" :
833 "Reserved tag number"));
835 tag_len = tvb_get_guint8(tvb, offset + 1);
836 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
838 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
845 memset (out_buff, 0, SHORT_STR);
847 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
848 out_buff[tag_len + 1] = 0;
850 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
857 case TAG_EXT_SUPP_RATES:
858 memset (out_buff, 0, SHORT_STR);
859 strcpy (out_buff, "Supported rates: ");
860 n = strlen (out_buff);
862 for (i = 0; i < tag_len && n < SHORT_STR; i++)
864 ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
865 (tag_data_ptr[i] & 0x7F) * 0.5,
866 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
867 if (ret == -1 || ret >= SHORT_STR - n) {
868 /* Some versions of snprintf return -1 if they'd truncate
869 the output. Others return <buf_size> or greater. */
875 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
877 out_buff[SHORT_STR-1] = '\0';
878 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
884 case TAG_FH_PARAMETER:
885 memset (out_buff, 0, SHORT_STR);
887 snprintf (out_buff, SHORT_STR,
888 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
889 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
890 tag_data_ptr[3], tag_data_ptr[4]);
892 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
898 case TAG_DS_PARAMETER:
899 memset (out_buff, 0, SHORT_STR);
901 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
902 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
907 case TAG_CF_PARAMETER:
908 memset (out_buff, 0, SHORT_STR);
910 snprintf (out_buff, SHORT_STR,
911 "CFP count %u, CFP period %u, CFP max duration %u, "
912 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
913 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
915 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
921 memset (out_buff, 0, SHORT_STR);
922 snprintf (out_buff, SHORT_STR,
923 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
924 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
926 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
932 case TAG_IBSS_PARAMETER:
933 memset (out_buff, 0, SHORT_STR);
934 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
935 pletohs (tag_data_ptr));
937 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
942 case TAG_COUNTRY_INFO:
943 memset (out_buff, 0, SHORT_STR);
945 snprintf (out_buff, SHORT_STR, "Country Code: %c%c, %s Environment",
946 tag_data_ptr[0], tag_data_ptr[1],
947 val_to_str(tag_data_ptr[2], environment_vals,"Unknown (0x%02x)"));
949 n = strlen (out_buff);
951 for (i = 3; (i + 3) <= tag_len && n < SHORT_STR; i += 3)
953 ret = snprintf(out_buff + n, SHORT_STR - n,
954 ", Start Channel: %u, Channels: %u, Max TX Power: %d dBm",
955 tag_data_ptr[i], tag_data_ptr[i + 1],
956 (gint)tag_data_ptr[i + 2]);
958 if (ret == -1 || ret >= SHORT_STR - n) {
959 /* Some versions of snprintf return -1 if they'd truncate
960 the output. Others return <buf_size> or greater. */
966 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,tag_len, out_buff);
970 case TAG_FH_HOPPING_PARAMETER:
971 memset (out_buff, 0, SHORT_STR);
972 snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u",
973 tag_data_ptr[0], tag_data_ptr[1]);
974 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, tag_len, out_buff);
980 case TAG_CHALLENGE_TEXT:
981 memset (out_buff, 0, SHORT_STR);
982 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
983 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
991 case TAG_ERP_INFO_OLD:
992 memset (out_buff, 0, SHORT_STR);
994 snprintf (out_buff, SHORT_STR,
995 "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)",
997 tag_data_ptr[0] & 0x01 ? "" : "no ",
998 tag_data_ptr[0] & 0x02 ? "" : "do not ",
999 tag_data_ptr[0] & 0x04 ? "short or long": "long");
1000 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1005 case TAG_VENDOR_SPECIFIC_IE:
1006 dissect_vendor_specific_ie(tree, tvb, offset + 2, tag_len,
1012 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1013 tag_len, "Not interpreted");
1021 ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, proto_tree * tree,
1022 int tagged_parameters_len)
1026 while (tagged_parameters_len > 0) {
1027 if ((next_len=add_tagged_field (tree, tvb, offset))==0)
1029 if (next_len > tagged_parameters_len) {
1030 /* XXX - flag this as an error? */
1031 next_len = tagged_parameters_len;
1034 tagged_parameters_len -= next_len;
1038 /* ************************************************************************* */
1039 /* Dissect 802.11 management frame */
1040 /* ************************************************************************* */
1042 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
1045 proto_item *ti = NULL;
1046 proto_tree *mgt_tree;
1047 proto_tree *fixed_tree;
1048 proto_tree *tagged_tree;
1050 int tagged_parameter_tree_len;
1052 CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
1056 ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
1057 mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
1059 switch (COMPOSE_FRAME_TYPE(fcf))
1063 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
1064 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1065 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1067 offset = 4; /* Size of fixed fields */
1068 tagged_parameter_tree_len =
1069 tvb_reported_length_remaining(tvb, offset);
1070 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1071 tagged_parameter_tree_len);
1073 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1074 tagged_parameter_tree_len);
1078 case MGT_ASSOC_RESP:
1079 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1080 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1081 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1082 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1084 offset = 6; /* Size of fixed fields */
1086 tagged_parameter_tree_len =
1087 tvb_reported_length_remaining(tvb, offset);
1088 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1089 tagged_parameter_tree_len);
1091 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1092 tagged_parameter_tree_len);
1096 case MGT_REASSOC_REQ:
1097 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1098 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1099 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1100 add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
1102 offset = 10; /* Size of fixed fields */
1103 tagged_parameter_tree_len =
1104 tvb_reported_length_remaining(tvb, offset);
1105 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1106 tagged_parameter_tree_len);
1108 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1109 tagged_parameter_tree_len);
1112 case MGT_REASSOC_RESP:
1113 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1114 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1115 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1116 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1118 offset = 6; /* Size of fixed fields */
1119 tagged_parameter_tree_len =
1120 tvb_reported_length_remaining(tvb, offset);
1121 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1122 tagged_parameter_tree_len);
1124 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1125 tagged_parameter_tree_len);
1131 tagged_parameter_tree_len =
1132 tvb_reported_length_remaining(tvb, offset);
1133 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1134 tagged_parameter_tree_len);
1136 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1137 tagged_parameter_tree_len);
1141 case MGT_PROBE_RESP:
1142 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1143 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1144 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1145 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1147 offset = 12; /* Size of fixed fields */
1148 tagged_parameter_tree_len =
1149 tvb_reported_length_remaining(tvb, offset);
1150 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1151 tagged_parameter_tree_len);
1153 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1154 tagged_parameter_tree_len);
1158 case MGT_BEACON: /* Dissect protocol payload fields */
1159 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1161 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1162 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1163 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1165 offset = 12; /* Size of fixed fields */
1166 tagged_parameter_tree_len =
1167 tvb_reported_length_remaining(tvb, offset);
1168 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1169 tagged_parameter_tree_len);
1171 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1172 tagged_parameter_tree_len);
1181 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1182 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1186 case MGT_AUTHENTICATION:
1187 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1188 add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
1189 add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
1190 add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
1192 offset = 6; /* Size of fixed fields */
1194 tagged_parameter_tree_len =
1195 tvb_reported_length_remaining(tvb, offset);
1196 if (tagged_parameter_tree_len != 0)
1198 tagged_tree = get_tagged_parameter_tree (mgt_tree,
1201 tagged_parameter_tree_len);
1203 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1204 tagged_parameter_tree_len);
1209 case MGT_DEAUTHENTICATION:
1210 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1211 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1218 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1220 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1221 col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
1222 get_ether_name(addr), type);
1223 if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
1224 col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
1225 ether_to_str(addr), type);
1229 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1231 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1232 col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
1233 get_ether_name(addr), type);
1234 if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
1235 col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
1236 ether_to_str(addr), type);
1239 /* ************************************************************************* */
1240 /* Dissect 802.11 frame */
1241 /* ************************************************************************* */
1243 dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
1244 proto_tree * tree, gboolean fixed_length_header,
1245 gboolean has_radio_information, gboolean has_no_fcs,
1246 gboolean wlan_broken_fc)
1248 guint16 fcf, flags, frame_type_subtype;
1249 guint16 seq_control;
1250 guint32 seq_number, frag_number;
1251 gboolean more_frags;
1252 const guint8 *src = NULL, *dst = NULL;
1253 proto_item *ti = NULL;
1254 proto_item *flag_item;
1255 proto_item *fc_item;
1256 proto_tree *hdr_tree = NULL;
1257 proto_tree *flag_tree;
1258 proto_tree *fc_tree;
1260 gint len, reported_len;
1261 gboolean save_fragmented;
1262 tvbuff_t *volatile next_tvb = NULL;
1264 volatile gboolean is_802_2;
1266 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1267 col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
1268 if (check_col (pinfo->cinfo, COL_INFO))
1269 col_clear (pinfo->cinfo, COL_INFO);
1271 fcf = tvb_get_letohs (tvb, 0);
1272 if (wlan_broken_fc) {
1274 fcf = ((fcf & 0xff) << 8) | (((fcf & 0xff00) >> 8) & 0xff);
1276 if (fixed_length_header)
1277 hdr_len = DATA_LONG_HDR_LEN;
1279 hdr_len = find_header_length (fcf);
1280 frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1282 if (check_col (pinfo->cinfo, COL_INFO))
1283 col_set_str (pinfo->cinfo, COL_INFO,
1284 val_to_str(frame_type_subtype, frame_type_subtype_vals,
1285 "Unrecognized (Reserved frame)"));
1287 flags = COOK_FLAGS (fcf);
1288 more_frags = HAVE_FRAGMENTS (flags);
1290 /* Add the radio information, if present, and the FC to the current tree */
1293 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1295 hdr_tree = proto_item_add_subtree (ti, ett_80211);
1297 if (has_radio_information) {
1298 proto_tree_add_uint_format(hdr_tree, hf_data_rate,
1300 pinfo->pseudo_header->ieee_802_11.data_rate,
1301 "Data Rate: %g mb/s",
1302 .5*pinfo->pseudo_header->ieee_802_11.data_rate);
1304 proto_tree_add_uint(hdr_tree, hf_channel,
1306 pinfo->pseudo_header->ieee_802_11.channel);
1308 proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
1310 pinfo->pseudo_header->ieee_802_11.signal_level,
1311 "Signal Strength: %u%%",
1312 pinfo->pseudo_header->ieee_802_11.signal_level);
1315 proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1317 wlan_broken_fc?1:0, 1,
1318 frame_type_subtype);
1320 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb,
1323 "Frame Control: 0x%04X (%s)",
1324 fcf, wlan_broken_fc?"Swapped":"Normal");
1326 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1329 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb,
1330 wlan_broken_fc?1:0, 1,
1331 COOK_PROT_VERSION (fcf));
1333 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb,
1334 wlan_broken_fc?1:0, 1,
1335 COOK_FRAME_TYPE (fcf));
1337 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1339 wlan_broken_fc?1:0, 1,
1340 COOK_FRAME_SUBTYPE (fcf));
1343 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb,
1344 wlan_broken_fc?0:1, 1,
1345 flags, "Flags: 0x%X", flags);
1347 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1349 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb,
1350 wlan_broken_fc?0:1, 1,
1351 COOK_DS_STATUS (flags));
1352 proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1,
1354 proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1,
1357 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb,
1358 wlan_broken_fc?0:1, 1,
1361 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb,
1362 wlan_broken_fc?0:1, 1, flags);
1364 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb,
1365 wlan_broken_fc?0:1, 1, flags);
1367 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb,
1368 wlan_broken_fc?0:1, 1,
1371 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb,
1372 wlan_broken_fc?0:1, 1, flags);
1374 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb,
1375 wlan_broken_fc?0:1, 1, flags);
1377 if (frame_type_subtype == CTRL_PS_POLL)
1378 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1379 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1382 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1383 tvb_get_letohs (tvb, 2));
1387 * Decode the part of the frame header that isn't the same for all
1394 switch (COOK_FRAME_TYPE (fcf))
1399 * All management frame types have the same header.
1401 src = tvb_get_ptr (tvb, 10, 6);
1402 dst = tvb_get_ptr (tvb, 4, 6);
1404 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1405 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1406 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1407 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1409 seq_control = tvb_get_letohs(tvb, 22);
1410 frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1411 seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1415 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1417 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1419 /* add items for wlan.addr filter */
1420 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1421 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1423 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1424 tvb_get_ptr (tvb, 16, 6));
1426 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1429 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1435 switch (frame_type_subtype)
1439 src = tvb_get_ptr (tvb, 10, 6);
1440 dst = tvb_get_ptr (tvb, 4, 6);
1442 set_src_addr_cols(pinfo, src, "BSSID");
1443 set_dst_addr_cols(pinfo, dst, "BSSID");
1447 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1449 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1455 src = tvb_get_ptr (tvb, 10, 6);
1456 dst = tvb_get_ptr (tvb, 4, 6);
1458 set_src_addr_cols(pinfo, src, "TA");
1459 set_dst_addr_cols(pinfo, dst, "RA");
1463 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1465 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1471 dst = tvb_get_ptr (tvb, 4, 6);
1473 set_dst_addr_cols(pinfo, dst, "RA");
1476 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1480 case CTRL_ACKNOWLEDGEMENT:
1481 dst = tvb_get_ptr (tvb, 4, 6);
1483 set_dst_addr_cols(pinfo, dst, "RA");
1486 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1491 src = tvb_get_ptr (tvb, 10, 6);
1492 dst = tvb_get_ptr (tvb, 4, 6);
1494 set_src_addr_cols(pinfo, src, "BSSID");
1495 set_dst_addr_cols(pinfo, dst, "RA");
1499 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1500 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1505 case CTRL_CFP_ENDACK:
1506 src = tvb_get_ptr (tvb, 10, 6);
1507 dst = tvb_get_ptr (tvb, 4, 6);
1509 set_src_addr_cols(pinfo, src, "BSSID");
1510 set_dst_addr_cols(pinfo, dst, "RA");
1514 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1516 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1523 addr_type = COOK_ADDR_SELECTOR (fcf);
1525 /* In order to show src/dst address we must always do the following */
1530 src = tvb_get_ptr (tvb, 10, 6);
1531 dst = tvb_get_ptr (tvb, 4, 6);
1536 src = tvb_get_ptr (tvb, 16, 6);
1537 dst = tvb_get_ptr (tvb, 4, 6);
1542 src = tvb_get_ptr (tvb, 10, 6);
1543 dst = tvb_get_ptr (tvb, 16, 6);
1548 src = tvb_get_ptr (tvb, 24, 6);
1549 dst = tvb_get_ptr (tvb, 16, 6);
1553 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1554 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1555 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1556 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1558 seq_control = tvb_get_letohs(tvb, 22);
1559 frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1560 seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1562 /* Now if we have a tree we start adding stuff */
1571 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1572 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1573 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1574 tvb_get_ptr (tvb, 16, 6));
1575 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1577 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1580 /* add items for wlan.addr filter */
1581 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1582 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1587 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1588 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1589 tvb_get_ptr (tvb, 10, 6));
1590 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1591 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1593 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1596 /* add items for wlan.addr filter */
1597 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1598 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1603 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1604 tvb_get_ptr (tvb, 4, 6));
1605 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1606 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1608 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1610 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1613 /* add items for wlan.addr filter */
1614 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1615 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1620 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1621 tvb_get_ptr (tvb, 4, 6));
1622 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1623 tvb_get_ptr (tvb, 10, 6));
1624 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1625 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1627 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1629 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1631 /* add items for wlan.addr filter */
1632 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1633 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1641 len = tvb_length_remaining(tvb, hdr_len);
1642 reported_len = tvb_reported_length_remaining(tvb, hdr_len);
1644 if (!has_no_fcs && (wlan_check_fcs))
1647 * Well, this packet should, in theory, have an FCS.
1648 * Do we have the entire packet, and does it have enough data for
1651 if (reported_len < 4)
1654 * The packet is claimed not to even have enough data for a 4-byte
1656 * Pretend it doesn't have an FCS.
1660 else if (len < reported_len)
1663 * The packet is claimed to have enough data for a 4-byte FCS, but
1664 * we didn't capture all of the packet.
1665 * Slice off the 4-byte FCS from the reported length, and trim the
1666 * captured length so it's no more than the reported length; that
1667 * will slice off what of the FCS, if any, is in the captured
1671 if (len > reported_len)
1677 * We have the entire packet, and it includes a 4-byte FCS.
1678 * Slice it off, and put it into the tree.
1684 guint32 fcs = crc32_tvb_802(tvb, hdr_len + len);
1685 guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
1686 if (fcs == sent_fcs)
1687 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1688 hdr_len + len, 4, sent_fcs,
1689 "Frame check sequence: 0x%08x (correct)", sent_fcs);
1691 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1692 hdr_len + len, 4, sent_fcs,
1693 "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
1700 * Only management and data frames have a body, so we don't have
1701 * anything more to do for other types of frames.
1703 switch (COOK_FRAME_TYPE (fcf))
1711 * No-data frames don't have a body.
1713 switch (frame_type_subtype)
1716 case DATA_NULL_FUNCTION:
1717 case DATA_CF_ACK_NOD:
1718 case DATA_CF_POLL_NOD:
1719 case DATA_CF_ACK_POLL_NOD:
1728 if (IS_WEP(COOK_FLAGS(fcf))) {
1730 * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
1731 * the data, if we have a matching key. Otherwise display it as data.
1733 gboolean can_decrypt = FALSE;
1734 proto_tree *wep_tree = NULL;
1739 * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
1740 * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
1743 * Also, just pass the data *following* the WEP parameters as the
1744 * buffer to decrypt.
1746 iv = tvb_get_letoh24(tvb, hdr_len);
1748 proto_item *wep_fields;
1750 wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
1753 wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
1754 proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
1756 key = COOK_WEP_KEY (tvb_get_guint8 (tvb, hdr_len + 3));
1758 proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
1760 /* Subtract out the length of the IV. */
1765 * Well, this packet should, in theory, have an ICV.
1766 * Do we have the entire packet, and does it have enough data for
1769 if (reported_len < 4) {
1771 * The packet is claimed not to even have enough data for a
1773 * Pretend it doesn't have an ICV.
1776 } else if (len < reported_len) {
1778 * The packet is claimed to have enough data for a 4-byte ICV,
1779 * but we didn't capture all of the packet.
1780 * Slice off the 4-byte ICV from the reported length, and trim
1781 * the captured length so it's no more than the reported length;
1782 * that will slice off what of the ICV, if any, is in the
1787 if (len > reported_len)
1791 * We have the entire packet, and it includes a 4-byte ICV.
1792 * Slice it off, and put it into the tree.
1794 * We only support decrypting if we have the the ICV.
1796 * XXX - the ICV is encrypted; we're putting the encrypted
1797 * value, not the decrypted value, into the tree.
1804 if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
1806 * WEP decode impossible or failed, treat payload as raw data
1807 * and don't attempt fragment reassembly or further dissection.
1809 next_tvb = tvb_new_subset(tvb, hdr_len + 4, len, reported_len);
1811 if (tree && can_decrypt)
1812 proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
1813 hdr_len + 4 + len, 4,
1814 tvb_get_ntohl(tvb, hdr_len + 4 + len),
1815 "WEP ICV: 0x%08x (not verified)",
1816 tvb_get_ntohl(tvb, hdr_len + 4 + len));
1818 call_dissector(data_handle, next_tvb, pinfo, tree);
1823 proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
1824 hdr_len + 4 + len, 4,
1825 tvb_get_ntohl(tvb, hdr_len + 4 + len),
1826 "WEP ICV: 0x%08x (correct)",
1827 tvb_get_ntohl(tvb, hdr_len + 4 + len));
1829 add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
1833 * WEP decryption successful!
1835 * Use the tvbuff we got back from the decryption; the data starts at
1836 * the beginning. The lengths are already correct for the decoded WEP
1843 * Not a WEP-encrypted frame; just use the data from the tvbuff
1846 * The payload starts at "hdr_len" (i.e., just past the 802.11
1847 * MAC header), the length of data in the tvbuff following the
1848 * 802.11 header is "len", and the length of data in the packet
1849 * following the 802.11 header is "reported_len".
1855 * Do defragmentation if "wlan_defragment" is true, and we have more
1856 * fragments or this isn't the first fragment.
1858 * We have to do some special handling to catch frames that
1859 * have the "More Fragments" indicator not set but that
1860 * don't show up as reassembled and don't have any other
1861 * fragments present. Some networking interfaces appear
1862 * to do reassembly even when you're capturing raw packets
1863 * *and* show the reassembled packet without the "More
1864 * Fragments" indicator set *but* with a non-zero fragment
1867 * "fragment_add_seq_check()" handles that; we want to call it
1868 * even if we have a short frame, so that it does those checks - if
1869 * the frame is short, it doesn't do reassembly on it.
1871 * (This could get some false positives if we really *did* only
1872 * capture the last fragment of a fragmented packet, but that's
1875 save_fragmented = pinfo->fragmented;
1876 if (wlan_defragment && (more_frags || frag_number != 0)) {
1877 fragment_data *fd_head;
1880 * If we've already seen this frame, look it up in the
1881 * table of reassembled packets, otherwise add it to
1882 * whatever reassembly is in progress, if any, and see
1885 fd_head = fragment_add_seq_check(next_tvb, hdr_len, pinfo, seq_number,
1886 wlan_fragment_table,
1887 wlan_reassembled_table,
1891 next_tvb = process_reassembled_data(tvb, hdr_len, pinfo,
1892 "Reassembled 802.11", fd_head,
1893 &frag_items, NULL, hdr_tree);
1896 * If this is the first fragment, dissect its contents, otherwise
1897 * just show it as a fragment.
1899 if (frag_number != 0) {
1900 /* Not the first fragment - don't dissect it. */
1903 /* First fragment, or not fragmented. Dissect what we have here. */
1905 /* Get a tvbuff for the payload. */
1906 next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1909 * If this is the first fragment, but not the only fragment,
1910 * tell the next protocol that.
1913 pinfo->fragmented = TRUE;
1915 pinfo->fragmented = FALSE;
1919 if (next_tvb == NULL) {
1920 /* Just show this as an incomplete fragment. */
1921 if (check_col(pinfo->cinfo, COL_INFO))
1922 col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
1923 next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
1924 call_dissector(data_handle, next_tvb, pinfo, tree);
1925 pinfo->fragmented = save_fragmented;
1929 switch (COOK_FRAME_TYPE (fcf))
1933 dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1938 /* I guess some bridges take Netware Ethernet_802_3 frames,
1939 which are 802.3 frames (with a length field rather than
1940 a type field, but with no 802.2 header in the payload),
1941 and just stick the payload into an 802.11 frame. I've seen
1942 captures that show frames of that sort.
1944 This means we have to do the same check for Netware 802.3 -
1945 or, if you will, "Netware 802.11" - that we do in the
1946 Ethernet dissector, i.e. checking for 0xffff as the first
1947 four bytes of the payload and, if we find it, treating it
1951 if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1954 CATCH2(BoundsError, ReportedBoundsError) {
1961 call_dissector(llc_handle, next_tvb, pinfo, tree);
1963 call_dissector(ipx_handle, next_tvb, pinfo, tree);
1966 pinfo->fragmented = save_fragmented;
1970 * Dissect 802.11 with a variable-length link-layer header.
1973 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1975 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE, FALSE);
1979 * Dissect 802.11 with a variable-length link-layer header and a pseudo-
1980 * header containing radio information.
1983 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1985 /* These packets do NOT have a FCS present */
1986 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE, TRUE, FALSE);
1990 * Dissect 802.11 with a variable-length link-layer header and a byte-swapped
1991 * control field (some hardware sends out LWAPP-encapsulated 802.11
1992 * packets with the control field byte swapped).
1995 dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1997 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE, TRUE);
2001 * Dissect 802.11 with a fixed-length link-layer header (padded to the
2005 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2007 dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE, FALSE);
2011 wlan_defragment_init(void)
2013 fragment_table_init(&wlan_fragment_table);
2014 reassembled_table_init(&wlan_reassembled_table);
2018 proto_register_ieee80211 (void)
2020 static const value_string frame_type[] = {
2021 {MGT_FRAME, "Management frame"},
2022 {CONTROL_FRAME, "Control frame"},
2023 {DATA_FRAME, "Data frame"},
2027 static const value_string tofrom_ds[] = {
2028 {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
2029 {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"},
2030 {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"},
2031 {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"},
2035 static const true_false_string tods_flag = {
2036 "Frame is entering DS",
2037 "Frame is not entering DS"
2040 static const true_false_string fromds_flag = {
2041 "Frame is exiting DS",
2042 "Frame is not exiting DS"
2045 static const true_false_string more_frags = {
2046 "More fragments follow",
2047 "This is the last fragment"
2050 static const true_false_string retry_flags = {
2051 "Frame is being retransmitted",
2052 "Frame is not being retransmitted"
2055 static const true_false_string pm_flags = {
2056 "STA will go to sleep",
2060 static const true_false_string md_flags = {
2061 "Data is buffered for STA at AP",
2065 static const true_false_string wep_flags = {
2070 static const true_false_string order_flags = {
2072 "Not strictly ordered"
2075 static const true_false_string cf_ess_flags = {
2076 "Transmitter is an AP",
2077 "Transmitter is a STA"
2081 static const true_false_string cf_privacy_flags = {
2082 "AP/STA can support WEP",
2083 "AP/STA cannot support WEP"
2086 static const true_false_string cf_preamble_flags = {
2087 "Short preamble allowed",
2088 "Short preamble not allowed"
2091 static const true_false_string cf_pbcc_flags = {
2092 "PBCC modulation allowed",
2093 "PBCC modulation not allowed"
2096 static const true_false_string cf_agility_flags = {
2097 "Channel agility in use",
2098 "Channel agility not in use"
2101 static const true_false_string short_slot_time_flags = {
2102 "Short slot time in use",
2103 "Short slot time not in use"
2106 static const true_false_string dsss_ofdm_flags = {
2107 "DSSS-OFDM modulation allowed",
2108 "DSSS-OFDM modulation not allowed"
2112 static const true_false_string cf_ibss_flags = {
2113 "Transmitter belongs to an IBSS",
2114 "Transmitter belongs to a BSS"
2117 static const value_string sta_cf_pollable[] = {
2118 {0x00, "Station is not CF-Pollable"},
2119 {0x02, "Station is CF-Pollable, "
2120 "not requesting to be placed on the CF-polling list"},
2121 {0x01, "Station is CF-Pollable, "
2122 "requesting to be placed on the CF-polling list"},
2123 {0x03, "Station is CF-Pollable, requesting never to be polled"},
2127 static const value_string ap_cf_pollable[] = {
2128 {0x00, "No point coordinator at AP"},
2129 {0x02, "Point coordinator at AP for delivery only (no polling)"},
2130 {0x01, "Point coordinator at AP for delivery and polling"},
2136 static const value_string auth_alg[] = {
2137 {0x00, "Open System"},
2138 {0x01, "Shared key"},
2142 static const value_string reason_codes[] = {
2144 {0x01, "Unspecified reason"},
2145 {0x02, "Previous authentication no longer valid"},
2146 {0x03, "Deauthenticated because sending STA is leaving (has left) "
2148 {0x04, "Disassociated due to inactivity"},
2149 {0x05, "Disassociated because AP is unable to handle all currently "
2150 "associated stations"},
2151 {0x06, "Class 2 frame received from nonauthenticated station"},
2152 {0x07, "Class 3 frame received from nonassociated station"},
2153 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
2154 {0x09, "Station requesting (re)association is not authenticated with "
2155 "responding station"},
2160 static const value_string status_codes[] = {
2161 {0x00, "Successful"},
2162 {0x01, "Unspecified failure"},
2163 {0x0A, "Cannot support all requested capabilities in the "
2164 "Capability information field"},
2165 {0x0B, "Reassociation denied due to inability to confirm that "
2166 "association exists"},
2167 {0x0C, "Association denied due to reason outside the scope of this "
2170 {0x0D, "Responding station does not support the specified authentication "
2172 {0x0E, "Received an Authentication frame with authentication sequence "
2173 "transaction sequence number out of expected sequence"},
2174 {0x0F, "Authentication rejected because of challenge failure"},
2175 {0x10, "Authentication rejected due to timeout waiting for next "
2176 "frame in sequence"},
2177 {0x11, "Association denied because AP is unable to handle additional "
2178 "associated stations"},
2179 {0x12, "Association denied due to requesting station not supporting all "
2180 "of the datarates in the BSSBasicServiceSet Parameter"},
2181 {0x13, "Association denied due to requesting station not supporting "
2182 "short preamble operation"},
2183 {0x14, "Association denied due to requesting station not supporting "
2185 {0x15, "Association denied due to requesting station not supporting "
2187 {0x19, "Association denied due to requesting station not supporting "
2188 "short slot operation"},
2189 {0x1A, "Association denied due to requesting station not supporting "
2190 "DSSS-OFDM operation"},
2194 static hf_register_info hf[] = {
2196 {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2197 "Data rate (.5 Mb/s units)", HFILL }},
2200 {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2201 "Radio channel", HFILL }},
2203 {&hf_signal_strength,
2204 {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2205 "Signal strength (percentage)", HFILL }},
2208 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2209 "MAC Frame control", HFILL }},
2211 {&hf_fc_proto_version,
2212 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2213 "MAC Protocol version", HFILL }}, /* 0 */
2216 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2217 "Frame type", HFILL }},
2219 {&hf_fc_frame_subtype,
2220 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2221 "Frame subtype", HFILL }}, /* 2 */
2223 {&hf_fc_frame_type_subtype,
2224 {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2225 "Type and subtype combined", HFILL }},
2228 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2229 "Protocol flags", HFILL }},
2232 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2233 "Data-frame DS-traversal status", HFILL }}, /* 3 */
2236 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2237 "To DS flag", HFILL }}, /* 4 */
2240 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2241 "From DS flag", HFILL }}, /* 5 */
2244 {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2245 "More Fragments flag", HFILL }}, /* 6 */
2248 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2249 "Retransmission flag", HFILL }},
2252 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2253 "Power management status", HFILL }},
2256 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2257 "More data flag", HFILL }},
2260 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2261 "WEP flag", HFILL }},
2264 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2265 "Strictly ordered flag", HFILL }},
2268 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2269 "Association-ID field", HFILL }},
2272 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2273 "Duration field", HFILL }},
2276 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2277 "Destination Hardware Address", HFILL }},
2280 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2281 "Source Hardware Address", HFILL }},
2284 {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2285 "Source or Destination Hardware Address", HFILL }},
2288 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2289 "Receiving Station Hardware Address", HFILL }},
2292 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2293 "Transmitting Station Hardware Address", HFILL }},
2296 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2297 "Basic Service Set ID", HFILL }},
2300 {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2301 "Fragment number", HFILL }},
2304 {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2305 "Sequence number", HFILL }},
2308 {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
2309 NULL, 0, "FCS", HFILL }},
2311 {&hf_fragment_overlap,
2312 {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2313 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2315 {&hf_fragment_overlap_conflict,
2316 {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2317 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2318 "Overlapping fragments contained conflicting data", HFILL }},
2320 {&hf_fragment_multiple_tails,
2321 {"Multiple tail fragments found", "wlan.fragment.multipletails",
2322 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2323 "Several tails were found when defragmenting the packet", HFILL }},
2325 {&hf_fragment_too_long_fragment,
2326 {"Fragment too long", "wlan.fragment.toolongfragment",
2327 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2328 "Fragment contained data past end of packet", HFILL }},
2330 {&hf_fragment_error,
2331 {"Defragmentation error", "wlan.fragment.error",
2332 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2333 "Defragmentation error due to illegal fragments", HFILL }},
2336 {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2337 "802.11 Fragment", HFILL }},
2340 {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2341 "802.11 Fragments", HFILL }},
2343 {&hf_reassembled_in,
2344 {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2345 "This 802.11 packet is reassembled in this frame", HFILL }},
2348 {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2349 "Initialization Vector", HFILL }},
2352 {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
2356 {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
2357 "WEP ICV", HFILL }},
2360 static hf_register_info ff[] = {
2362 {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
2363 NULL, 0, "", HFILL }},
2366 {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
2367 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
2369 {&ff_beacon_interval,
2370 {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
2373 {&hf_fixed_parameters,
2374 {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
2377 {&hf_tagged_parameters,
2378 {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
2382 {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
2383 "Capability information", HFILL }},
2386 {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
2387 FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
2390 {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
2391 FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
2394 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
2395 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C,
2396 "CF-Poll capabilities for a STA", HFILL }},
2399 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
2400 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C,
2401 "CF-Poll capabilities for an AP", HFILL }},
2404 {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
2405 FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
2408 {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
2409 FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
2412 {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
2413 FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
2416 {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
2417 FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
2419 {&ff_short_slot_time,
2420 {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
2421 FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
2425 {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
2426 FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
2430 {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
2431 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
2434 {"Association ID", "wlan_mgt.fixed.aid",
2435 FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
2438 {"Listen Interval", "wlan_mgt.fixed.listen_ival",
2439 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
2442 {"Current AP", "wlan_mgt.fixed.current_ap",
2443 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
2446 {"Reason code", "wlan_mgt.fixed.reason_code",
2447 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
2448 "Reason for unsolicited notification", HFILL }},
2451 {"Status code", "wlan_mgt.fixed.status_code",
2452 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
2453 "Status of requested event", HFILL }},
2456 {"Tag", "wlan_mgt.tag.number",
2457 FT_UINT8, BASE_DEC, VALS(tag_num_vals), 0,
2458 "Element ID", HFILL }},
2461 {"Tag length", "wlan_mgt.tag.length",
2462 FT_UINT8, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
2464 {&tag_interpretation,
2465 {"Tag interpretation", "wlan_mgt.tag.interpretation",
2466 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
2470 static gint *tree_array[] = {
2477 &ett_fixed_parameters,
2478 &ett_tagged_parameters,
2479 &ett_wep_parameters,
2482 module_t *wlan_module;
2484 static const enum_val_t wep_keys_options[] = {
2494 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
2495 "IEEE 802.11", "wlan");
2496 proto_register_field_array (proto_wlan, hf, array_length (hf));
2497 proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
2498 "802.11 MGT", "wlan_mgt");
2499 proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
2500 proto_register_subtree_array (tree_array, array_length (tree_array));
2502 register_dissector("wlan", dissect_ieee80211, proto_wlan);
2503 register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
2504 register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
2505 register_init_routine(wlan_defragment_init);
2507 /* Register configuration options */
2508 wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);
2509 prefs_register_bool_preference(wlan_module, "defragment",
2510 "Reassemble fragmented 802.11 datagrams",
2511 "Whether fragmented 802.11 datagrams should be reassembled",
2514 prefs_register_bool_preference(wlan_module, "check_fcs",
2515 "Assume packets have FCS",
2516 "Some 802.11 cards include the FCS at the end of a packet, others do not.",
2519 prefs_register_bool_preference(wlan_module, "ignore_wep",
2520 "Ignore the WEP bit",
2521 "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
2525 prefs_register_enum_preference(wlan_module, "wep_keys",
2527 "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
2528 &num_wepkeys, wep_keys_options, FALSE);
2530 prefs_register_string_preference(wlan_module, "wep_key1",
2532 "First WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
2534 prefs_register_string_preference(wlan_module, "wep_key2",
2536 "Second WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
2538 prefs_register_string_preference(wlan_module, "wep_key3",
2540 "Third WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
2542 prefs_register_string_preference(wlan_module, "wep_key4",
2544 "Fourth WEP key (A:B:C:D:E) [40bit] (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
2550 proto_reg_handoff_ieee80211(void)
2552 dissector_handle_t ieee80211_handle;
2553 dissector_handle_t ieee80211_radio_handle;
2556 * Get handles for the LLC and IPX dissectors.
2558 llc_handle = find_dissector("llc");
2559 ipx_handle = find_dissector("ipx");
2560 data_handle = find_dissector("data");
2562 ieee80211_handle = find_dissector("wlan");
2563 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
2564 ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
2566 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
2567 ieee80211_radio_handle);
2570 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
2573 tvbuff_t *decr_tvb = NULL;
2575 if (num_wepkeys < 1)
2578 if ((tmp = g_malloc(len)) == NULL)
2579 return NULL; /* krap! */
2581 /* try once with the key index in the packet, then look through our list. */
2582 for (i = -1; i < (int) num_wepkeys; i++) {
2583 /* copy the encrypted data over to the tmp buffer */
2585 printf("trying %d\n", i);
2587 tvb_memcpy(tvb, tmp, offset, len);
2588 if (wep_decrypt(tmp, len, i) == 0) {
2590 /* decrypt successful, let's set up a new data tvb. */
2591 decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
2592 tvb_set_free_cb(decr_tvb, g_free);
2593 tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2600 if ((!decr_tvb) && (tmp)) g_free(tmp);
2603 printf("de-wep %p\n", decr_tvb);
2610 /* de-weps the block. if successful, buf* will point to the data start. */
2611 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
2612 guint32 i, j, k, crc, keylen;
2613 guint8 s[256], key[128], c_crc[4];
2614 guint8 keyidx, *dpos, *cpos;
2616 /* Needs to be at least 8 bytes of payload */
2620 /* initialize the first bytes of the key from the IV */
2624 keyidx = COOK_WEP_KEY(buf[3]);
2626 if (key_override >= 0)
2627 keyidx = key_override;
2629 if (keyidx >= num_wepkeys)
2632 keylen = wep_keylens[keyidx];
2636 if (wep_keys[keyidx] == NULL)
2639 keylen+=3; /* add in ICV bytes */
2641 /* copy the rest of the key over from the designated key */
2642 memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
2645 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]);
2648 /* set up the RC4 state */
2649 for (i = 0; i < 256; i++)
2652 for (i = 0; i < 256; i++) {
2653 j = (j + s[i] + key[i % keylen]) & 0xff;
2657 /* Apply the RC4 to the data, update the CRC32 */
2662 for (k = 0; k < (len -8); k++) {
2664 j = (j+s[i]) & 0xff;
2667 printf("%d -- %02x ", k, *dpos);
2669 *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
2671 printf("%02x\n", *dpos);
2673 crc = crc32_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
2677 /* now let's check the crc */
2679 c_crc[1] = crc >> 8;
2680 c_crc[2] = crc >> 16;
2681 c_crc[3] = crc >> 24;
2683 for (k = 0; k < 4; k++) {
2685 j = (j+s[i]) & 0xff;
2688 printf("-- %02x %02x\n", *dpos, c_crc[k]);
2690 if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
2691 return -1; /* ICV mismatch */
2697 static void init_wepkeys(void) {
2705 tmp = getenv("ETHEREAL_WEPKEYNUM");
2710 num_wepkeys = atoi(tmp);
2712 if (num_wepkeys > 4)
2716 if (num_wepkeys < 1)
2723 g_free(wep_keylens);
2725 wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
2726 wep_keylens = g_malloc(num_wepkeys * sizeof(int));
2728 for (i = 0 ; i < num_wepkeys; i++) {
2733 sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
2736 tmp = wep_keystr[i];
2743 printf("%s -- %s\n", buf, tmp);
2745 printf("%d -- %s\n", i+1, tmp);
2750 g_free(wep_keys[i]);
2751 wep_keys[i] = g_malloc(32 * sizeof(guint8));
2752 memset(wep_keys[i], 0, 32 * sizeof(guint8));
2754 while ((tmp != NULL) && (*tmp != 0)) {
2755 tmp3[j] = strtoul(tmp, &tmp2, 16) & 0xff;
2757 printf("%d %d -- %02x\n", i, j, tmp3[j]);
2762 if ((tmp != NULL) && (*tmp == ':'))