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
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
42 * 03/22/2004 - Added dissection of RSN IE
43 * Jouni Malinen <jkmaline@cc.hut.fi>
53 #ifdef NEED_SNPRINTF_H
54 # include "snprintf.h"
59 #include <epan/bitswap.h>
60 #include <epan/proto.h>
61 #include <epan/packet.h>
62 #include <epan/resolv.h>
63 #include <epan/strutil.h>
65 #include "reassemble.h"
66 #include "packet-ipx.h"
67 #include "packet-llc.h"
68 #include "packet-ieee80211.h"
72 /* Defragment fragmented 802.11 datagrams */
73 static gboolean wlan_defragment = TRUE;
75 /* Check for the presence of the 802.11 FCS */
76 static gboolean wlan_check_fcs = FALSE;
78 /* Ignore the WEP bit; assume packet is decrypted */
79 static gboolean wlan_ignore_wep = FALSE;
81 /* Tables for reassembly of fragments. */
82 static GHashTable *wlan_fragment_table = NULL;
83 static GHashTable *wlan_reassembled_table = NULL;
85 /* Stuff for the WEP decoder */
86 static guint num_wepkeys = 0;
87 static guint8 **wep_keys = NULL;
88 static int *wep_keylens = NULL;
89 static void init_wepkeys(void);
90 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
91 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
92 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
95 /* When this is set, an unlimited number of WEP keys can be set in the
99 ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
100 ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
102 ... you get the idea.
104 otherwise you're limited to specifying four keys in the preference system.
108 static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
111 /* ************************************************************************* */
112 /* Miscellaneous Constants */
113 /* ************************************************************************* */
114 #define SHORT_STR 256
116 /* ************************************************************************* */
117 /* Define some very useful macros that are used to analyze frame types etc. */
118 /* ************************************************************************* */
119 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */
120 #define COOK_PROT_VERSION(x) ((x) & 0x3)
121 #define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2)
122 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
123 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
124 #define COOK_ASSOC_ID(x) ((x) & 0x3FFF)
125 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
126 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
127 #define COOK_QOS_PRIORITY(x) ((x) & 0x0007)
128 #define COOK_QOS_ACK_POLICY(x) (((x) & 0x0060) >> 5)
129 #define COOK_FLAGS(x) (((x) & 0xFF00) >> 8)
130 #define COOK_DS_STATUS(x) ((x) & 0x3)
131 #define COOK_WEP_KEY(x) (((x) & 0xC0) >> 6)
133 #define KEY_EXTIV 0x20
136 #define FLAG_TO_DS 0x01
137 #define FLAG_FROM_DS 0x02
138 #define FLAG_MORE_FRAGMENTS 0x04
139 #define FLAG_RETRY 0x08
140 #define FLAG_POWER_MGT 0x10
141 #define FLAG_MORE_DATA 0x20
142 #define FLAG_WEP 0x40
143 #define FLAG_ORDER 0x80
145 #define IS_TO_DS(x) ((x) & FLAG_TO_DS)
146 #define IS_FROM_DS(x) ((x) & FLAG_FROM_DS)
147 #define HAVE_FRAGMENTS(x) ((x) & FLAG_MORE_FRAGMENTS)
148 #define IS_RETRY(x) ((x) & FLAG_RETRY)
149 #define POWER_MGT_STATUS(x) ((x) & FLAG_POWER_MGT)
150 #define HAS_MORE_DATA(x) ((x) & FLAG_MORE_DATA)
151 #define IS_WEP(x) (!wlan_ignore_wep && ((x) & FLAG_WEP))
152 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
154 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
155 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
156 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
157 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
160 /* ************************************************************************* */
161 /* Constants used to identify cooked frame types */
162 /* ************************************************************************* */
163 #define MGT_FRAME 0x00 /* Frame type is management */
164 #define CONTROL_FRAME 0x01 /* Frame type is control */
165 #define DATA_FRAME 0x02 /* Frame type is Data */
167 #define DATA_SHORT_HDR_LEN 24
168 #define DATA_LONG_HDR_LEN 30
169 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
171 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
172 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
173 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
174 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
175 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
176 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
177 #define MGT_BEACON 0x08 /* Management - Beacon frame */
178 #define MGT_ATIM 0x09 /* Management - ATIM */
179 #define MGT_DISASS 0x0A /* Management - Disassociation */
180 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
181 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
182 #define MGT_ACTION 0x0D /* Management - Action */
184 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
185 #define CTRL_RTS 0x1B /* Control - request to send */
186 #define CTRL_CTS 0x1C /* Control - clear to send */
187 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
188 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
189 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
191 #define DATA 0x20 /* Data - Data */
192 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
193 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
194 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
195 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
196 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
197 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
198 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
199 #define DATA_QOS_DATA 0x28 /* Data - QoS Data */
200 #define DATA_QOS_NULL 0x2c /* Data - QoS Null */
202 #define DATA_ADDR_T1 0
203 #define DATA_ADDR_T2 (FLAG_FROM_DS << 8)
204 #define DATA_ADDR_T3 (FLAG_TO_DS << 8)
205 #define DATA_ADDR_T4 ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
208 /* ************************************************************************* */
209 /* Macros used to extract information about fixed fields */
210 /* ************************************************************************* */
211 #define ESS_SET(x) ((x) & 0x0001)
212 #define IBSS_SET(x) ((x) & 0x0002)
216 /* ************************************************************************* */
217 /* Logical field codes (dissector's encoding of fixed fields) */
218 /* ************************************************************************* */
219 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
220 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
221 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
222 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
223 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
224 #define FIELD_CURRENT_AP_ADDR 0x06
225 #define FIELD_LISTEN_IVAL 0x07
226 #define FIELD_REASON_CODE 0x08
227 #define FIELD_ASSOC_ID 0x09
228 #define FIELD_STATUS_CODE 0x0A
229 #define FIELD_CATEGORY_CODE 0x0B /* Management action category */
230 #define FIELD_ACTION_CODE 0x0C /* Management action code */
231 #define FIELD_DIALOG_TOKEN 0x0D /* Management action dialog token */
232 #define FIELD_WME_ACTION_CODE 0x0E /* Management notification action code */
233 #define FIELD_WME_DIALOG_TOKEN 0x0F /* Management notification dialog token */
234 #define FIELD_WME_STATUS_CODE 0x10 /* Management notification setup response status code */
236 /* ************************************************************************* */
237 /* Logical field codes (IEEE 802.11 encoding of tags) */
238 /* ************************************************************************* */
239 #define TAG_SSID 0x00
240 #define TAG_SUPP_RATES 0x01
241 #define TAG_FH_PARAMETER 0x02
242 #define TAG_DS_PARAMETER 0x03
243 #define TAG_CF_PARAMETER 0x04
245 #define TAG_IBSS_PARAMETER 0x06
246 #define TAG_COUNTRY_INFO 0x07
247 #define TAG_FH_HOPPING_PARAMETER 0x08
248 #define TAG_FH_HOPPING_TABLE 0x09
249 #define TAG_CHALLENGE_TEXT 0x10
250 #define TAG_ERP_INFO 0x2A
251 #define TAG_ERP_INFO_OLD 0x2F /* IEEE Std 802.11g/D4.0 */
252 #define TAG_RSN_IE 0x30
253 #define TAG_EXT_SUPP_RATES 0x32
254 #define TAG_VENDOR_SPECIFIC_IE 0xDD
256 #define WPA_OUI "\x00\x50\xF2"
257 #define RSN_OUI "\x00\x0F\xAC"
258 #define WME_OUI "\x00\x50\xF2"
262 /* ************************************************************************* */
263 /* Frame types, and their names */
264 /* ************************************************************************* */
265 static const value_string frame_type_subtype_vals[] = {
266 {MGT_ASSOC_REQ, "Association Request"},
267 {MGT_ASSOC_RESP, "Association Response"},
268 {MGT_REASSOC_REQ, "Reassociation Request"},
269 {MGT_REASSOC_RESP, "Reassociation Response"},
270 {MGT_PROBE_REQ, "Probe Request"},
271 {MGT_PROBE_RESP, "Probe Response"},
272 {MGT_BEACON, "Beacon frame"},
274 {MGT_DISASS, "Dissassociate"},
275 {MGT_AUTHENTICATION, "Authentication"},
276 {MGT_DEAUTHENTICATION, "Deauthentication"},
277 {MGT_ACTION, "Action"},
278 {CTRL_PS_POLL, "Power-Save poll"},
279 {CTRL_RTS, "Request-to-send"},
280 {CTRL_CTS, "Clear-to-send"},
281 {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
282 {CTRL_CFP_END, "CF-End (Control-frame)"},
283 {CTRL_CFP_ENDACK, "CF-End + CF-Ack (Control-frame)"},
285 {DATA_CF_ACK, "Data + CF-Acknowledgement"},
286 {DATA_CF_POLL, "Data + CF-Poll"},
287 {DATA_CF_ACK_POLL, "Data + CF-Acknowledgement/Poll"},
288 {DATA_NULL_FUNCTION, "Null function (No data)"},
289 {DATA_CF_ACK_NOD, "Data + Acknowledgement (No data)"},
290 {DATA_CF_POLL_NOD, "Data + CF-Poll (No data)"},
291 {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
292 {DATA_QOS_DATA, "QoS Data"},
293 {DATA_QOS_NULL, "QoS Null (No data)"},
297 /* ************************************************************************* */
298 /* 802.1D Tag Names */
299 /* ************************************************************************* */
300 static const char *qos_tags[8] = {
311 /* ************************************************************************* */
312 /* WME Access Category Names (by 802.1D Tag) */
313 /* ************************************************************************* */
314 static const char *qos_acs[8] = {
325 /* ************************************************************************* */
326 /* WME Access Category Names (by WME ACI) */
327 /* ************************************************************************* */
328 static const char *wme_acs[4] = {
335 static int proto_wlan = -1;
337 /* ************************************************************************* */
338 /* Header field info values for radio information */
339 /* ************************************************************************* */
340 static int hf_data_rate = -1;
341 static int hf_channel = -1;
342 static int hf_signal_strength = -1;
344 /* ************************************************************************* */
345 /* Header field info values for FC-field */
346 /* ************************************************************************* */
347 static int hf_fc_field = -1;
348 static int hf_fc_proto_version = -1;
349 static int hf_fc_frame_type = -1;
350 static int hf_fc_frame_subtype = -1;
351 static int hf_fc_frame_type_subtype = -1;
353 static int hf_fc_flags = -1;
354 static int hf_fc_to_ds = -1;
355 static int hf_fc_from_ds = -1;
356 static int hf_fc_data_ds = -1;
358 static int hf_fc_more_frag = -1;
359 static int hf_fc_retry = -1;
360 static int hf_fc_pwr_mgt = -1;
361 static int hf_fc_more_data = -1;
362 static int hf_fc_wep = -1;
363 static int hf_fc_order = -1;
366 /* ************************************************************************* */
367 /* Header values for Duration/ID field */
368 /* ************************************************************************* */
369 static int hf_did_duration = -1;
370 static int hf_assoc_id = -1;
373 /* ************************************************************************* */
374 /* Header values for different address-fields (all 4 of them) */
375 /* ************************************************************************* */
376 static int hf_addr_da = -1; /* Destination address subfield */
377 static int hf_addr_sa = -1; /* Source address subfield */
378 static int hf_addr_ra = -1; /* Receiver address subfield */
379 static int hf_addr_ta = -1; /* Transmitter address subfield */
380 static int hf_addr_bssid = -1; /* address is bssid */
382 static int hf_addr = -1; /* Source or destination address subfield */
385 /* ************************************************************************* */
386 /* Header values for QoS control field */
387 /* ************************************************************************* */
388 static int hf_qos_priority = -1;
389 static int hf_qos_ack_policy = -1;
391 /* ************************************************************************* */
392 /* Header values for sequence number field */
393 /* ************************************************************************* */
394 static int hf_frag_number = -1;
395 static int hf_seq_number = -1;
397 /* ************************************************************************* */
398 /* Header values for Frame Check field */
399 /* ************************************************************************* */
400 static int hf_fcs = -1;
402 /* ************************************************************************* */
403 /* Header values for reassembly */
404 /* ************************************************************************* */
405 static int hf_fragments = -1;
406 static int hf_fragment = -1;
407 static int hf_fragment_overlap = -1;
408 static int hf_fragment_overlap_conflict = -1;
409 static int hf_fragment_multiple_tails = -1;
410 static int hf_fragment_too_long_fragment = -1;
411 static int hf_fragment_error = -1;
412 static int hf_reassembled_in = -1;
415 static int proto_wlan_mgt = -1;
416 /* ************************************************************************* */
417 /* Fixed fields found in mgt frames */
418 /* ************************************************************************* */
419 static int ff_auth_alg = -1; /* Authentication algorithm field */
420 static int ff_auth_seq = -1; /* Authentication transaction sequence */
421 static int ff_current_ap = -1; /* Current AP MAC address */
422 static int ff_listen_ival = -1; /* Listen interval fixed field */
423 static int ff_timestamp = -1; /* 64 bit timestamp */
424 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
425 static int ff_assoc_id = -1; /* 16 bit AID field */
426 static int ff_reason = -1; /* 16 bit reason code */
427 static int ff_status_code = -1; /* Status code */
428 static int ff_category_code = -1; /* 8 bit Category code */
429 static int ff_action_code = -1; /* 8 bit Action code */
430 static int ff_dialog_token = -1; /* 8 bit Dialog token */
431 static int ff_wme_action_code = -1; /* Management notification action code */
432 static int ff_wme_status_code = -1; /* Management notification setup response status code */
434 /* ************************************************************************* */
435 /* Flags found in the capability field (fixed field) */
436 /* ************************************************************************* */
437 static int ff_capture = -1;
438 static int ff_cf_ess = -1;
439 static int ff_cf_ibss = -1;
440 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
441 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
442 static int ff_cf_privacy = -1;
443 static int ff_cf_preamble = -1;
444 static int ff_cf_pbcc = -1;
445 static int ff_cf_agility = -1;
446 static int ff_short_slot_time = -1;
447 static int ff_dsss_ofdm = -1;
449 /* ************************************************************************* */
450 /* Tagged value format fields */
451 /* ************************************************************************* */
452 static int tag_number = -1;
453 static int tag_length = -1;
454 static int tag_interpretation = -1;
458 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
459 static int hf_tagged_parameters = -1; /* Fixed payload item */
460 static int hf_wep_iv = -1;
461 static int hf_tkip_extiv = -1;
462 static int hf_ccmp_extiv = -1;
463 static int hf_wep_key = -1;
464 static int hf_wep_icv = -1;
467 static int rsn_cap = -1;
468 static int rsn_cap_preauth = -1;
469 static int rsn_cap_no_pairwise = -1;
470 static int rsn_cap_ptksa_replay_counter = -1;
471 static int rsn_cap_gtksa_replay_counter = -1;
473 /* ************************************************************************* */
475 /* ************************************************************************* */
476 static gint ett_80211 = -1;
477 static gint ett_proto_flags = -1;
478 static gint ett_cap_tree = -1;
479 static gint ett_fc_tree = -1;
480 static gint ett_fragments = -1;
481 static gint ett_fragment = -1;
483 static gint ett_80211_mgt = -1;
484 static gint ett_fixed_parameters = -1;
485 static gint ett_tagged_parameters = -1;
486 static gint ett_qos_parameters = -1;
487 static gint ett_wep_parameters = -1;
489 static gint ett_rsn_cap_tree = -1;
491 static const fragment_items frag_items = {
496 &hf_fragment_overlap,
497 &hf_fragment_overlap_conflict,
498 &hf_fragment_multiple_tails,
499 &hf_fragment_too_long_fragment,
505 static dissector_handle_t llc_handle;
506 static dissector_handle_t ipx_handle;
507 static dissector_handle_t eth_handle;
508 static dissector_handle_t data_handle;
510 /* ************************************************************************* */
511 /* Return the length of the current header (in bytes) */
512 /* ************************************************************************* */
514 find_header_length (guint16 fcf)
518 switch (COOK_FRAME_TYPE (fcf)) {
521 return MGT_FRAME_HDR_LEN;
524 switch (COMPOSE_FRAME_TYPE (fcf)) {
527 case CTRL_ACKNOWLEDGEMENT:
533 case CTRL_CFP_ENDACK:
539 len = (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
541 switch (COMPOSE_FRAME_TYPE (fcf)) {
556 /* ************************************************************************* */
557 /* This is the capture function used to update packet counts */
558 /* ************************************************************************* */
560 capture_ieee80211_common (const guchar * pd, int offset, int len,
561 packet_counts * ld, gboolean fixed_length_header)
563 guint16 fcf, hdr_length;
565 if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
570 fcf = pletohs (&pd[0]);
572 if (IS_WEP(COOK_FLAGS(fcf)))
578 switch (COMPOSE_FRAME_TYPE (fcf))
581 case DATA: /* We got a data frame */
582 case DATA_CF_ACK: /* Data with ACK */
584 case DATA_CF_ACK_POLL:
586 if (fixed_length_header)
587 hdr_length = DATA_LONG_HDR_LEN;
589 hdr_length = find_header_length (fcf);
590 /* I guess some bridges take Netware Ethernet_802_3 frames,
591 which are 802.3 frames (with a length field rather than
592 a type field, but with no 802.2 header in the payload),
593 and just stick the payload into an 802.11 frame. I've seen
594 captures that show frames of that sort.
596 This means we have to do the same check for Netware 802.3 -
597 or, if you will, "Netware 802.11" - that we do in the
598 Ethernet dissector, i.e. checking for 0xffff as the first
599 four bytes of the payload and, if we find it, treating it
601 if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
605 if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
609 capture_llc (pd, offset + hdr_length, len, ld);
620 * Handle 802.11 with a variable-length link-layer header.
623 capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
625 capture_ieee80211_common (pd, offset, len, ld, FALSE);
629 * Handle 802.11 with a fixed-length link-layer header (padded to the
633 capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
635 capture_ieee80211_common (pd, offset, len, ld, TRUE);
639 /* ************************************************************************* */
640 /* Add the subtree used to store the fixed parameters */
641 /* ************************************************************************* */
643 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
645 proto_item *fixed_fields;
647 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
648 size, size, "Fixed parameters (%d bytes)",
651 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
655 /* ************************************************************************* */
656 /* Add the subtree used to store tagged parameters */
657 /* ************************************************************************* */
659 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
661 proto_item *tagged_fields;
663 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
668 "Tagged parameters (%d bytes)",
671 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
675 /* ************************************************************************* */
676 /* Dissect and add fixed mgmt fields to protocol tree */
677 /* ************************************************************************* */
679 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
681 const guint8 *dataptr;
682 char out_buff[SHORT_STR];
684 proto_item *cap_item;
685 static proto_tree *cap_tree;
690 case FIELD_TIMESTAMP:
691 dataptr = tvb_get_ptr (tvb, offset, 8);
692 memset (out_buff, 0, SHORT_STR);
693 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
703 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
706 case FIELD_BEACON_INTERVAL:
707 temp_double = (double) tvb_get_letohs (tvb, offset);
708 temp_double = temp_double * 1024 / 1000000;
709 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
710 temp_double,"Beacon Interval: %f [Seconds]",
716 capability = tvb_get_letohs (tvb, offset);
718 cap_item = proto_tree_add_uint_format (tree, ff_capture,
721 "Capability Information: 0x%04X",
723 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
724 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
726 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
728 if (ESS_SET (capability) != 0) /* This is an AP */
729 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
732 else /* This is a STA */
733 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
735 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
737 proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
739 proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
741 proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
743 proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
745 proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
750 proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
753 case FIELD_AUTH_TRANS_SEQ:
754 proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
757 case FIELD_CURRENT_AP_ADDR:
758 proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
761 case FIELD_LISTEN_IVAL:
762 proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
765 case FIELD_REASON_CODE:
766 proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
770 proto_tree_add_uint(tree, ff_assoc_id, tvb, offset, 2,
771 COOK_ASSOC_ID(tvb_get_letohs(tvb,offset)));
772 /* proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE); */
775 case FIELD_STATUS_CODE:
776 proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
779 case FIELD_CATEGORY_CODE:
780 proto_tree_add_item (tree, ff_category_code, tvb, offset, 1, TRUE);
783 case FIELD_ACTION_CODE:
784 proto_tree_add_item (tree, ff_action_code, tvb, offset, 1, TRUE);
787 case FIELD_DIALOG_TOKEN:
788 proto_tree_add_item (tree, ff_dialog_token, tvb, offset, 1, TRUE);
791 case FIELD_WME_ACTION_CODE:
792 proto_tree_add_item (tree, ff_wme_action_code, tvb, offset, 1, TRUE);
795 case FIELD_WME_STATUS_CODE:
796 proto_tree_add_item (tree, ff_wme_status_code, tvb, offset, 1, TRUE);
801 static char *wpa_cipher_str[] =
812 wpa_cipher_idx2str(guint idx)
814 if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
815 return wpa_cipher_str[idx];
819 static char *wpa_keymgmt_str[] =
827 wpa_keymgmt_idx2str(guint idx)
829 if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
830 return wpa_keymgmt_str[idx];
835 dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
836 guint32 tag_len, const guint8 *tag_val)
838 guint32 tag_val_off = 0;
839 char out_buff[SHORT_STR], *pos;
842 /* Wi-Fi Protected Access (WPA) Information Element */
843 if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
844 snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
845 tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
846 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
849 if (tag_val_off + 4 <= tag_len) {
850 /* multicast cipher suite */
851 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
852 snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
853 wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
854 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
857 /* unicast cipher suites */
858 if (tag_val_off + 2 <= tag_len) {
859 snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
860 pletohs(tag_val + tag_val_off));
861 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
865 while (tag_val_off + 4 <= tag_len) {
866 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
867 snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
868 i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
869 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
877 /* authenticated key management suites */
878 if (tag_val_off + 2 <= tag_len) {
879 snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
880 pletohs(tag_val + tag_val_off));
881 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
885 while (tag_val_off + 4 <= tag_len) {
886 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
887 snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
888 i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
889 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
901 if (tag_val_off < tag_len)
902 proto_tree_add_string(tree, tag_interpretation, tvb,
903 offset, tag_len - tag_val_off, "Not interpreted");
904 } else if (tag_val_off + 7 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x00", 5)) {
905 /* Wireless Multimedia Enhancements (WME) Information Element */
906 snprintf(out_buff, SHORT_STR, "WME IE: type %u, subtype %u, version %u, parameter set %u",
907 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
908 tag_val[tag_val_off + 6]);
909 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
910 } else if (tag_val_off + 24 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x01", 5)) {
911 /* Wireless Multimedia Enhancements (WME) Parameter Element */
912 snprintf(out_buff, SHORT_STR, "WME PE: type %u, subtype %u, version %u, parameter set %u",
913 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
914 tag_val[tag_val_off + 6]);
915 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
918 for (i = 0; i < 4; i++) {
919 snprintf(out_buff, SHORT_STR, "WME AC Parameters: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
920 (tag_val[tag_val_off] & 0x60) >> 5,
921 wme_acs[(tag_val[tag_val_off] & 0x60) >> 5],
922 (tag_val[tag_val_off] & 0x10) ? "" : "not ",
923 tag_val[tag_val_off] & 0x0f,
924 tag_val[tag_val_off + 1] & 0x0f,
925 (tag_val[tag_val_off + 1] & 0xf0) >> 4,
926 tvb_get_letohs(tvb, offset + 2));
927 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
931 } else if (tag_val_off + 56 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x02", 5)) {
932 /* Wireless Multimedia Enhancements (WME) TSPEC Element */
933 guint16 ts_info, msdu_size, surplus_bandwidth;
934 const char *direction[] = { "Uplink", "Downlink", "Reserved", "Bi-directional" };
935 const value_string fields[] = {
936 {12, "Minimum Service Interval"},
937 {16, "Maximum Service Interval"},
938 {20, "Inactivity Interval"},
939 {24, "Service Start Time"},
940 {28, "Minimum Data Rate"},
941 {32, "Mean Data Rate"},
942 {36, "Maximum Burst Size"},
943 {40, "Minimum PHY Rate"},
944 {44, "Peak Data Rate"},
950 snprintf(out_buff, SHORT_STR, "WME TSPEC: type %u, subtype %u, version %u",
951 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5]);
952 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
956 ts_info = tvb_get_letohs(tvb, offset);
957 snprintf(out_buff, SHORT_STR, "WME TS Info: Priority %u (%s) (%s), Contention-based access %sset, %s",
958 (ts_info >> 11) & 0x7, qos_tags[(ts_info >> 11) & 0x7], qos_acs[(ts_info >> 11) & 0x7],
959 (ts_info & 0x0080) ? "" : "not ",
960 direction[(ts_info >> 5) & 0x3]);
961 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
965 msdu_size = tvb_get_letohs(tvb, offset);
966 snprintf(out_buff, SHORT_STR, "WME TSPEC: %s MSDU Size %u",
967 (msdu_size & 0x8000) ? "Fixed" : "Nominal", msdu_size & 0x7fff);
968 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
972 snprintf(out_buff, SHORT_STR, "WME TSPEC: Maximum MSDU Size %u", tvb_get_letohs(tvb, offset));
973 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
977 while ((field = val_to_str(tag_val_off, fields, NULL))) {
978 snprintf(out_buff, SHORT_STR, "WME TSPEC: %s %u", field, tvb_get_letohl(tvb, offset));
979 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
982 if (tag_val_off == 52)
986 surplus_bandwidth = tvb_get_letohs(tvb, offset);
987 snprintf(out_buff, SHORT_STR, "WME TSPEC: Surplus Bandwidth Allowance Factor %u.%u",
988 (surplus_bandwidth >> 13) & 0x7, (surplus_bandwidth & 0x1fff));
992 snprintf(out_buff, SHORT_STR, "WME TSPEC: Medium Time %u", tvb_get_letohs(tvb, offset));
993 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
996 } else if (tag_val_off + 4 <= tag_len && !memcmp(tag_val, RSN_OUI"\x04", 4)) {
997 /* IEEE 802.11i / Key Data Encapsulation / Data Type=4 - PMKID.
998 * This is only used within EAPOL-Key frame Key Data. */
1000 pos += snprintf(pos, out_buff + SHORT_STR - pos, "RSN PMKID: ");
1001 if (tag_len - 4 != PMKID_LEN) {
1002 pos += snprintf(pos, out_buff + SHORT_STR - pos,
1003 "(invalid PMKID len=%d, expected 16) ", tag_len - 4);
1005 for (i = 0; i < tag_len - 4; i++) {
1006 pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
1007 tag_val[tag_val_off + 4 + i]);
1009 proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1012 proto_tree_add_string(tree, tag_interpretation,
1013 tvb, offset, tag_len, "Not interpreted");
1017 dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
1018 guint32 tag_len, const guint8 *tag_val)
1020 guint32 tag_val_off = 0;
1022 char out_buff[SHORT_STR];
1024 proto_item *cap_item;
1025 proto_tree *cap_tree;
1027 if (tag_val_off + 2 > tag_len) {
1028 proto_tree_add_string(tree, tag_interpretation, tvb, offset, tag_len,
1033 snprintf(out_buff, SHORT_STR, "RSN IE, version %u",
1034 pletohs(&tag_val[tag_val_off]));
1035 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1040 if (tag_val_off + 4 > tag_len)
1043 /* multicast cipher suite */
1044 if (!memcmp(&tag_val[tag_val_off], RSN_OUI, 3)) {
1045 snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
1046 wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1047 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1052 if (tag_val_off + 2 > tag_len)
1055 /* unicast cipher suites */
1056 count = pletohs(tag_val + tag_val_off);
1057 snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", count);
1058 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1062 while (tag_val_off + 4 <= tag_len && i <= count) {
1063 if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
1065 snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
1066 i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1067 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1073 if (i <= count || tag_val_off + 2 > tag_len)
1076 /* authenticated key management suites */
1077 count = pletohs(tag_val + tag_val_off);
1078 snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", count);
1079 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1083 while (tag_val_off + 4 <= tag_len && i <= count) {
1084 if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
1086 snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
1087 i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
1088 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1094 if (i <= count || tag_val_off + 2 > tag_len)
1097 rsn_capab = pletohs(&tag_val[tag_val_off]);
1098 snprintf(out_buff, SHORT_STR, "RSN Capabilities 0x%04x", rsn_capab);
1099 cap_item = proto_tree_add_uint_format(tree, rsn_cap, tvb,
1100 offset, 2, rsn_capab,
1101 "RSN Capabilities: 0x%04X", rsn_capab);
1102 cap_tree = proto_item_add_subtree(cap_item, ett_rsn_cap_tree);
1103 proto_tree_add_boolean(cap_tree, rsn_cap_preauth, tvb, offset, 2,
1105 proto_tree_add_boolean(cap_tree, rsn_cap_no_pairwise, tvb, offset, 2,
1107 proto_tree_add_uint(cap_tree, rsn_cap_ptksa_replay_counter, tvb, offset, 2,
1109 proto_tree_add_uint(cap_tree, rsn_cap_gtksa_replay_counter, tvb, offset, 2,
1114 if (tag_val_off + 2 > tag_len)
1117 count = pletohs(tag_val + tag_val_off);
1118 snprintf(out_buff, SHORT_STR, "# of PMKIDs: %u", count);
1119 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1123 /* PMKID List (16 * n octets) */
1124 for (i = 0; i < count; i++) {
1126 if (tag_val_off + PMKID_LEN > tag_len)
1129 pos += snprintf(pos, out_buff + SHORT_STR - pos, "PMKID %u: ", i);
1130 for (j = 0; j < PMKID_LEN; j++) {
1131 pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
1132 tag_val[tag_val_off + j]);
1134 proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1135 PMKID_LEN, out_buff);
1136 offset += PMKID_LEN;
1137 tag_val_off += PMKID_LEN;
1141 if (tag_val_off < tag_len)
1142 proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1143 tag_len - tag_val_off, "Not interpreted");
1146 /* ************************************************************************* */
1147 /* Dissect and add tagged (optional) fields to proto tree */
1148 /* ************************************************************************* */
1150 static const value_string tag_num_vals[] = {
1151 { TAG_SSID, "SSID parameter set" },
1152 { TAG_SUPP_RATES, "Supported Rates" },
1153 { TAG_FH_PARAMETER, "FH Parameter set" },
1154 { TAG_DS_PARAMETER, "DS Parameter set" },
1155 { TAG_CF_PARAMETER, "CF Parameter set" },
1156 { TAG_TIM, "(TIM) Traffic Indication Map" },
1157 { TAG_IBSS_PARAMETER, "IBSS Parameter set" },
1158 { TAG_COUNTRY_INFO, "Country Information" },
1159 { TAG_FH_HOPPING_PARAMETER, "Hopping Pattern Parameters" },
1160 { TAG_CHALLENGE_TEXT, "Challenge text" },
1161 { TAG_ERP_INFO, "ERP Information" },
1162 { TAG_ERP_INFO_OLD, "ERP Information" },
1163 { TAG_RSN_IE, "RSN Information" },
1164 { TAG_EXT_SUPP_RATES, "Extended Supported Rates" },
1165 { TAG_VENDOR_SPECIFIC_IE, "Vendor Specific" },
1169 static const value_string environment_vals[] = {
1171 { 0x4f, "Outdoor" },
1177 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
1179 const guint8 *tag_data_ptr;
1180 guint32 tag_no, tag_len;
1183 char out_buff[SHORT_STR];
1186 tag_no = tvb_get_guint8(tvb, offset);
1187 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
1188 "Tag Number: %u (%s)",
1190 val_to_str(tag_no, tag_num_vals,
1191 (tag_no >= 17 && tag_no <= 31) ?
1192 "Reserved for challenge text" :
1193 "Reserved tag number"));
1195 tag_len = tvb_get_guint8(tvb, offset + 1);
1196 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
1198 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
1205 memset (out_buff, 0, SHORT_STR);
1207 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
1208 out_buff[tag_len + 1] = 0;
1210 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1216 case TAG_SUPP_RATES:
1217 case TAG_EXT_SUPP_RATES:
1218 memset (out_buff, 0, SHORT_STR);
1219 strcpy (out_buff, "Supported rates: ");
1220 n = strlen (out_buff);
1222 for (i = 0; i < tag_len && n < SHORT_STR; i++)
1224 ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
1225 (tag_data_ptr[i] & 0x7F) * 0.5,
1226 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
1227 if (ret == -1 || ret >= SHORT_STR - n) {
1228 /* Some versions of snprintf return -1 if they'd truncate
1229 the output. Others return <buf_size> or greater. */
1235 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
1237 out_buff[SHORT_STR-1] = '\0';
1238 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1244 case TAG_FH_PARAMETER:
1245 memset (out_buff, 0, SHORT_STR);
1247 snprintf (out_buff, SHORT_STR,
1248 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
1249 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
1250 tag_data_ptr[3], tag_data_ptr[4]);
1252 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1258 case TAG_DS_PARAMETER:
1259 memset (out_buff, 0, SHORT_STR);
1261 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
1262 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1267 case TAG_CF_PARAMETER:
1268 memset (out_buff, 0, SHORT_STR);
1270 snprintf (out_buff, SHORT_STR,
1271 "CFP count %u, CFP period %u, CFP max duration %u, "
1272 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
1273 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
1275 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1281 memset (out_buff, 0, SHORT_STR);
1282 snprintf (out_buff, SHORT_STR,
1283 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
1284 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
1286 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1292 case TAG_IBSS_PARAMETER:
1293 memset (out_buff, 0, SHORT_STR);
1294 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
1295 pletohs (tag_data_ptr));
1297 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1302 case TAG_COUNTRY_INFO:
1303 memset (out_buff, 0, SHORT_STR);
1305 snprintf (out_buff, SHORT_STR, "Country Code: %c%c, %s Environment",
1306 tag_data_ptr[0], tag_data_ptr[1],
1307 val_to_str(tag_data_ptr[2], environment_vals,"Unknown (0x%02x)"));
1309 n = strlen (out_buff);
1311 for (i = 3; (i + 3) <= tag_len && n < SHORT_STR; i += 3)
1313 ret = snprintf(out_buff + n, SHORT_STR - n,
1314 ", Start Channel: %u, Channels: %u, Max TX Power: %d dBm",
1315 tag_data_ptr[i], tag_data_ptr[i + 1],
1316 (gint)tag_data_ptr[i + 2]);
1318 if (ret == -1 || ret >= SHORT_STR - n) {
1319 /* Some versions of snprintf return -1 if they'd truncate
1320 the output. Others return <buf_size> or greater. */
1326 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,tag_len, out_buff);
1330 case TAG_FH_HOPPING_PARAMETER:
1331 memset (out_buff, 0, SHORT_STR);
1332 snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u",
1333 tag_data_ptr[0], tag_data_ptr[1]);
1334 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, tag_len, out_buff);
1340 case TAG_CHALLENGE_TEXT:
1341 memset (out_buff, 0, SHORT_STR);
1342 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
1343 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1351 case TAG_ERP_INFO_OLD:
1352 memset (out_buff, 0, SHORT_STR);
1354 snprintf (out_buff, SHORT_STR,
1355 "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)",
1357 tag_data_ptr[0] & 0x01 ? "" : "no ",
1358 tag_data_ptr[0] & 0x02 ? "" : "do not ",
1359 tag_data_ptr[0] & 0x04 ? "short or long": "long");
1360 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1365 case TAG_VENDOR_SPECIFIC_IE:
1366 dissect_vendor_specific_ie(tree, tvb, offset + 2, tag_len,
1371 dissect_rsn_ie(tree, tvb, offset + 2, tag_len, tag_data_ptr);
1376 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1377 tag_len, "Not interpreted");
1385 ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, proto_tree * tree,
1386 int tagged_parameters_len)
1390 while (tagged_parameters_len > 0) {
1391 if ((next_len=add_tagged_field (tree, tvb, offset))==0)
1393 if (next_len > tagged_parameters_len) {
1394 /* XXX - flag this as an error? */
1395 next_len = tagged_parameters_len;
1398 tagged_parameters_len -= next_len;
1402 /* ************************************************************************* */
1403 /* Dissect 802.11 management frame */
1404 /* ************************************************************************* */
1406 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
1409 proto_item *ti = NULL;
1410 proto_tree *mgt_tree;
1411 proto_tree *fixed_tree;
1412 proto_tree *tagged_tree;
1414 int tagged_parameter_tree_len;
1416 CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
1420 ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
1421 mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
1423 switch (COMPOSE_FRAME_TYPE(fcf))
1427 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
1428 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1429 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1431 offset = 4; /* Size of fixed fields */
1432 tagged_parameter_tree_len =
1433 tvb_reported_length_remaining(tvb, offset);
1434 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1435 tagged_parameter_tree_len);
1437 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1438 tagged_parameter_tree_len);
1442 case MGT_ASSOC_RESP:
1443 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1444 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1445 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1446 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1448 offset = 6; /* Size of fixed fields */
1450 tagged_parameter_tree_len =
1451 tvb_reported_length_remaining(tvb, offset);
1452 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1453 tagged_parameter_tree_len);
1455 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1456 tagged_parameter_tree_len);
1460 case MGT_REASSOC_REQ:
1461 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1462 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1463 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1464 add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
1466 offset = 10; /* Size of fixed fields */
1467 tagged_parameter_tree_len =
1468 tvb_reported_length_remaining(tvb, offset);
1469 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1470 tagged_parameter_tree_len);
1472 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1473 tagged_parameter_tree_len);
1476 case MGT_REASSOC_RESP:
1477 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1478 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1479 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1480 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1482 offset = 6; /* Size of fixed fields */
1483 tagged_parameter_tree_len =
1484 tvb_reported_length_remaining(tvb, offset);
1485 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1486 tagged_parameter_tree_len);
1488 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1489 tagged_parameter_tree_len);
1495 tagged_parameter_tree_len =
1496 tvb_reported_length_remaining(tvb, offset);
1497 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1498 tagged_parameter_tree_len);
1500 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1501 tagged_parameter_tree_len);
1505 case MGT_PROBE_RESP:
1506 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1507 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1508 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1509 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1511 offset = 12; /* Size of fixed fields */
1512 tagged_parameter_tree_len =
1513 tvb_reported_length_remaining(tvb, offset);
1514 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1515 tagged_parameter_tree_len);
1517 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1518 tagged_parameter_tree_len);
1522 case MGT_BEACON: /* Dissect protocol payload fields */
1523 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1525 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1526 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1527 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1529 offset = 12; /* Size of fixed fields */
1530 tagged_parameter_tree_len =
1531 tvb_reported_length_remaining(tvb, offset);
1532 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1533 tagged_parameter_tree_len);
1535 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1536 tagged_parameter_tree_len);
1545 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1546 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1550 case MGT_AUTHENTICATION:
1551 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1552 add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
1553 add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
1554 add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
1556 offset = 6; /* Size of fixed fields */
1558 tagged_parameter_tree_len =
1559 tvb_reported_length_remaining(tvb, offset);
1560 if (tagged_parameter_tree_len != 0)
1562 tagged_tree = get_tagged_parameter_tree (mgt_tree,
1565 tagged_parameter_tree_len);
1567 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1568 tagged_parameter_tree_len);
1573 case MGT_DEAUTHENTICATION:
1574 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1575 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1580 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 3);
1581 add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
1583 switch (tvb_get_guint8(tvb, 0))
1586 case 17: /* Management notification frame */
1587 add_fixed_field (fixed_tree, tvb, 1, FIELD_WME_ACTION_CODE);
1588 add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
1589 add_fixed_field (fixed_tree, tvb, 3, FIELD_WME_STATUS_CODE);
1591 offset = 4; /* Size of fixed fields */
1593 tagged_parameter_tree_len =
1594 tvb_reported_length_remaining(tvb, offset);
1595 if (tagged_parameter_tree_len != 0)
1597 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1598 tagged_parameter_tree_len);
1600 ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
1601 tagged_parameter_tree_len);
1605 default: /* Management action frame */
1606 add_fixed_field (fixed_tree, tvb, 1, FIELD_ACTION_CODE);
1607 add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
1616 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1618 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1619 col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
1620 get_ether_name(addr), type);
1621 if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
1622 col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
1623 ether_to_str(addr), type);
1627 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1629 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1630 col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
1631 get_ether_name(addr), type);
1632 if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
1633 col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
1634 ether_to_str(addr), type);
1643 /* ************************************************************************* */
1644 /* Dissect 802.11 frame */
1645 /* ************************************************************************* */
1647 dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
1648 proto_tree * tree, gboolean fixed_length_header,
1649 gboolean has_radio_information, gint fcs_len,
1650 gboolean wlan_broken_fc)
1652 guint16 fcf, flags, frame_type_subtype;
1653 guint16 seq_control;
1654 guint32 seq_number, frag_number;
1655 gboolean more_frags;
1656 const guint8 *src = NULL, *dst = NULL;
1657 proto_item *ti = NULL;
1658 proto_item *flag_item;
1659 proto_item *fc_item;
1660 proto_tree *hdr_tree = NULL;
1661 proto_tree *flag_tree;
1662 proto_tree *fc_tree;
1665 gint len, reported_len, ivlen;
1666 gboolean save_fragmented;
1667 tvbuff_t *volatile next_tvb = NULL;
1669 volatile encap_t encap_type;
1670 guint8 octet1, octet2;
1671 char out_buff[SHORT_STR];
1673 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1674 col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
1675 if (check_col (pinfo->cinfo, COL_INFO))
1676 col_clear (pinfo->cinfo, COL_INFO);
1678 /* Add the radio information, if present, to the column information */
1679 if (has_radio_information) {
1680 if (check_col(pinfo->cinfo, COL_TX_RATE)) {
1681 col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
1682 pinfo->pseudo_header->ieee_802_11.data_rate / 2,
1683 pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
1685 if (check_col(pinfo->cinfo, COL_RSSI)) {
1686 /* XX - this is a percentage, not a dBm or normalized or raw RSSI */
1687 col_add_fstr(pinfo->cinfo, COL_RSSI, "%u",
1688 pinfo->pseudo_header->ieee_802_11.signal_level);
1692 fcf = tvb_get_letohs (tvb, 0);
1693 if (wlan_broken_fc) {
1695 fcf = ((fcf & 0xff) << 8) | (((fcf & 0xff00) >> 8) & 0xff);
1697 if (fixed_length_header)
1698 hdr_len = DATA_LONG_HDR_LEN;
1700 hdr_len = find_header_length (fcf);
1701 frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1703 if (check_col (pinfo->cinfo, COL_INFO))
1704 col_set_str (pinfo->cinfo, COL_INFO,
1705 val_to_str(frame_type_subtype, frame_type_subtype_vals,
1706 "Unrecognized (Reserved frame)"));
1708 flags = COOK_FLAGS (fcf);
1709 more_frags = HAVE_FRAGMENTS (flags);
1711 /* Add the radio information, if present, and the FC to the current tree */
1714 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1716 hdr_tree = proto_item_add_subtree (ti, ett_80211);
1718 if (has_radio_information) {
1719 proto_tree_add_uint_format(hdr_tree, hf_data_rate,
1721 pinfo->pseudo_header->ieee_802_11.data_rate,
1722 "Data Rate: %u.%u Mb/s",
1723 pinfo->pseudo_header->ieee_802_11.data_rate / 2,
1724 pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
1726 proto_tree_add_uint(hdr_tree, hf_channel,
1728 pinfo->pseudo_header->ieee_802_11.channel);
1730 proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
1732 pinfo->pseudo_header->ieee_802_11.signal_level,
1733 "Signal Strength: %u%%",
1734 pinfo->pseudo_header->ieee_802_11.signal_level);
1737 proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1739 wlan_broken_fc?1:0, 1,
1740 frame_type_subtype);
1742 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb,
1745 "Frame Control: 0x%04X (%s)",
1746 fcf, wlan_broken_fc?"Swapped":"Normal");
1748 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1751 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb,
1752 wlan_broken_fc?1:0, 1,
1753 COOK_PROT_VERSION (fcf));
1755 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb,
1756 wlan_broken_fc?1:0, 1,
1757 COOK_FRAME_TYPE (fcf));
1759 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1761 wlan_broken_fc?1:0, 1,
1762 COOK_FRAME_SUBTYPE (fcf));
1765 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb,
1766 wlan_broken_fc?0:1, 1,
1767 flags, "Flags: 0x%X", flags);
1769 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1771 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb,
1772 wlan_broken_fc?0:1, 1,
1773 COOK_DS_STATUS (flags));
1774 proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1,
1776 proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1,
1779 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb,
1780 wlan_broken_fc?0:1, 1,
1783 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb,
1784 wlan_broken_fc?0:1, 1, flags);
1786 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb,
1787 wlan_broken_fc?0:1, 1, flags);
1789 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb,
1790 wlan_broken_fc?0:1, 1,
1793 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb,
1794 wlan_broken_fc?0:1, 1, flags);
1796 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb,
1797 wlan_broken_fc?0:1, 1, flags);
1799 if (frame_type_subtype == CTRL_PS_POLL)
1800 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1801 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1804 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1805 tvb_get_letohs (tvb, 2));
1809 * Decode the part of the frame header that isn't the same for all
1816 switch (COOK_FRAME_TYPE (fcf))
1821 * All management frame types have the same header.
1823 src = tvb_get_ptr (tvb, 10, 6);
1824 dst = tvb_get_ptr (tvb, 4, 6);
1826 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1827 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1828 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1829 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1831 seq_control = tvb_get_letohs(tvb, 22);
1832 frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1833 seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1837 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1839 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1841 /* add items for wlan.addr filter */
1842 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1843 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1845 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1846 tvb_get_ptr (tvb, 16, 6));
1848 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1851 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1857 switch (frame_type_subtype)
1861 src = tvb_get_ptr (tvb, 10, 6);
1862 dst = tvb_get_ptr (tvb, 4, 6);
1864 set_src_addr_cols(pinfo, src, "BSSID");
1865 set_dst_addr_cols(pinfo, dst, "BSSID");
1869 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1871 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1877 src = tvb_get_ptr (tvb, 10, 6);
1878 dst = tvb_get_ptr (tvb, 4, 6);
1880 set_src_addr_cols(pinfo, src, "TA");
1881 set_dst_addr_cols(pinfo, dst, "RA");
1885 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1887 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1893 dst = tvb_get_ptr (tvb, 4, 6);
1895 set_dst_addr_cols(pinfo, dst, "RA");
1898 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1902 case CTRL_ACKNOWLEDGEMENT:
1903 dst = tvb_get_ptr (tvb, 4, 6);
1905 set_dst_addr_cols(pinfo, dst, "RA");
1908 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1913 src = tvb_get_ptr (tvb, 10, 6);
1914 dst = tvb_get_ptr (tvb, 4, 6);
1916 set_src_addr_cols(pinfo, src, "BSSID");
1917 set_dst_addr_cols(pinfo, dst, "RA");
1921 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1922 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1927 case CTRL_CFP_ENDACK:
1928 src = tvb_get_ptr (tvb, 10, 6);
1929 dst = tvb_get_ptr (tvb, 4, 6);
1931 set_src_addr_cols(pinfo, src, "BSSID");
1932 set_dst_addr_cols(pinfo, dst, "RA");
1936 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1938 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1945 addr_type = COOK_ADDR_SELECTOR (fcf);
1947 /* In order to show src/dst address we must always do the following */
1952 src = tvb_get_ptr (tvb, 10, 6);
1953 dst = tvb_get_ptr (tvb, 4, 6);
1958 src = tvb_get_ptr (tvb, 16, 6);
1959 dst = tvb_get_ptr (tvb, 4, 6);
1964 src = tvb_get_ptr (tvb, 10, 6);
1965 dst = tvb_get_ptr (tvb, 16, 6);
1970 src = tvb_get_ptr (tvb, 24, 6);
1971 dst = tvb_get_ptr (tvb, 16, 6);
1975 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1976 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1977 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1978 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1980 seq_control = tvb_get_letohs(tvb, 22);
1981 frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1982 seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1984 /* Now if we have a tree we start adding stuff */
1993 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1994 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1995 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1996 tvb_get_ptr (tvb, 16, 6));
1997 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1999 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2002 /* add items for wlan.addr filter */
2003 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
2004 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2009 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
2010 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
2011 tvb_get_ptr (tvb, 10, 6));
2012 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
2013 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2015 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2018 /* add items for wlan.addr filter */
2019 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
2020 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
2025 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
2026 tvb_get_ptr (tvb, 4, 6));
2027 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
2028 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
2030 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2032 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2035 /* add items for wlan.addr filter */
2036 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2037 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
2042 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
2043 tvb_get_ptr (tvb, 4, 6));
2044 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
2045 tvb_get_ptr (tvb, 10, 6));
2046 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
2047 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2049 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2051 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
2053 /* add items for wlan.addr filter */
2054 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
2055 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
2063 len = tvb_length_remaining(tvb, hdr_len);
2064 reported_len = tvb_reported_length_remaining(tvb, hdr_len);
2068 case 0: /* Definitely has no FCS */
2072 case 4: /* Definitely has an FCS */
2076 default: /* Don't know - use "wlan_check_fcs" */
2077 has_fcs = wlan_check_fcs;
2083 * Well, this packet should, in theory, have an FCS.
2084 * Do we have the entire packet, and does it have enough data for
2087 if (reported_len < 4)
2090 * The packet is claimed not to even have enough data for a 4-byte
2092 * Pretend it doesn't have an FCS.
2096 else if (len < reported_len)
2099 * The packet is claimed to have enough data for a 4-byte FCS, but
2100 * we didn't capture all of the packet.
2101 * Slice off the 4-byte FCS from the reported length, and trim the
2102 * captured length so it's no more than the reported length; that
2103 * will slice off what of the FCS, if any, is in the captured
2107 if (len > reported_len)
2113 * We have the entire packet, and it includes a 4-byte FCS.
2114 * Slice it off, and put it into the tree.
2120 guint32 fcs = crc32_802_tvb(tvb, hdr_len + len);
2121 guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
2122 if (fcs == sent_fcs)
2123 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
2124 hdr_len + len, 4, sent_fcs,
2125 "Frame check sequence: 0x%08x (correct)", sent_fcs);
2127 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
2128 hdr_len + len, 4, sent_fcs,
2129 "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
2135 if (tree && (frame_type_subtype == DATA_QOS_DATA || frame_type_subtype == DATA_QOS_NULL)) {
2136 proto_item *qos_fields;
2137 proto_tree *qos_tree;
2139 guint16 qos_control, qos_priority, qos_ack_policy;
2141 qos_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len - 2, 2,
2143 qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters);
2145 qos_control = tvb_get_letohs(tvb, hdr_len - 2);
2146 qos_priority = COOK_QOS_PRIORITY(qos_control);
2147 qos_ack_policy = COOK_QOS_ACK_POLICY(qos_control);
2148 proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
2149 hdr_len - 2, 2, qos_priority,
2150 "Priority: %d (%s) (%s)",
2151 qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]);
2152 proto_tree_add_uint_format (qos_tree, hf_qos_ack_policy, tvb,
2153 hdr_len - 2, 2, qos_ack_policy,
2154 "Ack Policy: %d (%sAcknowledge)",
2155 qos_ack_policy, qos_ack_policy ? "Do not " : "");
2159 * Only management and data frames have a body, so we don't have
2160 * anything more to do for other types of frames.
2162 switch (COOK_FRAME_TYPE (fcf))
2170 * No-data frames don't have a body.
2172 switch (frame_type_subtype)
2175 case DATA_NULL_FUNCTION:
2176 case DATA_CF_ACK_NOD:
2177 case DATA_CF_POLL_NOD:
2178 case DATA_CF_ACK_POLL_NOD:
2188 if (IS_WEP(COOK_FLAGS(fcf))) {
2190 * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
2191 * the data, if we have a matching key. Otherwise display it as data.
2193 gboolean can_decrypt = FALSE;
2194 proto_tree *wep_tree = NULL;
2196 guint8 key, keybyte;
2198 keybyte = tvb_get_guint8(tvb, hdr_len + 3);
2199 key = COOK_WEP_KEY(keybyte);
2200 if ((keybyte & KEY_EXTIV) && (len >= EXTIV_LEN)) {
2201 /* Extended IV; this frame is likely encrypted with TKIP or CCMP */
2203 proto_item *extiv_fields;
2205 extiv_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 8,
2206 "TKIP/CCMP parameters");
2207 wep_tree = proto_item_add_subtree (extiv_fields, ett_wep_parameters);
2208 /* It is unknown whether this is a TKIP or CCMP encrypted packet, so
2209 * display both packet number alternatives unless the ExtIV can be
2210 * determined to be possible only with one of the encryption protocols.
2212 if (tvb_get_guint8(tvb, hdr_len + 1) & 0x20) {
2213 snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
2214 tvb_get_letohl(tvb, hdr_len + 4),
2215 tvb_get_guint8(tvb, hdr_len),
2216 tvb_get_guint8(tvb, hdr_len + 2));
2217 proto_tree_add_string(wep_tree, hf_tkip_extiv, tvb, hdr_len,
2218 EXTIV_LEN, out_buff);
2220 if (tvb_get_guint8(tvb, hdr_len + 2) == 0) {
2221 snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
2222 tvb_get_letohl(tvb, hdr_len + 4),
2223 tvb_get_guint8(tvb, hdr_len + 1),
2224 tvb_get_guint8(tvb, hdr_len));
2225 proto_tree_add_string(wep_tree, hf_ccmp_extiv, tvb, hdr_len,
2226 EXTIV_LEN, out_buff);
2228 proto_tree_add_uint(wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
2231 /* Subtract out the length of the IV. */
2233 reported_len -= EXTIV_LEN;
2235 /* It is unknown whether this is TKIP or CCMP, so let's not even try to
2236 * parse TKIP Michael MIC+ICV or CCMP MIC. */
2238 /* No Ext. IV - WEP packet */
2240 * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
2241 * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
2244 * Also, just pass the data *following* the WEP parameters as the
2245 * buffer to decrypt.
2247 iv = tvb_get_letoh24(tvb, hdr_len);
2249 proto_item *wep_fields;
2251 wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
2254 wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
2255 proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
2258 proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
2260 /* Subtract out the length of the IV. */
2266 * Well, this packet should, in theory, have an ICV.
2267 * Do we have the entire packet, and does it have enough data for
2270 if (reported_len < 4) {
2272 * The packet is claimed not to even have enough data for a
2274 * Pretend it doesn't have an ICV.
2277 } else if (len < reported_len) {
2279 * The packet is claimed to have enough data for a 4-byte ICV,
2280 * but we didn't capture all of the packet.
2281 * Slice off the 4-byte ICV from the reported length, and trim
2282 * the captured length so it's no more than the reported length;
2283 * that will slice off what of the ICV, if any, is in the
2288 if (len > reported_len)
2292 * We have the entire packet, and it includes a 4-byte ICV.
2293 * Slice it off, and put it into the tree.
2295 * We only support decrypting if we have the the ICV.
2297 * XXX - the ICV is encrypted; we're putting the encrypted
2298 * value, not the decrypted value, into the tree.
2306 if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
2308 * WEP decode impossible or failed, treat payload as raw data
2309 * and don't attempt fragment reassembly or further dissection.
2311 next_tvb = tvb_new_subset(tvb, hdr_len + ivlen, len, reported_len);
2313 if (tree && can_decrypt)
2314 proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
2315 hdr_len + ivlen + len, 4,
2316 tvb_get_ntohl(tvb, hdr_len + ivlen + len),
2317 "WEP ICV: 0x%08x (not verified)",
2318 tvb_get_ntohl(tvb, hdr_len + ivlen + len));
2320 call_dissector(data_handle, next_tvb, pinfo, tree);
2325 proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
2326 hdr_len + ivlen + len, 4,
2327 tvb_get_ntohl(tvb, hdr_len + ivlen + len),
2328 "WEP ICV: 0x%08x (correct)",
2329 tvb_get_ntohl(tvb, hdr_len + ivlen + len));
2331 add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
2335 * WEP decryption successful!
2337 * Use the tvbuff we got back from the decryption; the data starts at
2338 * the beginning. The lengths are already correct for the decoded WEP
2345 * Not a WEP-encrypted frame; just use the data from the tvbuff
2348 * The payload starts at "hdr_len" (i.e., just past the 802.11
2349 * MAC header), the length of data in the tvbuff following the
2350 * 802.11 header is "len", and the length of data in the packet
2351 * following the 802.11 header is "reported_len".
2357 * Do defragmentation if "wlan_defragment" is true, and we have more
2358 * fragments or this isn't the first fragment.
2360 * We have to do some special handling to catch frames that
2361 * have the "More Fragments" indicator not set but that
2362 * don't show up as reassembled and don't have any other
2363 * fragments present. Some networking interfaces appear
2364 * to do reassembly even when you're capturing raw packets
2365 * *and* show the reassembled packet without the "More
2366 * Fragments" indicator set *but* with a non-zero fragment
2369 * "fragment_add_seq_802_11()" handles that; we want to call it
2370 * even if we have a short frame, so that it does those checks - if
2371 * the frame is short, it doesn't do reassembly on it.
2373 * (This could get some false positives if we really *did* only
2374 * capture the last fragment of a fragmented packet, but that's
2377 save_fragmented = pinfo->fragmented;
2378 if (wlan_defragment && (more_frags || frag_number != 0)) {
2379 fragment_data *fd_head;
2382 * If we've already seen this frame, look it up in the
2383 * table of reassembled packets, otherwise add it to
2384 * whatever reassembly is in progress, if any, and see
2387 fd_head = fragment_add_seq_802_11(next_tvb, hdr_len, pinfo, seq_number,
2388 wlan_fragment_table,
2389 wlan_reassembled_table,
2393 next_tvb = process_reassembled_data(tvb, hdr_len, pinfo,
2394 "Reassembled 802.11", fd_head,
2395 &frag_items, NULL, hdr_tree);
2398 * If this is the first fragment, dissect its contents, otherwise
2399 * just show it as a fragment.
2401 if (frag_number != 0) {
2402 /* Not the first fragment - don't dissect it. */
2405 /* First fragment, or not fragmented. Dissect what we have here. */
2407 /* Get a tvbuff for the payload. */
2408 next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
2411 * If this is the first fragment, but not the only fragment,
2412 * tell the next protocol that.
2415 pinfo->fragmented = TRUE;
2417 pinfo->fragmented = FALSE;
2421 if (next_tvb == NULL) {
2422 /* Just show this as an incomplete fragment. */
2423 if (check_col(pinfo->cinfo, COL_INFO))
2424 col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
2425 next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
2426 call_dissector(data_handle, next_tvb, pinfo, tree);
2427 pinfo->fragmented = save_fragmented;
2431 switch (COOK_FRAME_TYPE (fcf))
2435 dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
2440 /* I guess some bridges take Netware Ethernet_802_3 frames,
2441 which are 802.3 frames (with a length field rather than
2442 a type field, but with no 802.2 header in the payload),
2443 and just stick the payload into an 802.11 frame. I've seen
2444 captures that show frames of that sort.
2446 We also handle some odd form of encapsulation in which a
2447 complete Ethernet frame is encapsulated within an 802.11
2448 data frame, with no 802.2 header. This has been seen
2451 So, if the packet doesn't start with 0xaa 0xaa:
2453 we first use the same scheme that linux-wlan-ng does to detect
2454 those encapsulated Ethernet frames, namely looking to see whether
2455 the frame either starts with 6 octets that match the destination
2456 address from the 802.11 header or has 6 octets that match the
2457 source address from the 802.11 header following the first 6 octets,
2458 and, if so, treat it as an encapsulated Ethernet frame;
2460 otherwise, we use the same scheme that we use in the Ethernet
2461 dissector to recognize Netware 802.3 frames, namely checking
2462 whether the packet starts with 0xff 0xff and, if so, treat it
2463 as an encapsulated IPX frame. */
2464 encap_type = ENCAP_802_2;
2466 octet1 = tvb_get_guint8(next_tvb, 0);
2467 octet2 = tvb_get_guint8(next_tvb, 1);
2468 if (octet1 != 0xaa || octet2 != 0xaa) {
2469 src = tvb_get_ptr (next_tvb, 6, 6);
2470 dst = tvb_get_ptr (next_tvb, 0, 6);
2471 if (memcmp(src, pinfo->dl_src.data, 6) == 0 ||
2472 memcmp(dst, pinfo->dl_dst.data, 6) == 0)
2473 encap_type = ENCAP_ETHERNET;
2474 else if (octet1 == 0xff && octet2 == 0xff)
2475 encap_type = ENCAP_IPX;
2478 CATCH2(BoundsError, ReportedBoundsError) {
2484 switch (encap_type) {
2487 call_dissector(llc_handle, next_tvb, pinfo, tree);
2490 case ENCAP_ETHERNET:
2491 call_dissector(eth_handle, next_tvb, pinfo, tree);
2495 call_dissector(ipx_handle, next_tvb, pinfo, tree);
2500 pinfo->fragmented = save_fragmented;
2504 * Dissect 802.11 with a variable-length link-layer header.
2507 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2509 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
2510 pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
2514 * Dissect 802.11 with a variable-length link-layer header and a pseudo-
2515 * header containing radio information.
2518 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2520 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE,
2521 pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
2525 * Dissect 802.11 with a variable-length link-layer header and a byte-swapped
2526 * control field (some hardware sends out LWAPP-encapsulated 802.11
2527 * packets with the control field byte swapped).
2530 dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2532 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE, TRUE);
2536 * Dissect 802.11 with a fixed-length link-layer header (padded to the
2540 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2542 dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE, FALSE);
2546 wlan_defragment_init(void)
2548 fragment_table_init(&wlan_fragment_table);
2549 reassembled_table_init(&wlan_reassembled_table);
2553 proto_register_ieee80211 (void)
2555 static const value_string frame_type[] = {
2556 {MGT_FRAME, "Management frame"},
2557 {CONTROL_FRAME, "Control frame"},
2558 {DATA_FRAME, "Data frame"},
2562 static const value_string tofrom_ds[] = {
2563 {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
2564 {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"},
2565 {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"},
2566 {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"},
2570 static const true_false_string tods_flag = {
2571 "Frame is entering DS",
2572 "Frame is not entering DS"
2575 static const true_false_string fromds_flag = {
2576 "Frame is exiting DS",
2577 "Frame is not exiting DS"
2580 static const true_false_string more_frags = {
2581 "More fragments follow",
2582 "This is the last fragment"
2585 static const true_false_string retry_flags = {
2586 "Frame is being retransmitted",
2587 "Frame is not being retransmitted"
2590 static const true_false_string pm_flags = {
2591 "STA will go to sleep",
2595 static const true_false_string md_flags = {
2596 "Data is buffered for STA at AP",
2600 static const true_false_string wep_flags = {
2605 static const true_false_string order_flags = {
2607 "Not strictly ordered"
2610 static const true_false_string cf_ess_flags = {
2611 "Transmitter is an AP",
2612 "Transmitter is a STA"
2616 static const true_false_string cf_privacy_flags = {
2617 "AP/STA can support WEP",
2618 "AP/STA cannot support WEP"
2621 static const true_false_string cf_preamble_flags = {
2622 "Short preamble allowed",
2623 "Short preamble not allowed"
2626 static const true_false_string cf_pbcc_flags = {
2627 "PBCC modulation allowed",
2628 "PBCC modulation not allowed"
2631 static const true_false_string cf_agility_flags = {
2632 "Channel agility in use",
2633 "Channel agility not in use"
2636 static const true_false_string short_slot_time_flags = {
2637 "Short slot time in use",
2638 "Short slot time not in use"
2641 static const true_false_string dsss_ofdm_flags = {
2642 "DSSS-OFDM modulation allowed",
2643 "DSSS-OFDM modulation not allowed"
2647 static const true_false_string cf_ibss_flags = {
2648 "Transmitter belongs to an IBSS",
2649 "Transmitter belongs to a BSS"
2652 static const value_string sta_cf_pollable[] = {
2653 {0x00, "Station is not CF-Pollable"},
2654 {0x02, "Station is CF-Pollable, "
2655 "not requesting to be placed on the CF-polling list"},
2656 {0x01, "Station is CF-Pollable, "
2657 "requesting to be placed on the CF-polling list"},
2658 {0x03, "Station is CF-Pollable, requesting never to be polled"},
2662 static const value_string ap_cf_pollable[] = {
2663 {0x00, "No point coordinator at AP"},
2664 {0x02, "Point coordinator at AP for delivery only (no polling)"},
2665 {0x01, "Point coordinator at AP for delivery and polling"},
2671 static const value_string auth_alg[] = {
2672 {0x00, "Open System"},
2673 {0x01, "Shared key"},
2677 static const value_string reason_codes[] = {
2679 {0x01, "Unspecified reason"},
2680 {0x02, "Previous authentication no longer valid"},
2681 {0x03, "Deauthenticated because sending STA is leaving (has left) "
2683 {0x04, "Disassociated due to inactivity"},
2684 {0x05, "Disassociated because AP is unable to handle all currently "
2685 "associated stations"},
2686 {0x06, "Class 2 frame received from nonauthenticated station"},
2687 {0x07, "Class 3 frame received from nonassociated station"},
2688 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
2689 {0x09, "Station requesting (re)association is not authenticated with "
2690 "responding station"},
2691 {0x0D, "Invalid Information Element"},
2692 {0x0E, "Michael MIC failure"},
2693 {0x0F, "4-Way Handshake timeout"},
2694 {0x10, "Group key update timeout"},
2695 {0x11, "Information element in 4-Way Handshake different from "
2696 "(Re)Association Request/Probe Response/Beacon"},
2697 {0x12, "Group Cipher is not valid"},
2698 {0x13, "Pairwise Cipher is not valid"},
2699 {0x14, "AKMP is not valid"},
2700 {0x15, "Unsupported RSN IE version"},
2701 {0x16, "Invalid RSN IE Capabilities"},
2702 {0x17, "IEEE 802.1X Authentication failed"},
2703 {0x18, "Cipher suite is rejected per security policy"},
2708 static const value_string status_codes[] = {
2709 {0x00, "Successful"},
2710 {0x01, "Unspecified failure"},
2711 {0x0A, "Cannot support all requested capabilities in the "
2712 "Capability information field"},
2713 {0x0B, "Reassociation denied due to inability to confirm that "
2714 "association exists"},
2715 {0x0C, "Association denied due to reason outside the scope of this "
2718 {0x0D, "Responding station does not support the specified authentication "
2720 {0x0E, "Received an Authentication frame with authentication sequence "
2721 "transaction sequence number out of expected sequence"},
2722 {0x0F, "Authentication rejected because of challenge failure"},
2723 {0x10, "Authentication rejected due to timeout waiting for next "
2724 "frame in sequence"},
2725 {0x11, "Association denied because AP is unable to handle additional "
2726 "associated stations"},
2727 {0x12, "Association denied due to requesting station not supporting all "
2728 "of the datarates in the BSSBasicServiceSet Parameter"},
2729 {0x13, "Association denied due to requesting station not supporting "
2730 "short preamble operation"},
2731 {0x14, "Association denied due to requesting station not supporting "
2733 {0x15, "Association denied due to requesting station not supporting "
2735 {0x19, "Association denied due to requesting station not supporting "
2736 "short slot operation"},
2737 {0x1A, "Association denied due to requesting station not supporting "
2738 "DSSS-OFDM operation"},
2739 {0x28, "Invalid Information Element"},
2740 {0x29, "Group Cipher is not valid"},
2741 {0x2A, "Pairwise Cipher is not valid"},
2742 {0x2B, "AKMP is not valid"},
2743 {0x2C, "Unsupported RSN IE version"},
2744 {0x2D, "Invalid RSN IE Capabilities"},
2745 {0x2E, "Cipher suite is rejected per security policy"},
2749 static const value_string category_codes[] = {
2750 {0x11, "Management notification frame"},
2754 static const value_string action_codes[] = {
2758 static const value_string wme_action_codes[] = {
2759 {0x00, "Setup request"},
2760 {0x01, "Setup response"},
2765 static const value_string wme_status_codes[] = {
2766 {0x00, "Admission accepted"},
2767 {0x01, "Invalid parameters"},
2772 static hf_register_info hf[] = {
2774 {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2775 "Data rate (.5 Mb/s units)", HFILL }},
2778 {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2779 "Radio channel", HFILL }},
2781 {&hf_signal_strength,
2782 {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2783 "Signal strength (percentage)", HFILL }},
2786 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2787 "MAC Frame control", HFILL }},
2789 {&hf_fc_proto_version,
2790 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2791 "MAC Protocol version", HFILL }}, /* 0 */
2794 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2795 "Frame type", HFILL }},
2797 {&hf_fc_frame_subtype,
2798 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2799 "Frame subtype", HFILL }}, /* 2 */
2801 {&hf_fc_frame_type_subtype,
2802 {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2803 "Type and subtype combined", HFILL }},
2806 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2807 "Protocol flags", HFILL }},
2810 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2811 "Data-frame DS-traversal status", HFILL }}, /* 3 */
2814 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2815 "To DS flag", HFILL }}, /* 4 */
2818 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2819 "From DS flag", HFILL }}, /* 5 */
2822 {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2823 "More Fragments flag", HFILL }}, /* 6 */
2826 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2827 "Retransmission flag", HFILL }},
2830 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2831 "Power management status", HFILL }},
2834 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2835 "More data flag", HFILL }},
2838 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2839 "WEP flag", HFILL }},
2842 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2843 "Strictly ordered flag", HFILL }},
2846 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2847 "Association-ID field", HFILL }},
2850 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2851 "Duration field", HFILL }},
2854 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2855 "Destination Hardware Address", HFILL }},
2858 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2859 "Source Hardware Address", HFILL }},
2862 {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2863 "Source or Destination Hardware Address", HFILL }},
2866 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2867 "Receiving Station Hardware Address", HFILL }},
2870 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2871 "Transmitting Station Hardware Address", HFILL }},
2874 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2875 "Basic Service Set ID", HFILL }},
2878 {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2879 "Fragment number", HFILL }},
2882 {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2883 "Sequence number", HFILL }},
2886 {"Priority", "wlan.qos.priority", FT_UINT16, BASE_DEC, NULL, 0,
2887 "802.1D Tag", HFILL }},
2889 {&hf_qos_ack_policy,
2890 {"Ack Policy", "wlan.qos.ack", FT_UINT16, BASE_DEC, NULL, 0,
2891 "Ack Policy", HFILL }},
2894 {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
2895 NULL, 0, "FCS", HFILL }},
2897 {&hf_fragment_overlap,
2898 {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2899 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2901 {&hf_fragment_overlap_conflict,
2902 {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2903 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2904 "Overlapping fragments contained conflicting data", HFILL }},
2906 {&hf_fragment_multiple_tails,
2907 {"Multiple tail fragments found", "wlan.fragment.multipletails",
2908 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2909 "Several tails were found when defragmenting the packet", HFILL }},
2911 {&hf_fragment_too_long_fragment,
2912 {"Fragment too long", "wlan.fragment.toolongfragment",
2913 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2914 "Fragment contained data past end of packet", HFILL }},
2916 {&hf_fragment_error,
2917 {"Defragmentation error", "wlan.fragment.error",
2918 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2919 "Defragmentation error due to illegal fragments", HFILL }},
2922 {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2923 "802.11 Fragment", HFILL }},
2926 {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2927 "802.11 Fragments", HFILL }},
2929 {&hf_reassembled_in,
2930 {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2931 "This 802.11 packet is reassembled in this frame", HFILL }},
2934 {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2935 "Initialization Vector", HFILL }},
2938 {"TKIP Ext. Initialization Vector", "wlan.tkip.extiv", FT_STRING,
2939 BASE_HEX, NULL, 0, "TKIP Extended Initialization Vector", HFILL }},
2942 {"CCMP Ext. Initialization Vector", "wlan.ccmp.extiv", FT_STRING,
2943 BASE_HEX, NULL, 0, "CCMP Extended Initialization Vector", HFILL }},
2946 {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
2950 {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
2951 "WEP ICV", HFILL }},
2954 static const true_false_string rsn_preauth_flags = {
2955 "Transmitter supports pre-authentication",
2956 "Transmitter does not support pre-authentication"
2959 static const true_false_string rsn_no_pairwise_flags = {
2960 "Transmitter cannot support WEP default key 0 simultaneously with "
2962 "Transmitter can support WEP default key 0 simultaneously with "
2966 static const value_string rsn_cap_replay_counter[] = {
2967 {0x00, "1 replay counter per PTKSA/GTKSA/STAKeySA"},
2968 {0x01, "2 replay counters per PTKSA/GTKSA/STAKeySA"},
2969 {0x02, "4 replay counters per PTKSA/GTKSA/STAKeySA"},
2970 {0x03, "16 replay counters per PTKSA/GTKSA/STAKeySA"},
2974 static hf_register_info ff[] = {
2976 {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
2977 NULL, 0, "", HFILL }},
2980 {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
2981 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
2983 {&ff_beacon_interval,
2984 {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
2987 {&hf_fixed_parameters,
2988 {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
2991 {&hf_tagged_parameters,
2992 {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
2996 {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
2997 "Capability information", HFILL }},
3000 {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
3001 FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
3004 {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
3005 FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
3008 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
3009 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C,
3010 "CF-Poll capabilities for a STA", HFILL }},
3013 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
3014 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C,
3015 "CF-Poll capabilities for an AP", HFILL }},
3018 {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
3019 FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
3022 {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
3023 FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
3026 {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
3027 FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
3030 {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
3031 FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
3033 {&ff_short_slot_time,
3034 {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
3035 FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
3039 {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
3040 FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
3044 {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
3045 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
3048 {"Association ID", "wlan_mgt.fixed.aid",
3049 FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
3052 {"Listen Interval", "wlan_mgt.fixed.listen_ival",
3053 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
3056 {"Current AP", "wlan_mgt.fixed.current_ap",
3057 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
3060 {"Reason code", "wlan_mgt.fixed.reason_code",
3061 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
3062 "Reason for unsolicited notification", HFILL }},
3065 {"Status code", "wlan_mgt.fixed.status_code",
3066 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
3067 "Status of requested event", HFILL }},
3070 {"Category code", "wlan_mgt.fixed.category_code",
3071 FT_UINT16, BASE_HEX, VALS (&category_codes), 0,
3072 "Management action category", HFILL }},
3075 {"Action code", "wlan_mgt.fixed.action_code",
3076 FT_UINT16, BASE_HEX, VALS (&action_codes), 0,
3077 "Management action code", HFILL }},
3080 {"Dialog token", "wlan_mgt.fixed.dialog_token",
3081 FT_UINT16, BASE_HEX, NULL, 0, "Management action dialog token", HFILL }},
3083 {&ff_wme_action_code,
3084 {"Action code", "wlan_mgt.fixed.action_code",
3085 FT_UINT16, BASE_HEX, VALS (&wme_action_codes), 0,
3086 "Management notification action code", HFILL }},
3088 {&ff_wme_status_code,
3089 {"Status code", "wlan_mgt.fixed.status_code",
3090 FT_UINT16, BASE_HEX, VALS (&wme_status_codes), 0,
3091 "Management notification setup response status code", HFILL }},
3094 {"Tag", "wlan_mgt.tag.number",
3095 FT_UINT8, BASE_DEC, VALS(tag_num_vals), 0,
3096 "Element ID", HFILL }},
3099 {"Tag length", "wlan_mgt.tag.length",
3100 FT_UINT8, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
3102 {&tag_interpretation,
3103 {"Tag interpretation", "wlan_mgt.tag.interpretation",
3104 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }},
3107 {"RSN Capabilities", "wlan_mgt.rsn.capabilities", FT_UINT16, BASE_HEX,
3108 NULL, 0, "RSN Capability information", HFILL }},
3111 {"RSN Pre-Auth capabilities", "wlan_mgt.rsn.capabilities.preauth",
3112 FT_BOOLEAN, 16, TFS (&rsn_preauth_flags), 0x0001,
3113 "RSN Pre-Auth capabilities", HFILL }},
3115 {&rsn_cap_no_pairwise,
3116 {"RSN No Pairwise capabilities", "wlan_mgt.rsn.capabilities.no_pairwise",
3117 FT_BOOLEAN, 16, TFS (&rsn_no_pairwise_flags), 0x0002,
3118 "RSN No Pairwise capabilities", HFILL }},
3120 {&rsn_cap_ptksa_replay_counter,
3121 {"RSN PTKSA Replay Counter capabilities",
3122 "wlan_mgt.rsn.capabilities.ptksa_replay_counter",
3123 FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x000C,
3124 "RSN PTKSA Replay Counter capabilities", HFILL }},
3126 {&rsn_cap_gtksa_replay_counter,
3127 {"RSN GTKSA Replay Counter capabilities",
3128 "wlan_mgt.rsn.capabilities.gtksa_replay_counter",
3129 FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x0030,
3130 "RSN GTKSA Replay Counter capabilities", HFILL }},
3133 static gint *tree_array[] = {
3140 &ett_fixed_parameters,
3141 &ett_tagged_parameters,
3142 &ett_qos_parameters,
3143 &ett_wep_parameters,
3147 module_t *wlan_module;
3149 static const enum_val_t wep_keys_options[] = {
3159 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
3160 "IEEE 802.11", "wlan");
3161 proto_register_field_array (proto_wlan, hf, array_length (hf));
3162 proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
3163 "802.11 MGT", "wlan_mgt");
3164 proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
3165 proto_register_subtree_array (tree_array, array_length (tree_array));
3167 register_dissector("wlan", dissect_ieee80211, proto_wlan);
3168 register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
3169 register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
3170 register_init_routine(wlan_defragment_init);
3172 /* Register configuration options */
3173 wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);
3174 prefs_register_bool_preference(wlan_module, "defragment",
3175 "Reassemble fragmented 802.11 datagrams",
3176 "Whether fragmented 802.11 datagrams should be reassembled",
3179 prefs_register_bool_preference(wlan_module, "check_fcs",
3180 "Assume packets have FCS",
3181 "Some 802.11 cards include the FCS at the end of a packet, others do not.",
3184 prefs_register_bool_preference(wlan_module, "ignore_wep",
3185 "Ignore the WEP bit",
3186 "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
3190 prefs_register_enum_preference(wlan_module, "wep_keys",
3192 "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
3193 &num_wepkeys, wep_keys_options, FALSE);
3195 prefs_register_string_preference(wlan_module, "wep_key1",
3197 "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",
3199 prefs_register_string_preference(wlan_module, "wep_key2",
3201 "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",
3203 prefs_register_string_preference(wlan_module, "wep_key3",
3205 "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",
3207 prefs_register_string_preference(wlan_module, "wep_key4",
3209 "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",
3215 proto_reg_handoff_ieee80211(void)
3217 dissector_handle_t ieee80211_handle;
3218 dissector_handle_t ieee80211_radio_handle;
3221 * Get handles for the LLC, IPX and Ethernet dissectors.
3223 llc_handle = find_dissector("llc");
3224 ipx_handle = find_dissector("ipx");
3225 eth_handle = find_dissector("eth");
3226 data_handle = find_dissector("data");
3228 ieee80211_handle = find_dissector("wlan");
3229 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
3230 ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
3232 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
3233 ieee80211_radio_handle);
3236 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
3237 const guint8 *enc_data;
3240 tvbuff_t *decr_tvb = NULL;
3242 if (num_wepkeys < 1)
3245 enc_data = tvb_get_ptr(tvb, offset, len);
3247 if ((tmp = g_malloc(len)) == NULL)
3248 return NULL; /* krap! */
3250 /* try once with the key index in the packet, then look through our list. */
3251 for (i = -1; i < (int) num_wepkeys; i++) {
3252 /* copy the encrypted data over to the tmp buffer */
3254 printf("trying %d\n", i);
3256 memcpy(tmp, enc_data, len);
3257 if (wep_decrypt(tmp, len, i) == 0) {
3259 /* decrypt successful, let's set up a new data tvb. */
3260 decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
3261 tvb_set_free_cb(decr_tvb, g_free);
3262 tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
3269 if ((!decr_tvb) && (tmp)) g_free(tmp);
3272 printf("de-wep %p\n", decr_tvb);
3279 /* de-weps the block. if successful, buf* will point to the data start. */
3280 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
3281 guint32 i, j, k, crc, keylen;
3282 guint8 s[256], key[128], c_crc[4];
3283 guint8 keyidx, *dpos, *cpos;
3285 /* Needs to be at least 8 bytes of payload */
3289 /* initialize the first bytes of the key from the IV */
3293 keyidx = COOK_WEP_KEY(buf[3]);
3295 if (key_override >= 0)
3296 keyidx = key_override;
3298 if (keyidx >= num_wepkeys)
3301 keylen = wep_keylens[keyidx];
3305 if (wep_keys[keyidx] == NULL)
3308 keylen+=3; /* add in ICV bytes */
3310 /* copy the rest of the key over from the designated key */
3311 memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
3314 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]);
3317 /* set up the RC4 state */
3318 for (i = 0; i < 256; i++)
3321 for (i = 0; i < 256; i++) {
3322 j = (j + s[i] + key[i % keylen]) & 0xff;
3326 /* Apply the RC4 to the data, update the CRC32 */
3331 for (k = 0; k < (len -8); k++) {
3333 j = (j+s[i]) & 0xff;
3336 printf("%d -- %02x ", k, *dpos);
3338 *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
3340 printf("%02x\n", *dpos);
3342 crc = crc32_ccitt_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
3346 /* now let's check the crc */
3348 c_crc[1] = crc >> 8;
3349 c_crc[2] = crc >> 16;
3350 c_crc[3] = crc >> 24;
3352 for (k = 0; k < 4; k++) {
3354 j = (j+s[i]) & 0xff;
3357 printf("-- %02x %02x\n", *dpos, c_crc[k]);
3359 if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
3360 return -1; /* ICV mismatch */
3366 static void init_wepkeys(void) {
3375 tmp = getenv("ETHEREAL_WEPKEYNUM");
3380 num_wepkeys = atoi(tmp);
3382 if (num_wepkeys > 4)
3386 if (num_wepkeys < 1)
3393 g_free(wep_keylens);
3395 wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
3396 wep_keylens = g_malloc(num_wepkeys * sizeof(int));
3397 bytes = g_byte_array_new();
3399 for (i = 0 ; i < num_wepkeys; i++) {
3404 sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
3407 tmp = wep_keystr[i];
3413 printf("%s -- %s\n", buf, tmp);
3415 printf("%d -- %s\n", i+1, tmp);
3420 g_free(wep_keys[i]);
3423 res = hex_str_to_bytes(tmp, bytes, FALSE);
3424 if (res && bytes->len > 0) {
3425 if (bytes->len > 32) {
3428 wep_keys[i] = g_malloc(32 * sizeof(guint8));
3429 memset(wep_keys[i], 0, 32 * sizeof(guint8));
3430 memcpy(wep_keys[i], bytes->data, bytes->len * sizeof(guint8));
3431 wep_keylens[i] = bytes->len;
3433 printf("%d: %d bytes\n", i, bytes->len);
3434 printf("%d: %s\n", i, bytes_to_str(bytes->data, bytes->len));
3438 printf("res: %d bytes->len: %d\n", res, bytes->len);
3440 g_warning("Could not parse WEP key %d: %s", i + 1, tmp);
3444 g_byte_array_free(bytes, TRUE);