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.40 2001/09/25 02:21:15 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 && n < SHORT_STR; i++)
672 ret = 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 /* Some versions of snprintf return -1 if they'd truncate
683 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
685 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
691 case TAG_FH_PARAMETER:
692 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
693 "Tag Number: %u (FH Parameter set)",
696 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
697 memset (out_buff, 0, SHORT_STR);
699 snprintf (out_buff, SHORT_STR,
700 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
701 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
702 tag_data_ptr[3], tag_data_ptr[4]);
704 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
710 case TAG_DS_PARAMETER:
711 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
712 "Tag Number: %u (DS Parameter set)",
715 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
716 memset (out_buff, 0, SHORT_STR);
718 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
719 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
724 case TAG_CF_PARAMETER:
725 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
726 "Tag Number: %u (CF Parameter set)",
729 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
730 memset (out_buff, 0, SHORT_STR);
732 snprintf (out_buff, SHORT_STR,
733 "CFP count %u, CFP period %u, CFP max duration %u, "
734 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
735 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
737 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
743 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
744 "Tag Number: %u ((TIM) Traffic Indication Map)",
747 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
748 memset (out_buff, 0, SHORT_STR);
749 snprintf (out_buff, SHORT_STR,
750 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
751 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
753 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
759 case TAG_IBSS_PARAMETER:
760 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
761 "Tag Number: %u (IBSS Parameter set)",
764 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
765 memset (out_buff, 0, SHORT_STR);
766 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
767 pletohs (tag_data_ptr));
769 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
775 case TAG_CHALLENGE_TEXT:
776 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
777 "Tag Number: %u (Challenge text)", tag_no);
779 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
780 memset (out_buff, 0, SHORT_STR);
781 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
782 proto_tree_add_string (tree, tag_interpretation, tvb, offset, tag_len,
794 /* ************************************************************************* */
795 /* Dissect 802.11 management frame */
796 /* ************************************************************************* */
798 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
801 proto_item *ti = NULL;
802 proto_tree *mgt_tree;
803 proto_tree *fixed_tree;
804 proto_tree *tagged_tree;
807 int tagged_parameter_tree_len;
809 CHECK_DISPLAY_AS_DATA(proto_wlan_mgt, tvb, pinfo, tree);
813 ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, tvb_length(tvb), FALSE);
814 mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
816 switch (COMPOSE_FRAME_TYPE(fcf))
820 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
821 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
822 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
824 next_idx = 4; /* Size of fixed fields */
825 tagged_parameter_tree_len =
826 tvb_reported_length_remaining(tvb, next_idx + 4);
827 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
828 tagged_parameter_tree_len);
830 while (tagged_parameter_tree_len > 0) {
831 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
834 tagged_parameter_tree_len -= next_len;
840 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
841 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
842 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
843 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
845 next_idx = 6; /* Size of fixed fields */
847 tagged_parameter_tree_len =
848 tvb_reported_length_remaining(tvb, next_idx + 4);
849 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
850 tagged_parameter_tree_len);
852 while (tagged_parameter_tree_len > 0) {
853 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
856 tagged_parameter_tree_len -= next_len;
861 case MGT_REASSOC_REQ:
862 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
863 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
864 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
865 add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
867 next_idx = 10; /* Size of fixed fields */
868 tagged_parameter_tree_len =
869 tvb_reported_length_remaining(tvb, next_idx + 4);
870 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
871 tagged_parameter_tree_len);
873 while (tagged_parameter_tree_len > 0) {
874 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
877 tagged_parameter_tree_len -= next_len;
881 case MGT_REASSOC_RESP:
882 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
883 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
884 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
885 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
887 next_idx = 6; /* Size of fixed fields */
888 tagged_parameter_tree_len =
889 tvb_reported_length_remaining(tvb, next_idx + 4);
890 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
891 tagged_parameter_tree_len);
893 while (tagged_parameter_tree_len > 0) {
894 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
897 tagged_parameter_tree_len -= next_len;
904 tagged_parameter_tree_len =
905 tvb_reported_length_remaining(tvb, next_idx + 4);
906 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
907 tagged_parameter_tree_len);
909 while (tagged_parameter_tree_len > 0) {
910 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
913 tagged_parameter_tree_len -= next_len;
919 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
920 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
921 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
922 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
924 next_idx = 12; /* Size of fixed fields */
925 tagged_parameter_tree_len =
926 tvb_reported_length_remaining(tvb, next_idx + 4);
927 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
928 tagged_parameter_tree_len);
930 while (tagged_parameter_tree_len > 0) {
931 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
934 tagged_parameter_tree_len -= next_len;
939 case MGT_BEACON: /* Dissect protocol payload fields */
940 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
942 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
943 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
944 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
946 next_idx = 12; /* Size of fixed fields */
947 tagged_parameter_tree_len =
948 tvb_reported_length_remaining(tvb, next_idx + 4);
949 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
950 tagged_parameter_tree_len);
952 while (tagged_parameter_tree_len > 0) {
953 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
956 tagged_parameter_tree_len -= next_len;
966 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
967 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
971 case MGT_AUTHENTICATION:
972 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
973 add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
974 add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
975 add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
977 next_idx = 6; /* Size of fixed fields */
979 tagged_parameter_tree_len =
980 tvb_reported_length_remaining(tvb, next_idx + 4);
981 if (tagged_parameter_tree_len != 0)
983 tagged_tree = get_tagged_parameter_tree (mgt_tree,
986 tagged_parameter_tree_len);
988 while (tagged_parameter_tree_len > 0) {
989 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
992 tagged_parameter_tree_len -= next_len;
998 case MGT_DEAUTHENTICATION:
999 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1000 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1007 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1009 if (check_col(pinfo->fd, COL_RES_DL_SRC))
1010 col_add_fstr(pinfo->fd, COL_RES_DL_SRC, "%s (%s)",
1011 get_ether_name(addr), type);
1012 if (check_col(pinfo->fd, COL_UNRES_DL_SRC))
1013 col_add_fstr(pinfo->fd, COL_UNRES_DL_SRC, "%s (%s)",
1014 ether_to_str(addr), type);
1018 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1020 if (check_col(pinfo->fd, COL_RES_DL_DST))
1021 col_add_fstr(pinfo->fd, COL_RES_DL_DST, "%s (%s)",
1022 get_ether_name(addr), type);
1023 if (check_col(pinfo->fd, COL_UNRES_DL_DST))
1024 col_add_fstr(pinfo->fd, COL_UNRES_DL_DST, "%s (%s)",
1025 ether_to_str(addr), type);
1028 /* ************************************************************************* */
1029 /* Dissect 802.11 frame */
1030 /* ************************************************************************* */
1032 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1034 guint16 fcf, flags, frame_type_subtype;
1035 const guint8 *src = NULL, *dst = NULL;
1036 proto_item *ti = NULL;
1037 proto_item *flag_item;
1038 proto_item *fc_item;
1039 proto_tree *hdr_tree = NULL;
1040 proto_tree *flag_tree;
1041 proto_tree *fc_tree;
1045 volatile gboolean is_802_2;
1047 if (check_col (pinfo->fd, COL_PROTOCOL))
1048 col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
1049 if (check_col (pinfo->fd, COL_INFO))
1050 col_clear (pinfo->fd, COL_INFO);
1052 fcf = tvb_get_letohs (tvb, 0);
1053 hdr_len = find_header_length (fcf);
1054 frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1056 COL_SHOW_INFO_CONST (pinfo->fd,
1057 val_to_str(frame_type_subtype, frame_type_subtype_vals,
1058 "Unrecognized (Reserved frame)"));
1060 /* Add the FC to the current tree */
1063 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1065 hdr_tree = proto_item_add_subtree (ti, ett_80211);
1067 proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1069 frame_type_subtype);
1071 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
1073 "Frame Control: 0x%04X",
1076 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1079 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
1080 COOK_PROT_VERSION (fcf));
1082 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
1083 COOK_FRAME_TYPE (fcf));
1085 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1087 COOK_FRAME_SUBTYPE (fcf));
1089 flags = COOK_FLAGS (fcf);
1092 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
1093 flags, "Flags: 0x%X", flags);
1095 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1097 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
1098 COOK_DS_STATUS (flags));
1100 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1103 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1105 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1107 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1110 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1112 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1114 if (frame_type_subtype == CTRL_PS_POLL)
1115 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1116 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1119 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1120 tvb_get_letohs (tvb, 2));
1124 * Decode the part of the frame header that isn't the same for all
1127 switch (frame_type_subtype)
1131 case MGT_ASSOC_RESP:
1132 case MGT_REASSOC_REQ:
1133 case MGT_REASSOC_RESP:
1135 case MGT_PROBE_RESP:
1139 case MGT_AUTHENTICATION:
1140 case MGT_DEAUTHENTICATION:
1142 * All management frame types have the same header.
1144 src = tvb_get_ptr (tvb, 10, 6);
1145 dst = tvb_get_ptr (tvb, 4, 6);
1147 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1148 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1149 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1150 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1154 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1156 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1158 /* add items for wlan.addr filter */
1159 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1160 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1162 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1163 tvb_get_ptr (tvb, 16, 6));
1165 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1166 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1169 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1170 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1177 src = tvb_get_ptr (tvb, 10, 6);
1178 dst = tvb_get_ptr (tvb, 4, 6);
1180 set_src_addr_cols(pinfo, src, "BSSID");
1181 set_dst_addr_cols(pinfo, dst, "BSSID");
1185 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1187 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1193 src = tvb_get_ptr (tvb, 10, 6);
1194 dst = tvb_get_ptr (tvb, 4, 6);
1196 set_src_addr_cols(pinfo, src, "TA");
1197 set_dst_addr_cols(pinfo, dst, "RA");
1201 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1203 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1209 dst = tvb_get_ptr (tvb, 4, 6);
1211 set_dst_addr_cols(pinfo, dst, "RA");
1214 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1218 case CTRL_ACKNOWLEDGEMENT:
1219 dst = tvb_get_ptr (tvb, 4, 6);
1221 set_dst_addr_cols(pinfo, dst, "RA");
1224 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1229 src = tvb_get_ptr (tvb, 10, 6);
1230 dst = tvb_get_ptr (tvb, 4, 6);
1232 set_src_addr_cols(pinfo, src, "BSSID");
1233 set_dst_addr_cols(pinfo, dst, "RA");
1237 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1238 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1243 case CTRL_CFP_ENDACK:
1244 src = tvb_get_ptr (tvb, 10, 6);
1245 dst = tvb_get_ptr (tvb, 4, 6);
1247 set_src_addr_cols(pinfo, src, "BSSID");
1248 set_dst_addr_cols(pinfo, dst, "RA");
1252 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1254 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1262 case DATA_CF_ACK_POLL:
1263 addr_type = COOK_ADDR_SELECTOR (fcf);
1265 /* In order to show src/dst address we must always do the following */
1270 src = tvb_get_ptr (tvb, 10, 6);
1271 dst = tvb_get_ptr (tvb, 4, 6);
1276 src = tvb_get_ptr (tvb, 16, 6);
1277 dst = tvb_get_ptr (tvb, 4, 6);
1282 src = tvb_get_ptr (tvb, 10, 6);
1283 dst = tvb_get_ptr (tvb, 16, 6);
1288 src = tvb_get_ptr (tvb, 24, 6);
1289 dst = tvb_get_ptr (tvb, 16, 6);
1293 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1294 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1295 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1296 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1298 /* Now if we have a tree we start adding stuff */
1307 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1308 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1309 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1310 tvb_get_ptr (tvb, 16, 6));
1311 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1312 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1314 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1315 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1318 /* add items for wlan.addr filter */
1319 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1320 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1325 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1326 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1327 tvb_get_ptr (tvb, 10, 6));
1328 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1329 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1330 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1332 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1333 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1336 /* add items for wlan.addr filter */
1337 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1338 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1343 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1344 tvb_get_ptr (tvb, 4, 6));
1345 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1346 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1348 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1349 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1351 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1352 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1355 /* add items for wlan.addr filter */
1356 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1357 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1362 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1363 tvb_get_ptr (tvb, 4, 6));
1364 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1365 tvb_get_ptr (tvb, 10, 6));
1366 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1367 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1368 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1370 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1371 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1373 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1375 /* add items for wlan.addr filter */
1376 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1377 proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1386 * Only management and data frames have a body, so we don't have
1387 * anything more to do for other types of frames.
1389 switch (COOK_FRAME_TYPE (fcf))
1401 * For WEP-encrypted frames, dissect the WEP parameters and
1402 * display the payload as data.
1404 * XXX - allow the key to be specified, and, if it is, decrypt
1405 * the payload and dissect it?
1407 if (IS_WEP(COOK_FLAGS(fcf)))
1409 int pkt_len = tvb_reported_length (tvb);
1410 int cap_len = tvb_length (tvb);
1414 get_wep_parameter_tree (tree, tvb, hdr_len, pkt_len);
1415 pkt_len -= hdr_len + 4;
1416 cap_len -= hdr_len + 4;
1419 * OK, pkt_len and cap_len have had the length of the 802.11
1420 * header and WEP parameters subtracted.
1422 * If there's anything left:
1424 * if cap_len is greater than or equal to pkt_len (i.e., we
1425 * captured the entire packet), subtract the length of the
1426 * WEP CRC from cap_len;
1428 * if cap_len is from 1 to 3 bytes less than pkt_len (i.e.,
1429 * we captured some but not all of the WEP CRC), subtract
1430 * the length of the part of the WEP CRC we captured from
1433 * otherwise, (i.e., we captured none of the WEP CRC),
1434 * leave cap_len alone;
1436 * and subtract the length of the WEP CRC from pkt_len.
1438 if (cap_len >= pkt_len)
1440 else if ((pkt_len - cap_len) >= 1 && (pkt_len - cap_len) <= 3)
1441 cap_len -= 4 - (pkt_len - cap_len);
1443 if (cap_len > 0 && pkt_len > 0)
1444 dissect_data (tvb, hdr_len + 4, pinfo, tree);
1450 * Now dissect the body of a non-WEP-encrypted frame.
1452 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1453 switch (COOK_FRAME_TYPE (fcf))
1457 dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1462 /* I guess some bridges take Netware Ethernet_802_3 frames,
1463 which are 802.3 frames (with a length field rather than
1464 a type field, but with no 802.2 header in the payload),
1465 and just stick the payload into an 802.11 frame. I've seen
1466 captures that show frames of that sort.
1468 This means we have to do the same check for Netware 802.3 -
1469 or, if you will, "Netware 802.11" - that we do in the
1470 Ethernet dissector, i.e. checking for 0xffff as the first
1471 four bytes of the payload and, if we find it, treating it
1475 if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1478 CATCH2(BoundsError, ReportedBoundsError) {
1485 call_dissector(llc_handle, next_tvb, pinfo, tree);
1487 call_dissector(ipx_handle, next_tvb, pinfo, tree);
1493 proto_register_wlan (void)
1495 static const value_string frame_type[] = {
1496 {MGT_FRAME, "Management frame"},
1497 {CONTROL_FRAME, "Control frame"},
1498 {DATA_FRAME, "Data frame"},
1502 static const value_string tofrom_ds[] = {
1503 {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
1504 {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"},
1505 {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"},
1506 {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"},
1510 static const true_false_string tods_flag = {
1511 "TO DS: Should be false",
1515 static const true_false_string fromds_flag = {
1516 "FROM DS: Should be false",
1520 static const true_false_string more_frags = {
1521 "MSDU/MMPDU is fragmented",
1525 static const true_false_string retry_flags = {
1526 "Frame is being retransmitted",
1527 "Frame is not being retransmitted"
1530 static const true_false_string pm_flags = {
1531 "STA will go to sleep",
1535 static const true_false_string md_flags = {
1536 "Data is buffered for STA at AP",
1540 static const true_false_string wep_flags = {
1545 static const true_false_string order_flags = {
1547 "Not strictly ordered"
1550 static const true_false_string cf_ess_flags = {
1551 "Transmitter is an AP",
1552 "Transmitter is a STA"
1556 static const true_false_string cf_privacy_flags = {
1557 "AP/STA can support WEP",
1558 "AP/STA cannot support WEP"
1561 static const true_false_string cf_preamble_flags = {
1562 "Short preamble allowed",
1563 "Short preamble not allowed"
1566 static const true_false_string cf_pbcc_flags = {
1567 "PBCC modulation allowed",
1568 "PBCC modulation not allowed"
1571 static const true_false_string cf_agility_flags = {
1572 "Channel agility in use",
1573 "Channel agility not in use"
1577 static const true_false_string cf_ibss_flags = {
1578 "Transmitter belongs to an IBSS",
1579 "Transmitter belongs to a BSS"
1582 static const value_string sta_cf_pollable[] = {
1583 {0x00, "Station is not CF-Pollable"},
1584 {0x02, "Station is CF-Pollable, "
1585 "not requesting to be placed on the CF-polling list"},
1586 {0x01, "Station is CF-Pollable, "
1587 "requesting to be placed on the CF-polling list"},
1588 {0x03, "Station is CF-Pollable, requesting never to be polled"},
1592 static const value_string ap_cf_pollable[] = {
1593 {0x00, "No point coordinator at AP"},
1594 {0x02, "Point coordinator at AP for delivery only (no polling)"},
1595 {0x01, "Point coordinator at AP for delivery and polling"},
1601 static const value_string auth_alg[] = {
1602 {0x00, "Open System"},
1603 {0x01, "Shared key"},
1607 static const value_string reason_codes[] = {
1609 {0x01, "Unspecified reason"},
1610 {0x02, "Previous authentication no longer valid"},
1611 {0x03, "Deauthenticated because sending STA is leaving (has left) "
1613 {0x04, "Disassociated due to inactivity"},
1614 {0x05, "Disassociated because AP is unable to handle all currently "
1615 "associated stations"},
1616 {0x06, "Class 2 frame received from nonauthenticated station"},
1617 {0x07, "Class 3 frame received from nonassociated station"},
1618 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1619 {0x09, "Station requesting (re)association is not authenticated with "
1620 "responding station"},
1625 static const value_string status_codes[] = {
1626 {0x00, "Successful"},
1627 {0x01, "Unspecified failure"},
1628 {0x0A, "Cannot support all requested capabilities in the "
1629 "Capability information field"},
1630 {0x0B, "Reassociation denied due to inability to confirm that "
1631 "association exists"},
1632 {0x0C, "Association denied due to reason outside the scope of this "
1635 {0x0D, "Responding station does not support the specified authentication "
1637 {0x0E, "Received an Authentication frame with authentication sequence "
1638 "transaction sequence number out of expected sequence"},
1639 {0x0F, "Authentication rejected because of challenge failure"},
1640 {0x10, "Authentication rejected due to timeout waiting for next "
1641 "frame in sequence"},
1642 {0x11, "Association denied because AP is unable to handle additional "
1643 "associated stations"},
1644 {0x12, "Association denied due to requesting station not supporting all "
1645 "of the datarates in the BSSBasicServiceSet Parameter"},
1649 static hf_register_info hf[] = {
1651 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
1652 "MAC Frame control", HFILL }},
1654 {&hf_fc_proto_version,
1655 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
1656 "MAC Protocol version", HFILL }}, /* 0 */
1659 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
1660 "Frame type", HFILL }},
1662 {&hf_fc_frame_subtype,
1663 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
1664 "Frame subtype", HFILL }}, /* 2 */
1666 {&hf_fc_frame_type_subtype,
1667 {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
1668 "Type and subtype combined", HFILL }},
1671 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
1672 "Protocol flags", HFILL }},
1675 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
1676 "Data-frame DS-traversal status", HFILL }}, /* 3 */
1679 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
1680 "To DS flag", HFILL }}, /* 4 */
1683 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
1684 "From DS flag", HFILL }}, /* 5 */
1687 {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
1688 "More Fragments flag", HFILL }}, /* 6 */
1691 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
1692 "Retransmission flag", HFILL }},
1695 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
1696 "Power management status", HFILL }},
1699 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
1700 "More data flag", HFILL }},
1703 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
1704 "WEP flag", HFILL }},
1707 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
1708 "Strictly ordered flag", HFILL }},
1711 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
1712 "Association-ID field", HFILL }},
1715 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
1716 "Duration field", HFILL }},
1719 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
1720 "Destination Hardware Address", HFILL }},
1723 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
1724 "Source Hardware Address", HFILL }},
1727 {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
1728 "Source or Destination Hardware Address", HFILL }},
1731 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
1732 "Receiving Station Hardware Address", HFILL }},
1735 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
1736 "Transmitting Station Hardware Address", HFILL }},
1739 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
1740 "Basic Service Set ID", HFILL }},
1743 {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
1744 "Fragment number", HFILL }},
1747 {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
1748 "Sequence number", HFILL }},
1751 {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
1752 NULL, 0, "", HFILL }},
1755 {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
1756 "Initialization Vector", HFILL }},
1759 {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
1763 {"WEP CRC (not verified)", "wlan.wep.crc", FT_UINT32, BASE_HEX, NULL, 0,
1764 "WEP CRC", HFILL }},
1767 static hf_register_info ff[] = {
1769 {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
1770 NULL, 0, "", HFILL }},
1773 {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
1774 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
1776 {&ff_beacon_interval,
1777 {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
1780 {&hf_fixed_parameters,
1781 {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
1784 {&hf_tagged_parameters,
1785 {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
1789 {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
1790 "Capability information", HFILL }},
1793 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
1794 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
1795 "CF-Poll capabilities for a STA", HFILL }},
1798 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
1799 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
1800 "CF-Poll capabilities for an AP", HFILL }},
1803 {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
1804 FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
1808 {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
1809 FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
1812 {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
1813 FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
1816 {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
1817 FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
1820 {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
1821 FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
1824 {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
1825 FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
1828 {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
1829 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
1832 {"Association ID", "wlan_mgt.fixed.aid",
1833 FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
1836 {"Listen Interval", "wlan_mgt.fixed.listen_ival",
1837 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
1840 {"Current AP", "wlan_mgt.fixed.current_ap",
1841 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
1844 {"Reason code", "wlan_mgt.fixed.reason_code",
1845 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
1846 "Reason for unsolicited notification", HFILL }},
1849 {"Status code", "wlan_mgt.fixed.status_code",
1850 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
1851 "Status of requested event", HFILL }},
1854 {"Tag", "wlan_mgt.tag.number",
1855 FT_UINT16, BASE_DEC, NULL, 0,
1856 "Element ID", HFILL }},
1859 {"Tag length", "wlan_mgt.tag.length",
1860 FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
1862 {&tag_interpretation,
1863 {"Tag interpretation", "wlan_mgt.tag.interpretation",
1864 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
1868 static gint *tree_array[] = {
1873 &ett_fixed_parameters,
1874 &ett_tagged_parameters,
1875 &ett_wep_parameters,
1879 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
1880 "IEEE 802.11", "wlan");
1881 proto_register_field_array (proto_wlan, hf, array_length (hf));
1882 proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
1883 "802.11 MGT", "wlan_mgt");
1884 proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
1885 proto_register_subtree_array (tree_array, array_length (tree_array));
1889 proto_reg_handoff_wlan(void)
1892 * Get handles for the LLC and IPX dissectors.
1894 llc_handle = find_dissector("llc");
1895 ipx_handle = find_dissector("ipx");
1897 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,