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/addr_resolv.h>
63 #include <epan/strutil.h>
64 #include <epan/prefs.h>
65 #include "reassemble.h"
66 #include "packet-ipx.h"
67 #include "packet-llc.h"
68 #include "packet-ieee80211.h"
70 #include <epan/crc32.h>
76 /* Defragment fragmented 802.11 datagrams */
77 static gboolean wlan_defragment = TRUE;
79 /* Check for the presence of the 802.11 FCS */
80 static gboolean wlan_check_fcs = FALSE;
82 /* Ignore the WEP bit; assume packet is decrypted */
83 static gboolean wlan_ignore_wep = FALSE;
85 /* Tables for reassembly of fragments. */
86 static GHashTable *wlan_fragment_table = NULL;
87 static GHashTable *wlan_reassembled_table = NULL;
89 /* Stuff for the WEP decoder */
90 static guint num_wepkeys = 0;
91 static guint8 **wep_keys = NULL;
92 static int *wep_keylens = NULL;
93 static void init_wepkeys(void);
94 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
95 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
96 static int weak_iv(guchar *iv);
97 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
100 /* When this is set, an unlimited number of WEP keys can be set in the
103 ETHEREAL_WEPKEYNUM=##
104 ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
105 ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
107 ... you get the idea.
109 otherwise you're limited to specifying four keys in the preference system.
113 static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
116 /* ************************************************************************* */
117 /* Miscellaneous Constants */
118 /* ************************************************************************* */
119 #define SHORT_STR 256
121 /* ************************************************************************* */
122 /* Define some very useful macros that are used to analyze frame types etc. */
123 /* ************************************************************************* */
124 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */
125 #define COOK_PROT_VERSION(x) ((x) & 0x3)
126 #define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2)
127 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
128 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
129 #define COOK_ASSOC_ID(x) ((x) & 0x3FFF)
130 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
131 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
132 #define COOK_QOS_PRIORITY(x) ((x) & 0x0007)
133 #define COOK_QOS_ACK_POLICY(x) (((x) & 0x0060) >> 5)
134 #define COOK_FLAGS(x) (((x) & 0xFF00) >> 8)
135 #define COOK_DS_STATUS(x) ((x) & 0x3)
136 #define COOK_WEP_KEY(x) (((x) & 0xC0) >> 6)
138 #define KEY_EXTIV 0x20
141 #define FLAG_TO_DS 0x01
142 #define FLAG_FROM_DS 0x02
143 #define FLAG_MORE_FRAGMENTS 0x04
144 #define FLAG_RETRY 0x08
145 #define FLAG_POWER_MGT 0x10
146 #define FLAG_MORE_DATA 0x20
147 #define FLAG_WEP 0x40
148 #define FLAG_ORDER 0x80
150 #define IS_TO_DS(x) ((x) & FLAG_TO_DS)
151 #define IS_FROM_DS(x) ((x) & FLAG_FROM_DS)
152 #define HAVE_FRAGMENTS(x) ((x) & FLAG_MORE_FRAGMENTS)
153 #define IS_RETRY(x) ((x) & FLAG_RETRY)
154 #define POWER_MGT_STATUS(x) ((x) & FLAG_POWER_MGT)
155 #define HAS_MORE_DATA(x) ((x) & FLAG_MORE_DATA)
156 #define IS_WEP(x) (!wlan_ignore_wep && ((x) & FLAG_WEP))
157 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
159 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
160 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
161 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
162 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
165 /* ************************************************************************* */
166 /* Constants used to identify cooked frame types */
167 /* ************************************************************************* */
168 #define MGT_FRAME 0x00 /* Frame type is management */
169 #define CONTROL_FRAME 0x01 /* Frame type is control */
170 #define DATA_FRAME 0x02 /* Frame type is Data */
172 #define DATA_SHORT_HDR_LEN 24
173 #define DATA_LONG_HDR_LEN 30
174 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
176 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
177 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
178 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
179 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
180 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
181 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
182 #define MGT_BEACON 0x08 /* Management - Beacon frame */
183 #define MGT_ATIM 0x09 /* Management - ATIM */
184 #define MGT_DISASS 0x0A /* Management - Disassociation */
185 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
186 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
187 #define MGT_ACTION 0x0D /* Management - Action */
189 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
190 #define CTRL_RTS 0x1B /* Control - request to send */
191 #define CTRL_CTS 0x1C /* Control - clear to send */
192 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
193 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
194 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
196 #define DATA 0x20 /* Data - Data */
197 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
198 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
199 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
200 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
201 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
202 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
203 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
204 #define DATA_QOS_DATA 0x28 /* Data - QoS Data */
205 #define DATA_QOS_NULL 0x2c /* Data - QoS Null */
207 #define DATA_ADDR_T1 0
208 #define DATA_ADDR_T2 (FLAG_FROM_DS << 8)
209 #define DATA_ADDR_T3 (FLAG_TO_DS << 8)
210 #define DATA_ADDR_T4 ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
213 /* ************************************************************************* */
214 /* Macros used to extract information about fixed fields */
215 /* ************************************************************************* */
216 #define ESS_SET(x) ((x) & 0x0001)
217 #define IBSS_SET(x) ((x) & 0x0002)
221 /* ************************************************************************* */
222 /* Logical field codes (dissector's encoding of fixed fields) */
223 /* ************************************************************************* */
224 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
225 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
226 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
227 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
228 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
229 #define FIELD_CURRENT_AP_ADDR 0x06
230 #define FIELD_LISTEN_IVAL 0x07
231 #define FIELD_REASON_CODE 0x08
232 #define FIELD_ASSOC_ID 0x09
233 #define FIELD_STATUS_CODE 0x0A
234 #define FIELD_CATEGORY_CODE 0x0B /* Management action category */
235 #define FIELD_ACTION_CODE 0x0C /* Management action code */
236 #define FIELD_DIALOG_TOKEN 0x0D /* Management action dialog token */
237 #define FIELD_WME_ACTION_CODE 0x0E /* Management notification action code */
238 #define FIELD_WME_DIALOG_TOKEN 0x0F /* Management notification dialog token */
239 #define FIELD_WME_STATUS_CODE 0x10 /* Management notification setup response status code */
241 /* ************************************************************************* */
242 /* Logical field codes (IEEE 802.11 encoding of tags) */
243 /* ************************************************************************* */
244 #define TAG_SSID 0x00
245 #define TAG_SUPP_RATES 0x01
246 #define TAG_FH_PARAMETER 0x02
247 #define TAG_DS_PARAMETER 0x03
248 #define TAG_CF_PARAMETER 0x04
250 #define TAG_IBSS_PARAMETER 0x06
251 #define TAG_COUNTRY_INFO 0x07
252 #define TAG_FH_HOPPING_PARAMETER 0x08
253 #define TAG_FH_HOPPING_TABLE 0x09
254 #define TAG_CHALLENGE_TEXT 0x10
255 #define TAG_ERP_INFO 0x2A
256 #define TAG_ERP_INFO_OLD 0x2F /* IEEE Std 802.11g/D4.0 */
257 #define TAG_RSN_IE 0x30
258 #define TAG_EXT_SUPP_RATES 0x32
259 #define TAG_VENDOR_SPECIFIC_IE 0xDD
261 #define WPA_OUI "\x00\x50\xF2"
262 #define RSN_OUI "\x00\x0F\xAC"
263 #define WME_OUI "\x00\x50\xF2"
267 /* ************************************************************************* */
268 /* Frame types, and their names */
269 /* ************************************************************************* */
270 static const value_string frame_type_subtype_vals[] = {
271 {MGT_ASSOC_REQ, "Association Request"},
272 {MGT_ASSOC_RESP, "Association Response"},
273 {MGT_REASSOC_REQ, "Reassociation Request"},
274 {MGT_REASSOC_RESP, "Reassociation Response"},
275 {MGT_PROBE_REQ, "Probe Request"},
276 {MGT_PROBE_RESP, "Probe Response"},
277 {MGT_BEACON, "Beacon frame"},
279 {MGT_DISASS, "Dissassociate"},
280 {MGT_AUTHENTICATION, "Authentication"},
281 {MGT_DEAUTHENTICATION, "Deauthentication"},
282 {MGT_ACTION, "Action"},
283 {CTRL_PS_POLL, "Power-Save poll"},
284 {CTRL_RTS, "Request-to-send"},
285 {CTRL_CTS, "Clear-to-send"},
286 {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
287 {CTRL_CFP_END, "CF-End (Control-frame)"},
288 {CTRL_CFP_ENDACK, "CF-End + CF-Ack (Control-frame)"},
290 {DATA_CF_ACK, "Data + CF-Acknowledgement"},
291 {DATA_CF_POLL, "Data + CF-Poll"},
292 {DATA_CF_ACK_POLL, "Data + CF-Acknowledgement/Poll"},
293 {DATA_NULL_FUNCTION, "Null function (No data)"},
294 {DATA_CF_ACK_NOD, "Data + Acknowledgement (No data)"},
295 {DATA_CF_POLL_NOD, "Data + CF-Poll (No data)"},
296 {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
297 {DATA_QOS_DATA, "QoS Data"},
298 {DATA_QOS_NULL, "QoS Null (No data)"},
302 /* ************************************************************************* */
303 /* 802.1D Tag Names */
304 /* ************************************************************************* */
305 static const char *qos_tags[8] = {
316 /* ************************************************************************* */
317 /* WME Access Category Names (by 802.1D Tag) */
318 /* ************************************************************************* */
319 static const char *qos_acs[8] = {
330 /* ************************************************************************* */
331 /* WME Access Category Names (by WME ACI) */
332 /* ************************************************************************* */
333 static const char *wme_acs[4] = {
340 static int proto_wlan = -1;
342 /* ************************************************************************* */
343 /* Header field info values for radio information */
344 /* ************************************************************************* */
345 static int hf_data_rate = -1;
346 static int hf_channel = -1;
347 static int hf_signal_strength = -1;
349 /* ************************************************************************* */
350 /* Header field info values for FC-field */
351 /* ************************************************************************* */
352 static int hf_fc_field = -1;
353 static int hf_fc_proto_version = -1;
354 static int hf_fc_frame_type = -1;
355 static int hf_fc_frame_subtype = -1;
356 static int hf_fc_frame_type_subtype = -1;
358 static int hf_fc_flags = -1;
359 static int hf_fc_to_ds = -1;
360 static int hf_fc_from_ds = -1;
361 static int hf_fc_data_ds = -1;
363 static int hf_fc_more_frag = -1;
364 static int hf_fc_retry = -1;
365 static int hf_fc_pwr_mgt = -1;
366 static int hf_fc_more_data = -1;
367 static int hf_fc_wep = -1;
368 static int hf_fc_order = -1;
371 /* ************************************************************************* */
372 /* Header values for Duration/ID field */
373 /* ************************************************************************* */
374 static int hf_did_duration = -1;
375 static int hf_assoc_id = -1;
378 /* ************************************************************************* */
379 /* Header values for different address-fields (all 4 of them) */
380 /* ************************************************************************* */
381 static int hf_addr_da = -1; /* Destination address subfield */
382 static int hf_addr_sa = -1; /* Source address subfield */
383 static int hf_addr_ra = -1; /* Receiver address subfield */
384 static int hf_addr_ta = -1; /* Transmitter address subfield */
385 static int hf_addr_bssid = -1; /* address is bssid */
387 static int hf_addr = -1; /* Source or destination address subfield */
390 /* ************************************************************************* */
391 /* Header values for QoS control field */
392 /* ************************************************************************* */
393 static int hf_qos_priority = -1;
394 static int hf_qos_ack_policy = -1;
396 /* ************************************************************************* */
397 /* Header values for sequence number field */
398 /* ************************************************************************* */
399 static int hf_frag_number = -1;
400 static int hf_seq_number = -1;
402 /* ************************************************************************* */
403 /* Header values for Frame Check field */
404 /* ************************************************************************* */
405 static int hf_fcs = -1;
407 /* ************************************************************************* */
408 /* Header values for reassembly */
409 /* ************************************************************************* */
410 static int hf_fragments = -1;
411 static int hf_fragment = -1;
412 static int hf_fragment_overlap = -1;
413 static int hf_fragment_overlap_conflict = -1;
414 static int hf_fragment_multiple_tails = -1;
415 static int hf_fragment_too_long_fragment = -1;
416 static int hf_fragment_error = -1;
417 static int hf_reassembled_in = -1;
420 static int proto_wlan_mgt = -1;
421 /* ************************************************************************* */
422 /* Fixed fields found in mgt frames */
423 /* ************************************************************************* */
424 static int ff_auth_alg = -1; /* Authentication algorithm field */
425 static int ff_auth_seq = -1; /* Authentication transaction sequence */
426 static int ff_current_ap = -1; /* Current AP MAC address */
427 static int ff_listen_ival = -1; /* Listen interval fixed field */
428 static int ff_timestamp = -1; /* 64 bit timestamp */
429 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
430 static int ff_assoc_id = -1; /* 16 bit AID field */
431 static int ff_reason = -1; /* 16 bit reason code */
432 static int ff_status_code = -1; /* Status code */
433 static int ff_category_code = -1; /* 8 bit Category code */
434 static int ff_action_code = -1; /* 8 bit Action code */
435 static int ff_dialog_token = -1; /* 8 bit Dialog token */
436 static int ff_wme_action_code = -1; /* Management notification action code */
437 static int ff_wme_status_code = -1; /* Management notification setup response status code */
439 /* ************************************************************************* */
440 /* Flags found in the capability field (fixed field) */
441 /* ************************************************************************* */
442 static int ff_capture = -1;
443 static int ff_cf_ess = -1;
444 static int ff_cf_ibss = -1;
445 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
446 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
447 static int ff_cf_privacy = -1;
448 static int ff_cf_preamble = -1;
449 static int ff_cf_pbcc = -1;
450 static int ff_cf_agility = -1;
451 static int ff_short_slot_time = -1;
452 static int ff_dsss_ofdm = -1;
454 /* ************************************************************************* */
455 /* Tagged value format fields */
456 /* ************************************************************************* */
457 static int tag_number = -1;
458 static int tag_length = -1;
459 static int tag_interpretation = -1;
463 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
464 static int hf_tagged_parameters = -1; /* Fixed payload item */
465 static int hf_wep_iv = -1;
466 static int hf_wep_iv_weak = -1;
467 static int hf_tkip_extiv = -1;
468 static int hf_ccmp_extiv = -1;
469 static int hf_wep_key = -1;
470 static int hf_wep_icv = -1;
473 static int rsn_cap = -1;
474 static int rsn_cap_preauth = -1;
475 static int rsn_cap_no_pairwise = -1;
476 static int rsn_cap_ptksa_replay_counter = -1;
477 static int rsn_cap_gtksa_replay_counter = -1;
479 /* ************************************************************************* */
481 /* ************************************************************************* */
482 static gint ett_80211 = -1;
483 static gint ett_proto_flags = -1;
484 static gint ett_cap_tree = -1;
485 static gint ett_fc_tree = -1;
486 static gint ett_fragments = -1;
487 static gint ett_fragment = -1;
489 static gint ett_80211_mgt = -1;
490 static gint ett_fixed_parameters = -1;
491 static gint ett_tagged_parameters = -1;
492 static gint ett_qos_parameters = -1;
493 static gint ett_wep_parameters = -1;
495 static gint ett_rsn_cap_tree = -1;
497 static const fragment_items frag_items = {
502 &hf_fragment_overlap,
503 &hf_fragment_overlap_conflict,
504 &hf_fragment_multiple_tails,
505 &hf_fragment_too_long_fragment,
511 static dissector_handle_t llc_handle;
512 static dissector_handle_t ipx_handle;
513 static dissector_handle_t eth_withoutfcs_handle;
514 static dissector_handle_t data_handle;
516 static int wlan_tap = -1;
518 /* ************************************************************************* */
519 /* Return the length of the current header (in bytes) */
520 /* ************************************************************************* */
522 find_header_length (guint16 fcf)
526 switch (COOK_FRAME_TYPE (fcf)) {
529 return MGT_FRAME_HDR_LEN;
532 switch (COMPOSE_FRAME_TYPE (fcf)) {
535 case CTRL_ACKNOWLEDGEMENT:
541 case CTRL_CFP_ENDACK:
547 len = (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
549 switch (COMPOSE_FRAME_TYPE (fcf)) {
564 /* ************************************************************************* */
565 /* This is the capture function used to update packet counts */
566 /* ************************************************************************* */
568 capture_ieee80211_common (const guchar * pd, int offset, int len,
569 packet_counts * ld, gboolean fixed_length_header)
571 guint16 fcf, hdr_length;
573 if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
578 fcf = pletohs (&pd[0]);
580 if (IS_WEP(COOK_FLAGS(fcf)))
586 switch (COMPOSE_FRAME_TYPE (fcf))
589 case DATA: /* We got a data frame */
590 case DATA_CF_ACK: /* Data with ACK */
592 case DATA_CF_ACK_POLL:
594 if (fixed_length_header)
595 hdr_length = DATA_LONG_HDR_LEN;
597 hdr_length = find_header_length (fcf);
598 /* I guess some bridges take Netware Ethernet_802_3 frames,
599 which are 802.3 frames (with a length field rather than
600 a type field, but with no 802.2 header in the payload),
601 and just stick the payload into an 802.11 frame. I've seen
602 captures that show frames of that sort.
604 This means we have to do the same check for Netware 802.3 -
605 or, if you will, "Netware 802.11" - that we do in the
606 Ethernet dissector, i.e. checking for 0xffff as the first
607 four bytes of the payload and, if we find it, treating it
609 if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
613 if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
617 capture_llc (pd, offset + hdr_length, len, ld);
628 * Handle 802.11 with a variable-length link-layer header.
631 capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
633 capture_ieee80211_common (pd, offset, len, ld, FALSE);
637 * Handle 802.11 with a fixed-length link-layer header (padded to the
641 capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
643 capture_ieee80211_common (pd, offset, len, ld, TRUE);
647 /* ************************************************************************* */
648 /* Add the subtree used to store the fixed parameters */
649 /* ************************************************************************* */
651 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
653 proto_item *fixed_fields;
655 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
656 size, size, "Fixed parameters (%d bytes)",
659 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
663 /* ************************************************************************* */
664 /* Add the subtree used to store tagged parameters */
665 /* ************************************************************************* */
667 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
669 proto_item *tagged_fields;
671 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
676 "Tagged parameters (%d bytes)",
679 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
683 /* ************************************************************************* */
684 /* Dissect and add fixed mgmt fields to protocol tree */
685 /* ************************************************************************* */
687 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
689 const guint8 *dataptr;
690 char out_buff[SHORT_STR];
692 proto_item *cap_item;
693 static proto_tree *cap_tree;
698 case FIELD_TIMESTAMP:
699 dataptr = tvb_get_ptr (tvb, offset, 8);
700 memset (out_buff, 0, SHORT_STR);
701 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
711 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
714 case FIELD_BEACON_INTERVAL:
715 temp_double = (double) tvb_get_letohs (tvb, offset);
716 temp_double = temp_double * 1024 / 1000000;
717 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
718 temp_double,"Beacon Interval: %f [Seconds]",
724 capability = tvb_get_letohs (tvb, offset);
726 cap_item = proto_tree_add_uint_format (tree, ff_capture,
729 "Capability Information: 0x%04X",
731 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
732 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
734 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
736 if (ESS_SET (capability) != 0) /* This is an AP */
737 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
740 else /* This is a STA */
741 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
743 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
745 proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
747 proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
749 proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
751 proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
753 proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
758 proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
761 case FIELD_AUTH_TRANS_SEQ:
762 proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
765 case FIELD_CURRENT_AP_ADDR:
766 proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
769 case FIELD_LISTEN_IVAL:
770 proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
773 case FIELD_REASON_CODE:
774 proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
778 proto_tree_add_uint(tree, ff_assoc_id, tvb, offset, 2,
779 COOK_ASSOC_ID(tvb_get_letohs(tvb,offset)));
780 /* proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE); */
783 case FIELD_STATUS_CODE:
784 proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
787 case FIELD_CATEGORY_CODE:
788 proto_tree_add_item (tree, ff_category_code, tvb, offset, 1, TRUE);
791 case FIELD_ACTION_CODE:
792 proto_tree_add_item (tree, ff_action_code, tvb, offset, 1, TRUE);
795 case FIELD_DIALOG_TOKEN:
796 proto_tree_add_item (tree, ff_dialog_token, tvb, offset, 1, TRUE);
799 case FIELD_WME_ACTION_CODE:
800 proto_tree_add_item (tree, ff_wme_action_code, tvb, offset, 1, TRUE);
803 case FIELD_WME_STATUS_CODE:
804 proto_tree_add_item (tree, ff_wme_status_code, tvb, offset, 1, TRUE);
809 static char *wpa_cipher_str[] =
820 wpa_cipher_idx2str(guint idx)
822 if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
823 return wpa_cipher_str[idx];
827 static char *wpa_keymgmt_str[] =
835 wpa_keymgmt_idx2str(guint idx)
837 if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
838 return wpa_keymgmt_str[idx];
843 dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
844 guint32 tag_len, const guint8 *tag_val)
846 guint32 tag_val_off = 0;
847 char out_buff[SHORT_STR], *pos;
850 /* Wi-Fi Protected Access (WPA) Information Element */
851 if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
852 snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
853 tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
854 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
857 if (tag_val_off + 4 <= tag_len) {
858 /* multicast cipher suite */
859 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
860 snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
861 wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
862 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
865 /* unicast cipher suites */
866 if (tag_val_off + 2 <= tag_len) {
867 snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
868 pletohs(tag_val + tag_val_off));
869 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
873 while (tag_val_off + 4 <= tag_len) {
874 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
875 snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
876 i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
877 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
885 /* authenticated key management suites */
886 if (tag_val_off + 2 <= tag_len) {
887 snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
888 pletohs(tag_val + tag_val_off));
889 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
893 while (tag_val_off + 4 <= tag_len) {
894 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
895 snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
896 i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
897 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
909 if (tag_val_off < tag_len)
910 proto_tree_add_string(tree, tag_interpretation, tvb,
911 offset, tag_len - tag_val_off, "Not interpreted");
912 } else if (tag_val_off + 7 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x00", 5)) {
913 /* Wireless Multimedia Enhancements (WME) Information Element */
914 snprintf(out_buff, SHORT_STR, "WME IE: type %u, subtype %u, version %u, parameter set %u",
915 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
916 tag_val[tag_val_off + 6]);
917 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
918 } else if (tag_val_off + 24 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x01", 5)) {
919 /* Wireless Multimedia Enhancements (WME) Parameter Element */
920 snprintf(out_buff, SHORT_STR, "WME PE: type %u, subtype %u, version %u, parameter set %u",
921 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
922 tag_val[tag_val_off + 6]);
923 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
926 for (i = 0; i < 4; i++) {
927 snprintf(out_buff, SHORT_STR, "WME AC Parameters: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
928 (tag_val[tag_val_off] & 0x60) >> 5,
929 wme_acs[(tag_val[tag_val_off] & 0x60) >> 5],
930 (tag_val[tag_val_off] & 0x10) ? "" : "not ",
931 tag_val[tag_val_off] & 0x0f,
932 tag_val[tag_val_off + 1] & 0x0f,
933 (tag_val[tag_val_off + 1] & 0xf0) >> 4,
934 tvb_get_letohs(tvb, offset + 2));
935 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
939 } else if (tag_val_off + 56 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x02", 5)) {
940 /* Wireless Multimedia Enhancements (WME) TSPEC Element */
941 guint16 ts_info, msdu_size, surplus_bandwidth;
942 const char *direction[] = { "Uplink", "Downlink", "Reserved", "Bi-directional" };
943 const value_string fields[] = {
944 {12, "Minimum Service Interval"},
945 {16, "Maximum Service Interval"},
946 {20, "Inactivity Interval"},
947 {24, "Service Start Time"},
948 {28, "Minimum Data Rate"},
949 {32, "Mean Data Rate"},
950 {36, "Maximum Burst Size"},
951 {40, "Minimum PHY Rate"},
952 {44, "Peak Data Rate"},
958 snprintf(out_buff, SHORT_STR, "WME TSPEC: type %u, subtype %u, version %u",
959 tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5]);
960 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
964 ts_info = tvb_get_letohs(tvb, offset);
965 snprintf(out_buff, SHORT_STR, "WME TS Info: Priority %u (%s) (%s), Contention-based access %sset, %s",
966 (ts_info >> 11) & 0x7, qos_tags[(ts_info >> 11) & 0x7], qos_acs[(ts_info >> 11) & 0x7],
967 (ts_info & 0x0080) ? "" : "not ",
968 direction[(ts_info >> 5) & 0x3]);
969 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
973 msdu_size = tvb_get_letohs(tvb, offset);
974 snprintf(out_buff, SHORT_STR, "WME TSPEC: %s MSDU Size %u",
975 (msdu_size & 0x8000) ? "Fixed" : "Nominal", msdu_size & 0x7fff);
976 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
980 snprintf(out_buff, SHORT_STR, "WME TSPEC: Maximum MSDU Size %u", tvb_get_letohs(tvb, offset));
981 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
985 while ((field = val_to_str(tag_val_off, fields, NULL))) {
986 snprintf(out_buff, SHORT_STR, "WME TSPEC: %s %u", field, tvb_get_letohl(tvb, offset));
987 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
990 if (tag_val_off == 52)
994 surplus_bandwidth = tvb_get_letohs(tvb, offset);
995 snprintf(out_buff, SHORT_STR, "WME TSPEC: Surplus Bandwidth Allowance Factor %u.%u",
996 (surplus_bandwidth >> 13) & 0x7, (surplus_bandwidth & 0x1fff));
1000 snprintf(out_buff, SHORT_STR, "WME TSPEC: Medium Time %u", tvb_get_letohs(tvb, offset));
1001 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1004 } else if (tag_val_off + 4 <= tag_len && !memcmp(tag_val, RSN_OUI"\x04", 4)) {
1005 /* IEEE 802.11i / Key Data Encapsulation / Data Type=4 - PMKID.
1006 * This is only used within EAPOL-Key frame Key Data. */
1008 pos += snprintf(pos, out_buff + SHORT_STR - pos, "RSN PMKID: ");
1009 if (tag_len - 4 != PMKID_LEN) {
1010 pos += snprintf(pos, out_buff + SHORT_STR - pos,
1011 "(invalid PMKID len=%d, expected 16) ", tag_len - 4);
1013 for (i = 0; i < tag_len - 4; i++) {
1014 pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
1015 tag_val[tag_val_off + 4 + i]);
1017 proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1020 proto_tree_add_string(tree, tag_interpretation,
1021 tvb, offset, tag_len, "Not interpreted");
1025 dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
1026 guint32 tag_len, const guint8 *tag_val)
1028 guint32 tag_val_off = 0;
1030 char out_buff[SHORT_STR];
1032 proto_item *cap_item;
1033 proto_tree *cap_tree;
1035 if (tag_val_off + 2 > tag_len) {
1036 proto_tree_add_string(tree, tag_interpretation, tvb, offset, tag_len,
1041 snprintf(out_buff, SHORT_STR, "RSN IE, version %u",
1042 pletohs(&tag_val[tag_val_off]));
1043 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1048 if (tag_val_off + 4 > tag_len)
1051 /* multicast cipher suite */
1052 if (!memcmp(&tag_val[tag_val_off], RSN_OUI, 3)) {
1053 snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
1054 wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1055 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1060 if (tag_val_off + 2 > tag_len)
1063 /* unicast cipher suites */
1064 count = pletohs(tag_val + tag_val_off);
1065 snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", count);
1066 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1070 while (tag_val_off + 4 <= tag_len && i <= count) {
1071 if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
1073 snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
1074 i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
1075 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1081 if (i <= count || tag_val_off + 2 > tag_len)
1084 /* authenticated key management suites */
1085 count = pletohs(tag_val + tag_val_off);
1086 snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", count);
1087 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1091 while (tag_val_off + 4 <= tag_len && i <= count) {
1092 if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
1094 snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
1095 i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
1096 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
1102 if (i <= count || tag_val_off + 2 > tag_len)
1105 rsn_capab = pletohs(&tag_val[tag_val_off]);
1106 snprintf(out_buff, SHORT_STR, "RSN Capabilities 0x%04x", rsn_capab);
1107 cap_item = proto_tree_add_uint_format(tree, rsn_cap, tvb,
1108 offset, 2, rsn_capab,
1109 "RSN Capabilities: 0x%04X", rsn_capab);
1110 cap_tree = proto_item_add_subtree(cap_item, ett_rsn_cap_tree);
1111 proto_tree_add_boolean(cap_tree, rsn_cap_preauth, tvb, offset, 2,
1113 proto_tree_add_boolean(cap_tree, rsn_cap_no_pairwise, tvb, offset, 2,
1115 proto_tree_add_uint(cap_tree, rsn_cap_ptksa_replay_counter, tvb, offset, 2,
1117 proto_tree_add_uint(cap_tree, rsn_cap_gtksa_replay_counter, tvb, offset, 2,
1122 if (tag_val_off + 2 > tag_len)
1125 count = pletohs(tag_val + tag_val_off);
1126 snprintf(out_buff, SHORT_STR, "# of PMKIDs: %u", count);
1127 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
1131 /* PMKID List (16 * n octets) */
1132 for (i = 0; i < count; i++) {
1134 if (tag_val_off + PMKID_LEN > tag_len)
1137 pos += snprintf(pos, out_buff + SHORT_STR - pos, "PMKID %u: ", i);
1138 for (j = 0; j < PMKID_LEN; j++) {
1139 pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
1140 tag_val[tag_val_off + j]);
1142 proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1143 PMKID_LEN, out_buff);
1144 offset += PMKID_LEN;
1145 tag_val_off += PMKID_LEN;
1149 if (tag_val_off < tag_len)
1150 proto_tree_add_string(tree, tag_interpretation, tvb, offset,
1151 tag_len - tag_val_off, "Not interpreted");
1154 /* ************************************************************************* */
1155 /* Dissect and add tagged (optional) fields to proto tree */
1156 /* ************************************************************************* */
1158 static const value_string tag_num_vals[] = {
1159 { TAG_SSID, "SSID parameter set" },
1160 { TAG_SUPP_RATES, "Supported Rates" },
1161 { TAG_FH_PARAMETER, "FH Parameter set" },
1162 { TAG_DS_PARAMETER, "DS Parameter set" },
1163 { TAG_CF_PARAMETER, "CF Parameter set" },
1164 { TAG_TIM, "(TIM) Traffic Indication Map" },
1165 { TAG_IBSS_PARAMETER, "IBSS Parameter set" },
1166 { TAG_COUNTRY_INFO, "Country Information" },
1167 { TAG_FH_HOPPING_PARAMETER, "Hopping Pattern Parameters" },
1168 { TAG_CHALLENGE_TEXT, "Challenge text" },
1169 { TAG_ERP_INFO, "ERP Information" },
1170 { TAG_ERP_INFO_OLD, "ERP Information" },
1171 { TAG_RSN_IE, "RSN Information" },
1172 { TAG_EXT_SUPP_RATES, "Extended Supported Rates" },
1173 { TAG_VENDOR_SPECIFIC_IE, "Vendor Specific" },
1177 static const value_string environment_vals[] = {
1179 { 0x4f, "Outdoor" },
1185 add_tagged_field (packet_info * pinfo, proto_tree * tree, tvbuff_t * tvb, int offset)
1187 const guint8 *tag_data_ptr;
1188 guint32 tag_no, tag_len;
1191 char out_buff[SHORT_STR];
1194 tag_no = tvb_get_guint8(tvb, offset);
1195 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
1196 "Tag Number: %u (%s)",
1198 val_to_str(tag_no, tag_num_vals,
1199 (tag_no >= 17 && tag_no <= 31) ?
1200 "Reserved for challenge text" :
1201 "Reserved tag number"));
1203 tag_len = tvb_get_guint8(tvb, offset + 1);
1204 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
1206 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
1213 memset (out_buff, 0, SHORT_STR);
1215 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
1216 out_buff[tag_len + 1] = 0;
1217 for (i = 0; i < tag_len; i++) {
1218 if (!isprint( (int) out_buff[i])) {
1222 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1224 if (check_col (pinfo->cinfo, COL_INFO)) {
1226 col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID: \"%s\"", out_buff);
1228 col_append_fstr(pinfo->cinfo, COL_INFO, ", SSID: Broadcast");
1235 case TAG_SUPP_RATES:
1236 case TAG_EXT_SUPP_RATES:
1237 memset (out_buff, 0, SHORT_STR);
1238 strcpy (out_buff, "Supported rates: ");
1239 n = strlen (out_buff);
1241 for (i = 0; i < tag_len && n < SHORT_STR; i++)
1243 ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
1244 (tag_data_ptr[i] & 0x7F) * 0.5,
1245 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
1246 if (ret == -1 || ret >= SHORT_STR - n) {
1247 /* Some versions of snprintf return -1 if they'd truncate
1248 the output. Others return <buf_size> or greater. */
1254 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
1256 out_buff[SHORT_STR-1] = '\0';
1257 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1263 case TAG_FH_PARAMETER:
1264 memset (out_buff, 0, SHORT_STR);
1266 snprintf (out_buff, SHORT_STR,
1267 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
1268 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
1269 tag_data_ptr[3], tag_data_ptr[4]);
1271 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1277 case TAG_DS_PARAMETER:
1278 memset (out_buff, 0, SHORT_STR);
1280 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
1281 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1286 case TAG_CF_PARAMETER:
1287 memset (out_buff, 0, SHORT_STR);
1289 snprintf (out_buff, SHORT_STR,
1290 "CFP count %u, CFP period %u, CFP max duration %u, "
1291 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
1292 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
1294 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1300 memset (out_buff, 0, SHORT_STR);
1301 snprintf (out_buff, SHORT_STR,
1302 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
1303 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
1305 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1311 case TAG_IBSS_PARAMETER:
1312 memset (out_buff, 0, SHORT_STR);
1313 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
1314 pletohs (tag_data_ptr));
1316 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1321 case TAG_COUNTRY_INFO:
1322 memset (out_buff, 0, SHORT_STR);
1324 snprintf (out_buff, SHORT_STR, "Country Code: %c%c, %s Environment",
1325 tag_data_ptr[0], tag_data_ptr[1],
1326 val_to_str(tag_data_ptr[2], environment_vals,"Unknown (0x%02x)"));
1328 n = strlen (out_buff);
1330 for (i = 3; (i + 3) <= tag_len && n < SHORT_STR; i += 3)
1332 ret = snprintf(out_buff + n, SHORT_STR - n,
1333 ", Start Channel: %u, Channels: %u, Max TX Power: %d dBm",
1334 tag_data_ptr[i], tag_data_ptr[i + 1],
1335 (gint)tag_data_ptr[i + 2]);
1337 if (ret == -1 || ret >= SHORT_STR - n) {
1338 /* Some versions of snprintf return -1 if they'd truncate
1339 the output. Others return <buf_size> or greater. */
1345 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,tag_len, out_buff);
1349 case TAG_FH_HOPPING_PARAMETER:
1350 memset (out_buff, 0, SHORT_STR);
1351 snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u",
1352 tag_data_ptr[0], tag_data_ptr[1]);
1353 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, tag_len, out_buff);
1359 case TAG_CHALLENGE_TEXT:
1360 memset (out_buff, 0, SHORT_STR);
1361 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
1362 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1370 case TAG_ERP_INFO_OLD:
1371 memset (out_buff, 0, SHORT_STR);
1373 snprintf (out_buff, SHORT_STR,
1374 "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)",
1376 tag_data_ptr[0] & 0x01 ? "" : "no ",
1377 tag_data_ptr[0] & 0x02 ? "" : "do not ",
1378 tag_data_ptr[0] & 0x04 ? "short or long": "long");
1379 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1384 case TAG_VENDOR_SPECIFIC_IE:
1385 dissect_vendor_specific_ie(tree, tvb, offset + 2, tag_len,
1390 dissect_rsn_ie(tree, tvb, offset + 2, tag_len, tag_data_ptr);
1395 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1396 tag_len, "Not interpreted");
1404 ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, packet_info * pinfo,
1405 proto_tree * tree, int tagged_parameters_len)
1409 while (tagged_parameters_len > 0) {
1410 if ((next_len=add_tagged_field (pinfo, tree, tvb, offset))==0)
1412 if (next_len > tagged_parameters_len) {
1413 /* XXX - flag this as an error? */
1414 next_len = tagged_parameters_len;
1417 tagged_parameters_len -= next_len;
1421 /* ************************************************************************* */
1422 /* Dissect 802.11 management frame */
1423 /* ************************************************************************* */
1425 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
1428 proto_item *ti = NULL;
1429 proto_tree *mgt_tree;
1430 proto_tree *fixed_tree;
1431 proto_tree *tagged_tree;
1433 int tagged_parameter_tree_len;
1435 CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
1437 ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
1438 mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
1440 switch (COMPOSE_FRAME_TYPE(fcf))
1444 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
1445 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1446 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1448 offset = 4; /* Size of fixed fields */
1449 tagged_parameter_tree_len =
1450 tvb_reported_length_remaining(tvb, offset);
1451 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1452 tagged_parameter_tree_len);
1454 ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1455 tagged_parameter_tree_len);
1459 case MGT_ASSOC_RESP:
1460 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1461 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1462 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1463 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1465 offset = 6; /* 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, pinfo, tagged_tree,
1473 tagged_parameter_tree_len);
1477 case MGT_REASSOC_REQ:
1478 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1479 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1480 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1481 add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
1483 offset = 10; /* Size of fixed fields */
1484 tagged_parameter_tree_len =
1485 tvb_reported_length_remaining(tvb, offset);
1486 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1487 tagged_parameter_tree_len);
1489 ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1490 tagged_parameter_tree_len);
1493 case MGT_REASSOC_RESP:
1494 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1495 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1496 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1497 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1499 offset = 6; /* Size of fixed fields */
1500 tagged_parameter_tree_len =
1501 tvb_reported_length_remaining(tvb, offset);
1502 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1503 tagged_parameter_tree_len);
1505 ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1506 tagged_parameter_tree_len);
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, pinfo, tagged_tree,
1518 tagged_parameter_tree_len);
1522 case MGT_PROBE_RESP:
1523 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1524 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1525 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1526 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1528 offset = 12; /* Size of fixed fields */
1529 tagged_parameter_tree_len =
1530 tvb_reported_length_remaining(tvb, offset);
1531 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1532 tagged_parameter_tree_len);
1534 ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1535 tagged_parameter_tree_len);
1539 case MGT_BEACON: /* Dissect protocol payload fields */
1540 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1542 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1543 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1544 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1546 offset = 12; /* Size of fixed fields */
1547 tagged_parameter_tree_len =
1548 tvb_reported_length_remaining(tvb, offset);
1549 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1550 tagged_parameter_tree_len);
1552 ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1553 tagged_parameter_tree_len);
1562 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1563 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1567 case MGT_AUTHENTICATION:
1568 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1569 add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
1570 add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
1571 add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
1573 offset = 6; /* Size of fixed fields */
1575 tagged_parameter_tree_len =
1576 tvb_reported_length_remaining(tvb, offset);
1577 if (tagged_parameter_tree_len != 0)
1579 tagged_tree = get_tagged_parameter_tree (mgt_tree,
1582 tagged_parameter_tree_len);
1584 ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1585 tagged_parameter_tree_len);
1590 case MGT_DEAUTHENTICATION:
1591 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1592 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1597 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 3);
1598 add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
1600 switch (tvb_get_guint8(tvb, 0))
1603 case 17: /* Management notification frame */
1604 add_fixed_field (fixed_tree, tvb, 1, FIELD_WME_ACTION_CODE);
1605 add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
1606 add_fixed_field (fixed_tree, tvb, 3, FIELD_WME_STATUS_CODE);
1608 offset = 4; /* Size of fixed fields */
1610 tagged_parameter_tree_len =
1611 tvb_reported_length_remaining(tvb, offset);
1612 if (tagged_parameter_tree_len != 0)
1614 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
1615 tagged_parameter_tree_len);
1617 ieee_80211_add_tagged_parameters (tvb, offset, pinfo, tagged_tree,
1618 tagged_parameter_tree_len);
1622 default: /* Management action frame */
1623 add_fixed_field (fixed_tree, tvb, 1, FIELD_ACTION_CODE);
1624 add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
1632 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1634 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1635 col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
1636 get_ether_name(addr), type);
1637 if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
1638 col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
1639 ether_to_str(addr), type);
1643 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1645 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1646 col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
1647 get_ether_name(addr), type);
1648 if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
1649 col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
1650 ether_to_str(addr), type);
1659 /* ************************************************************************* */
1660 /* Dissect 802.11 frame */
1661 /* ************************************************************************* */
1663 dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
1664 proto_tree * tree, gboolean fixed_length_header,
1665 gboolean has_radio_information, gint fcs_len,
1666 gboolean wlan_broken_fc)
1668 guint16 fcf, flags, frame_type_subtype;
1669 guint16 seq_control;
1670 guint32 seq_number, frag_number;
1671 gboolean more_frags;
1672 const guint8 *src = NULL, *dst = NULL;
1673 proto_item *ti = NULL;
1674 proto_item *flag_item;
1675 proto_item *fc_item;
1676 proto_tree *hdr_tree = NULL;
1677 proto_tree *flag_tree;
1678 proto_tree *fc_tree;
1681 gint len, reported_len, ivlen;
1682 gboolean save_fragmented;
1683 tvbuff_t *volatile next_tvb = NULL;
1685 volatile encap_t encap_type;
1686 guint8 octet1, octet2;
1687 char out_buff[SHORT_STR];
1690 wlan_hdr *volatile whdr;
1691 static wlan_hdr whdrs[4];
1695 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1696 col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
1697 if (check_col (pinfo->cinfo, COL_INFO))
1698 col_clear (pinfo->cinfo, COL_INFO);
1700 /* Add the radio information, if present, to the column information */
1701 if (has_radio_information) {
1702 if (check_col(pinfo->cinfo, COL_TX_RATE)) {
1703 col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
1704 pinfo->pseudo_header->ieee_802_11.data_rate / 2,
1705 pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
1707 if (check_col(pinfo->cinfo, COL_RSSI)) {
1708 /* XX - this is a percentage, not a dBm or normalized or raw RSSI */
1709 col_add_fstr(pinfo->cinfo, COL_RSSI, "%u",
1710 pinfo->pseudo_header->ieee_802_11.signal_level);
1714 fcf = tvb_get_letohs (tvb, 0);
1715 if (wlan_broken_fc) {
1717 fcf = ((fcf & 0xff) << 8) | (((fcf & 0xff00) >> 8) & 0xff);
1719 if (fixed_length_header)
1720 hdr_len = DATA_LONG_HDR_LEN;
1722 hdr_len = find_header_length (fcf);
1723 frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1725 if (check_col (pinfo->cinfo, COL_INFO))
1726 col_set_str (pinfo->cinfo, COL_INFO,
1727 val_to_str(frame_type_subtype, frame_type_subtype_vals,
1728 "Unrecognized (Reserved frame)"));
1730 flags = COOK_FLAGS (fcf);
1731 more_frags = HAVE_FRAGMENTS (flags);
1733 /* Add the radio information, if present, and the FC to the current tree */
1736 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1738 hdr_tree = proto_item_add_subtree (ti, ett_80211);
1740 if (has_radio_information) {
1741 proto_tree_add_uint_format(hdr_tree, hf_data_rate,
1743 pinfo->pseudo_header->ieee_802_11.data_rate,
1744 "Data Rate: %u.%u Mb/s",
1745 pinfo->pseudo_header->ieee_802_11.data_rate / 2,
1746 pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
1748 proto_tree_add_uint(hdr_tree, hf_channel,
1750 pinfo->pseudo_header->ieee_802_11.channel);
1752 proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
1754 pinfo->pseudo_header->ieee_802_11.signal_level,
1755 "Signal Strength: %u%%",
1756 pinfo->pseudo_header->ieee_802_11.signal_level);
1759 proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1761 wlan_broken_fc?1:0, 1,
1762 frame_type_subtype);
1764 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb,
1767 "Frame Control: 0x%04X (%s)",
1768 fcf, wlan_broken_fc?"Swapped":"Normal");
1770 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1773 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb,
1774 wlan_broken_fc?1:0, 1,
1775 COOK_PROT_VERSION (fcf));
1777 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb,
1778 wlan_broken_fc?1:0, 1,
1779 COOK_FRAME_TYPE (fcf));
1781 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1783 wlan_broken_fc?1:0, 1,
1784 COOK_FRAME_SUBTYPE (fcf));
1787 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb,
1788 wlan_broken_fc?0:1, 1,
1789 flags, "Flags: 0x%X", flags);
1791 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1793 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb,
1794 wlan_broken_fc?0:1, 1,
1795 COOK_DS_STATUS (flags));
1796 proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1,
1798 proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1,
1801 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb,
1802 wlan_broken_fc?0:1, 1,
1805 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb,
1806 wlan_broken_fc?0:1, 1, flags);
1808 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb,
1809 wlan_broken_fc?0:1, 1, flags);
1811 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb,
1812 wlan_broken_fc?0:1, 1,
1815 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb,
1816 wlan_broken_fc?0:1, 1, flags);
1818 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb,
1819 wlan_broken_fc?0:1, 1, flags);
1821 if (frame_type_subtype == CTRL_PS_POLL)
1822 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1823 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1826 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1827 tvb_get_letohs (tvb, 2));
1831 * Decode the part of the frame header that isn't the same for all
1838 switch (COOK_FRAME_TYPE (fcf))
1843 * All management frame types have the same header.
1845 src = tvb_get_ptr (tvb, 10, 6);
1846 dst = tvb_get_ptr (tvb, 4, 6);
1848 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1849 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1850 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1851 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1854 SET_ADDRESS(&whdr->bssid, AT_ETHER, 6, tvb_get_ptr(tvb, 16,6));
1855 SET_ADDRESS(&whdr->src, AT_ETHER, 6, src);
1856 SET_ADDRESS(&whdr->dst, AT_ETHER, 6, dst);
1858 seq_control = tvb_get_letohs(tvb, 22);
1859 frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1860 seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1864 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1866 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1868 /* add items for wlan.addr filter */
1869 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1870 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1872 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1873 tvb_get_ptr (tvb, 16, 6));
1875 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1878 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1884 switch (frame_type_subtype)
1888 src = tvb_get_ptr (tvb, 10, 6);
1889 dst = tvb_get_ptr (tvb, 4, 6);
1891 set_src_addr_cols(pinfo, src, "BSSID");
1892 set_dst_addr_cols(pinfo, dst, "BSSID");
1896 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1898 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1904 src = tvb_get_ptr (tvb, 10, 6);
1905 dst = tvb_get_ptr (tvb, 4, 6);
1907 set_src_addr_cols(pinfo, src, "TA");
1908 set_dst_addr_cols(pinfo, dst, "RA");
1912 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1914 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1920 dst = tvb_get_ptr (tvb, 4, 6);
1922 set_dst_addr_cols(pinfo, dst, "RA");
1925 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1929 case CTRL_ACKNOWLEDGEMENT:
1930 dst = tvb_get_ptr (tvb, 4, 6);
1932 set_dst_addr_cols(pinfo, dst, "RA");
1935 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1940 src = tvb_get_ptr (tvb, 10, 6);
1941 dst = tvb_get_ptr (tvb, 4, 6);
1943 set_src_addr_cols(pinfo, src, "BSSID");
1944 set_dst_addr_cols(pinfo, dst, "RA");
1948 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1949 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1954 case CTRL_CFP_ENDACK:
1955 src = tvb_get_ptr (tvb, 10, 6);
1956 dst = tvb_get_ptr (tvb, 4, 6);
1958 set_src_addr_cols(pinfo, src, "BSSID");
1959 set_dst_addr_cols(pinfo, dst, "RA");
1963 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1965 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1972 addr_type = COOK_ADDR_SELECTOR (fcf);
1974 /* In order to show src/dst address we must always do the following */
1979 src = tvb_get_ptr (tvb, 10, 6);
1980 dst = tvb_get_ptr (tvb, 4, 6);
1985 src = tvb_get_ptr (tvb, 16, 6);
1986 dst = tvb_get_ptr (tvb, 4, 6);
1991 src = tvb_get_ptr (tvb, 10, 6);
1992 dst = tvb_get_ptr (tvb, 16, 6);
1997 src = tvb_get_ptr (tvb, 24, 6);
1998 dst = tvb_get_ptr (tvb, 16, 6);
2002 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
2003 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
2004 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
2005 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
2009 SET_ADDRESS(&whdr->bssid, AT_ETHER, 6, tvb_get_ptr(tvb, 16,6));
2010 SET_ADDRESS(&whdr->src, AT_ETHER, 6, src);
2011 SET_ADDRESS(&whdr->dst, AT_ETHER, 6, dst);
2013 seq_control = tvb_get_letohs(tvb, 22);
2014 frag_number = COOK_FRAGMENT_NUMBER(seq_control);
2015 seq_number = COOK_SEQUENCE_NUMBER(seq_control);
2017 /* Now if we have a tree we start adding stuff */
2026 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
2027 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
2028 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
2029 tvb_get_ptr (tvb, 16, 6));
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, 4, 6, dst);
2037 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2042 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
2043 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
2044 tvb_get_ptr (tvb, 10, 6));
2045 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
2046 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2048 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2051 /* add items for wlan.addr filter */
2052 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
2053 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
2058 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
2059 tvb_get_ptr (tvb, 4, 6));
2060 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
2061 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
2063 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2065 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2068 /* add items for wlan.addr filter */
2069 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
2070 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
2075 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
2076 tvb_get_ptr (tvb, 4, 6));
2077 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
2078 tvb_get_ptr (tvb, 10, 6));
2079 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
2080 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
2082 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
2084 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
2086 /* add items for wlan.addr filter */
2087 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
2088 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
2096 len = tvb_length_remaining(tvb, hdr_len);
2097 reported_len = tvb_reported_length_remaining(tvb, hdr_len);
2101 case 0: /* Definitely has no FCS */
2105 case 4: /* Definitely has an FCS */
2109 default: /* Don't know - use "wlan_check_fcs" */
2110 has_fcs = wlan_check_fcs;
2116 * Well, this packet should, in theory, have an FCS.
2117 * Do we have the entire packet, and does it have enough data for
2120 if (reported_len < 4)
2123 * The packet is claimed not to even have enough data for a 4-byte
2125 * Pretend it doesn't have an FCS.
2129 else if (len < reported_len)
2132 * The packet is claimed to have enough data for a 4-byte FCS, but
2133 * we didn't capture all of the packet.
2134 * Slice off the 4-byte FCS from the reported length, and trim the
2135 * captured length so it's no more than the reported length; that
2136 * will slice off what of the FCS, if any, is in the captured
2140 if (len > reported_len)
2146 * We have the entire packet, and it includes a 4-byte FCS.
2147 * Slice it off, and put it into the tree.
2153 guint32 fcs = crc32_802_tvb(tvb, hdr_len + len);
2154 guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
2155 if (fcs == sent_fcs)
2156 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
2157 hdr_len + len, 4, sent_fcs,
2158 "Frame check sequence: 0x%08x (correct)", sent_fcs);
2160 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
2161 hdr_len + len, 4, sent_fcs,
2162 "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
2168 if (tree && (frame_type_subtype == DATA_QOS_DATA || frame_type_subtype == DATA_QOS_NULL)) {
2169 proto_item *qos_fields;
2170 proto_tree *qos_tree;
2172 guint16 qos_control, qos_priority, qos_ack_policy;
2174 qos_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len - 2, 2,
2176 qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters);
2178 qos_control = tvb_get_letohs(tvb, hdr_len - 2);
2179 qos_priority = COOK_QOS_PRIORITY(qos_control);
2180 qos_ack_policy = COOK_QOS_ACK_POLICY(qos_control);
2181 proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
2182 hdr_len - 2, 2, qos_priority,
2183 "Priority: %d (%s) (%s)",
2184 qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]);
2185 proto_tree_add_uint_format (qos_tree, hf_qos_ack_policy, tvb,
2186 hdr_len - 2, 2, qos_ack_policy,
2187 "Ack Policy: %d (%sAcknowledge)",
2188 qos_ack_policy, qos_ack_policy ? "Do not " : "");
2192 * Only management and data frames have a body, so we don't have
2193 * anything more to do for other types of frames.
2195 switch (COOK_FRAME_TYPE (fcf))
2203 * No-data frames don't have a body.
2205 switch (frame_type_subtype)
2208 case DATA_NULL_FUNCTION:
2209 case DATA_CF_ACK_NOD:
2210 case DATA_CF_POLL_NOD:
2211 case DATA_CF_ACK_POLL_NOD:
2221 if (IS_WEP(COOK_FLAGS(fcf))) {
2223 * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
2224 * the data, if we have a matching key. Otherwise display it as data.
2226 gboolean can_decrypt = FALSE;
2227 proto_tree *wep_tree = NULL;
2229 guint8 key, keybyte;
2231 keybyte = tvb_get_guint8(tvb, hdr_len + 3);
2232 key = COOK_WEP_KEY(keybyte);
2233 if ((keybyte & KEY_EXTIV) && (len >= EXTIV_LEN)) {
2234 /* Extended IV; this frame is likely encrypted with TKIP or CCMP */
2236 proto_item *extiv_fields;
2238 extiv_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 8,
2239 "TKIP/CCMP parameters");
2240 wep_tree = proto_item_add_subtree (extiv_fields, ett_wep_parameters);
2241 /* It is unknown whether this is a TKIP or CCMP encrypted packet, so
2242 * display both packet number alternatives unless the ExtIV can be
2243 * determined to be possible only with one of the encryption protocols.
2245 if (tvb_get_guint8(tvb, hdr_len + 1) & 0x20) {
2246 snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
2247 tvb_get_letohl(tvb, hdr_len + 4),
2248 tvb_get_guint8(tvb, hdr_len),
2249 tvb_get_guint8(tvb, hdr_len + 2));
2250 proto_tree_add_string(wep_tree, hf_tkip_extiv, tvb, hdr_len,
2251 EXTIV_LEN, out_buff);
2253 if (tvb_get_guint8(tvb, hdr_len + 2) == 0) {
2254 snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
2255 tvb_get_letohl(tvb, hdr_len + 4),
2256 tvb_get_guint8(tvb, hdr_len + 1),
2257 tvb_get_guint8(tvb, hdr_len));
2258 proto_tree_add_string(wep_tree, hf_ccmp_extiv, tvb, hdr_len,
2259 EXTIV_LEN, out_buff);
2261 proto_tree_add_uint(wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
2264 /* Subtract out the length of the IV. */
2266 reported_len -= EXTIV_LEN;
2268 /* It is unknown whether this is TKIP or CCMP, so let's not even try to
2269 * parse TKIP Michael MIC+ICV or CCMP MIC. */
2271 /* No Ext. IV - WEP packet */
2273 * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
2274 * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
2277 * Also, just pass the data *following* the WEP parameters as the
2278 * buffer to decrypt.
2280 iv = tvb_get_ntoh24(tvb, hdr_len);
2282 proto_item *wep_fields;
2284 wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
2287 wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
2288 proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
2289 tvb_memcpy(tvb, iv_buff, hdr_len, 3);
2290 is_iv_bad = weak_iv(iv_buff);
2291 if (is_iv_bad != -1) {
2292 proto_tree_add_boolean_format (wep_tree, hf_wep_iv_weak,
2294 "Weak IV for key byte %d",
2299 proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
2301 /* Subtract out the length of the IV. */
2307 * Well, this packet should, in theory, have an ICV.
2308 * Do we have the entire packet, and does it have enough data for
2311 if (reported_len < 4) {
2313 * The packet is claimed not to even have enough data for a
2315 * Pretend it doesn't have an ICV.
2318 } else if (len < reported_len) {
2320 * The packet is claimed to have enough data for a 4-byte ICV,
2321 * but we didn't capture all of the packet.
2322 * Slice off the 4-byte ICV from the reported length, and trim
2323 * the captured length so it's no more than the reported length;
2324 * that will slice off what of the ICV, if any, is in the
2329 if (len > reported_len)
2333 * We have the entire packet, and it includes a 4-byte ICV.
2334 * Slice it off, and put it into the tree.
2336 * We only support decrypting if we have the the ICV.
2338 * XXX - the ICV is encrypted; we're putting the encrypted
2339 * value, not the decrypted value, into the tree.
2347 if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
2349 * WEP decode impossible or failed, treat payload as raw data
2350 * and don't attempt fragment reassembly or further dissection.
2352 next_tvb = tvb_new_subset(tvb, hdr_len + ivlen, len, reported_len);
2354 if (tree && can_decrypt)
2355 proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
2356 hdr_len + ivlen + len, 4,
2357 tvb_get_ntohl(tvb, hdr_len + ivlen + len),
2358 "WEP ICV: 0x%08x (not verified)",
2359 tvb_get_ntohl(tvb, hdr_len + ivlen + len));
2361 if (pinfo->ethertype != ETHERTYPE_CENTRINO_PROMISC)
2363 /* Some wireless drivers (such as Centrino) WEP payload already decrypted */
2364 call_dissector(data_handle, next_tvb, pinfo, tree);
2370 proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
2371 hdr_len + ivlen + len, 4,
2372 tvb_get_ntohl(tvb, hdr_len + ivlen + len),
2373 "WEP ICV: 0x%08x (correct)",
2374 tvb_get_ntohl(tvb, hdr_len + ivlen + len));
2376 add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
2380 * WEP decryption successful!
2382 * Use the tvbuff we got back from the decryption; the data starts at
2383 * the beginning. The lengths are already correct for the decoded WEP
2390 * Not a WEP-encrypted frame; just use the data from the tvbuff
2393 * The payload starts at "hdr_len" (i.e., just past the 802.11
2394 * MAC header), the length of data in the tvbuff following the
2395 * 802.11 header is "len", and the length of data in the packet
2396 * following the 802.11 header is "reported_len".
2402 * Do defragmentation if "wlan_defragment" is true, and we have more
2403 * fragments or this isn't the first fragment.
2405 * We have to do some special handling to catch frames that
2406 * have the "More Fragments" indicator not set but that
2407 * don't show up as reassembled and don't have any other
2408 * fragments present. Some networking interfaces appear
2409 * to do reassembly even when you're capturing raw packets
2410 * *and* show the reassembled packet without the "More
2411 * Fragments" indicator set *but* with a non-zero fragment
2414 * "fragment_add_seq_802_11()" handles that; we want to call it
2415 * even if we have a short frame, so that it does those checks - if
2416 * the frame is short, it doesn't do reassembly on it.
2418 * (This could get some false positives if we really *did* only
2419 * capture the last fragment of a fragmented packet, but that's
2422 save_fragmented = pinfo->fragmented;
2423 if (wlan_defragment && (more_frags || frag_number != 0)) {
2424 fragment_data *fd_head;
2427 * If we've already seen this frame, look it up in the
2428 * table of reassembled packets, otherwise add it to
2429 * whatever reassembly is in progress, if any, and see
2432 fd_head = fragment_add_seq_802_11(next_tvb, hdr_len, pinfo, seq_number,
2433 wlan_fragment_table,
2434 wlan_reassembled_table,
2438 next_tvb = process_reassembled_data(tvb, hdr_len, pinfo,
2439 "Reassembled 802.11", fd_head,
2440 &frag_items, NULL, hdr_tree);
2443 * If this is the first fragment, dissect its contents, otherwise
2444 * just show it as a fragment.
2446 if (frag_number != 0) {
2447 /* Not the first fragment - don't dissect it. */
2450 /* First fragment, or not fragmented. Dissect what we have here. */
2452 /* Get a tvbuff for the payload. */
2453 next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
2456 * If this is the first fragment, but not the only fragment,
2457 * tell the next protocol that.
2460 pinfo->fragmented = TRUE;
2462 pinfo->fragmented = FALSE;
2466 if (next_tvb == NULL) {
2467 /* Just show this as an incomplete fragment. */
2468 if (check_col(pinfo->cinfo, COL_INFO))
2469 col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
2470 next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
2471 call_dissector(data_handle, next_tvb, pinfo, tree);
2472 pinfo->fragmented = save_fragmented;
2476 switch (COOK_FRAME_TYPE (fcf))
2480 dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
2485 /* I guess some bridges take Netware Ethernet_802_3 frames,
2486 which are 802.3 frames (with a length field rather than
2487 a type field, but with no 802.2 header in the payload),
2488 and just stick the payload into an 802.11 frame. I've seen
2489 captures that show frames of that sort.
2491 We also handle some odd form of encapsulation in which a
2492 complete Ethernet frame is encapsulated within an 802.11
2493 data frame, with no 802.2 header. This has been seen
2496 So, if the packet doesn't start with 0xaa 0xaa:
2498 we first use the same scheme that linux-wlan-ng does to detect
2499 those encapsulated Ethernet frames, namely looking to see whether
2500 the frame either starts with 6 octets that match the destination
2501 address from the 802.11 header or has 6 octets that match the
2502 source address from the 802.11 header following the first 6 octets,
2503 and, if so, treat it as an encapsulated Ethernet frame;
2505 otherwise, we use the same scheme that we use in the Ethernet
2506 dissector to recognize Netware 802.3 frames, namely checking
2507 whether the packet starts with 0xff 0xff and, if so, treat it
2508 as an encapsulated IPX frame. */
2509 encap_type = ENCAP_802_2;
2511 octet1 = tvb_get_guint8(next_tvb, 0);
2512 octet2 = tvb_get_guint8(next_tvb, 1);
2513 if (octet1 != 0xaa || octet2 != 0xaa) {
2514 src = tvb_get_ptr (next_tvb, 6, 6);
2515 dst = tvb_get_ptr (next_tvb, 0, 6);
2516 if (memcmp(src, pinfo->dl_src.data, 6) == 0 ||
2517 memcmp(dst, pinfo->dl_dst.data, 6) == 0)
2518 encap_type = ENCAP_ETHERNET;
2519 else if (octet1 == 0xff && octet2 == 0xff)
2520 encap_type = ENCAP_IPX;
2523 CATCH2(BoundsError, ReportedBoundsError) {
2529 switch (encap_type) {
2532 call_dissector(llc_handle, next_tvb, pinfo, tree);
2535 case ENCAP_ETHERNET:
2536 call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
2540 call_dissector(ipx_handle, next_tvb, pinfo, tree);
2545 pinfo->fragmented = save_fragmented;
2548 tap_queue_packet(wlan_tap, pinfo, whdr);
2552 * Dissect 802.11 with a variable-length link-layer header.
2555 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2557 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
2558 pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
2562 * Dissect 802.11 with a variable-length link-layer header and a pseudo-
2563 * header containing radio information.
2566 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2568 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE,
2569 pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
2573 * Dissect 802.11 with a variable-length link-layer header and a byte-swapped
2574 * control field (some hardware sends out LWAPP-encapsulated 802.11
2575 * packets with the control field byte swapped).
2578 dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2580 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE, TRUE);
2584 * Dissect 802.11 with a fixed-length link-layer header (padded to the
2588 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2590 dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE, FALSE);
2594 wlan_defragment_init(void)
2596 fragment_table_init(&wlan_fragment_table);
2597 reassembled_table_init(&wlan_reassembled_table);
2601 proto_register_ieee80211 (void)
2603 static const value_string frame_type[] = {
2604 {MGT_FRAME, "Management frame"},
2605 {CONTROL_FRAME, "Control frame"},
2606 {DATA_FRAME, "Data frame"},
2610 static const value_string tofrom_ds[] = {
2611 {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
2612 {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"},
2613 {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"},
2614 {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"},
2618 static const true_false_string tods_flag = {
2619 "Frame is entering DS",
2620 "Frame is not entering DS"
2623 static const true_false_string fromds_flag = {
2624 "Frame is exiting DS",
2625 "Frame is not exiting DS"
2628 static const true_false_string more_frags = {
2629 "More fragments follow",
2630 "This is the last fragment"
2633 static const true_false_string retry_flags = {
2634 "Frame is being retransmitted",
2635 "Frame is not being retransmitted"
2638 static const true_false_string pm_flags = {
2639 "STA will go to sleep",
2643 static const true_false_string md_flags = {
2644 "Data is buffered for STA at AP",
2648 static const true_false_string wep_flags = {
2653 static const true_false_string order_flags = {
2655 "Not strictly ordered"
2658 static const true_false_string cf_ess_flags = {
2659 "Transmitter is an AP",
2660 "Transmitter is a STA"
2664 static const true_false_string cf_privacy_flags = {
2665 "AP/STA can support WEP",
2666 "AP/STA cannot support WEP"
2669 static const true_false_string cf_preamble_flags = {
2670 "Short preamble allowed",
2671 "Short preamble not allowed"
2674 static const true_false_string cf_pbcc_flags = {
2675 "PBCC modulation allowed",
2676 "PBCC modulation not allowed"
2679 static const true_false_string cf_agility_flags = {
2680 "Channel agility in use",
2681 "Channel agility not in use"
2684 static const true_false_string short_slot_time_flags = {
2685 "Short slot time in use",
2686 "Short slot time not in use"
2689 static const true_false_string dsss_ofdm_flags = {
2690 "DSSS-OFDM modulation allowed",
2691 "DSSS-OFDM modulation not allowed"
2695 static const true_false_string cf_ibss_flags = {
2696 "Transmitter belongs to an IBSS",
2697 "Transmitter belongs to a BSS"
2700 static const value_string sta_cf_pollable[] = {
2701 {0x00, "Station is not CF-Pollable"},
2702 {0x02, "Station is CF-Pollable, "
2703 "not requesting to be placed on the CF-polling list"},
2704 {0x01, "Station is CF-Pollable, "
2705 "requesting to be placed on the CF-polling list"},
2706 {0x03, "Station is CF-Pollable, requesting never to be polled"},
2710 static const value_string ap_cf_pollable[] = {
2711 {0x00, "No point coordinator at AP"},
2712 {0x02, "Point coordinator at AP for delivery only (no polling)"},
2713 {0x01, "Point coordinator at AP for delivery and polling"},
2719 static const value_string auth_alg[] = {
2720 {0x00, "Open System"},
2721 {0x01, "Shared key"},
2725 static const value_string reason_codes[] = {
2727 {0x01, "Unspecified reason"},
2728 {0x02, "Previous authentication no longer valid"},
2729 {0x03, "Deauthenticated because sending STA is leaving (has left) "
2731 {0x04, "Disassociated due to inactivity"},
2732 {0x05, "Disassociated because AP is unable to handle all currently "
2733 "associated stations"},
2734 {0x06, "Class 2 frame received from nonauthenticated station"},
2735 {0x07, "Class 3 frame received from nonassociated station"},
2736 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
2737 {0x09, "Station requesting (re)association is not authenticated with "
2738 "responding station"},
2739 {0x0D, "Invalid Information Element"},
2740 {0x0E, "Michael MIC failure"},
2741 {0x0F, "4-Way Handshake timeout"},
2742 {0x10, "Group key update timeout"},
2743 {0x11, "Information element in 4-Way Handshake different from "
2744 "(Re)Association Request/Probe Response/Beacon"},
2745 {0x12, "Group Cipher is not valid"},
2746 {0x13, "Pairwise Cipher is not valid"},
2747 {0x14, "AKMP is not valid"},
2748 {0x15, "Unsupported RSN IE version"},
2749 {0x16, "Invalid RSN IE Capabilities"},
2750 {0x17, "IEEE 802.1X Authentication failed"},
2751 {0x18, "Cipher suite is rejected per security policy"},
2756 static const value_string status_codes[] = {
2757 {0x00, "Successful"},
2758 {0x01, "Unspecified failure"},
2759 {0x0A, "Cannot support all requested capabilities in the "
2760 "Capability information field"},
2761 {0x0B, "Reassociation denied due to inability to confirm that "
2762 "association exists"},
2763 {0x0C, "Association denied due to reason outside the scope of this "
2766 {0x0D, "Responding station does not support the specified authentication "
2768 {0x0E, "Received an Authentication frame with authentication sequence "
2769 "transaction sequence number out of expected sequence"},
2770 {0x0F, "Authentication rejected because of challenge failure"},
2771 {0x10, "Authentication rejected due to timeout waiting for next "
2772 "frame in sequence"},
2773 {0x11, "Association denied because AP is unable to handle additional "
2774 "associated stations"},
2775 {0x12, "Association denied due to requesting station not supporting all "
2776 "of the datarates in the BSSBasicServiceSet Parameter"},
2777 {0x13, "Association denied due to requesting station not supporting "
2778 "short preamble operation"},
2779 {0x14, "Association denied due to requesting station not supporting "
2781 {0x15, "Association denied due to requesting station not supporting "
2783 {0x19, "Association denied due to requesting station not supporting "
2784 "short slot operation"},
2785 {0x1A, "Association denied due to requesting station not supporting "
2786 "DSSS-OFDM operation"},
2787 {0x28, "Invalid Information Element"},
2788 {0x29, "Group Cipher is not valid"},
2789 {0x2A, "Pairwise Cipher is not valid"},
2790 {0x2B, "AKMP is not valid"},
2791 {0x2C, "Unsupported RSN IE version"},
2792 {0x2D, "Invalid RSN IE Capabilities"},
2793 {0x2E, "Cipher suite is rejected per security policy"},
2797 static const value_string category_codes[] = {
2798 {0x11, "Management notification frame"},
2802 static const value_string action_codes[] = {
2806 static const value_string wme_action_codes[] = {
2807 {0x00, "Setup request"},
2808 {0x01, "Setup response"},
2813 static const value_string wme_status_codes[] = {
2814 {0x00, "Admission accepted"},
2815 {0x01, "Invalid parameters"},
2820 static hf_register_info hf[] = {
2822 {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2823 "Data rate (.5 Mb/s units)", HFILL }},
2826 {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2827 "Radio channel", HFILL }},
2829 {&hf_signal_strength,
2830 {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2831 "Signal strength (percentage)", HFILL }},
2834 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2835 "MAC Frame control", HFILL }},
2837 {&hf_fc_proto_version,
2838 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2839 "MAC Protocol version", HFILL }}, /* 0 */
2842 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2843 "Frame type", HFILL }},
2845 {&hf_fc_frame_subtype,
2846 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2847 "Frame subtype", HFILL }}, /* 2 */
2849 {&hf_fc_frame_type_subtype,
2850 {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2851 "Type and subtype combined", HFILL }},
2854 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2855 "Protocol flags", HFILL }},
2858 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2859 "Data-frame DS-traversal status", HFILL }}, /* 3 */
2862 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2863 "To DS flag", HFILL }}, /* 4 */
2866 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2867 "From DS flag", HFILL }}, /* 5 */
2870 {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2871 "More Fragments flag", HFILL }}, /* 6 */
2874 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2875 "Retransmission flag", HFILL }},
2878 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2879 "Power management status", HFILL }},
2882 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2883 "More data flag", HFILL }},
2886 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2887 "WEP flag", HFILL }},
2890 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2891 "Strictly ordered flag", HFILL }},
2894 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2895 "Association-ID field", HFILL }},
2898 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2899 "Duration field", HFILL }},
2902 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2903 "Destination Hardware Address", HFILL }},
2906 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2907 "Source Hardware Address", HFILL }},
2910 {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2911 "Source or Destination Hardware Address", HFILL }},
2914 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2915 "Receiving Station Hardware Address", HFILL }},
2918 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2919 "Transmitting Station Hardware Address", HFILL }},
2922 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2923 "Basic Service Set ID", HFILL }},
2926 {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2927 "Fragment number", HFILL }},
2930 {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2931 "Sequence number", HFILL }},
2934 {"Priority", "wlan.qos.priority", FT_UINT16, BASE_DEC, NULL, 0,
2935 "802.1D Tag", HFILL }},
2937 {&hf_qos_ack_policy,
2938 {"Ack Policy", "wlan.qos.ack", FT_UINT16, BASE_DEC, NULL, 0,
2939 "Ack Policy", HFILL }},
2942 {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
2943 NULL, 0, "FCS", HFILL }},
2945 {&hf_fragment_overlap,
2946 {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2947 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2949 {&hf_fragment_overlap_conflict,
2950 {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2951 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2952 "Overlapping fragments contained conflicting data", HFILL }},
2954 {&hf_fragment_multiple_tails,
2955 {"Multiple tail fragments found", "wlan.fragment.multipletails",
2956 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2957 "Several tails were found when defragmenting the packet", HFILL }},
2959 {&hf_fragment_too_long_fragment,
2960 {"Fragment too long", "wlan.fragment.toolongfragment",
2961 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2962 "Fragment contained data past end of packet", HFILL }},
2964 {&hf_fragment_error,
2965 {"Defragmentation error", "wlan.fragment.error",
2966 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2967 "Defragmentation error due to illegal fragments", HFILL }},
2970 {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2971 "802.11 Fragment", HFILL }},
2974 {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2975 "802.11 Fragments", HFILL }},
2977 {&hf_reassembled_in,
2978 {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2979 "This 802.11 packet is reassembled in this frame", HFILL }},
2982 {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2983 "Initialization Vector", HFILL }},
2986 {"Weak IV", "wlan.wep.weakiv", FT_BOOLEAN,BASE_NONE, NULL,0x0,
2990 {"TKIP Ext. Initialization Vector", "wlan.tkip.extiv", FT_STRING,
2991 BASE_HEX, NULL, 0, "TKIP Extended Initialization Vector", HFILL }},
2994 {"CCMP Ext. Initialization Vector", "wlan.ccmp.extiv", FT_STRING,
2995 BASE_HEX, NULL, 0, "CCMP Extended Initialization Vector", HFILL }},
2998 {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
3002 {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
3003 "WEP ICV", HFILL }},
3006 static const true_false_string rsn_preauth_flags = {
3007 "Transmitter supports pre-authentication",
3008 "Transmitter does not support pre-authentication"
3011 static const true_false_string rsn_no_pairwise_flags = {
3012 "Transmitter cannot support WEP default key 0 simultaneously with "
3014 "Transmitter can support WEP default key 0 simultaneously with "
3018 static const value_string rsn_cap_replay_counter[] = {
3019 {0x00, "1 replay counter per PTKSA/GTKSA/STAKeySA"},
3020 {0x01, "2 replay counters per PTKSA/GTKSA/STAKeySA"},
3021 {0x02, "4 replay counters per PTKSA/GTKSA/STAKeySA"},
3022 {0x03, "16 replay counters per PTKSA/GTKSA/STAKeySA"},
3026 static hf_register_info ff[] = {
3028 {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
3029 NULL, 0, "", HFILL }},
3032 {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
3033 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
3035 {&ff_beacon_interval,
3036 {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
3039 {&hf_fixed_parameters,
3040 {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
3043 {&hf_tagged_parameters,
3044 {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
3048 {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
3049 "Capability information", HFILL }},
3052 {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
3053 FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
3056 {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
3057 FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
3060 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
3061 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C,
3062 "CF-Poll capabilities for a STA", HFILL }},
3065 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
3066 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C,
3067 "CF-Poll capabilities for an AP", HFILL }},
3070 {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
3071 FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
3074 {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
3075 FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
3078 {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
3079 FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
3082 {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
3083 FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
3085 {&ff_short_slot_time,
3086 {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
3087 FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
3091 {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
3092 FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
3096 {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
3097 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
3100 {"Association ID", "wlan_mgt.fixed.aid",
3101 FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
3104 {"Listen Interval", "wlan_mgt.fixed.listen_ival",
3105 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
3108 {"Current AP", "wlan_mgt.fixed.current_ap",
3109 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
3112 {"Reason code", "wlan_mgt.fixed.reason_code",
3113 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
3114 "Reason for unsolicited notification", HFILL }},
3117 {"Status code", "wlan_mgt.fixed.status_code",
3118 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
3119 "Status of requested event", HFILL }},
3122 {"Category code", "wlan_mgt.fixed.category_code",
3123 FT_UINT16, BASE_HEX, VALS (&category_codes), 0,
3124 "Management action category", HFILL }},
3127 {"Action code", "wlan_mgt.fixed.action_code",
3128 FT_UINT16, BASE_HEX, VALS (&action_codes), 0,
3129 "Management action code", HFILL }},
3132 {"Dialog token", "wlan_mgt.fixed.dialog_token",
3133 FT_UINT16, BASE_HEX, NULL, 0, "Management action dialog token", HFILL }},
3135 {&ff_wme_action_code,
3136 {"Action code", "wlan_mgt.fixed.action_code",
3137 FT_UINT16, BASE_HEX, VALS (&wme_action_codes), 0,
3138 "Management notification action code", HFILL }},
3140 {&ff_wme_status_code,
3141 {"Status code", "wlan_mgt.fixed.status_code",
3142 FT_UINT16, BASE_HEX, VALS (&wme_status_codes), 0,
3143 "Management notification setup response status code", HFILL }},
3146 {"Tag", "wlan_mgt.tag.number",
3147 FT_UINT8, BASE_DEC, VALS(tag_num_vals), 0,
3148 "Element ID", HFILL }},
3151 {"Tag length", "wlan_mgt.tag.length",
3152 FT_UINT8, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
3154 {&tag_interpretation,
3155 {"Tag interpretation", "wlan_mgt.tag.interpretation",
3156 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }},
3159 {"RSN Capabilities", "wlan_mgt.rsn.capabilities", FT_UINT16, BASE_HEX,
3160 NULL, 0, "RSN Capability information", HFILL }},
3163 {"RSN Pre-Auth capabilities", "wlan_mgt.rsn.capabilities.preauth",
3164 FT_BOOLEAN, 16, TFS (&rsn_preauth_flags), 0x0001,
3165 "RSN Pre-Auth capabilities", HFILL }},
3167 {&rsn_cap_no_pairwise,
3168 {"RSN No Pairwise capabilities", "wlan_mgt.rsn.capabilities.no_pairwise",
3169 FT_BOOLEAN, 16, TFS (&rsn_no_pairwise_flags), 0x0002,
3170 "RSN No Pairwise capabilities", HFILL }},
3172 {&rsn_cap_ptksa_replay_counter,
3173 {"RSN PTKSA Replay Counter capabilities",
3174 "wlan_mgt.rsn.capabilities.ptksa_replay_counter",
3175 FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x000C,
3176 "RSN PTKSA Replay Counter capabilities", HFILL }},
3178 {&rsn_cap_gtksa_replay_counter,
3179 {"RSN GTKSA Replay Counter capabilities",
3180 "wlan_mgt.rsn.capabilities.gtksa_replay_counter",
3181 FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x0030,
3182 "RSN GTKSA Replay Counter capabilities", HFILL }},
3185 static gint *tree_array[] = {
3192 &ett_fixed_parameters,
3193 &ett_tagged_parameters,
3194 &ett_qos_parameters,
3195 &ett_wep_parameters,
3199 module_t *wlan_module;
3201 static const enum_val_t wep_keys_options[] = {
3211 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
3212 "IEEE 802.11", "wlan");
3213 proto_register_field_array (proto_wlan, hf, array_length (hf));
3214 proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
3215 "802.11 MGT", "wlan_mgt");
3216 proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
3217 proto_register_subtree_array (tree_array, array_length (tree_array));
3219 register_dissector("wlan", dissect_ieee80211, proto_wlan);
3220 register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
3221 register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
3222 register_init_routine(wlan_defragment_init);
3224 wlan_tap = register_tap("wlan");
3226 /* Register configuration options */
3227 wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);
3228 prefs_register_bool_preference(wlan_module, "defragment",
3229 "Reassemble fragmented 802.11 datagrams",
3230 "Whether fragmented 802.11 datagrams should be reassembled",
3233 prefs_register_bool_preference(wlan_module, "check_fcs",
3234 "Assume packets have FCS",
3235 "Some 802.11 cards include the FCS at the end of a packet, others do not.",
3238 prefs_register_bool_preference(wlan_module, "ignore_wep",
3239 "Ignore the WEP bit",
3240 "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
3244 prefs_register_enum_preference(wlan_module, "wep_keys",
3246 "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
3247 &num_wepkeys, wep_keys_options, FALSE);
3249 prefs_register_string_preference(wlan_module, "wep_key1",
3251 "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",
3253 prefs_register_string_preference(wlan_module, "wep_key2",
3255 "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",
3257 prefs_register_string_preference(wlan_module, "wep_key3",
3259 "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",
3261 prefs_register_string_preference(wlan_module, "wep_key4",
3263 "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",
3269 proto_reg_handoff_ieee80211(void)
3271 dissector_handle_t ieee80211_handle;
3272 dissector_handle_t ieee80211_radio_handle;
3275 * Get handles for the LLC, IPX and Ethernet dissectors.
3277 llc_handle = find_dissector("llc");
3278 ipx_handle = find_dissector("ipx");
3279 eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
3280 data_handle = find_dissector("data");
3282 ieee80211_handle = find_dissector("wlan");
3283 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
3284 ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
3286 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
3287 ieee80211_radio_handle);
3288 dissector_add("ethertype", ETHERTYPE_CENTRINO_PROMISC, ieee80211_handle);
3291 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
3292 const guint8 *enc_data;
3295 tvbuff_t *decr_tvb = NULL;
3297 if (num_wepkeys < 1)
3300 enc_data = tvb_get_ptr(tvb, offset, len);
3302 if ((tmp = g_malloc(len)) == NULL)
3303 return NULL; /* krap! */
3305 /* try once with the key index in the packet, then look through our list. */
3306 for (i = -1; i < (int) num_wepkeys; i++) {
3307 /* copy the encrypted data over to the tmp buffer */
3309 printf("trying %d\n", i);
3311 memcpy(tmp, enc_data, len);
3312 if (wep_decrypt(tmp, len, i) == 0) {
3314 /* decrypt successful, let's set up a new data tvb. */
3315 decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
3316 tvb_set_free_cb(decr_tvb, g_free);
3317 tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
3324 if ((!decr_tvb) && (tmp)) g_free(tmp);
3327 printf("de-wep %p\n", decr_tvb);
3334 /* de-weps the block. if successful, buf* will point to the data start. */
3335 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
3336 guint32 i, j, k, crc, keylen;
3337 guint8 s[256], key[128], c_crc[4];
3338 guint8 keyidx, *dpos, *cpos;
3340 /* Needs to be at least 8 bytes of payload */
3344 /* initialize the first bytes of the key from the IV */
3348 keyidx = COOK_WEP_KEY(buf[3]);
3350 if (key_override >= 0)
3351 keyidx = key_override;
3353 if (keyidx >= num_wepkeys)
3356 keylen = wep_keylens[keyidx];
3360 if (wep_keys[keyidx] == NULL)
3363 keylen+=3; /* add in ICV bytes */
3365 /* copy the rest of the key over from the designated key */
3366 memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
3369 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]);
3372 /* set up the RC4 state */
3373 for (i = 0; i < 256; i++)
3376 for (i = 0; i < 256; i++) {
3377 j = (j + s[i] + key[i % keylen]) & 0xff;
3381 /* Apply the RC4 to the data, update the CRC32 */
3386 for (k = 0; k < (len -8); k++) {
3388 j = (j+s[i]) & 0xff;
3391 printf("%d -- %02x ", k, *dpos);
3393 *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
3395 printf("%02x\n", *dpos);
3397 crc = crc32_ccitt_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
3401 /* now let's check the crc */
3403 c_crc[1] = crc >> 8;
3404 c_crc[2] = crc >> 16;
3405 c_crc[3] = crc >> 24;
3407 for (k = 0; k < 4; k++) {
3409 j = (j+s[i]) & 0xff;
3412 printf("-- %02x %02x\n", *dpos, c_crc[k]);
3414 if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
3415 return -1; /* ICV mismatch */
3421 static void init_wepkeys(void) {
3430 tmp = getenv("ETHEREAL_WEPKEYNUM");
3435 num_wepkeys = atoi(tmp);
3437 if (num_wepkeys > 4)
3441 if (num_wepkeys < 1)
3448 g_free(wep_keylens);
3450 wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
3451 wep_keylens = g_malloc(num_wepkeys * sizeof(int));
3452 bytes = g_byte_array_new();
3454 for (i = 0 ; i < num_wepkeys; i++) {
3459 sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
3462 tmp = wep_keystr[i];
3468 printf("%s -- %s\n", buf, tmp);
3470 printf("%d -- %s\n", i+1, tmp);
3475 g_free(wep_keys[i]);
3478 res = hex_str_to_bytes(tmp, bytes, FALSE);
3479 if (res && bytes->len > 0) {
3480 if (bytes->len > 32) {
3483 wep_keys[i] = g_malloc(32 * sizeof(guint8));
3484 memset(wep_keys[i], 0, 32 * sizeof(guint8));
3485 memcpy(wep_keys[i], bytes->data, bytes->len * sizeof(guint8));
3486 wep_keylens[i] = bytes->len;
3488 printf("%d: %d bytes\n", i, bytes->len);
3489 printf("%d: %s\n", i, bytes_to_str(bytes->data, bytes->len));
3493 printf("res: %d bytes->len: %d\n", res, bytes->len);
3495 g_warning("Could not parse WEP key %d: %s", i + 1, tmp);
3499 g_byte_array_free(bytes, TRUE);
3502 * This code had been taken from AirSnort crack.c function classify()
3503 * Permission granted by snax <at> shmoo dot com
3504 * weak_iv - determine which key byte an iv is useful in resolving
3505 * parm - p, pointer to the first byte of an IV
3506 * return - n - this IV is weak for byte n of a WEP key
3507 * -1 - this IV is not weak for any key bytes
3509 * This function tests for IVs that are known to satisfy the criteria
3510 * for a weak IV as specified in FMS section 7.1
3518 if (iv[1] == 255 && iv[0] > 2 && iv[0] < 16) {
3522 sum = iv[0] + iv[1];
3524 if (iv[2] <= 0x0a) {
3527 else if (iv[2] == 0xff){
3532 if (sum == k && (iv[2] >= 0xf2 && iv[2] <= 0xfe && iv[2] != 0xfd)){