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.39 2001/09/25 00:34:24 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * Copied from README.developer
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 * The following people helped me by pointing out bugs etc. Thank you!
34 * Magnus Hultman-Persson
45 #ifdef HAVE_SYS_TYPES_H
46 # include <sys/types.h>
49 #ifdef HAVE_NETINET_IN_H
50 # include <netinet/in.h>
53 #ifdef NEED_SNPRINTF_H
59 # include "snprintf.h"
68 #include "packet-ipx.h"
69 #include "packet-llc.h"
70 #include "packet-ieee80211.h"
73 /* ************************************************************************* */
74 /* Miscellaneous Constants */
75 /* ************************************************************************* */
78 /* ************************************************************************* */
79 /* Define some very useful macros that are used to analyze frame types etc. */
80 /* ************************************************************************* */
81 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */
82 #define COOK_PROT_VERSION(x) ((x) & 0x3)
83 #define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2)
84 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
85 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
86 #define COOK_ASSOC_ID(x) ((x) & 0x3FFF)
87 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
88 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
89 #define COOK_FLAGS(x) (((x) & 0xFF00) >> 8)
90 #define COOK_DS_STATUS(x) ((x) & 0x3)
91 #define COOK_WEP_KEY(x) (((x) & 0xC0) >> 6)
92 #define COL_SHOW_INFO(fd,info) if (check_col(fd,COL_INFO)) \
93 col_add_str(fd,COL_INFO,info);
94 #define COL_SHOW_INFO_CONST(fd,info) if (check_col(fd,COL_INFO)) \
95 col_set_str(fd,COL_INFO,info);
97 #define FLAG_TO_DS 0x01
98 #define FLAG_FROM_DS 0x02
99 #define FLAG_MORE_FRAGMENTS 0x04
100 #define FLAG_RETRY 0x08
101 #define FLAG_POWER_MGT 0x10
102 #define FLAG_MORE_DATA 0x20
103 #define FLAG_WEP 0x40
104 #define FLAG_ORDER 0x80
106 #define IS_TO_DS(x) ((x) & FLAG_TO_DS)
107 #define IS_FROM_DS(x) ((x) & FLAG_FROM_DS)
108 #define HAVE_FRAGMENTS(x) ((x) & FLAG_MORE_FRAGMENTS)
109 #define IS_RETRY(x) ((x) & FLAG_RETRY)
110 #define POWER_MGT_STATUS(x) ((x) & FLAG_POWER_MGT)
111 #define HAS_MORE_DATA(x) ((x) & FLAG_MORE_DATA)
112 #define IS_WEP(x) ((x) & FLAG_WEP)
113 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
115 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
116 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
117 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
118 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
121 /* ************************************************************************* */
122 /* Constants used to identify cooked frame types */
123 /* ************************************************************************* */
124 #define MGT_FRAME 0x00 /* Frame type is management */
125 #define CONTROL_FRAME 0x01 /* Frame type is control */
126 #define DATA_FRAME 0x02 /* Frame type is Data */
128 #define DATA_SHORT_HDR_LEN 24
129 #define DATA_LONG_HDR_LEN 30
130 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
132 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
133 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
134 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
135 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
136 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
137 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
138 #define MGT_BEACON 0x08 /* Management - Beacon frame */
139 #define MGT_ATIM 0x09 /* Management - ATIM */
140 #define MGT_DISASS 0x0A /* Management - Disassociation */
141 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
142 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
144 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
145 #define CTRL_RTS 0x1B /* Control - request to send */
146 #define CTRL_CTS 0x1C /* Control - clear to send */
147 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
148 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
149 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
151 #define DATA 0x20 /* Data - Data */
152 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
153 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
154 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
155 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
156 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
157 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
158 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
160 #define DATA_ADDR_T1 0
161 #define DATA_ADDR_T2 (FLAG_FROM_DS << 8)
162 #define DATA_ADDR_T3 (FLAG_TO_DS << 8)
163 #define DATA_ADDR_T4 ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
166 /* ************************************************************************* */
167 /* Macros used to extract information about fixed fields */
168 /* ************************************************************************* */
169 #define ESS_SET(x) ((x) & 0x0001)
170 #define IBSS_SET(x) ((x) & 0x0002)
174 /* ************************************************************************* */
175 /* Logical field codes (dissector's encoding of fixed fields) */
176 /* ************************************************************************* */
177 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
178 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
179 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
180 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
181 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
182 #define FIELD_CURRENT_AP_ADDR 0x06
183 #define FIELD_LISTEN_IVAL 0x07
184 #define FIELD_REASON_CODE 0x08
185 #define FIELD_ASSOC_ID 0x09
186 #define FIELD_STATUS_CODE 0x0A
188 /* ************************************************************************* */
189 /* Logical field codes (IEEE 802.11 encoding of tags) */
190 /* ************************************************************************* */
191 #define TAG_SSID 0x00
192 #define TAG_SUPP_RATES 0x01
193 #define TAG_FH_PARAMETER 0x02
194 #define TAG_DS_PARAMETER 0x03
195 #define TAG_CF_PARAMETER 0x04
197 #define TAG_IBSS_PARAMETER 0x06
198 #define TAG_CHALLENGE_TEXT 0x10
200 /* ************************************************************************* */
201 /* Frame types, and their names */
202 /* ************************************************************************* */
203 static const value_string frame_type_subtype_vals[] = {
204 {MGT_ASSOC_REQ, "Association Request"},
205 {MGT_ASSOC_RESP, "Association Response"},
206 {MGT_REASSOC_REQ, "Reassociation Request"},
207 {MGT_REASSOC_RESP, "Reassociation Response"},
208 {MGT_PROBE_REQ, "Probe Request"},
209 {MGT_PROBE_RESP, "Probe Response"},
210 {MGT_BEACON, "Beacon frame"},
212 {MGT_DISASS, "Dissassociate"},
213 {MGT_AUTHENTICATION, "Authentication"},
214 {MGT_DEAUTHENTICATION, "Deauthentication"},
215 {CTRL_PS_POLL, "Power-Save poll"},
216 {CTRL_RTS, "Request-to-send"},
217 {CTRL_CTS, "Clear-to-send"},
218 {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
219 {CTRL_CFP_END, "CF-End (Control-frame)"},
220 {CTRL_CFP_ENDACK, "CF-End + CF-Ack (Control-frame)"},
222 {DATA_CF_ACK, "Data + CF-Acknowledgement"},
223 {DATA_CF_POLL, "Data + CF-Poll"},
224 {DATA_CF_ACK_POLL, "Data + CF-Acknowledgement/Poll"},
225 {DATA_NULL_FUNCTION, "Null function (No data)"},
226 {DATA_CF_ACK_NOD, "Data + Acknowledgement (No data)"},
227 {DATA_CF_POLL_NOD, "Data + CF-Poll (No data)"},
228 {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
232 static int proto_wlan = -1;
233 /* ************************************************************************* */
234 /* Header field info values for FC-field */
235 /* ************************************************************************* */
236 static int hf_fc_field = -1;
237 static int hf_fc_proto_version = -1;
238 static int hf_fc_frame_type = -1;
239 static int hf_fc_frame_subtype = -1;
240 static int hf_fc_frame_type_subtype = -1;
242 static int hf_fc_flags = -1;
243 static int hf_fc_to_ds = -1;
244 static int hf_fc_from_ds = -1;
245 static int hf_fc_data_ds = -1;
247 static int hf_fc_more_frag = -1;
248 static int hf_fc_retry = -1;
249 static int hf_fc_pwr_mgt = -1;
250 static int hf_fc_more_data = -1;
251 static int hf_fc_wep = -1;
252 static int hf_fc_order = -1;
255 /* ************************************************************************* */
256 /* Header values for Duration/ID field */
257 /* ************************************************************************* */
258 static int hf_did_duration = -1;
259 static int hf_assoc_id = -1;
262 /* ************************************************************************* */
263 /* Header values for different address-fields (all 4 of them) */
264 /* ************************************************************************* */
265 static int hf_addr_da = -1; /* Destination address subfield */
266 static int hf_addr_sa = -1; /* Source address subfield */
267 static int hf_addr_ra = -1; /* Receiver address subfield */
268 static int hf_addr_ta = -1; /* Transmitter address subfield */
269 static int hf_addr_bssid = -1; /* address is bssid */
271 static int hf_addr = -1; /* Source or destination address subfield */
274 /* ************************************************************************* */
275 /* Header values for sequence number field */
276 /* ************************************************************************* */
277 static int hf_frag_number = -1;
278 static int hf_seq_number = -1;
280 /* ************************************************************************* */
281 /* Header values for Frame Check field */
282 /* ************************************************************************* */
283 static int hf_fcs = -1;
287 static int proto_wlan_mgt = -1;
288 /* ************************************************************************* */
289 /* Fixed fields found in mgt frames */
290 /* ************************************************************************* */
291 static int ff_auth_alg = -1; /* Authentication algorithm field */
292 static int ff_auth_seq = -1; /* Authentication transaction sequence */
293 static int ff_current_ap = -1; /* Current AP MAC address */
294 static int ff_listen_ival = -1; /* Listen interval fixed field */
295 static int ff_timestamp = -1; /* 64 bit timestamp */
296 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
297 static int ff_assoc_id = -1; /* 16 bit AID field */
298 static int ff_reason = -1; /* 16 bit reason code */
299 static int ff_status_code = -1; /* Status code */
301 /* ************************************************************************* */
302 /* Flags found in the capability field (fixed field) */
303 /* ************************************************************************* */
304 static int ff_capture = -1;
305 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
306 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
307 static int ff_cf_ess = -1;
308 static int ff_cf_ibss = -1;
309 static int ff_cf_privacy = -1;
310 static int ff_cf_preamble = -1;
311 static int ff_cf_pbcc = -1;
312 static int ff_cf_agility = -1;
314 /* ************************************************************************* */
315 /* Tagged value format fields */
316 /* ************************************************************************* */
317 static int tag_number = -1;
318 static int tag_length = -1;
319 static int tag_interpretation = -1;
323 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
324 static int hf_tagged_parameters = -1; /* Fixed payload item */
325 static int hf_wep_iv = -1;
326 static int hf_wep_key = -1;
327 static int hf_wep_crc = -1;
329 /* ************************************************************************* */
331 /* ************************************************************************* */
332 static gint ett_80211 = -1;
333 static gint ett_proto_flags = -1;
334 static gint ett_cap_tree = -1;
335 static gint ett_fc_tree = -1;
337 static gint ett_80211_mgt = -1;
338 static gint ett_fixed_parameters = -1;
339 static gint ett_tagged_parameters = -1;
340 static gint ett_wep_parameters = -1;
342 static dissector_handle_t llc_handle;
343 static dissector_handle_t ipx_handle;
345 /* ************************************************************************* */
346 /* Return the length of the current header (in bytes) */
347 /* ************************************************************************* */
349 find_header_length (guint16 fcf)
351 switch (COOK_FRAME_TYPE (fcf)) {
354 return MGT_FRAME_HDR_LEN;
357 switch (COMPOSE_FRAME_TYPE (fcf)) {
360 case CTRL_ACKNOWLEDGEMENT:
366 case CTRL_CFP_ENDACK:
372 return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
380 /* ************************************************************************* */
381 /* This is the capture function used to update packet counts */
382 /* ************************************************************************* */
384 capture_ieee80211 (const u_char * pd, int offset, packet_counts * ld)
386 guint16 fcf, hdr_length;
388 fcf = pletohs (&pd[0]);
390 if (IS_WEP(COOK_FLAGS(fcf)))
396 switch (COMPOSE_FRAME_TYPE (fcf))
399 case DATA: /* We got a data frame */
400 case DATA_CF_ACK: /* Data with ACK */
402 case DATA_CF_ACK_POLL:
403 hdr_length = find_header_length (fcf);
404 /* I guess some bridges take Netware Ethernet_802_3 frames,
405 which are 802.3 frames (with a length field rather than
406 a type field, but with no 802.2 header in the payload),
407 and just stick the payload into an 802.11 frame. I've seen
408 captures that show frames of that sort.
410 This means we have to do the same check for Netware 802.3 -
411 or, if you will, "Netware 802.11" - that we do in the
412 Ethernet dissector, i.e. checking for 0xffff as the first
413 four bytes of the payload and, if we find it, treating it
415 if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
416 capture_ipx (pd, offset + hdr_length, ld);
419 capture_llc (pd, offset + hdr_length, ld);
431 /* ************************************************************************* */
432 /* Add the subtree used to store the fixed parameters */
433 /* ************************************************************************* */
435 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
437 proto_item *fixed_fields;
439 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
440 size, size, "Fixed parameters (%d bytes)",
443 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
447 /* ************************************************************************* */
448 /* Add the subtree used to store tagged parameters */
449 /* ************************************************************************* */
451 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
453 proto_item *tagged_fields;
455 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
460 "Tagged parameters (%d bytes)",
463 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
467 /* ************************************************************************* */
468 /* Add the subtree used to store WEP parameters */
469 /* ************************************************************************* */
471 get_wep_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
473 proto_item *wep_fields;
474 proto_tree *wep_tree;
475 int crc_offset = size - 4;
477 wep_fields = proto_tree_add_text(tree, tvb, start, 4, "WEP parameters");
479 wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
480 proto_tree_add_item (wep_tree, hf_wep_iv, tvb, start, 3, TRUE);
482 proto_tree_add_uint (wep_tree, hf_wep_key, tvb, start + 3, 1,
483 COOK_WEP_KEY (tvb_get_guint8 (tvb, start + 3)));
485 if (tvb_bytes_exist(tvb, start + crc_offset, 4))
486 proto_tree_add_uint (wep_tree, hf_wep_crc, tvb, start + crc_offset, 4,
487 tvb_get_ntohl (tvb, start + crc_offset));
490 /* ************************************************************************* */
491 /* Dissect and add fixed mgmt fields to protocol tree */
492 /* ************************************************************************* */
494 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
496 const guint8 *dataptr;
497 char out_buff[SHORT_STR];
499 proto_item *cap_item;
500 static proto_tree *cap_tree;
505 case FIELD_TIMESTAMP:
506 dataptr = tvb_get_ptr (tvb, offset, 8);
507 memset (out_buff, 0, SHORT_STR);
508 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
518 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
521 case FIELD_BEACON_INTERVAL:
522 temp_double = (double) tvb_get_letohs (tvb, offset);
523 temp_double = temp_double * 1024 / 1000000;
524 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
525 temp_double,"Beacon Interval: %f [Seconds]",
531 capability = tvb_get_letohs (tvb, offset);
533 cap_item = proto_tree_add_uint_format (tree, ff_capture,
536 "Capability Information: 0x%04X",
538 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
539 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
541 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
543 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
545 proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 1,
547 proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 1,
549 proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 1,
551 if (ESS_SET (capability) != 0) /* This is an AP */
552 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
553 ((capability & 0xC) >> 2));
555 else /* This is a STA */
556 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
557 ((capability & 0xC) >> 2));
561 proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2, TRUE);
564 case FIELD_AUTH_TRANS_SEQ:
565 proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2, TRUE);
568 case FIELD_CURRENT_AP_ADDR:
569 proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
572 case FIELD_LISTEN_IVAL:
573 proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
576 case FIELD_REASON_CODE:
577 proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
581 proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE);
584 case FIELD_STATUS_CODE:
585 proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
591 /* ************************************************************************* */
592 /* Dissect and add tagged (optional) fields to proto tree */
593 /* ************************************************************************* */
595 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
597 const guint8 *tag_data_ptr;
598 guint32 tag_no, tag_len;
601 char out_buff[SHORT_STR];
604 tag_no = tvb_get_guint8(tvb, offset);
605 tag_len = tvb_get_guint8(tvb, offset + 1);
607 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
610 if ((tag_no >= 17) && (tag_no <= 31))
611 { /* Reserved for challenge text */
612 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
613 "Tag Number: %u (Reserved for challenge text)",
616 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
617 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
618 tag_len, "Not interpreted");
619 return (int) tag_len + 2;
622 /* Next See if tag is reserved - if true, skip it! */
623 if (((tag_no >= 7) && (tag_no <= 15))
624 || ((tag_no >= 32) && (tag_no <= 255)))
626 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
627 "Tag Number: %u (Reserved tag number)",
630 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
632 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
633 tag_len, "Not interpreted");
634 return (int) tag_len + 2;
643 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
644 "Tag Number: %u (SSID parameter set)",
647 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
649 memset (out_buff, 0, SHORT_STR);
651 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
652 out_buff[tag_len + 1] = 0;
654 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
661 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
662 "Tag Number: %u (Supported Rates)", tag_no);
664 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
666 memset (out_buff, 0, SHORT_STR);
667 strcpy (out_buff, "Supported rates: ");
668 n = strlen (out_buff);
670 for (i = 0; i < tag_len; i++)
672 n += snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
673 (tag_data_ptr[i] & 0x7F) * 0.5,
674 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
676 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
678 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
684 case TAG_FH_PARAMETER:
685 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
686 "Tag Number: %u (FH Parameter set)",
689 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
690 memset (out_buff, 0, SHORT_STR);
692 snprintf (out_buff, SHORT_STR,
693 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
694 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
695 tag_data_ptr[3], tag_data_ptr[4]);
697 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
703 case TAG_DS_PARAMETER:
704 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
705 "Tag Number: %u (DS Parameter set)",
708 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
709 memset (out_buff, 0, SHORT_STR);
711 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
712 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
717 case TAG_CF_PARAMETER:
718 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
719 "Tag Number: %u (CF Parameter set)",
722 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
723 memset (out_buff, 0, SHORT_STR);
725 snprintf (out_buff, SHORT_STR,
726 "CFP count %u, CFP period %u, CFP max duration %u, "
727 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
728 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
730 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
736 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
737 "Tag Number: %u ((TIM) Traffic Indication Map)",
740 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
741 memset (out_buff, 0, SHORT_STR);
742 snprintf (out_buff, SHORT_STR,
743 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
744 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
746 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
752 case TAG_IBSS_PARAMETER:
753 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
754 "Tag Number: %u (IBSS Parameter set)",
757 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
758 memset (out_buff, 0, SHORT_STR);
759 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
760 pletohs (tag_data_ptr));
762 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
768 case TAG_CHALLENGE_TEXT:
769 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
770 "Tag Number: %u (Challenge text)", tag_no);
772 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
773 memset (out_buff, 0, SHORT_STR);
774 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
775 proto_tree_add_string (tree, tag_interpretation, tvb, offset, tag_len,
787 /* ************************************************************************* */
788 /* Dissect 802.11 management frame */
789 /* ************************************************************************* */
791 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
794 proto_item *ti = NULL;
795 proto_tree *mgt_tree;
796 proto_tree *fixed_tree;
797 proto_tree *tagged_tree;
800 int tagged_parameter_tree_len;
802 CHECK_DISPLAY_AS_DATA(proto_wlan_mgt, tvb, pinfo, tree);
806 ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, tvb_length(tvb), FALSE);
807 mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
809 switch (COMPOSE_FRAME_TYPE(fcf))
813 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
814 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
815 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
817 next_idx = 4; /* Size of fixed fields */
818 tagged_parameter_tree_len =
819 tvb_reported_length_remaining(tvb, next_idx + 4);
820 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
821 tagged_parameter_tree_len);
823 while (tagged_parameter_tree_len > 0) {
824 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
827 tagged_parameter_tree_len -= next_len;
833 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
834 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
835 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
836 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
838 next_idx = 6; /* Size of fixed fields */
840 tagged_parameter_tree_len =
841 tvb_reported_length_remaining(tvb, next_idx + 4);
842 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
843 tagged_parameter_tree_len);
845 while (tagged_parameter_tree_len > 0) {
846 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
849 tagged_parameter_tree_len -= next_len;
854 case MGT_REASSOC_REQ:
855 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
856 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
857 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
858 add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
860 next_idx = 10; /* Size of fixed fields */
861 tagged_parameter_tree_len =
862 tvb_reported_length_remaining(tvb, next_idx + 4);
863 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
864 tagged_parameter_tree_len);
866 while (tagged_parameter_tree_len > 0) {
867 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
870 tagged_parameter_tree_len -= next_len;
874 case MGT_REASSOC_RESP:
875 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
876 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
877 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
878 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
880 next_idx = 6; /* Size of fixed fields */
881 tagged_parameter_tree_len =
882 tvb_reported_length_remaining(tvb, next_idx + 4);
883 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
884 tagged_parameter_tree_len);
886 while (tagged_parameter_tree_len > 0) {
887 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
890 tagged_parameter_tree_len -= next_len;
897 tagged_parameter_tree_len =
898 tvb_reported_length_remaining(tvb, next_idx + 4);
899 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
900 tagged_parameter_tree_len);
902 while (tagged_parameter_tree_len > 0) {
903 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
906 tagged_parameter_tree_len -= next_len;
912 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
913 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
914 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
915 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
917 next_idx = 12; /* Size of fixed fields */
918 tagged_parameter_tree_len =
919 tvb_reported_length_remaining(tvb, next_idx + 4);
920 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
921 tagged_parameter_tree_len);
923 while (tagged_parameter_tree_len > 0) {
924 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
927 tagged_parameter_tree_len -= next_len;
932 case MGT_BEACON: /* Dissect protocol payload fields */
933 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
935 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
936 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
937 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
939 next_idx = 12; /* Size of fixed fields */
940 tagged_parameter_tree_len =
941 tvb_reported_length_remaining(tvb, next_idx + 4);
942 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
943 tagged_parameter_tree_len);
945 while (tagged_parameter_tree_len > 0) {
946 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
949 tagged_parameter_tree_len -= next_len;
959 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
960 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
964 case MGT_AUTHENTICATION:
965 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
966 add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
967 add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
968 add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
970 next_idx = 6; /* Size of fixed fields */
972 tagged_parameter_tree_len =
973 tvb_reported_length_remaining(tvb, next_idx + 4);
974 if (tagged_parameter_tree_len != 0)
976 tagged_tree = get_tagged_parameter_tree (mgt_tree,
979 tagged_parameter_tree_len);
981 while (tagged_parameter_tree_len > 0) {
982 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
985 tagged_parameter_tree_len -= next_len;
991 case MGT_DEAUTHENTICATION:
992 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
993 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1000 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1002 if (check_col(pinfo->fd, COL_RES_DL_SRC))
1003 col_add_fstr(pinfo->fd, COL_RES_DL_SRC, "%s (%s)",
1004 get_ether_name(addr), type);
1005 if (check_col(pinfo->fd, COL_UNRES_DL_SRC))
1006 col_add_fstr(pinfo->fd, COL_UNRES_DL_SRC, "%s (%s)",
1007 ether_to_str(addr), type);
1011 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1013 if (check_col(pinfo->fd, COL_RES_DL_DST))
1014 col_add_fstr(pinfo->fd, COL_RES_DL_DST, "%s (%s)",
1015 get_ether_name(addr), type);
1016 if (check_col(pinfo->fd, COL_UNRES_DL_DST))
1017 col_add_fstr(pinfo->fd, COL_UNRES_DL_DST, "%s (%s)",
1018 ether_to_str(addr), type);
1021 /* ************************************************************************* */
1022 /* Dissect 802.11 frame */
1023 /* ************************************************************************* */
1025 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1027 guint16 fcf, flags, frame_type_subtype;
1028 const guint8 *src = NULL, *dst = NULL;
1029 proto_item *ti = NULL;
1030 proto_item *flag_item;
1031 proto_item *fc_item;
1032 proto_tree *hdr_tree = NULL;
1033 proto_tree *flag_tree;
1034 proto_tree *fc_tree;
1038 volatile gboolean is_802_2;
1040 if (check_col (pinfo->fd, COL_PROTOCOL))
1041 col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
1042 if (check_col (pinfo->fd, COL_INFO))
1043 col_clear (pinfo->fd, COL_INFO);
1045 fcf = tvb_get_letohs (tvb, 0);
1046 hdr_len = find_header_length (fcf);
1047 frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1049 COL_SHOW_INFO_CONST (pinfo->fd,
1050 val_to_str(frame_type_subtype, frame_type_subtype_vals,
1051 "Unrecognized (Reserved frame)"));
1053 /* Add the FC to the current tree */
1056 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1058 hdr_tree = proto_item_add_subtree (ti, ett_80211);
1060 proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1062 frame_type_subtype);
1064 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
1066 "Frame Control: 0x%04X",
1069 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1072 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
1073 COOK_PROT_VERSION (fcf));
1075 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
1076 COOK_FRAME_TYPE (fcf));
1078 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1080 COOK_FRAME_SUBTYPE (fcf));
1082 flags = COOK_FLAGS (fcf);
1085 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
1086 flags, "Flags: 0x%X", flags);
1088 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1090 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
1091 COOK_DS_STATUS (flags));
1093 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1096 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1098 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1100 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1103 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1105 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1107 if (frame_type_subtype == CTRL_PS_POLL)
1108 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1109 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1112 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1113 tvb_get_letohs (tvb, 2));
1117 * Decode the part of the frame header that isn't the same for all
1120 switch (frame_type_subtype)
1124 case MGT_ASSOC_RESP:
1125 case MGT_REASSOC_REQ:
1126 case MGT_REASSOC_RESP:
1128 case MGT_PROBE_RESP:
1132 case MGT_AUTHENTICATION:
1133 case MGT_DEAUTHENTICATION:
1135 * All management frame types have the same header.
1137 src = tvb_get_ptr (tvb, 10, 6);
1138 dst = tvb_get_ptr (tvb, 4, 6);
1140 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1141 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1142 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1143 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1147 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1149 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1151 /* add items for wlan.addr filter */
1152 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1153 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1155 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1156 tvb_get_ptr (tvb, 16, 6));
1158 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1159 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1162 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1163 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1170 src = tvb_get_ptr (tvb, 10, 6);
1171 dst = tvb_get_ptr (tvb, 4, 6);
1173 set_src_addr_cols(pinfo, src, "BSSID");
1174 set_dst_addr_cols(pinfo, dst, "BSSID");
1178 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1180 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1186 src = tvb_get_ptr (tvb, 10, 6);
1187 dst = tvb_get_ptr (tvb, 4, 6);
1189 set_src_addr_cols(pinfo, src, "TA");
1190 set_dst_addr_cols(pinfo, dst, "RA");
1194 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1196 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1202 dst = tvb_get_ptr (tvb, 4, 6);
1204 set_dst_addr_cols(pinfo, dst, "RA");
1207 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1211 case CTRL_ACKNOWLEDGEMENT:
1212 dst = tvb_get_ptr (tvb, 4, 6);
1214 set_dst_addr_cols(pinfo, dst, "RA");
1217 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1222 src = tvb_get_ptr (tvb, 10, 6);
1223 dst = tvb_get_ptr (tvb, 4, 6);
1225 set_src_addr_cols(pinfo, src, "BSSID");
1226 set_dst_addr_cols(pinfo, dst, "RA");
1230 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1231 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1236 case CTRL_CFP_ENDACK:
1237 src = tvb_get_ptr (tvb, 10, 6);
1238 dst = tvb_get_ptr (tvb, 4, 6);
1240 set_src_addr_cols(pinfo, src, "BSSID");
1241 set_dst_addr_cols(pinfo, dst, "RA");
1245 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1247 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1255 case DATA_CF_ACK_POLL:
1256 addr_type = COOK_ADDR_SELECTOR (fcf);
1258 /* In order to show src/dst address we must always do the following */
1263 src = tvb_get_ptr (tvb, 10, 6);
1264 dst = tvb_get_ptr (tvb, 4, 6);
1269 src = tvb_get_ptr (tvb, 16, 6);
1270 dst = tvb_get_ptr (tvb, 4, 6);
1275 src = tvb_get_ptr (tvb, 10, 6);
1276 dst = tvb_get_ptr (tvb, 16, 6);
1281 src = tvb_get_ptr (tvb, 24, 6);
1282 dst = tvb_get_ptr (tvb, 16, 6);
1286 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1287 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1288 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1289 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1291 /* Now if we have a tree we start adding stuff */
1300 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1301 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1302 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1303 tvb_get_ptr (tvb, 16, 6));
1304 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1305 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1307 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1308 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1311 /* add items for wlan.addr filter */
1312 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1313 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1318 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1319 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1320 tvb_get_ptr (tvb, 10, 6));
1321 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1322 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1323 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1325 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1326 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1329 /* add items for wlan.addr filter */
1330 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1331 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1336 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1337 tvb_get_ptr (tvb, 4, 6));
1338 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1339 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1341 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1342 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1344 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1345 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1348 /* add items for wlan.addr filter */
1349 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1350 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1355 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1356 tvb_get_ptr (tvb, 4, 6));
1357 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1358 tvb_get_ptr (tvb, 10, 6));
1359 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1360 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1361 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1363 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1364 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1366 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1368 /* add items for wlan.addr filter */
1369 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1370 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1379 * Only management and data frames have a body, so we don't have
1380 * anything more to do for other types of frames.
1382 switch (COOK_FRAME_TYPE (fcf))
1394 * For WEP-encrypted frames, dissect the WEP parameters and
1395 * display the payload as data.
1397 * XXX - allow the key to be specified, and, if it is, decrypt
1398 * the payload and dissect it?
1400 if (IS_WEP(COOK_FLAGS(fcf)))
1402 int pkt_len = tvb_reported_length (tvb);
1403 int cap_len = tvb_length (tvb);
1407 get_wep_parameter_tree (tree, tvb, hdr_len, pkt_len);
1408 pkt_len -= hdr_len + 4;
1409 cap_len -= hdr_len + 4;
1412 * OK, pkt_len and cap_len have had the length of the 802.11
1413 * header and WEP parameters subtracted.
1415 * If there's anything left:
1417 * if cap_len is greater than or equal to pkt_len (i.e., we
1418 * captured the entire packet), subtract the length of the
1419 * WEP CRC from cap_len;
1421 * if cap_len is from 1 to 3 bytes less than pkt_len (i.e.,
1422 * we captured some but not all of the WEP CRC), subtract
1423 * the length of the part of the WEP CRC we captured from
1426 * otherwise, (i.e., we captured none of the WEP CRC),
1427 * leave cap_len alone;
1429 * and subtract the length of the WEP CRC from pkt_len.
1431 if (cap_len >= pkt_len)
1433 else if ((pkt_len - cap_len) >= 1 && (pkt_len - cap_len) <= 3)
1434 cap_len -= 4 - (pkt_len - cap_len);
1436 if (cap_len > 0 && pkt_len > 0)
1437 dissect_data (tvb, hdr_len + 4, pinfo, tree);
1443 * Now dissect the body of a non-WEP-encrypted frame.
1445 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1446 switch (COOK_FRAME_TYPE (fcf))
1450 dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1455 /* I guess some bridges take Netware Ethernet_802_3 frames,
1456 which are 802.3 frames (with a length field rather than
1457 a type field, but with no 802.2 header in the payload),
1458 and just stick the payload into an 802.11 frame. I've seen
1459 captures that show frames of that sort.
1461 This means we have to do the same check for Netware 802.3 -
1462 or, if you will, "Netware 802.11" - that we do in the
1463 Ethernet dissector, i.e. checking for 0xffff as the first
1464 four bytes of the payload and, if we find it, treating it
1468 if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1471 CATCH2(BoundsError, ReportedBoundsError) {
1478 call_dissector(llc_handle, next_tvb, pinfo, tree);
1480 call_dissector(ipx_handle, next_tvb, pinfo, tree);
1486 proto_register_wlan (void)
1488 static const value_string frame_type[] = {
1489 {MGT_FRAME, "Management frame"},
1490 {CONTROL_FRAME, "Control frame"},
1491 {DATA_FRAME, "Data frame"},
1495 static const value_string tofrom_ds[] = {
1496 {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
1497 {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"},
1498 {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"},
1499 {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"},
1503 static const true_false_string tods_flag = {
1504 "TO DS: Should be false",
1508 static const true_false_string fromds_flag = {
1509 "FROM DS: Should be false",
1513 static const true_false_string more_frags = {
1514 "MSDU/MMPDU is fragmented",
1518 static const true_false_string retry_flags = {
1519 "Frame is being retransmitted",
1520 "Frame is not being retransmitted"
1523 static const true_false_string pm_flags = {
1524 "STA will go to sleep",
1528 static const true_false_string md_flags = {
1529 "Data is buffered for STA at AP",
1533 static const true_false_string wep_flags = {
1538 static const true_false_string order_flags = {
1540 "Not strictly ordered"
1543 static const true_false_string cf_ess_flags = {
1544 "Transmitter is an AP",
1545 "Transmitter is a STA"
1549 static const true_false_string cf_privacy_flags = {
1550 "AP/STA can support WEP",
1551 "AP/STA cannot support WEP"
1554 static const true_false_string cf_preamble_flags = {
1555 "Short preamble allowed",
1556 "Short preamble not allowed"
1559 static const true_false_string cf_pbcc_flags = {
1560 "PBCC modulation allowed",
1561 "PBCC modulation not allowed"
1564 static const true_false_string cf_agility_flags = {
1565 "Channel agility in use",
1566 "Channel agility not in use"
1570 static const true_false_string cf_ibss_flags = {
1571 "Transmitter belongs to an IBSS",
1572 "Transmitter belongs to a BSS"
1575 static const value_string sta_cf_pollable[] = {
1576 {0x00, "Station is not CF-Pollable"},
1577 {0x02, "Station is CF-Pollable, "
1578 "not requesting to be placed on the CF-polling list"},
1579 {0x01, "Station is CF-Pollable, "
1580 "requesting to be placed on the CF-polling list"},
1581 {0x03, "Station is CF-Pollable, requesting never to be polled"},
1585 static const value_string ap_cf_pollable[] = {
1586 {0x00, "No point coordinator at AP"},
1587 {0x02, "Point coordinator at AP for delivery only (no polling)"},
1588 {0x01, "Point coordinator at AP for delivery and polling"},
1594 static const value_string auth_alg[] = {
1595 {0x00, "Open System"},
1596 {0x01, "Shared key"},
1600 static const value_string reason_codes[] = {
1602 {0x01, "Unspecified reason"},
1603 {0x02, "Previous authentication no longer valid"},
1604 {0x03, "Deauthenticated because sending STA is leaving (has left) "
1606 {0x04, "Disassociated due to inactivity"},
1607 {0x05, "Disassociated because AP is unable to handle all currently "
1608 "associated stations"},
1609 {0x06, "Class 2 frame received from nonauthenticated station"},
1610 {0x07, "Class 3 frame received from nonassociated station"},
1611 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1612 {0x09, "Station requesting (re)association is not authenticated with "
1613 "responding station"},
1618 static const value_string status_codes[] = {
1619 {0x00, "Successful"},
1620 {0x01, "Unspecified failure"},
1621 {0x0A, "Cannot support all requested capabilities in the "
1622 "Capability information field"},
1623 {0x0B, "Reassociation denied due to inability to confirm that "
1624 "association exists"},
1625 {0x0C, "Association denied due to reason outside the scope of this "
1628 {0x0D, "Responding station does not support the specified authentication "
1630 {0x0E, "Received an Authentication frame with authentication sequence "
1631 "transaction sequence number out of expected sequence"},
1632 {0x0F, "Authentication rejected because of challenge failure"},
1633 {0x10, "Authentication rejected due to timeout waiting for next "
1634 "frame in sequence"},
1635 {0x11, "Association denied because AP is unable to handle additional "
1636 "associated stations"},
1637 {0x12, "Association denied due to requesting station not supporting all "
1638 "of the datarates in the BSSBasicServiceSet Parameter"},
1642 static hf_register_info hf[] = {
1644 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
1645 "MAC Frame control", HFILL }},
1647 {&hf_fc_proto_version,
1648 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
1649 "MAC Protocol version", HFILL }}, /* 0 */
1652 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
1653 "Frame type", HFILL }},
1655 {&hf_fc_frame_subtype,
1656 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
1657 "Frame subtype", HFILL }}, /* 2 */
1659 {&hf_fc_frame_type_subtype,
1660 {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
1661 "Type and subtype combined", HFILL }},
1664 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
1665 "Protocol flags", HFILL }},
1668 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
1669 "Data-frame DS-traversal status", HFILL }}, /* 3 */
1672 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
1673 "To DS flag", HFILL }}, /* 4 */
1676 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
1677 "From DS flag", HFILL }}, /* 5 */
1680 {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
1681 "More Fragments flag", HFILL }}, /* 6 */
1684 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
1685 "Retransmission flag", HFILL }},
1688 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
1689 "Power management status", HFILL }},
1692 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
1693 "More data flag", HFILL }},
1696 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
1697 "WEP flag", HFILL }},
1700 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
1701 "Strictly ordered flag", HFILL }},
1704 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
1705 "Association-ID field", HFILL }},
1708 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
1709 "Duration field", HFILL }},
1712 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
1713 "Destination Hardware Address", HFILL }},
1716 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
1717 "Source Hardware Address", HFILL }},
1720 {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
1721 "Source or Destination Hardware Address", HFILL }},
1724 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
1725 "Receiving Station Hardware Address", HFILL }},
1728 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
1729 "Transmitting Station Hardware Address", HFILL }},
1732 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
1733 "Basic Service Set ID", HFILL }},
1736 {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
1737 "Fragment number", HFILL }},
1740 {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
1741 "Sequence number", HFILL }},
1744 {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
1745 NULL, 0, "", HFILL }},
1748 {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
1749 "Initialization Vector", HFILL }},
1752 {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
1756 {"WEP CRC (not verified)", "wlan.wep.crc", FT_UINT32, BASE_HEX, NULL, 0,
1757 "WEP CRC", HFILL }},
1760 static hf_register_info ff[] = {
1762 {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
1763 NULL, 0, "", HFILL }},
1766 {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
1767 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
1769 {&ff_beacon_interval,
1770 {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
1773 {&hf_fixed_parameters,
1774 {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
1777 {&hf_tagged_parameters,
1778 {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
1782 {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
1783 "Capability information", HFILL }},
1786 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
1787 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
1788 "CF-Poll capabilities for a STA", HFILL }},
1791 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
1792 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
1793 "CF-Poll capabilities for an AP", HFILL }},
1796 {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
1797 FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
1801 {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
1802 FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
1805 {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
1806 FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
1809 {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
1810 FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
1813 {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
1814 FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
1817 {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
1818 FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
1821 {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
1822 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
1825 {"Association ID", "wlan_mgt.fixed.aid",
1826 FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
1829 {"Listen Interval", "wlan_mgt.fixed.listen_ival",
1830 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
1833 {"Current AP", "wlan_mgt.fixed.current_ap",
1834 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
1837 {"Reason code", "wlan_mgt.fixed.reason_code",
1838 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
1839 "Reason for unsolicited notification", HFILL }},
1842 {"Status code", "wlan_mgt.fixed.status_code",
1843 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
1844 "Status of requested event", HFILL }},
1847 {"Tag", "wlan_mgt.tag.number",
1848 FT_UINT16, BASE_DEC, NULL, 0,
1849 "Element ID", HFILL }},
1852 {"Tag length", "wlan_mgt.tag.length",
1853 FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
1855 {&tag_interpretation,
1856 {"Tag interpretation", "wlan_mgt.tag.interpretation",
1857 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
1861 static gint *tree_array[] = {
1866 &ett_fixed_parameters,
1867 &ett_tagged_parameters,
1868 &ett_wep_parameters,
1872 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
1873 "IEEE 802.11", "wlan");
1874 proto_register_field_array (proto_wlan, hf, array_length (hf));
1875 proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
1876 "802.11 MGT", "wlan_mgt");
1877 proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
1878 proto_register_subtree_array (tree_array, array_length (tree_array));
1882 proto_reg_handoff_wlan(void)
1885 * Get handles for the LLC and IPX dissectors.
1887 llc_handle = find_dissector("llc");
1888 ipx_handle = find_dissector("ipx");
1890 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,