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.36 2001/06/22 08:12:11 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-llc.h"
69 #include "packet-ieee80211.h"
72 /* ************************************************************************* */
73 /* Miscellaneous Constants */
74 /* ************************************************************************* */
77 /* ************************************************************************* */
78 /* Define some very useful macros that are used to analyze frame types etc. */
79 /* ************************************************************************* */
80 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */
81 #define COOK_PROT_VERSION(x) ((x) & 0x3)
82 #define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2)
83 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
84 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
85 #define COOK_ASSOC_ID(x) ((x) & 0x3FFF)
86 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
87 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
88 #define COOK_FLAGS(x) (((x) & 0xFF00) >> 8)
89 #define COOK_DS_STATUS(x) ((x) & 0x3)
90 #define COOK_WEP_KEY(x) (((x) & 0xC0) >> 6)
91 #define COL_SHOW_INFO(fd,info) if (check_col(fd,COL_INFO)) \
92 col_add_str(fd,COL_INFO,info);
93 #define COL_SHOW_INFO_CONST(fd,info) if (check_col(fd,COL_INFO)) \
94 col_set_str(fd,COL_INFO,info);
96 #define FLAG_TO_DS 0x01
97 #define FLAG_FROM_DS 0x02
98 #define FLAG_MORE_FRAGMENTS 0x04
99 #define FLAG_RETRY 0x08
100 #define FLAG_POWER_MGT 0x10
101 #define FLAG_MORE_DATA 0x20
102 #define FLAG_WEP 0x40
103 #define FLAG_ORDER 0x80
105 #define IS_TO_DS(x) ((x) & FLAG_TO_DS)
106 #define IS_FROM_DS(x) ((x) & FLAG_FROM_DS)
107 #define HAVE_FRAGMENTS(x) ((x) & FLAG_MORE_FRAGMENTS)
108 #define IS_RETRY(x) ((x) & FLAG_RETRY)
109 #define POWER_MGT_STATUS(x) ((x) & FLAG_POWER_MGT)
110 #define HAS_MORE_DATA(x) ((x) & FLAG_MORE_DATA)
111 #define IS_WEP(x) ((x) & FLAG_WEP)
112 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
114 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
115 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
116 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
117 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
120 /* ************************************************************************* */
121 /* Constants used to identify cooked frame types */
122 /* ************************************************************************* */
123 #define MGT_FRAME 0x00 /* Frame type is management */
124 #define CONTROL_FRAME 0x01 /* Frame type is control */
125 #define DATA_FRAME 0x02 /* Frame type is Data */
127 #define DATA_SHORT_HDR_LEN 24
128 #define DATA_LONG_HDR_LEN 30
129 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
131 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
132 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
133 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
134 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
135 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
136 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
137 #define MGT_BEACON 0x08 /* Management - Beacon frame */
138 #define MGT_ATIM 0x09 /* Management - ATIM */
139 #define MGT_DISASS 0x0A /* Management - Disassociation */
140 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
141 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
143 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
144 #define CTRL_RTS 0x1B /* Control - request to send */
145 #define CTRL_CTS 0x1C /* Control - clear to send */
146 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
147 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
148 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
150 #define DATA 0x20 /* Data - Data */
151 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
152 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
153 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
154 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
155 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
156 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
157 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
159 #define DATA_ADDR_T1 0
160 #define DATA_ADDR_T2 (FLAG_FROM_DS << 8)
161 #define DATA_ADDR_T3 (FLAG_TO_DS << 8)
162 #define DATA_ADDR_T4 ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
165 /* ************************************************************************* */
166 /* Macros used to extract information about fixed fields */
167 /* ************************************************************************* */
168 #define ESS_SET(x) ((x) & 0x0001)
169 #define IBSS_SET(x) ((x) & 0x0002)
173 /* ************************************************************************* */
174 /* Logical field codes (dissector's encoding of fixed fields) */
175 /* ************************************************************************* */
176 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
177 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
178 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
179 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
180 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
181 #define FIELD_CURRENT_AP_ADDR 0x06
182 #define FIELD_LISTEN_IVAL 0x07
183 #define FIELD_REASON_CODE 0x08
184 #define FIELD_ASSOC_ID 0x09
185 #define FIELD_STATUS_CODE 0x0A
187 /* ************************************************************************* */
188 /* Logical field codes (IEEE 802.11 encoding of tags) */
189 /* ************************************************************************* */
190 #define TAG_SSID 0x00
191 #define TAG_SUPP_RATES 0x01
192 #define TAG_FH_PARAMETER 0x02
193 #define TAG_DS_PARAMETER 0x03
194 #define TAG_CF_PARAMETER 0x04
196 #define TAG_IBSS_PARAMETER 0x06
197 #define TAG_CHALLENGE_TEXT 0x10
199 /* ************************************************************************* */
200 /* Frame types, and their names */
201 /* ************************************************************************* */
202 static const value_string frame_type_subtype_vals[] = {
203 {MGT_ASSOC_REQ, "Association Request"},
204 {MGT_ASSOC_RESP, "Association Response"},
205 {MGT_REASSOC_REQ, "Reassociation Request"},
206 {MGT_REASSOC_RESP, "Reassociation Response"},
207 {MGT_PROBE_REQ, "Probe Request"},
208 {MGT_PROBE_RESP, "Probe Response"},
209 {MGT_BEACON, "Beacon frame"},
211 {MGT_DISASS, "Dissassociate"},
212 {MGT_AUTHENTICATION, "Authentication"},
213 {MGT_DEAUTHENTICATION, "Deauthentication"},
214 {CTRL_PS_POLL, "Power-Save poll"},
215 {CTRL_RTS, "Request-to-send"},
216 {CTRL_CTS, "Clear-to-send"},
217 {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
218 {CTRL_CFP_END, "CF-End (Control-frame)"},
219 {CTRL_CFP_ENDACK, "CF-End + CF-Ack (Control-frame)"},
221 {DATA_CF_ACK, "Data + CF-Acknowledgement"},
222 {DATA_CF_POLL, "Data + CF-Poll"},
223 {DATA_CF_ACK_POLL, "Data + CF-Acknowledgement/Poll"},
224 {DATA_NULL_FUNCTION, "Null function (No data)"},
225 {DATA_CF_ACK_NOD, "Data + Acknowledgement (No data)"},
226 {DATA_CF_POLL_NOD, "Data + CF-Poll (No data)"},
227 {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
231 static int proto_wlan = -1;
232 /* ************************************************************************* */
233 /* Header field info values for FC-field */
234 /* ************************************************************************* */
235 static int hf_fc_field = -1;
236 static int hf_fc_proto_version = -1;
237 static int hf_fc_frame_type = -1;
238 static int hf_fc_frame_subtype = -1;
239 static int hf_fc_frame_type_subtype = -1;
241 static int hf_fc_flags = -1;
242 static int hf_fc_to_ds = -1;
243 static int hf_fc_from_ds = -1;
244 static int hf_fc_data_ds = -1;
246 static int hf_fc_more_frag = -1;
247 static int hf_fc_retry = -1;
248 static int hf_fc_pwr_mgt = -1;
249 static int hf_fc_more_data = -1;
250 static int hf_fc_wep = -1;
251 static int hf_fc_order = -1;
254 /* ************************************************************************* */
255 /* Header values for Duration/ID field */
256 /* ************************************************************************* */
257 static int hf_did_duration = -1;
258 static int hf_assoc_id = -1;
261 /* ************************************************************************* */
262 /* Header values for different address-fields (all 4 of them) */
263 /* ************************************************************************* */
264 static int hf_addr_da = -1; /* Destination address subfield */
265 static int hf_addr_sa = -1; /* Source address subfield */
266 static int hf_addr_ra = -1; /* Receiver address subfield */
267 static int hf_addr_ta = -1; /* Transmitter address subfield */
268 static int hf_addr_bssid = -1; /* address is bssid */
272 /* ************************************************************************* */
273 /* Header values for sequence number field */
274 /* ************************************************************************* */
275 static int hf_frag_number = -1;
276 static int hf_seq_number = -1;
278 /* ************************************************************************* */
279 /* Header values for Frame Check field */
280 /* ************************************************************************* */
281 static int hf_fcs = -1;
285 static int proto_wlan_mgt = -1;
286 /* ************************************************************************* */
287 /* Fixed fields found in mgt frames */
288 /* ************************************************************************* */
289 static int ff_auth_alg = -1; /* Authentication algorithm field */
290 static int ff_auth_seq = -1; /* Authentication transaction sequence */
291 static int ff_current_ap = -1; /* Current AP MAC address */
292 static int ff_listen_ival = -1; /* Listen interval fixed field */
293 static int ff_timestamp = -1; /* 64 bit timestamp */
294 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
295 static int ff_assoc_id = -1; /* 16 bit AID field */
296 static int ff_reason = -1; /* 16 bit reason code */
297 static int ff_status_code = -1; /* Status code */
299 /* ************************************************************************* */
300 /* Flags found in the capability field (fixed field) */
301 /* ************************************************************************* */
302 static int ff_capture = -1;
303 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
304 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
305 static int ff_cf_ess = -1;
306 static int ff_cf_ibss = -1;
307 static int ff_cf_privacy = -1;
308 static int ff_cf_preamble = -1;
309 static int ff_cf_pbcc = -1;
310 static int ff_cf_agility = -1;
312 /* ************************************************************************* */
313 /* Tagged value format fields */
314 /* ************************************************************************* */
315 static int tag_number = -1;
316 static int tag_length = -1;
317 static int tag_interpretation = -1;
321 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
322 static int hf_tagged_parameters = -1; /* Fixed payload item */
323 static int hf_wep_iv = -1;
324 static int hf_wep_key = -1;
325 static int hf_wep_crc = -1;
327 /* ************************************************************************* */
329 /* ************************************************************************* */
330 static gint ett_80211 = -1;
331 static gint ett_proto_flags = -1;
332 static gint ett_cap_tree = -1;
333 static gint ett_fc_tree = -1;
335 static gint ett_80211_mgt = -1;
336 static gint ett_fixed_parameters = -1;
337 static gint ett_tagged_parameters = -1;
338 static gint ett_wep_parameters = -1;
340 static dissector_handle_t llc_handle;
342 /* ************************************************************************* */
343 /* Return the length of the current header (in bytes) */
344 /* ************************************************************************* */
346 find_header_length (guint16 fcf)
348 switch (COOK_FRAME_TYPE (fcf)) {
351 return MGT_FRAME_HDR_LEN;
354 switch (COMPOSE_FRAME_TYPE (fcf)) {
357 case CTRL_ACKNOWLEDGEMENT:
363 case CTRL_CFP_ENDACK:
369 return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
377 /* ************************************************************************* */
378 /* This is the capture function used to update packet counts */
379 /* ************************************************************************* */
381 capture_ieee80211 (const u_char * pd, int offset, packet_counts * ld)
383 guint16 fcf, hdr_length;
385 fcf = pletohs (&pd[0]);
387 if (IS_WEP(COOK_FLAGS(fcf)))
393 switch (COMPOSE_FRAME_TYPE (fcf))
396 case DATA: /* We got a data frame */
397 case DATA_CF_ACK: /* Data with ACK */
399 case DATA_CF_ACK_POLL:
400 hdr_length = find_header_length (fcf);
401 capture_llc (pd, offset + hdr_length, ld);
412 /* ************************************************************************* */
413 /* Add the subtree used to store the fixed parameters */
414 /* ************************************************************************* */
416 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
418 proto_item *fixed_fields;
420 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
421 size, size, "Fixed parameters (%d bytes)",
424 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
428 /* ************************************************************************* */
429 /* Add the subtree used to store tagged parameters */
430 /* ************************************************************************* */
432 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
434 proto_item *tagged_fields;
436 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
441 "Tagged parameters (%d bytes)",
444 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
448 /* ************************************************************************* */
449 /* Add the subtree used to store WEP parameters */
450 /* ************************************************************************* */
452 get_wep_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
454 proto_item *wep_fields;
455 proto_tree *wep_tree;
456 int crc_offset = size - 4;
458 wep_fields = proto_tree_add_text(tree, tvb, start, 4, "WEP parameters");
460 wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
461 proto_tree_add_item (wep_tree, hf_wep_iv, tvb, start, 3, TRUE);
463 proto_tree_add_uint (wep_tree, hf_wep_key, tvb, start + 3, 1,
464 COOK_WEP_KEY (tvb_get_guint8 (tvb, start + 3)));
466 if (tvb_bytes_exist(tvb, start + crc_offset, 4))
467 proto_tree_add_uint (wep_tree, hf_wep_crc, tvb, start + crc_offset, 4,
468 tvb_get_ntohl (tvb, start + crc_offset));
471 /* ************************************************************************* */
472 /* Dissect and add fixed mgmt fields to protocol tree */
473 /* ************************************************************************* */
475 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
477 const guint8 *dataptr;
478 char out_buff[SHORT_STR];
480 proto_item *cap_item;
481 static proto_tree *cap_tree;
486 case FIELD_TIMESTAMP:
487 dataptr = tvb_get_ptr (tvb, offset, 8);
488 memset (out_buff, 0, SHORT_STR);
489 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
499 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
502 case FIELD_BEACON_INTERVAL:
503 temp_double = (double) tvb_get_letohs (tvb, offset);
504 temp_double = temp_double * 1024 / 1000000;
505 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
506 temp_double,"Beacon Interval: %f [Seconds]",
512 capability = tvb_get_letohs (tvb, offset);
514 cap_item = proto_tree_add_uint_format (tree, ff_capture,
517 "Capability Information: 0x%04X",
519 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
520 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
522 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
524 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
526 proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 1,
528 proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 1,
530 proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 1,
532 if (ESS_SET (capability) != 0) /* This is an AP */
533 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
534 ((capability & 0xC) >> 2));
536 else /* This is a STA */
537 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
538 ((capability & 0xC) >> 2));
542 proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2, TRUE);
545 case FIELD_AUTH_TRANS_SEQ:
546 proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2, TRUE);
549 case FIELD_CURRENT_AP_ADDR:
550 proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
553 case FIELD_LISTEN_IVAL:
554 proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
557 case FIELD_REASON_CODE:
558 proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
562 proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE);
565 case FIELD_STATUS_CODE:
566 proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
572 /* ************************************************************************* */
573 /* Dissect and add tagged (optional) fields to proto tree */
574 /* ************************************************************************* */
576 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
578 const guint8 *tag_data_ptr;
579 guint32 tag_no, tag_len;
582 char out_buff[SHORT_STR];
585 tag_no = tvb_get_guint8(tvb, offset);
586 tag_len = tvb_get_guint8(tvb, offset + 1);
588 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
591 if ((tag_no >= 17) && (tag_no <= 31))
592 { /* Reserved for challenge text */
593 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
594 "Tag Number: %u (Reserved for challenge text)",
597 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
598 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
599 tag_len, "Not interpreted");
600 return (int) tag_len + 2;
603 /* Next See if tag is reserved - if true, skip it! */
604 if (((tag_no >= 7) && (tag_no <= 15))
605 || ((tag_no >= 32) && (tag_no <= 255)))
607 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
608 "Tag Number: %u (Reserved tag number)",
611 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
613 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
614 tag_len, "Not interpreted");
615 return (int) tag_len + 2;
624 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
625 "Tag Number: %u (SSID parameter set)",
628 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
630 memset (out_buff, 0, SHORT_STR);
632 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
633 out_buff[tag_len + 1] = 0;
635 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
642 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
643 "Tag Number: %u (Supported Rates)", tag_no);
645 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
647 memset (out_buff, 0, SHORT_STR);
648 strcpy (out_buff, "Supported rates: ");
649 n = strlen (out_buff);
651 for (i = 0; i < tag_len; i++)
653 n += snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
654 (tag_data_ptr[i] & 0x7F) * 0.5,
655 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
657 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
659 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
665 case TAG_FH_PARAMETER:
666 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
667 "Tag Number: %u (FH Parameter set)",
670 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
671 memset (out_buff, 0, SHORT_STR);
673 snprintf (out_buff, SHORT_STR,
674 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
675 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
676 tag_data_ptr[3], tag_data_ptr[4]);
678 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
684 case TAG_DS_PARAMETER:
685 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
686 "Tag Number: %u (DS 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, "Current Channel: %u", tag_data_ptr[0]);
693 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
698 case TAG_CF_PARAMETER:
699 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
700 "Tag Number: %u (CF Parameter set)",
703 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
704 memset (out_buff, 0, SHORT_STR);
706 snprintf (out_buff, SHORT_STR,
707 "CFP count %u, CFP period %u, CFP max duration %u, "
708 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
709 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
711 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
717 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
718 "Tag Number: %u ((TIM) Traffic Indication Map)",
721 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
722 memset (out_buff, 0, SHORT_STR);
723 snprintf (out_buff, SHORT_STR,
724 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
725 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
727 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
733 case TAG_IBSS_PARAMETER:
734 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
735 "Tag Number: %u (IBSS Parameter set)",
738 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
739 memset (out_buff, 0, SHORT_STR);
740 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
741 pletohs (tag_data_ptr));
743 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
749 case TAG_CHALLENGE_TEXT:
750 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
751 "Tag Number: %u (Challenge text)", tag_no);
753 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
754 memset (out_buff, 0, SHORT_STR);
755 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
756 proto_tree_add_string (tree, tag_interpretation, tvb, offset, tag_len,
768 /* ************************************************************************* */
769 /* Dissect 802.11 management frame */
770 /* ************************************************************************* */
772 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
775 proto_item *ti = NULL;
776 proto_tree *mgt_tree;
777 proto_tree *fixed_tree;
778 proto_tree *tagged_tree;
781 int tagged_parameter_tree_len;
783 CHECK_DISPLAY_AS_DATA(proto_wlan_mgt, tvb, pinfo, tree);
787 ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, tvb_length(tvb), FALSE);
788 mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
790 switch (COMPOSE_FRAME_TYPE(fcf))
794 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
795 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
796 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
798 next_idx = 4; /* Size of fixed fields */
799 tagged_parameter_tree_len =
800 tvb_reported_length_remaining(tvb, next_idx + 4);
801 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
802 tagged_parameter_tree_len);
804 while (tagged_parameter_tree_len > 0) {
805 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
808 tagged_parameter_tree_len -= next_len;
814 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
815 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
816 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
817 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
819 next_idx = 6; /* Size of fixed fields */
821 tagged_parameter_tree_len =
822 tvb_reported_length_remaining(tvb, next_idx + 4);
823 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
824 tagged_parameter_tree_len);
826 while (tagged_parameter_tree_len > 0) {
827 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
830 tagged_parameter_tree_len -= next_len;
835 case MGT_REASSOC_REQ:
836 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
837 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
838 add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
839 add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
841 next_idx = 10; /* Size of fixed fields */
842 tagged_parameter_tree_len =
843 tvb_reported_length_remaining(tvb, next_idx + 4);
844 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
845 tagged_parameter_tree_len);
847 while (tagged_parameter_tree_len > 0) {
848 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
851 tagged_parameter_tree_len -= next_len;
855 case MGT_REASSOC_RESP:
856 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
857 add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
858 add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
859 add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
861 next_idx = 6; /* Size of fixed fields */
862 tagged_parameter_tree_len =
863 tvb_reported_length_remaining(tvb, next_idx + 4);
864 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
865 tagged_parameter_tree_len);
867 while (tagged_parameter_tree_len > 0) {
868 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
871 tagged_parameter_tree_len -= next_len;
878 tagged_parameter_tree_len =
879 tvb_reported_length_remaining(tvb, next_idx + 4);
880 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
881 tagged_parameter_tree_len);
883 while (tagged_parameter_tree_len > 0) {
884 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
887 tagged_parameter_tree_len -= next_len;
893 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
894 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
895 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
896 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
898 next_idx = 12; /* Size of fixed fields */
899 tagged_parameter_tree_len =
900 tvb_reported_length_remaining(tvb, next_idx + 4);
901 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
902 tagged_parameter_tree_len);
904 while (tagged_parameter_tree_len > 0) {
905 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
908 tagged_parameter_tree_len -= next_len;
913 case MGT_BEACON: /* Dissect protocol payload fields */
914 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
916 add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
917 add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
918 add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
920 next_idx = 12; /* Size of fixed fields */
921 tagged_parameter_tree_len =
922 tvb_reported_length_remaining(tvb, next_idx + 4);
923 tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
924 tagged_parameter_tree_len);
926 while (tagged_parameter_tree_len > 0) {
927 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
930 tagged_parameter_tree_len -= next_len;
940 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
941 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
945 case MGT_AUTHENTICATION:
946 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
947 add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
948 add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
949 add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
951 next_idx = 6; /* Size of fixed fields */
953 tagged_parameter_tree_len =
954 tvb_reported_length_remaining(tvb, next_idx + 4);
955 if (tagged_parameter_tree_len != 0)
957 tagged_tree = get_tagged_parameter_tree (mgt_tree,
960 tagged_parameter_tree_len);
962 while (tagged_parameter_tree_len > 0) {
963 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
966 tagged_parameter_tree_len -= next_len;
972 case MGT_DEAUTHENTICATION:
973 fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
974 add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
981 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
983 if (check_col(pinfo->fd, COL_RES_DL_SRC))
984 col_add_fstr(pinfo->fd, COL_RES_DL_SRC, "%s (%s)",
985 get_ether_name(addr), type);
986 if (check_col(pinfo->fd, COL_UNRES_DL_SRC))
987 col_add_fstr(pinfo->fd, COL_UNRES_DL_SRC, "%s (%s)",
988 ether_to_str(addr), type);
992 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
994 if (check_col(pinfo->fd, COL_RES_DL_DST))
995 col_add_fstr(pinfo->fd, COL_RES_DL_DST, "%s (%s)",
996 get_ether_name(addr), type);
997 if (check_col(pinfo->fd, COL_UNRES_DL_DST))
998 col_add_fstr(pinfo->fd, COL_UNRES_DL_DST, "%s (%s)",
999 ether_to_str(addr), type);
1002 /* ************************************************************************* */
1003 /* Dissect 802.11 frame */
1004 /* ************************************************************************* */
1006 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1008 guint16 fcf, flags, frame_type_subtype;
1009 const guint8 *src = NULL, *dst = NULL;
1010 proto_item *ti = NULL;
1011 proto_item *flag_item;
1012 proto_item *fc_item;
1013 proto_tree *hdr_tree = NULL;
1014 proto_tree *flag_tree;
1015 proto_tree *fc_tree;
1020 if (check_col (pinfo->fd, COL_PROTOCOL))
1021 col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
1022 if (check_col (pinfo->fd, COL_INFO))
1023 col_clear (pinfo->fd, COL_INFO);
1025 fcf = tvb_get_letohs (tvb, 0);
1026 hdr_len = find_header_length (fcf);
1027 frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1029 COL_SHOW_INFO_CONST (pinfo->fd,
1030 val_to_str(frame_type_subtype, frame_type_subtype_vals,
1031 "Unrecognized (Reserved frame)"));
1033 /* Add the FC to the current tree */
1036 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1038 hdr_tree = proto_item_add_subtree (ti, ett_80211);
1040 proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1042 frame_type_subtype);
1044 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
1046 "Frame Control: 0x%04X",
1049 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1052 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
1053 COOK_PROT_VERSION (fcf));
1055 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
1056 COOK_FRAME_TYPE (fcf));
1058 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1060 COOK_FRAME_SUBTYPE (fcf));
1062 flags = COOK_FLAGS (fcf);
1065 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
1066 flags, "Flags: 0x%X", flags);
1068 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1070 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
1071 COOK_DS_STATUS (flags));
1073 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1076 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1078 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1080 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1083 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1085 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1087 if (frame_type_subtype == CTRL_PS_POLL)
1088 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1089 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1092 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1093 tvb_get_letohs (tvb, 2));
1097 * Decode the part of the frame header that isn't the same for all
1100 switch (frame_type_subtype)
1104 case MGT_ASSOC_RESP:
1105 case MGT_REASSOC_REQ:
1106 case MGT_REASSOC_RESP:
1108 case MGT_PROBE_RESP:
1112 case MGT_AUTHENTICATION:
1113 case MGT_DEAUTHENTICATION:
1115 * All management frame types have the same header.
1117 src = tvb_get_ptr (tvb, 10, 6);
1118 dst = tvb_get_ptr (tvb, 4, 6);
1120 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1121 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1122 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1123 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1127 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1129 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1131 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1132 tvb_get_ptr (tvb, 16, 6));
1134 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1135 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1138 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1139 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1146 src = tvb_get_ptr (tvb, 10, 6);
1147 dst = tvb_get_ptr (tvb, 4, 6);
1149 set_src_addr_cols(pinfo, src, "BSSID");
1150 set_dst_addr_cols(pinfo, dst, "BSSID");
1154 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1156 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1162 src = tvb_get_ptr (tvb, 10, 6);
1163 dst = tvb_get_ptr (tvb, 4, 6);
1165 set_src_addr_cols(pinfo, src, "TA");
1166 set_dst_addr_cols(pinfo, dst, "RA");
1170 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1172 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1178 dst = tvb_get_ptr (tvb, 4, 6);
1180 set_dst_addr_cols(pinfo, dst, "RA");
1183 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1187 case CTRL_ACKNOWLEDGEMENT:
1188 dst = tvb_get_ptr (tvb, 4, 6);
1190 set_dst_addr_cols(pinfo, dst, "RA");
1193 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1198 src = tvb_get_ptr (tvb, 10, 6);
1199 dst = tvb_get_ptr (tvb, 4, 6);
1201 set_src_addr_cols(pinfo, src, "BSSID");
1202 set_dst_addr_cols(pinfo, dst, "RA");
1206 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1207 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1212 case CTRL_CFP_ENDACK:
1213 src = tvb_get_ptr (tvb, 10, 6);
1214 dst = tvb_get_ptr (tvb, 4, 6);
1216 set_src_addr_cols(pinfo, src, "BSSID");
1217 set_dst_addr_cols(pinfo, dst, "RA");
1221 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1223 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1231 case DATA_CF_ACK_POLL:
1232 addr_type = COOK_ADDR_SELECTOR (fcf);
1234 /* In order to show src/dst address we must always do the following */
1239 src = tvb_get_ptr (tvb, 10, 6);
1240 dst = tvb_get_ptr (tvb, 4, 6);
1245 src = tvb_get_ptr (tvb, 16, 6);
1246 dst = tvb_get_ptr (tvb, 4, 6);
1251 src = tvb_get_ptr (tvb, 10, 6);
1252 dst = tvb_get_ptr (tvb, 16, 6);
1257 src = tvb_get_ptr (tvb, 24, 6);
1258 dst = tvb_get_ptr (tvb, 16, 6);
1262 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1263 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1264 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1265 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1267 /* Now if we have a tree we start adding stuff */
1276 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1277 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1278 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1279 tvb_get_ptr (tvb, 16, 6));
1280 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1281 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1283 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1284 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1290 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1291 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1292 tvb_get_ptr (tvb, 10, 6));
1293 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1294 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1295 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1297 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1298 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1304 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1305 tvb_get_ptr (tvb, 4, 6));
1306 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1307 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1308 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1309 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1311 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1312 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1318 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1319 tvb_get_ptr (tvb, 4, 6));
1320 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1321 tvb_get_ptr (tvb, 10, 6));
1322 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1323 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1324 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1326 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1327 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1329 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1338 * Only management and data frames have a body, so we don't have
1339 * anything more to do for other types of frames.
1341 switch (COOK_FRAME_TYPE (fcf))
1353 * For WEP-encrypted frames, dissect the WEP parameters and
1354 * display the payload as data.
1356 * XXX - allow the key to be specified, and, if it is, decrypt
1357 * the payload and dissect it?
1359 if (IS_WEP(COOK_FLAGS(fcf)))
1361 int pkt_len = tvb_reported_length (tvb);
1362 int cap_len = tvb_length (tvb);
1366 get_wep_parameter_tree (tree, tvb, hdr_len, pkt_len);
1367 pkt_len -= hdr_len + 4;
1368 cap_len -= hdr_len + 4;
1371 * OK, pkt_len and cap_len have had the length of the 802.11
1372 * header and WEP parameters subtracted.
1374 * If there's anything left:
1376 * if cap_len is greater than or equal to pkt_len (i.e., we
1377 * captured the entire packet), subtract the length of the
1378 * WEP CRC from cap_len;
1380 * if cap_len is from 1 to 3 bytes less than pkt_len (i.e.,
1381 * we captured some but not all of the WEP CRC), subtract
1382 * the length of the part of the WEP CRC we captured from
1385 * otherwise, (i.e., we captured none of the WEP CRC),
1386 * leave cap_len alone;
1388 * and subtract the length of the WEP CRC from pkt_len.
1390 if (cap_len >= pkt_len)
1392 else if ((pkt_len - cap_len) >= 1 && (pkt_len - cap_len) <= 3)
1393 cap_len -= 4 - (pkt_len - cap_len);
1395 if (cap_len > 0 && pkt_len > 0)
1396 dissect_data (tvb, hdr_len + 4, pinfo, tree);
1402 * Now dissect the body of a non-WEP-encrypted frame.
1404 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1405 switch (COOK_FRAME_TYPE (fcf))
1409 dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1414 call_dissector (llc_handle, next_tvb, pinfo, tree);
1420 proto_register_wlan (void)
1422 static const value_string frame_type[] = {
1423 {MGT_FRAME, "Management frame"},
1424 {CONTROL_FRAME, "Control frame"},
1425 {DATA_FRAME, "Data frame"},
1429 static const value_string tofrom_ds[] = {
1430 {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
1431 {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"},
1432 {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"},
1433 {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"},
1437 static const true_false_string tods_flag = {
1438 "TO DS: Should be false",
1442 static const true_false_string fromds_flag = {
1443 "FROM DS: Should be false",
1447 static const true_false_string more_frags = {
1448 "MSDU/MMPDU is fragmented",
1452 static const true_false_string retry_flags = {
1453 "Frame is being retransmitted",
1454 "Frame is not being retransmitted"
1457 static const true_false_string pm_flags = {
1458 "STA will go to sleep",
1462 static const true_false_string md_flags = {
1463 "Data is buffered for STA at AP",
1467 static const true_false_string wep_flags = {
1472 static const true_false_string order_flags = {
1474 "Not strictly ordered"
1477 static const true_false_string cf_ess_flags = {
1478 "Transmitter is an AP",
1479 "Transmitter is a STA"
1483 static const true_false_string cf_privacy_flags = {
1484 "AP/STA can support WEP",
1485 "AP/STA cannot support WEP"
1488 static const true_false_string cf_preamble_flags = {
1489 "Short preamble allowed",
1490 "Short preamble not allowed"
1493 static const true_false_string cf_pbcc_flags = {
1494 "PBCC modulation allowed",
1495 "PBCC modulation not allowed"
1498 static const true_false_string cf_agility_flags = {
1499 "Channel agility in use",
1500 "Channel agility not in use"
1504 static const true_false_string cf_ibss_flags = {
1505 "Transmitter belongs to an IBSS",
1506 "Transmitter belongs to a BSS"
1509 static const value_string sta_cf_pollable[] = {
1510 {0x00, "Station is not CF-Pollable"},
1511 {0x02, "Station is CF-Pollable, "
1512 "not requesting to be placed on the CF-polling list"},
1513 {0x01, "Station is CF-Pollable, "
1514 "requesting to be placed on the CF-polling list"},
1515 {0x03, "Station is CF-Pollable, requesting never to be polled"},
1519 static const value_string ap_cf_pollable[] = {
1520 {0x00, "No point coordinator at AP"},
1521 {0x02, "Point coordinator at AP for delivery only (no polling)"},
1522 {0x01, "Point coordinator at AP for delivery and polling"},
1528 static const value_string auth_alg[] = {
1529 {0x00, "Open System"},
1530 {0x01, "Shared key"},
1534 static const value_string reason_codes[] = {
1536 {0x01, "Unspecified reason"},
1537 {0x02, "Previous authentication no longer valid"},
1538 {0x03, "Deauthenticated because sending STA is leaving (has left) "
1540 {0x04, "Disassociated due to inactivity"},
1541 {0x05, "Disassociated because AP is unable to handle all currently "
1542 "associated stations"},
1543 {0x06, "Class 2 frame received from nonauthenticated station"},
1544 {0x07, "Class 3 frame received from nonassociated station"},
1545 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1546 {0x09, "Station requesting (re)association is not authenticated with "
1547 "responding station"},
1552 static const value_string status_codes[] = {
1553 {0x00, "Successful"},
1554 {0x01, "Unspecified failure"},
1555 {0x0A, "Cannot support all requested capabilities in the "
1556 "Capability information field"},
1557 {0x0B, "Reassociation denied due to inability to confirm that "
1558 "association exists"},
1559 {0x0C, "Association denied due to reason outside the scope of this "
1562 {0x0D, "Responding station does not support the specified authentication "
1564 {0x0E, "Received an Authentication frame with authentication sequence "
1565 "transaction sequence number out of expected sequence"},
1566 {0x0F, "Authentication rejected because of challenge failure"},
1567 {0x10, "Authentication rejected due to timeout waiting for next "
1568 "frame in sequence"},
1569 {0x11, "Association denied because AP is unable to handle additional "
1570 "associated stations"},
1571 {0x12, "Association denied due to requesting station not supporting all "
1572 "of the datarates in the BSSBasicServiceSet Parameter"},
1576 static hf_register_info hf[] = {
1578 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
1579 "MAC Frame control", HFILL }},
1581 {&hf_fc_proto_version,
1582 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
1583 "MAC Protocol version", HFILL }}, /* 0 */
1586 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
1587 "Frame type", HFILL }},
1589 {&hf_fc_frame_subtype,
1590 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
1591 "Frame subtype", HFILL }}, /* 2 */
1593 {&hf_fc_frame_type_subtype,
1594 {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
1595 "Type and subtype combined", HFILL }},
1598 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
1599 "Protocol flags", HFILL }},
1602 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
1603 "Data-frame DS-traversal status", HFILL }}, /* 3 */
1606 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
1607 "To DS flag", HFILL }}, /* 4 */
1610 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
1611 "From DS flag", HFILL }}, /* 5 */
1614 {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
1615 "More Fragments flag", HFILL }}, /* 6 */
1618 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
1619 "Retransmission flag", HFILL }},
1622 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
1623 "Power management status", HFILL }},
1626 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
1627 "More data flag", HFILL }},
1630 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
1631 "WEP flag", HFILL }},
1634 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
1635 "Strictly ordered flag", HFILL }},
1638 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
1639 "Association-ID field", HFILL }},
1642 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
1643 "Duration field", HFILL }},
1646 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
1647 "Destination Hardware address", HFILL }},
1650 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
1651 "Source Hardware address", HFILL }},
1654 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
1655 "Receiving Station Hardware Address", HFILL }},
1658 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
1659 "Transmitting Station Hardware Address", HFILL }},
1662 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
1663 "Basic Service Set ID", HFILL }},
1666 {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
1667 "Fragment number", HFILL }},
1670 {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
1671 "Sequence number", HFILL }},
1674 {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
1675 NULL, 0, "", HFILL }},
1678 {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
1679 "Initialization Vector", HFILL }},
1682 {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
1686 {"WEP CRC (not verified)", "wlan.wep.crc", FT_UINT32, BASE_HEX, NULL, 0,
1687 "WEP CRC", HFILL }},
1690 static hf_register_info ff[] = {
1692 {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
1693 NULL, 0, "", HFILL }},
1696 {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
1697 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
1699 {&ff_beacon_interval,
1700 {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
1703 {&hf_fixed_parameters,
1704 {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
1707 {&hf_tagged_parameters,
1708 {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
1712 {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
1713 "Capability information", HFILL }},
1716 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
1717 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
1718 "CF-Poll capabilities for a STA", HFILL }},
1721 {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
1722 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
1723 "CF-Poll capabilities for an AP", HFILL }},
1726 {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
1727 FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
1731 {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
1732 FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
1735 {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
1736 FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
1739 {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
1740 FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
1743 {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
1744 FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
1747 {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
1748 FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
1751 {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
1752 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
1755 {"Association ID", "wlan_mgt.fixed.aid",
1756 FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
1759 {"Listen Interval", "wlan_mgt.fixed.listen_ival",
1760 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
1763 {"Current AP", "wlan_mgt.fixed.current_ap",
1764 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
1767 {"Reason code", "wlan_mgt.fixed.reason_code",
1768 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
1769 "Reason for unsolicited notification", HFILL }},
1772 {"Status code", "wlan_mgt.fixed.status_code",
1773 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
1774 "Status of requested event", HFILL }},
1777 {"Tag", "wlan_mgt.tag.number",
1778 FT_UINT16, BASE_DEC, NULL, 0,
1779 "Element ID", HFILL }},
1782 {"Tag length", "wlan_mgt.tag.length",
1783 FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
1785 {&tag_interpretation,
1786 {"Tag interpretation", "wlan_mgt.tag.interpretation",
1787 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
1791 static gint *tree_array[] = {
1796 &ett_fixed_parameters,
1797 &ett_tagged_parameters,
1798 &ett_wep_parameters,
1802 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
1803 "IEEE 802.11", "wlan");
1804 proto_register_field_array (proto_wlan, hf, array_length (hf));
1805 proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
1806 "802.11 MGT", "wlan_mgt");
1807 proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
1808 proto_register_subtree_array (tree_array, array_length (tree_array));
1812 proto_reg_handoff_wlan(void)
1815 * Get a handle for the LLC dissector.
1817 llc_handle = find_dissector("llc");
1819 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,