2 * Routines for Wireless LAN (IEEE 802.11) dissection
3 * Copyright 2000, Axis Communications AB
4 * Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com
6 * $Id: packet-ieee80211.c,v 1.91 2003/06/05 22:10:49 gerald Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * Copied from README.developer
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 * The following people helped me by pointing out bugs etc. Thank you!
34 * Magnus Hultman-Persson
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
50 #include <epan/bitswap.h>
51 #include <epan/proto.h>
52 #include <epan/packet.h>
53 #include <epan/resolv.h>
55 #include "reassemble.h"
56 #include "packet-ipx.h"
57 #include "packet-llc.h"
58 #include "packet-ieee80211.h"
61 /* Defragment fragmented 802.11 datagrams */
62 static gboolean wlan_defragment = TRUE;
64 /* Check for the presence of the 802.11 FCS */
65 static gboolean wlan_check_fcs = FALSE;
67 /* Ignore the WEP bit; assume packet is decrypted */
68 static gboolean wlan_ignore_wep = FALSE;
70 /* Tables for reassembly of fragments. */
71 static GHashTable *wlan_fragment_table = NULL;
72 static GHashTable *wlan_reassembled_table = NULL;
74 /* Stuff for the WEP decoder */
75 static guint num_wepkeys = 0;
76 static guint8 **wep_keys = NULL;
77 static int *wep_keylens = NULL;
78 static void init_wepkeys(void);
79 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
80 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
81 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
83 /* FCS utility function. */
84 static guint32 crc32(const unsigned char* buf, unsigned int len);
87 /* When this is set, an unlimited number of WEP keys can be set in the
91 ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
92 ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
96 otherwise you're limited to specifying four keys in the preference system.
100 static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
103 /* ************************************************************************* */
104 /* Miscellaneous Constants */
105 /* ************************************************************************* */
106 #define SHORT_STR 256
108 /* ************************************************************************* */
109 /* Define some very useful macros that are used to analyze frame types etc. */
110 /* ************************************************************************* */
111 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */
112 #define COOK_PROT_VERSION(x) ((x) & 0x3)
113 #define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2)
114 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
115 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
116 #define COOK_ASSOC_ID(x) ((x) & 0x3FFF)
117 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
118 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
119 #define COOK_FLAGS(x) (((x) & 0xFF00) >> 8)
120 #define COOK_DS_STATUS(x) ((x) & 0x3)
121 #define COOK_WEP_KEY(x) (((x) & 0xC0) >> 6)
123 #define FLAG_TO_DS 0x01
124 #define FLAG_FROM_DS 0x02
125 #define FLAG_MORE_FRAGMENTS 0x04
126 #define FLAG_RETRY 0x08
127 #define FLAG_POWER_MGT 0x10
128 #define FLAG_MORE_DATA 0x20
129 #define FLAG_WEP 0x40
130 #define FLAG_ORDER 0x80
132 #define IS_TO_DS(x) ((x) & FLAG_TO_DS)
133 #define IS_FROM_DS(x) ((x) & FLAG_FROM_DS)
134 #define HAVE_FRAGMENTS(x) ((x) & FLAG_MORE_FRAGMENTS)
135 #define IS_RETRY(x) ((x) & FLAG_RETRY)
136 #define POWER_MGT_STATUS(x) ((x) & FLAG_POWER_MGT)
137 #define HAS_MORE_DATA(x) ((x) & FLAG_MORE_DATA)
138 #define IS_WEP(x) (!wlan_ignore_wep && ((x) & FLAG_WEP))
139 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
141 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
142 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
143 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
144 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
147 /* ************************************************************************* */
148 /* Constants used to identify cooked frame types */
149 /* ************************************************************************* */
150 #define MGT_FRAME 0x00 /* Frame type is management */
151 #define CONTROL_FRAME 0x01 /* Frame type is control */
152 #define DATA_FRAME 0x02 /* Frame type is Data */
154 #define DATA_SHORT_HDR_LEN 24
155 #define DATA_LONG_HDR_LEN 30
156 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
158 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
159 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
160 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
161 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
162 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
163 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
164 #define MGT_BEACON 0x08 /* Management - Beacon frame */
165 #define MGT_ATIM 0x09 /* Management - ATIM */
166 #define MGT_DISASS 0x0A /* Management - Disassociation */
167 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
168 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
170 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
171 #define CTRL_RTS 0x1B /* Control - request to send */
172 #define CTRL_CTS 0x1C /* Control - clear to send */
173 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
174 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
175 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
177 #define DATA 0x20 /* Data - Data */
178 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
179 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
180 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
181 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
182 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
183 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
184 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
186 #define DATA_ADDR_T1 0
187 #define DATA_ADDR_T2 (FLAG_FROM_DS << 8)
188 #define DATA_ADDR_T3 (FLAG_TO_DS << 8)
189 #define DATA_ADDR_T4 ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
192 /* ************************************************************************* */
193 /* Macros used to extract information about fixed fields */
194 /* ************************************************************************* */
195 #define ESS_SET(x) ((x) & 0x0001)
196 #define IBSS_SET(x) ((x) & 0x0002)
200 /* ************************************************************************* */
201 /* Logical field codes (dissector's encoding of fixed fields) */
202 /* ************************************************************************* */
203 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
204 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
205 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
206 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
207 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
208 #define FIELD_CURRENT_AP_ADDR 0x06
209 #define FIELD_LISTEN_IVAL 0x07
210 #define FIELD_REASON_CODE 0x08
211 #define FIELD_ASSOC_ID 0x09
212 #define FIELD_STATUS_CODE 0x0A
214 /* ************************************************************************* */
215 /* Logical field codes (IEEE 802.11 encoding of tags) */
216 /* ************************************************************************* */
217 #define TAG_SSID 0x00
218 #define TAG_SUPP_RATES 0x01
219 #define TAG_FH_PARAMETER 0x02
220 #define TAG_DS_PARAMETER 0x03
221 #define TAG_CF_PARAMETER 0x04
223 #define TAG_IBSS_PARAMETER 0x06
224 #define TAG_CHALLENGE_TEXT 0x10
225 #define TAG_ERP_INFO 0x2A
226 #define TAG_ERP_INFO_OLD 0x2F /* IEEE Std 802.11g/D4.0 */
227 #define TAG_EXT_SUPP_RATES 0x32
228 #define TAG_VENDOR_SPECIFIC_IE 0xDD
230 #define WPA_OUI "\x00\x50\xF2"
232 /* ************************************************************************* */
233 /* Frame types, and their names */
234 /* ************************************************************************* */
235 static const value_string frame_type_subtype_vals[] = {
236 {MGT_ASSOC_REQ, "Association Request"},
237 {MGT_ASSOC_RESP, "Association Response"},
238 {MGT_REASSOC_REQ, "Reassociation Request"},
239 {MGT_REASSOC_RESP, "Reassociation Response"},
240 {MGT_PROBE_REQ, "Probe Request"},
241 {MGT_PROBE_RESP, "Probe Response"},
242 {MGT_BEACON, "Beacon frame"},
244 {MGT_DISASS, "Dissassociate"},
245 {MGT_AUTHENTICATION, "Authentication"},
246 {MGT_DEAUTHENTICATION, "Deauthentication"},
247 {CTRL_PS_POLL, "Power-Save poll"},
248 {CTRL_RTS, "Request-to-send"},
249 {CTRL_CTS, "Clear-to-send"},
250 {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
251 {CTRL_CFP_END, "CF-End (Control-frame)"},
252 {CTRL_CFP_ENDACK, "CF-End + CF-Ack (Control-frame)"},
254 {DATA_CF_ACK, "Data + CF-Acknowledgement"},
255 {DATA_CF_POLL, "Data + CF-Poll"},
256 {DATA_CF_ACK_POLL, "Data + CF-Acknowledgement/Poll"},
257 {DATA_NULL_FUNCTION, "Null function (No data)"},
258 {DATA_CF_ACK_NOD, "Data + Acknowledgement (No data)"},
259 {DATA_CF_POLL_NOD, "Data + CF-Poll (No data)"},
260 {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
264 static int proto_wlan = -1;
266 /* ************************************************************************* */
267 /* Header field info values for radio information */
268 /* ************************************************************************* */
269 static int hf_data_rate = -1;
270 static int hf_channel = -1;
271 static int hf_signal_strength = -1;
273 /* ************************************************************************* */
274 /* Header field info values for FC-field */
275 /* ************************************************************************* */
276 static int hf_fc_field = -1;
277 static int hf_fc_proto_version = -1;
278 static int hf_fc_frame_type = -1;
279 static int hf_fc_frame_subtype = -1;
280 static int hf_fc_frame_type_subtype = -1;
282 static int hf_fc_flags = -1;
283 static int hf_fc_to_ds = -1;
284 static int hf_fc_from_ds = -1;
285 static int hf_fc_data_ds = -1;
287 static int hf_fc_more_frag = -1;
288 static int hf_fc_retry = -1;
289 static int hf_fc_pwr_mgt = -1;
290 static int hf_fc_more_data = -1;
291 static int hf_fc_wep = -1;
292 static int hf_fc_order = -1;
295 /* ************************************************************************* */
296 /* Header values for Duration/ID field */
297 /* ************************************************************************* */
298 static int hf_did_duration = -1;
299 static int hf_assoc_id = -1;
302 /* ************************************************************************* */
303 /* Header values for different address-fields (all 4 of them) */
304 /* ************************************************************************* */
305 static int hf_addr_da = -1; /* Destination address subfield */
306 static int hf_addr_sa = -1; /* Source address subfield */
307 static int hf_addr_ra = -1; /* Receiver address subfield */
308 static int hf_addr_ta = -1; /* Transmitter address subfield */
309 static int hf_addr_bssid = -1; /* address is bssid */
311 static int hf_addr = -1; /* Source or destination address subfield */
314 /* ************************************************************************* */
315 /* Header values for sequence number field */
316 /* ************************************************************************* */
317 static int hf_frag_number = -1;
318 static int hf_seq_number = -1;
320 /* ************************************************************************* */
321 /* Header values for Frame Check field */
322 /* ************************************************************************* */
323 static int hf_fcs = -1;
325 /* ************************************************************************* */
326 /* Header values for reassembly */
327 /* ************************************************************************* */
328 static int hf_fragments = -1;
329 static int hf_fragment = -1;
330 static int hf_fragment_overlap = -1;
331 static int hf_fragment_overlap_conflict = -1;
332 static int hf_fragment_multiple_tails = -1;
333 static int hf_fragment_too_long_fragment = -1;
334 static int hf_fragment_error = -1;
335 static int hf_reassembled_in = -1;
338 static int proto_wlan_mgt = -1;
339 /* ************************************************************************* */
340 /* Fixed fields found in mgt frames */
341 /* ************************************************************************* */
342 static int ff_auth_alg = -1; /* Authentication algorithm field */
343 static int ff_auth_seq = -1; /* Authentication transaction sequence */
344 static int ff_current_ap = -1; /* Current AP MAC address */
345 static int ff_listen_ival = -1; /* Listen interval fixed field */
346 static int ff_timestamp = -1; /* 64 bit timestamp */
347 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
348 static int ff_assoc_id = -1; /* 16 bit AID field */
349 static int ff_reason = -1; /* 16 bit reason code */
350 static int ff_status_code = -1; /* Status code */
352 /* ************************************************************************* */
353 /* Flags found in the capability field (fixed field) */
354 /* ************************************************************************* */
355 static int ff_capture = -1;
356 static int ff_cf_ess = -1;
357 static int ff_cf_ibss = -1;
358 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
359 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
360 static int ff_cf_privacy = -1;
361 static int ff_cf_preamble = -1;
362 static int ff_cf_pbcc = -1;
363 static int ff_cf_agility = -1;
364 static int ff_short_slot_time = -1;
365 static int ff_dsss_ofdm = -1;
367 /* ************************************************************************* */
368 /* Tagged value format fields */
369 /* ************************************************************************* */
370 static int tag_number = -1;
371 static int tag_length = -1;
372 static int tag_interpretation = -1;
376 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
377 static int hf_tagged_parameters = -1; /* Fixed payload item */
378 static int hf_wep_iv = -1;
379 static int hf_wep_key = -1;
380 static int hf_wep_icv = -1;
382 /* ************************************************************************* */
384 /* ************************************************************************* */
385 static gint ett_80211 = -1;
386 static gint ett_proto_flags = -1;
387 static gint ett_cap_tree = -1;
388 static gint ett_fc_tree = -1;
389 static gint ett_fragments = -1;
390 static gint ett_fragment = -1;
392 static gint ett_80211_mgt = -1;
393 static gint ett_fixed_parameters = -1;
394 static gint ett_tagged_parameters = -1;
395 static gint ett_wep_parameters = -1;
397 static const fragment_items frag_items = {
402 &hf_fragment_overlap,
403 &hf_fragment_overlap_conflict,
404 &hf_fragment_multiple_tails,
405 &hf_fragment_too_long_fragment,
411 static dissector_handle_t llc_handle;
412 static dissector_handle_t ipx_handle;
413 static dissector_handle_t data_handle;
415 /* ************************************************************************* */
416 /* Return the length of the current header (in bytes) */
417 /* ************************************************************************* */
419 find_header_length (guint16 fcf)
421 switch (COOK_FRAME_TYPE (fcf)) {
424 return MGT_FRAME_HDR_LEN;
427 switch (COMPOSE_FRAME_TYPE (fcf)) {
430 case CTRL_ACKNOWLEDGEMENT:
436 case CTRL_CFP_ENDACK:
442 return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
450 /* ************************************************************************* */
451 /* This is the capture function used to update packet counts */
452 /* ************************************************************************* */
454 capture_ieee80211_common (const guchar * pd, int offset, int len,
455 packet_counts * ld, gboolean fixed_length_header)
457 guint16 fcf, hdr_length;
459 if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
464 fcf = pletohs (&pd[0]);
466 if (IS_WEP(COOK_FLAGS(fcf)))
472 switch (COMPOSE_FRAME_TYPE (fcf))
475 case DATA: /* We got a data frame */
476 case DATA_CF_ACK: /* Data with ACK */
478 case DATA_CF_ACK_POLL:
479 if (fixed_length_header)
480 hdr_length = DATA_LONG_HDR_LEN;
482 hdr_length = find_header_length (fcf);
483 /* I guess some bridges take Netware Ethernet_802_3 frames,
484 which are 802.3 frames (with a length field rather than
485 a type field, but with no 802.2 header in the payload),
486 and just stick the payload into an 802.11 frame. I've seen
487 captures that show frames of that sort.
489 This means we have to do the same check for Netware 802.3 -
490 or, if you will, "Netware 802.11" - that we do in the
491 Ethernet dissector, i.e. checking for 0xffff as the first
492 four bytes of the payload and, if we find it, treating it
494 if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
498 if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
502 capture_llc (pd, offset + hdr_length, len, ld);
513 * Handle 802.11 with a variable-length link-layer header.
516 capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
518 capture_ieee80211_common (pd, offset, len, ld, FALSE);
522 * Handle 802.11 with a fixed-length link-layer header (padded to the
526 capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
528 capture_ieee80211_common (pd, offset, len, ld, TRUE);
532 /* ************************************************************************* */
533 /* Add the subtree used to store the fixed parameters */
534 /* ************************************************************************* */
536 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
538 proto_item *fixed_fields;
540 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
541 size, size, "Fixed parameters (%d bytes)",
544 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
548 /* ************************************************************************* */
549 /* Add the subtree used to store tagged parameters */
550 /* ************************************************************************* */
552 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
554 proto_item *tagged_fields;
556 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
561 "Tagged parameters (%d bytes)",
564 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
568 /* ************************************************************************* */
569 /* Dissect and add fixed mgmt fields to protocol tree */
570 /* ************************************************************************* */
572 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
574 const guint8 *dataptr;
575 char out_buff[SHORT_STR];
577 proto_item *cap_item;
578 static proto_tree *cap_tree;
583 case FIELD_TIMESTAMP:
584 dataptr = tvb_get_ptr (tvb, offset, 8);
585 memset (out_buff, 0, SHORT_STR);
586 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
596 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
599 case FIELD_BEACON_INTERVAL:
600 temp_double = (double) tvb_get_letohs (tvb, offset);
601 temp_double = temp_double * 1024 / 1000000;
602 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
603 temp_double,"Beacon Interval: %f [Seconds]",
609 capability = tvb_get_letohs (tvb, offset);
611 cap_item = proto_tree_add_uint_format (tree, ff_capture,
614 "Capability Information: 0x%04X",
616 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
617 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
619 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
621 if (ESS_SET (capability) != 0) /* This is an AP */
622 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
625 else /* This is a STA */
626 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
628 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
630 proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
632 proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
634 proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
636 proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
638 proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
643 proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
646 case FIELD_AUTH_TRANS_SEQ:
647 proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
650 case FIELD_CURRENT_AP_ADDR:
651 proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
654 case FIELD_LISTEN_IVAL:
655 proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
658 case FIELD_REASON_CODE:
659 proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
663 proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE);
666 case FIELD_STATUS_CODE:
667 proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
672 static char *wpa_cipher_str[] =
683 wpa_cipher_idx2str(guint idx)
685 if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
686 return wpa_cipher_str[idx];
690 static char *wpa_keymgmt_str[] =
698 wpa_keymgmt_idx2str(guint idx)
700 if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
701 return wpa_keymgmt_str[idx];
706 dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
707 int tag_number, int tag_length, int tag_interpretation)
711 const guint8 *tag_val;
712 guint32 tag_val_off = 0;
713 char out_buff[SHORT_STR];
716 tag_no = tvb_get_guint8(tvb, offset);
717 tag_len = tvb_get_guint8(tvb, offset + 1);
718 tag_val = tvb_get_ptr(tvb, offset + 2, tag_len);
720 proto_tree_add_uint(tree, tag_number, tvb, offset, 1, tag_no);
723 proto_tree_add_uint(tree, tag_length, tvb, offset, 1, tag_len);
726 if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
727 snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
728 tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
729 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
732 if (tag_val_off + 4 <= tag_len) {
733 /* multicast cipher suite */
734 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
735 snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
736 wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
737 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
740 /* unicast cipher suites */
741 if (tag_val_off + 2 <= tag_len) {
742 snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
743 pletohs(tag_val + tag_val_off));
744 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
748 while (tag_val_off + 4 <= tag_len) {
749 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
750 snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
751 i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
752 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
760 /* authenticated key management suites */
761 if (tag_val_off + 2 <= tag_len) {
762 snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
763 pletohs(tag_val + tag_val_off));
764 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
768 while (tag_val_off + 4 <= tag_len) {
769 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
770 snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
771 i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
772 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
784 if (tag_val_off < tag_len)
785 proto_tree_add_string(tree, tag_interpretation, tvb,
786 offset, tag_len - tag_val_off, "Not interpreted");
789 proto_tree_add_string(tree, tag_interpretation,
790 tvb, offset, tag_len, "Not interpreted");
793 /* ************************************************************************* */
794 /* Dissect and add tagged (optional) fields to proto tree */
795 /* ************************************************************************* */
797 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
799 const guint8 *tag_data_ptr;
800 guint32 tag_no, tag_len;
803 char out_buff[SHORT_STR];
806 tag_no = tvb_get_guint8(tvb, offset);
807 tag_len = tvb_get_guint8(tvb, offset + 1);
809 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
812 if ((tag_no >= 17) && (tag_no <= 31))
813 { /* Reserved for challenge text */
814 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
815 "Tag Number: %u (Reserved for challenge text)",
818 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
819 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
820 tag_len, "Not interpreted");
821 return (int) tag_len + 2;
824 /* Next See if tag is reserved - if true, skip it! */
825 if (((tag_no >= 7) && (tag_no <= 15))
826 || ((tag_no >= 32) && (tag_no <= 255) && (tag_no != TAG_ERP_INFO) &&
827 (tag_no != TAG_EXT_SUPP_RATES) &&
828 (tag_no != TAG_ERP_INFO_OLD) && (tag_no != TAG_VENDOR_SPECIFIC_IE)))
830 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
831 "Tag Number: %u (Reserved tag number)",
834 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
836 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
837 tag_len, "Not interpreted");
838 return (int) tag_len + 2;
847 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
848 "Tag Number: %u (SSID parameter set)",
851 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
853 memset (out_buff, 0, SHORT_STR);
855 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
856 out_buff[tag_len + 1] = 0;
858 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
865 case TAG_EXT_SUPP_RATES:
866 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
867 "Tag Number: %u (%sSupported Rates)",
869 tag_no == TAG_EXT_SUPP_RATES ? "Extended " :
872 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
874 memset (out_buff, 0, SHORT_STR);
875 strcpy (out_buff, "Supported rates: ");
876 n = strlen (out_buff);
878 for (i = 0; i < tag_len && n < SHORT_STR; i++)
880 ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
881 (tag_data_ptr[i] & 0x7F) * 0.5,
882 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
883 if (ret == -1 || ret >= SHORT_STR - n) {
884 /* Some versions of snprintf return -1 if they'd truncate
885 the output. Others return <buf_size> or greater. */
891 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
893 out_buff[SHORT_STR-1] = '\0';
894 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
900 case TAG_FH_PARAMETER:
901 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
902 "Tag Number: %u (FH Parameter set)",
905 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
906 memset (out_buff, 0, SHORT_STR);
908 snprintf (out_buff, SHORT_STR,
909 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
910 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
911 tag_data_ptr[3], tag_data_ptr[4]);
913 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
919 case TAG_DS_PARAMETER:
920 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
921 "Tag Number: %u (DS Parameter set)",
924 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
925 memset (out_buff, 0, SHORT_STR);
927 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
928 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
933 case TAG_CF_PARAMETER:
934 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
935 "Tag Number: %u (CF Parameter set)",
938 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
939 memset (out_buff, 0, SHORT_STR);
941 snprintf (out_buff, SHORT_STR,
942 "CFP count %u, CFP period %u, CFP max duration %u, "
943 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
944 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
946 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
952 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
953 "Tag Number: %u ((TIM) Traffic Indication Map)",
956 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
957 memset (out_buff, 0, SHORT_STR);
958 snprintf (out_buff, SHORT_STR,
959 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
960 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
962 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
968 case TAG_IBSS_PARAMETER:
969 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
970 "Tag Number: %u (IBSS Parameter set)",
973 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
974 memset (out_buff, 0, SHORT_STR);
975 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
976 pletohs (tag_data_ptr));
978 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
984 case TAG_CHALLENGE_TEXT:
985 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
986 "Tag Number: %u (Challenge text)", tag_no);
988 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
989 memset (out_buff, 0, SHORT_STR);
990 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
991 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
999 case TAG_ERP_INFO_OLD:
1000 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
1001 "Tag Number: %u (ERP Information)",
1004 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
1005 memset (out_buff, 0, SHORT_STR);
1007 snprintf (out_buff, SHORT_STR,
1008 "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)",
1010 tag_data_ptr[0] & 0x01 ? "" : "no ",
1011 tag_data_ptr[0] & 0x02 ? "" : "do not ",
1012 tag_data_ptr[0] & 0x04 ? "short or long": "long");
1013 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1018 case TAG_VENDOR_SPECIFIC_IE:
1019 dissect_vendor_specific_ie(tree, tvb, offset, tag_number, tag_length, tag_interpretation);
1030 /* ************************************************************************* */
1031 /* Dissect 802.11 management frame */
1032 /* ************************************************************************* */
1034 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
1037 proto_item *ti = NULL;
1038 proto_tree *mgt_tree;
1039 proto_tree *fixed_tree;
1040 proto_tree *tagged_tree;
1043 int tagged_parameter_tree_len;
1045 CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
1049 ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
1050 mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
1052 switch (COMPOSE_FRAME_TYPE(fcf))
1056 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
1057 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1058 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1060 next_idx = 4; /* Size of fixed fields */
1061 tagged_parameter_tree_len =
1062 tvb_reported_length_remaining(tvb, next_idx);
1063 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1064 tagged_parameter_tree_len);
1066 while (tagged_parameter_tree_len > 0) {
1067 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1069 next_idx +=next_len;
1070 tagged_parameter_tree_len -= next_len;
1075 case MGT_ASSOC_RESP:
1076 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1077 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1078 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1079 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1081 next_idx = 6; /* Size of fixed fields */
1083 tagged_parameter_tree_len =
1084 tvb_reported_length_remaining(tvb, next_idx);
1085 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1086 tagged_parameter_tree_len);
1088 while (tagged_parameter_tree_len > 0) {
1089 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1091 next_idx +=next_len;
1092 tagged_parameter_tree_len -= next_len;
1097 case MGT_REASSOC_REQ:
1098 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1099 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1100 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1101 add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
1103 next_idx = 10; /* Size of fixed fields */
1104 tagged_parameter_tree_len =
1105 tvb_reported_length_remaining(tvb, next_idx);
1106 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1107 tagged_parameter_tree_len);
1109 while (tagged_parameter_tree_len > 0) {
1110 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1112 next_idx +=next_len;
1113 tagged_parameter_tree_len -= next_len;
1117 case MGT_REASSOC_RESP:
1118 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1119 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1120 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1121 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1123 next_idx = 6; /* Size of fixed fields */
1124 tagged_parameter_tree_len =
1125 tvb_reported_length_remaining(tvb, next_idx);
1126 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1127 tagged_parameter_tree_len);
1129 while (tagged_parameter_tree_len > 0) {
1130 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1132 next_idx +=next_len;
1133 tagged_parameter_tree_len -= next_len;
1140 tagged_parameter_tree_len =
1141 tvb_reported_length_remaining(tvb, next_idx);
1142 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1143 tagged_parameter_tree_len);
1145 while (tagged_parameter_tree_len > 0) {
1146 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1148 next_idx +=next_len;
1149 tagged_parameter_tree_len -= next_len;
1154 case MGT_PROBE_RESP:
1155 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1156 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1157 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1158 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1160 next_idx = 12; /* Size of fixed fields */
1161 tagged_parameter_tree_len =
1162 tvb_reported_length_remaining(tvb, next_idx);
1163 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1164 tagged_parameter_tree_len);
1166 while (tagged_parameter_tree_len > 0) {
1167 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1169 next_idx +=next_len;
1170 tagged_parameter_tree_len -= next_len;
1175 case MGT_BEACON: /* Dissect protocol payload fields */
1176 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1178 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1179 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1180 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1182 next_idx = 12; /* Size of fixed fields */
1183 tagged_parameter_tree_len =
1184 tvb_reported_length_remaining(tvb, next_idx);
1185 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1186 tagged_parameter_tree_len);
1188 while (tagged_parameter_tree_len > 0) {
1189 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1191 next_idx +=next_len;
1192 tagged_parameter_tree_len -= next_len;
1202 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1203 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1207 case MGT_AUTHENTICATION:
1208 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1209 add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
1210 add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
1211 add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
1213 next_idx = 6; /* Size of fixed fields */
1215 tagged_parameter_tree_len =
1216 tvb_reported_length_remaining(tvb, next_idx);
1217 if (tagged_parameter_tree_len != 0)
1219 tagged_tree = get_tagged_parameter_tree (mgt_tree,
1222 tagged_parameter_tree_len);
1224 while (tagged_parameter_tree_len > 0) {
1225 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1227 next_idx +=next_len;
1228 tagged_parameter_tree_len -= next_len;
1234 case MGT_DEAUTHENTICATION:
1235 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1236 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1243 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1245 if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1246 col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
1247 get_ether_name(addr), type);
1248 if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
1249 col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
1250 ether_to_str(addr), type);
1254 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1256 if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1257 col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
1258 get_ether_name(addr), type);
1259 if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
1260 col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
1261 ether_to_str(addr), type);
1264 /* ************************************************************************* */
1265 /* Dissect 802.11 frame */
1266 /* ************************************************************************* */
1268 dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
1269 proto_tree * tree, gboolean fixed_length_header,
1270 gboolean has_radio_information, gboolean has_no_fcs)
1272 guint16 fcf, flags, frame_type_subtype;
1273 guint16 seq_control;
1274 guint32 seq_number, frag_number;
1275 gboolean more_frags;
1276 const guint8 *src = NULL, *dst = NULL;
1277 proto_item *ti = NULL;
1278 proto_item *flag_item;
1279 proto_item *fc_item;
1280 proto_tree *hdr_tree = NULL;
1281 proto_tree *flag_tree;
1282 proto_tree *fc_tree;
1284 gint len, reported_len;
1285 gboolean save_fragmented;
1286 tvbuff_t *volatile next_tvb = NULL;
1288 volatile gboolean is_802_2;
1290 if (check_col (pinfo->cinfo, COL_PROTOCOL))
1291 col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
1292 if (check_col (pinfo->cinfo, COL_INFO))
1293 col_clear (pinfo->cinfo, COL_INFO);
1295 fcf = tvb_get_letohs (tvb, 0);
1296 if (fixed_length_header)
1297 hdr_len = DATA_LONG_HDR_LEN;
1299 hdr_len = find_header_length (fcf);
1300 frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1302 if (check_col (pinfo->cinfo, COL_INFO))
1303 col_set_str (pinfo->cinfo, COL_INFO,
1304 val_to_str(frame_type_subtype, frame_type_subtype_vals,
1305 "Unrecognized (Reserved frame)"));
1307 flags = COOK_FLAGS (fcf);
1308 more_frags = HAVE_FRAGMENTS (flags);
1310 /* Add the radio information, if present, and the FC to the current tree */
1313 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1315 hdr_tree = proto_item_add_subtree (ti, ett_80211);
1317 if (has_radio_information) {
1318 proto_tree_add_uint_format(hdr_tree, hf_data_rate,
1320 pinfo->pseudo_header->ieee_802_11.data_rate,
1321 "Data Rate: %g mb/s",
1322 .5*pinfo->pseudo_header->ieee_802_11.data_rate);
1324 proto_tree_add_uint(hdr_tree, hf_channel,
1326 pinfo->pseudo_header->ieee_802_11.channel);
1328 proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
1330 pinfo->pseudo_header->ieee_802_11.signal_level,
1331 "Signal Strength: %u%%",
1332 pinfo->pseudo_header->ieee_802_11.signal_level);
1335 proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1337 frame_type_subtype);
1339 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
1341 "Frame Control: 0x%04X",
1344 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1347 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
1348 COOK_PROT_VERSION (fcf));
1350 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
1351 COOK_FRAME_TYPE (fcf));
1353 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1355 COOK_FRAME_SUBTYPE (fcf));
1358 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
1359 flags, "Flags: 0x%X", flags);
1361 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1363 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
1364 COOK_DS_STATUS (flags));
1365 proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1,
1367 proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1,
1370 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1373 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1375 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1377 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1380 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1382 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1384 if (frame_type_subtype == CTRL_PS_POLL)
1385 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1386 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1389 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1390 tvb_get_letohs (tvb, 2));
1394 * Decode the part of the frame header that isn't the same for all
1401 switch (COOK_FRAME_TYPE (fcf))
1406 * All management frame types have the same header.
1408 src = tvb_get_ptr (tvb, 10, 6);
1409 dst = tvb_get_ptr (tvb, 4, 6);
1411 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1412 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1413 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1414 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1416 seq_control = tvb_get_letohs(tvb, 22);
1417 frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1418 seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1422 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1424 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1426 /* add items for wlan.addr filter */
1427 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1428 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1430 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1431 tvb_get_ptr (tvb, 16, 6));
1433 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1436 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1442 switch (frame_type_subtype)
1446 src = tvb_get_ptr (tvb, 10, 6);
1447 dst = tvb_get_ptr (tvb, 4, 6);
1449 set_src_addr_cols(pinfo, src, "BSSID");
1450 set_dst_addr_cols(pinfo, dst, "BSSID");
1454 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1456 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1462 src = tvb_get_ptr (tvb, 10, 6);
1463 dst = tvb_get_ptr (tvb, 4, 6);
1465 set_src_addr_cols(pinfo, src, "TA");
1466 set_dst_addr_cols(pinfo, dst, "RA");
1470 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1472 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1478 dst = tvb_get_ptr (tvb, 4, 6);
1480 set_dst_addr_cols(pinfo, dst, "RA");
1483 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1487 case CTRL_ACKNOWLEDGEMENT:
1488 dst = tvb_get_ptr (tvb, 4, 6);
1490 set_dst_addr_cols(pinfo, dst, "RA");
1493 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1498 src = tvb_get_ptr (tvb, 10, 6);
1499 dst = tvb_get_ptr (tvb, 4, 6);
1501 set_src_addr_cols(pinfo, src, "BSSID");
1502 set_dst_addr_cols(pinfo, dst, "RA");
1506 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1507 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1512 case CTRL_CFP_ENDACK:
1513 src = tvb_get_ptr (tvb, 10, 6);
1514 dst = tvb_get_ptr (tvb, 4, 6);
1516 set_src_addr_cols(pinfo, src, "BSSID");
1517 set_dst_addr_cols(pinfo, dst, "RA");
1521 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1523 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1530 addr_type = COOK_ADDR_SELECTOR (fcf);
1532 /* In order to show src/dst address we must always do the following */
1537 src = tvb_get_ptr (tvb, 10, 6);
1538 dst = tvb_get_ptr (tvb, 4, 6);
1543 src = tvb_get_ptr (tvb, 16, 6);
1544 dst = tvb_get_ptr (tvb, 4, 6);
1549 src = tvb_get_ptr (tvb, 10, 6);
1550 dst = tvb_get_ptr (tvb, 16, 6);
1555 src = tvb_get_ptr (tvb, 24, 6);
1556 dst = tvb_get_ptr (tvb, 16, 6);
1560 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1561 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1562 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1563 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1565 seq_control = tvb_get_letohs(tvb, 22);
1566 frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1567 seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1569 /* Now if we have a tree we start adding stuff */
1578 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1579 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1580 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1581 tvb_get_ptr (tvb, 16, 6));
1582 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1584 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1587 /* add items for wlan.addr filter */
1588 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1589 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1594 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1595 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1596 tvb_get_ptr (tvb, 10, 6));
1597 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1598 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1600 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1603 /* add items for wlan.addr filter */
1604 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1605 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1610 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1611 tvb_get_ptr (tvb, 4, 6));
1612 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1613 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1615 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1617 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1620 /* add items for wlan.addr filter */
1621 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1622 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1627 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1628 tvb_get_ptr (tvb, 4, 6));
1629 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1630 tvb_get_ptr (tvb, 10, 6));
1631 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1632 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1634 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1636 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1638 /* add items for wlan.addr filter */
1639 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1640 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1648 len = tvb_length_remaining(tvb, hdr_len);
1649 reported_len = tvb_reported_length_remaining(tvb, hdr_len);
1651 if (!has_no_fcs && (wlan_check_fcs))
1654 * Well, this packet should, in theory, have an FCS.
1655 * Do we have the entire packet, and does it have enough data for
1658 if (reported_len < 4)
1661 * The packet is claimed not to even have enough data for a 4-byte
1663 * Pretend it doesn't have an FCS.
1667 else if (len < reported_len)
1670 * The packet is claimed to have enough data for a 4-byte FCS, but
1671 * we didn't capture all of the packet.
1672 * Slice off the 4-byte FCS from the reported length, and trim the
1673 * captured length so it's no more than the reported length; that
1674 * will slice off what of the FCS, if any, is in the captured
1678 if (len > reported_len)
1684 * We have the entire packet, and it includes a 4-byte FCS.
1685 * Slice it off, and put it into the tree.
1691 guint32 fcs = crc32(tvb_get_ptr(tvb, 0, hdr_len + len), hdr_len + len);
1692 guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
1693 if (fcs == sent_fcs)
1694 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1695 hdr_len + len, 4, sent_fcs,
1696 "Frame check sequence: 0x%08x (correct)", sent_fcs);
1698 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1699 hdr_len + len, 4, sent_fcs,
1700 "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
1707 * Only management and data frames have a body, so we don't have
1708 * anything more to do for other types of frames.
1710 switch (COOK_FRAME_TYPE (fcf))
1718 * No-data frames don't have a body.
1720 switch (frame_type_subtype)
1723 case DATA_NULL_FUNCTION:
1724 case DATA_CF_ACK_NOD:
1725 case DATA_CF_POLL_NOD:
1726 case DATA_CF_ACK_POLL_NOD:
1735 if (IS_WEP(COOK_FLAGS(fcf))) {
1737 * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
1738 * the data, if we have a matching key. Otherwise display it as data.
1740 gboolean can_decrypt = FALSE;
1741 proto_tree *wep_tree = NULL;
1746 * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
1747 * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
1750 * Also, just pass the data *following* the WEP parameters as the
1751 * buffer to decrypt.
1753 iv = tvb_get_letoh24(tvb, hdr_len);
1755 proto_item *wep_fields;
1757 wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
1760 wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
1761 proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
1763 key = COOK_WEP_KEY (tvb_get_guint8 (tvb, hdr_len + 3));
1765 proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
1767 /* Subtract out the length of the IV. */
1772 * Well, this packet should, in theory, have an ICV.
1773 * Do we have the entire packet, and does it have enough data for
1776 if (reported_len < 4) {
1778 * The packet is claimed not to even have enough data for a
1780 * Pretend it doesn't have an ICV.
1783 } else if (len < reported_len) {
1785 * The packet is claimed to have enough data for a 4-byte ICV,
1786 * but we didn't capture all of the packet.
1787 * Slice off the 4-byte ICV from the reported length, and trim
1788 * the captured length so it's no more than the reported length;
1789 * that will slice off what of the ICV, if any, is in the
1794 if (len > reported_len)
1798 * We have the entire packet, and it includes a 4-byte ICV.
1799 * Slice it off, and put it into the tree.
1801 * We only support decrypting if we have the the ICV.
1803 * XXX - the ICV is encrypted; we're putting the encrypted
1804 * value, not the decrypted value, into the tree.
1811 if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
1813 * WEP decode impossible or failed, treat payload as raw data
1814 * and don't attempt fragment reassembly or further dissection.
1816 next_tvb = tvb_new_subset(tvb, hdr_len + 4, len, reported_len);
1818 if (tree && can_decrypt)
1819 proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
1820 hdr_len + 4 + len, 4,
1821 tvb_get_ntohl(tvb, hdr_len + 4 + len),
1822 "WEP ICV: 0x%08x (not verified)",
1823 tvb_get_ntohl(tvb, hdr_len + 4 + len));
1825 call_dissector(data_handle, next_tvb, pinfo, tree);
1830 proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
1831 hdr_len + 4 + len, 4,
1832 tvb_get_ntohl(tvb, hdr_len + 4 + len),
1833 "WEP ICV: 0x%08x (correct)",
1834 tvb_get_ntohl(tvb, hdr_len + 4 + len));
1836 add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
1840 * WEP decryption successful!
1842 * Use the tvbuff we got back from the decryption; the data starts at
1843 * the beginning. The lengths are already correct for the decoded WEP
1850 * Not a WEP-encrypted frame; just use the data from the tvbuff
1853 * The payload starts at "hdr_len" (i.e., just past the 802.11
1854 * MAC header), the length of data in the tvbuff following the
1855 * 802.11 header is "len", and the length of data in the packet
1856 * following the 802.11 header is "reported_len".
1862 * Do defragmentation if "wlan_defragment" is true, and we have more
1863 * fragments or this isn't the first fragment.
1865 * We have to do some special handling to catch frames that
1866 * have the "More Fragments" indicator not set but that
1867 * don't show up as reassembled and don't have any other
1868 * fragments present. Some networking interfaces appear
1869 * to do reassembly even when you're capturing raw packets
1870 * *and* show the reassembled packet without the "More
1871 * Fragments" indicator set *but* with a non-zero fragment
1874 * "fragment_add_seq_check()" handles that; we want to call it
1875 * even if we have a short frame, so that it does those checks - if
1876 * the frame is short, it doesn't do reassembly on it.
1878 * (This could get some false positives if we really *did* only
1879 * capture the last fragment of a fragmented packet, but that's
1882 save_fragmented = pinfo->fragmented;
1883 if (wlan_defragment && (more_frags || frag_number != 0)) {
1884 fragment_data *fd_head;
1887 * If we've already seen this frame, look it up in the
1888 * table of reassembled packets, otherwise add it to
1889 * whatever reassembly is in progress, if any, and see
1892 fd_head = fragment_add_seq_check(next_tvb, hdr_len, pinfo, seq_number,
1893 wlan_fragment_table,
1894 wlan_reassembled_table,
1898 if (fd_head != NULL) {
1900 * Either this is reassembled or it wasn't fragmented
1901 * (see comment above about some networking interfaces).
1902 * In either case, it's now in the table of reassembled
1905 * If the "fragment_data" structure doesn't have a list of
1906 * fragments, we assume it's a placeholder to mark those
1907 * not-really-fragmented packets, and just treat this as
1908 * a non-fragmented frame.
1910 if (fd_head->next != NULL) {
1911 next_tvb = process_reassembled_data(tvb, pinfo, "Reassembled 802.11",
1912 fd_head, &frag_items, NULL, hdr_tree);
1915 * Not fragmented, really.
1916 * Show it as a regular frame.
1918 next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1921 /* It's not fragmented. */
1922 pinfo->fragmented = FALSE;
1924 /* We don't have the complete reassembled payload. */
1929 * If this is the first fragment, dissect its contents, otherwise
1930 * just show it as a fragment.
1932 if (frag_number != 0) {
1933 /* Not the first fragment - don't dissect it. */
1936 /* First fragment, or not fragmented. Dissect what we have here. */
1938 /* Get a tvbuff for the payload. */
1939 next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1942 * If this is the first fragment, but not the only fragment,
1943 * tell the next protocol that.
1946 pinfo->fragmented = TRUE;
1948 pinfo->fragmented = FALSE;
1952 if (next_tvb == NULL) {
1953 /* Just show this as an incomplete fragment. */
1954 if (check_col(pinfo->cinfo, COL_INFO))
1955 col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
1956 next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
1957 call_dissector(data_handle, next_tvb, pinfo, tree);
1958 pinfo->fragmented = save_fragmented;
1962 switch (COOK_FRAME_TYPE (fcf))
1966 dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1971 /* I guess some bridges take Netware Ethernet_802_3 frames,
1972 which are 802.3 frames (with a length field rather than
1973 a type field, but with no 802.2 header in the payload),
1974 and just stick the payload into an 802.11 frame. I've seen
1975 captures that show frames of that sort.
1977 This means we have to do the same check for Netware 802.3 -
1978 or, if you will, "Netware 802.11" - that we do in the
1979 Ethernet dissector, i.e. checking for 0xffff as the first
1980 four bytes of the payload and, if we find it, treating it
1984 if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1987 CATCH2(BoundsError, ReportedBoundsError) {
1994 call_dissector(llc_handle, next_tvb, pinfo, tree);
1996 call_dissector(ipx_handle, next_tvb, pinfo, tree);
1999 pinfo->fragmented = save_fragmented;
2003 * Dissect 802.11 with a variable-length link-layer header.
2006 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2008 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE);
2012 * Dissect 802.11 with a variable-length link-layer header and a pseudo-
2013 * header containing radio information.
2016 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2018 /* These packets do NOT have a FCS present */
2019 dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE, TRUE);
2023 * Dissect 802.11 with a fixed-length link-layer header (padded to the
2027 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2029 dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE);
2033 wlan_defragment_init(void)
2035 fragment_table_init(&wlan_fragment_table);
2036 reassembled_table_init(&wlan_reassembled_table);
2040 proto_register_ieee80211 (void)
2042 static const value_string frame_type[] = {
2043 {MGT_FRAME, "Management frame"},
2044 {CONTROL_FRAME, "Control frame"},
2045 {DATA_FRAME, "Data frame"},
2049 static const value_string tofrom_ds[] = {
2050 {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
2051 {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"},
2052 {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"},
2053 {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"},
2057 static const true_false_string tods_flag = {
2058 "Frame is entering DS",
2059 "Frame is not entering DS"
2062 static const true_false_string fromds_flag = {
2063 "Frame is exiting DS",
2064 "Frame is not exiting DS"
2067 static const true_false_string more_frags = {
2068 "More fragments follow",
2069 "This is the last fragment"
2072 static const true_false_string retry_flags = {
2073 "Frame is being retransmitted",
2074 "Frame is not being retransmitted"
2077 static const true_false_string pm_flags = {
2078 "STA will go to sleep",
2082 static const true_false_string md_flags = {
2083 "Data is buffered for STA at AP",
2087 static const true_false_string wep_flags = {
2092 static const true_false_string order_flags = {
2094 "Not strictly ordered"
2097 static const true_false_string cf_ess_flags = {
2098 "Transmitter is an AP",
2099 "Transmitter is a STA"
2103 static const true_false_string cf_privacy_flags = {
2104 "AP/STA can support WEP",
2105 "AP/STA cannot support WEP"
2108 static const true_false_string cf_preamble_flags = {
2109 "Short preamble allowed",
2110 "Short preamble not allowed"
2113 static const true_false_string cf_pbcc_flags = {
2114 "PBCC modulation allowed",
2115 "PBCC modulation not allowed"
2118 static const true_false_string cf_agility_flags = {
2119 "Channel agility in use",
2120 "Channel agility not in use"
2123 static const true_false_string short_slot_time_flags = {
2124 "Short slot time in use",
2125 "Short slot time not in use"
2128 static const true_false_string dsss_ofdm_flags = {
2129 "DSSS-OFDM modulation allowed",
2130 "DSSS-OFDM modulation not allowed"
2134 static const true_false_string cf_ibss_flags = {
2135 "Transmitter belongs to an IBSS",
2136 "Transmitter belongs to a BSS"
2139 static const value_string sta_cf_pollable[] = {
2140 {0x00, "Station is not CF-Pollable"},
2141 {0x02, "Station is CF-Pollable, "
2142 "not requesting to be placed on the CF-polling list"},
2143 {0x01, "Station is CF-Pollable, "
2144 "requesting to be placed on the CF-polling list"},
2145 {0x03, "Station is CF-Pollable, requesting never to be polled"},
2149 static const value_string ap_cf_pollable[] = {
2150 {0x00, "No point coordinator at AP"},
2151 {0x02, "Point coordinator at AP for delivery only (no polling)"},
2152 {0x01, "Point coordinator at AP for delivery and polling"},
2158 static const value_string auth_alg[] = {
2159 {0x00, "Open System"},
2160 {0x01, "Shared key"},
2164 static const value_string reason_codes[] = {
2166 {0x01, "Unspecified reason"},
2167 {0x02, "Previous authentication no longer valid"},
2168 {0x03, "Deauthenticated because sending STA is leaving (has left) "
2170 {0x04, "Disassociated due to inactivity"},
2171 {0x05, "Disassociated because AP is unable to handle all currently "
2172 "associated stations"},
2173 {0x06, "Class 2 frame received from nonauthenticated station"},
2174 {0x07, "Class 3 frame received from nonassociated station"},
2175 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
2176 {0x09, "Station requesting (re)association is not authenticated with "
2177 "responding station"},
2182 static const value_string status_codes[] = {
2183 {0x00, "Successful"},
2184 {0x01, "Unspecified failure"},
2185 {0x0A, "Cannot support all requested capabilities in the "
2186 "Capability information field"},
2187 {0x0B, "Reassociation denied due to inability to confirm that "
2188 "association exists"},
2189 {0x0C, "Association denied due to reason outside the scope of this "
2192 {0x0D, "Responding station does not support the specified authentication "
2194 {0x0E, "Received an Authentication frame with authentication sequence "
2195 "transaction sequence number out of expected sequence"},
2196 {0x0F, "Authentication rejected because of challenge failure"},
2197 {0x10, "Authentication rejected due to timeout waiting for next "
2198 "frame in sequence"},
2199 {0x11, "Association denied because AP is unable to handle additional "
2200 "associated stations"},
2201 {0x12, "Association denied due to requesting station not supporting all "
2202 "of the datarates in the BSSBasicServiceSet Parameter"},
2203 {0x13, "Association denied due to requesting station not supporting "
2204 "short preamble operation"},
2205 {0x14, "Association denied due to requesting station not supporting "
2207 {0x15, "Association denied due to requesting station not supporting "
2209 {0x19, "Association denied due to requesting station not supporting "
2210 "short slot operation"},
2211 {0x1A, "Association denied due to requesting station not supporting "
2212 "DSSS-OFDM operation"},
2216 static hf_register_info hf[] = {
2218 {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2219 "Data rate (.5 Mb/s units)", HFILL }},
2222 {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2223 "Radio channel", HFILL }},
2225 {&hf_signal_strength,
2226 {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2227 "Signal strength (percentage)", HFILL }},
2230 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2231 "MAC Frame control", HFILL }},
2233 {&hf_fc_proto_version,
2234 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2235 "MAC Protocol version", HFILL }}, /* 0 */
2238 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2239 "Frame type", HFILL }},
2241 {&hf_fc_frame_subtype,
2242 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2243 "Frame subtype", HFILL }}, /* 2 */
2245 {&hf_fc_frame_type_subtype,
2246 {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2247 "Type and subtype combined", HFILL }},
2250 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2251 "Protocol flags", HFILL }},
2254 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2255 "Data-frame DS-traversal status", HFILL }}, /* 3 */
2258 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2259 "To DS flag", HFILL }}, /* 4 */
2262 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2263 "From DS flag", HFILL }}, /* 5 */
2266 {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2267 "More Fragments flag", HFILL }}, /* 6 */
2270 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2271 "Retransmission flag", HFILL }},
2274 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2275 "Power management status", HFILL }},
2278 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2279 "More data flag", HFILL }},
2282 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2283 "WEP flag", HFILL }},
2286 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2287 "Strictly ordered flag", HFILL }},
2290 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2291 "Association-ID field", HFILL }},
2294 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2295 "Duration field", HFILL }},
2298 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2299 "Destination Hardware Address", HFILL }},
2302 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2303 "Source Hardware Address", HFILL }},
2306 {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2307 "Source or Destination Hardware Address", HFILL }},
2310 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2311 "Receiving Station Hardware Address", HFILL }},
2314 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2315 "Transmitting Station Hardware Address", HFILL }},
2318 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2319 "Basic Service Set ID", HFILL }},
2322 {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2323 "Fragment number", HFILL }},
2326 {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2327 "Sequence number", HFILL }},
2330 {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
2331 NULL, 0, "FCS", HFILL }},
2333 {&hf_fragment_overlap,
2334 {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2335 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2337 {&hf_fragment_overlap_conflict,
2338 {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2339 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2340 "Overlapping fragments contained conflicting data", HFILL }},
2342 {&hf_fragment_multiple_tails,
2343 {"Multiple tail fragments found", "wlan.fragment.multipletails",
2344 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2345 "Several tails were found when defragmenting the packet", HFILL }},
2347 {&hf_fragment_too_long_fragment,
2348 {"Fragment too long", "wlan.fragment.toolongfragment",
2349 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2350 "Fragment contained data past end of packet", HFILL }},
2352 {&hf_fragment_error,
2353 {"Defragmentation error", "wlan.fragment.error",
2354 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2355 "Defragmentation error due to illegal fragments", HFILL }},
2358 {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2359 "802.11 Fragment", HFILL }},
2362 {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2363 "802.11 Fragments", HFILL }},
2365 {&hf_reassembled_in,
2366 {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2367 "This 802.11 packet is reassembled in this frame", HFILL }},
2370 {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2371 "Initialization Vector", HFILL }},
2374 {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
2378 {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
2379 "WEP ICV", HFILL }},
2382 static hf_register_info ff[] = {
2384 {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
2385 NULL, 0, "", HFILL }},
2388 {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
2389 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
2391 {&ff_beacon_interval,
2392 {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
2395 {&hf_fixed_parameters,
2396 {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
2399 {&hf_tagged_parameters,
2400 {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
2404 {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
2405 "Capability information", HFILL }},
2408 {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
2409 FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
2412 {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
2413 FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
2416 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
2417 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C,
2418 "CF-Poll capabilities for a STA", HFILL }},
2421 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
2422 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C,
2423 "CF-Poll capabilities for an AP", HFILL }},
2426 {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
2427 FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
2430 {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
2431 FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
2434 {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
2435 FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
2438 {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
2439 FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
2441 {&ff_short_slot_time,
2442 {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
2443 FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
2447 {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
2448 FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
2452 {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
2453 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
2456 {"Association ID", "wlan_mgt.fixed.aid",
2457 FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
2460 {"Listen Interval", "wlan_mgt.fixed.listen_ival",
2461 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
2464 {"Current AP", "wlan_mgt.fixed.current_ap",
2465 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
2468 {"Reason code", "wlan_mgt.fixed.reason_code",
2469 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
2470 "Reason for unsolicited notification", HFILL }},
2473 {"Status code", "wlan_mgt.fixed.status_code",
2474 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
2475 "Status of requested event", HFILL }},
2478 {"Tag", "wlan_mgt.tag.number",
2479 FT_UINT16, BASE_DEC, NULL, 0,
2480 "Element ID", HFILL }},
2483 {"Tag length", "wlan_mgt.tag.length",
2484 FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
2486 {&tag_interpretation,
2487 {"Tag interpretation", "wlan_mgt.tag.interpretation",
2488 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
2492 static gint *tree_array[] = {
2499 &ett_fixed_parameters,
2500 &ett_tagged_parameters,
2501 &ett_wep_parameters,
2504 module_t *wlan_module;
2506 static const enum_val_t wep_keys_options[] = {
2516 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
2517 "IEEE 802.11", "wlan");
2518 proto_register_field_array (proto_wlan, hf, array_length (hf));
2519 proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
2520 "802.11 MGT", "wlan_mgt");
2521 proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
2522 proto_register_subtree_array (tree_array, array_length (tree_array));
2524 register_dissector("wlan", dissect_ieee80211, proto_wlan);
2525 register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
2526 register_init_routine(wlan_defragment_init);
2528 /* Register configuration options */
2529 wlan_module = prefs_register_protocol(proto_wlan, NULL);
2530 prefs_register_bool_preference(wlan_module, "defragment",
2531 "Reassemble fragmented 802.11 datagrams",
2532 "Whether fragmented 802.11 datagrams should be reassembled",
2535 prefs_register_bool_preference(wlan_module, "check_fcs",
2536 "Assume packets have FCS",
2537 "Some 802.11 cards include the FCS at the end of a packet, others do not.",
2540 prefs_register_bool_preference(wlan_module, "ignore_wep",
2541 "Ignore the WEP bit",
2542 "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
2546 prefs_register_enum_preference(wlan_module, "wep_keys",
2548 "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
2549 &num_wepkeys, wep_keys_options, FALSE);
2551 prefs_register_string_preference(wlan_module, "wep_key1",
2553 "First WEP key (A:B:C:D:E:F)",
2555 prefs_register_string_preference(wlan_module, "wep_key2",
2557 "Second WEP key (A:B:C:D:E:F)",
2559 prefs_register_string_preference(wlan_module, "wep_key3",
2561 "Third WEP key (A:B:C:D:E:F)",
2563 prefs_register_string_preference(wlan_module, "wep_key4",
2565 "Fourth WEP key (A:B:C:D:E:F)",
2571 proto_reg_handoff_ieee80211(void)
2573 dissector_handle_t ieee80211_handle;
2574 dissector_handle_t ieee80211_radio_handle;
2577 * Get handles for the LLC and IPX dissectors.
2579 llc_handle = find_dissector("llc");
2580 ipx_handle = find_dissector("ipx");
2581 data_handle = find_dissector("data");
2583 ieee80211_handle = find_dissector("wlan");
2584 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
2585 ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
2587 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
2588 ieee80211_radio_handle);
2591 static const guint32 wep_crc32_table[256] = {
2592 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
2593 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
2594 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
2595 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2596 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
2597 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
2598 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
2599 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2600 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
2601 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
2602 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
2603 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2604 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
2605 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
2606 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
2607 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2608 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
2609 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
2610 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
2611 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2612 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
2613 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
2614 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
2615 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2616 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
2617 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
2618 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
2619 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2620 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
2621 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
2622 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
2623 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2624 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
2625 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
2626 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
2627 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2628 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
2629 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
2630 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
2631 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2632 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
2633 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
2634 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
2635 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2636 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
2637 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
2638 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
2639 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2640 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
2641 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
2642 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
2646 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
2649 tvbuff_t *decr_tvb = NULL;
2651 if (num_wepkeys < 1)
2653 if (wep_keylens == NULL)
2656 if ((tmp = g_malloc(len)) == NULL)
2657 return NULL; /* krap! */
2659 /* try once with the key index in the packet, then look through our list. */
2660 for (i = -1; i < (int) num_wepkeys; i++) {
2661 /* copy the encrypted data over to the tmp buffer */
2663 printf("trying %d\n", i);
2665 tvb_memcpy(tvb, tmp, offset, len);
2666 if (wep_decrypt(tmp, len, i) == 0) {
2668 /* decrypt successful, let's set up a new data tvb. */
2669 decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
2670 tvb_set_free_cb(decr_tvb, g_free);
2671 tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2678 if ((!decr_tvb) && (tmp)) g_free(tmp);
2681 printf("de-wep %p\n", decr_tvb);
2688 /* de-weps the block. if successful, buf* will point to the data start. */
2689 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
2690 guint32 i, j, k, crc, keylen;
2691 guint8 s[256], key[128], c_crc[4];
2692 guint8 keyidx, *dpos, *cpos;
2694 /* Needs to be at least 8 bytes of payload */
2698 /* initialize the first bytes of the key from the IV */
2702 keyidx = COOK_WEP_KEY(buf[3]);
2704 if (key_override >= 0)
2705 keyidx = key_override;
2707 if (keyidx >= num_wepkeys)
2710 keylen = wep_keylens[keyidx];
2714 if (wep_keys[keyidx] == NULL)
2717 keylen+=3; /* add in ICV bytes */
2719 /* copy the rest of the key over from the designated key */
2720 memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
2723 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]);
2726 /* set up the RC4 state */
2727 for (i = 0; i < 256; i++)
2730 for (i = 0; i < 256; i++) {
2731 j = (j + s[i] + key[i % keylen]) & 0xff;
2735 /* Apply the RC4 to the data, update the CRC32 */
2740 for (k = 0; k < (len -8); k++) {
2742 j = (j+s[i]) & 0xff;
2745 printf("%d -- %02x ", k, *dpos);
2747 *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
2749 printf("%02x\n", *dpos);
2751 crc = wep_crc32_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
2755 /* now let's check the crc */
2757 c_crc[1] = crc >> 8;
2758 c_crc[2] = crc >> 16;
2759 c_crc[3] = crc >> 24;
2761 for (k = 0; k < 4; k++) {
2763 j = (j+s[i]) & 0xff;
2766 printf("-- %02x %02x\n", *dpos, c_crc[k]);
2768 if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
2769 return -1; /* ICV mismatch */
2775 static void init_wepkeys(void) {
2783 tmp = getenv("ETHEREAL_WEPKEYNUM");
2788 num_wepkeys = atoi(tmp);
2790 if (num_wepkeys > 4)
2794 if (num_wepkeys < 1)
2797 if (wep_keylens != NULL)
2800 wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
2801 wep_keylens = g_malloc(num_wepkeys * sizeof(int));
2803 for (i = 0 ; i < num_wepkeys; i++) {
2808 sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
2811 tmp = wep_keystr[i];
2818 printf("%s -- %s\n", buf, tmp);
2820 printf("%d -- %s\n", i+1, tmp);
2824 wep_keys[i] = g_malloc(32 * sizeof(guint8));
2825 memset(wep_keys[i], 0, 32 * sizeof(guint8));
2827 while ((tmp != NULL) && (*tmp != 0)) {
2828 tmp3[j] = strtoul(tmp, &tmp2, 16) & 0xff;
2830 printf("%d %d -- %02x\n", i, j, tmp3[j]);
2835 if ((tmp != NULL) && (*tmp == ':'))
2847 crc32(const unsigned char* buf, unsigned int len)
2850 guint32 crc32 = 0xFFFFFFFF, c_crc;
2852 for (i = 0; i < len; i++)
2853 crc32 = wep_crc32_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8);
2856 c_crc = ((unsigned char)(crc32>>0)<<24) |
2857 ((unsigned char)(crc32>>8)<<16) |
2858 ((unsigned char)(crc32>>16)<<8) |
2859 ((unsigned char)(crc32>>24)<<0);