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.18 2001/05/30 19:17:31 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"
67 #include "packet-llc.h"
68 #include "packet-ieee80211.h"
71 /* ************************************************************************* */
72 /* Miscellaneous Constants */
73 /* ************************************************************************* */
75 #define MGT_FRAME_LEN 24
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 & 0x2)) && ((x & 0x1)))
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 COL_SHOW_INFO(fd,info) if (check_col(fd,COL_INFO)) \
91 col_add_str(fd,COL_INFO,info);
93 #define IS_TO_DS(x) ((x & 0x1))
94 #define IS_FROM_DS(x) ((x & 0x2))
95 #define HAVE_FRAGMENTS(x) ((x & 0x4))
96 #define IS_RETRY(x) ((x & 0x8))
97 #define POWER_MGT_STATUS(x) ((x & 0x10))
98 #define HAS_MORE_DATA(x) ((x & 0x20))
99 #define IS_WEP(x) ((x & 0x40))
100 #define IS_STRICTLY_ORDERED(x) ((x & 0x80))
102 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
103 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
104 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
105 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
108 /* ************************************************************************* */
109 /* Constants used to identify cooked frame types */
110 /* ************************************************************************* */
111 #define MGT_FRAME 0x00 /* Frame type is management */
112 #define CONTROL_FRAME 0x01 /* Frame type is control */
113 #define DATA_FRAME 0x02 /* Frame type is Data */
115 #define DATA_SHORT_HDR_LEN 24
116 #define DATA_LONG_HDR_LEN 30
117 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
119 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
120 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
121 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
122 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
123 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
124 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
125 #define MGT_BEACON 0x08 /* Management - Beacon frame */
126 #define MGT_ATIM 0x09 /* Management - ATIM */
127 #define MGT_DISASS 0x0A /* Management - Disassociation */
128 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
129 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
131 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
132 #define CTRL_RTS 0x1B /* Control - request to send */
133 #define CTRL_CTS 0x1C /* Control - clear to send */
134 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
135 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
136 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
138 #define DATA 0x20 /* Data - Data */
139 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
140 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
141 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
142 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
143 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
144 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
145 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
147 #define DATA_ADDR_T1 0x00
148 #define DATA_ADDR_T2 0x01
149 #define DATA_ADDR_T3 0x02
150 #define DATA_ADDR_T4 0x03
153 /* ************************************************************************* */
154 /* Macros used to extract information about fixed fields */
155 /* ************************************************************************* */
156 #define ESS_SET(x) ((x & 0x0001))
157 #define IBSS_SET(x) ((x & 0x0002))
161 /* ************************************************************************* */
162 /* Logical field codes (dissector's encoding of fixed fields) */
163 /* ************************************************************************* */
164 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
165 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
166 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
167 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
168 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
169 #define FIELD_CURRENT_AP_ADDR 0x06
170 #define FIELD_LISTEN_IVAL 0x07
171 #define FIELD_REASON_CODE 0x08
172 #define FIELD_ASSOC_ID 0x09
173 #define FIELD_STATUS_CODE 0x0A
175 /* ************************************************************************* */
176 /* Logical field codes (IEEE 802.11 encoding of tags) */
177 /* ************************************************************************* */
178 #define TAG_SSID 0x00
179 #define TAG_SUPP_RATES 0x01
180 #define TAG_FH_PARAMETER 0x02
181 #define TAG_DS_PARAMETER 0x03
182 #define TAG_CF_PARAMETER 0x04
184 #define TAG_IBSS_PARAMETER 0x06
185 #define TAG_CHALLENGE_TEXT 0x10
188 static int proto_wlan = -1;
189 /* ************************************************************************* */
190 /* Header field info values for FC-field */
191 /* ************************************************************************* */
192 static int hf_fc_field = -1;
193 static int hf_fc_proto_version = -1;
194 static int hf_fc_frame_type = -1;
195 static int hf_fc_frame_subtype = -1;
197 static int hf_fc_flags = -1;
198 static int hf_fc_to_ds = -1;
199 static int hf_fc_from_ds = -1;
200 static int hf_fc_data_ds = -1;
202 static int hf_fc_more_frag = -1;
203 static int hf_fc_retry = -1;
204 static int hf_fc_pwr_mgt = -1;
205 static int hf_fc_more_data = -1;
206 static int hf_fc_wep = -1;
207 static int hf_fc_order = -1;
210 /* ************************************************************************* */
211 /* Header values for Duration/ID field */
212 /* ************************************************************************* */
213 static int hf_did_duration = -1;
214 static int hf_assoc_id = -1;
217 /* ************************************************************************* */
218 /* Header values for different address-fields (all 4 of them) */
219 /* ************************************************************************* */
220 static int hf_addr_da = -1; /* Destination address subfield */
221 static int hf_addr_sa = -1; /* Source address subfield */
222 static int hf_addr_ra = -1; /* Receiver address subfield */
223 static int hf_addr_ta = -1; /* Transmitter address subfield */
224 static int hf_addr_bssid = -1; /* address is bssid */
228 /* ************************************************************************* */
229 /* Header values for sequence number field */
230 /* ************************************************************************* */
231 static int hf_frag_number = -1;
232 static int hf_seq_number = -1;
234 /* ************************************************************************* */
235 /* Header values for Frame Check field */
236 /* ************************************************************************* */
237 static int hf_fcs = -1;
240 /* ************************************************************************* */
241 /* Fixed fields found in mgt frames */
242 /* ************************************************************************* */
243 static int ff_auth_alg = -1; /* Authentication algorithm field */
244 static int ff_auth_seq = -1; /* Authentication transaction sequence */
245 static int ff_current_ap = -1; /* Current AP MAC address */
246 static int ff_listen_ival = -1; /* Listen interval fixed field */
247 static int ff_timestamp = -1; /* 64 bit timestamp */
248 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
249 static int ff_assoc_id = -1; /* 16 bit AID field */
250 static int ff_reason = -1; /* 16 bit reason code */
251 static int ff_status_code = -1; /* Status code */
253 /* ************************************************************************* */
254 /* Flags found in the capability field (fixed field) */
255 /* ************************************************************************* */
256 static int ff_capture = -1;
257 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
258 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
259 static int ff_cf_ess = -1;
260 static int ff_cf_ibss = -1;
261 static int ff_cf_privacy = -1;
263 /* ************************************************************************* */
264 /* Tagged value format fields */
265 /* ************************************************************************* */
266 static int tag_number = -1;
267 static int tag_length = -1;
268 static int tag_interpretation = -1;
272 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
273 static int hf_tagged_parameters = -1; /* Fixed payload item */
275 /* ************************************************************************* */
277 /* ************************************************************************* */
278 static gint ett_80211 = -1;
279 static gint ett_proto_flags = -1;
280 static gint ett_cap_tree = -1;
281 static gint ett_fc_tree = -1;
282 static gint ett_fixed_parameters = -1;
283 static gint ett_tagged_parameters = -1;
285 static dissector_handle_t llc_handle;
287 /* ************************************************************************* */
288 /* Return the length of the current header (in bytes) */
289 /* ************************************************************************* */
291 find_header_length (const u_char * pd, int offset)
293 guint16 frame_control;
295 frame_control = pntohs (pd);
296 return ((IS_FROM_DS(frame_control))
297 && (IS_TO_DS(frame_control))) ? 30 : 24;
301 /* ************************************************************************* */
302 /* This is the capture function used to update packet counts */
303 /* ************************************************************************* */
305 capture_ieee80211 (const u_char * pd, int offset, packet_counts * ld)
307 guint16 fcf, hdr_length;
309 fcf = pletohs (&pd[0]);
312 hdr_length = MGT_FRAME_HDR_LEN; /* Set the header length of the frame */
314 switch (COMPOSE_FRAME_TYPE (fcf))
317 case DATA: /* We got a data frame */
318 hdr_length = find_header_length (pd, offset);
319 capture_llc (pd, offset + hdr_length, ld);
322 case DATA_CF_ACK: /* Data with ACK */
323 hdr_length = find_header_length (pd, offset);
324 capture_llc (pd, offset + hdr_length, ld);
328 hdr_length = find_header_length (pd, offset);
329 capture_llc (pd, offset + hdr_length, ld);
332 case DATA_CF_ACK_POLL:
333 hdr_length = find_header_length (pd, offset);
334 capture_llc (pd, offset + hdr_length, ld);
345 /* ************************************************************************* */
346 /* Add the subtree used to store the fixed parameters */
347 /* ************************************************************************* */
349 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
351 proto_item *fixed_fields;
353 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
354 size, size, "Fixed parameters (%d bytes)",
357 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
361 /* ************************************************************************* */
362 /* Add the subtree used to store tagged parameters */
363 /* ************************************************************************* */
365 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
367 proto_item *tagged_fields;
369 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
374 "Tagged parameters (%d bytes)",
377 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
382 /* ************************************************************************* */
383 /* Dissect and add fixed mgmt fields to protocol tree */
384 /* ************************************************************************* */
386 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
388 const guint8 *dataptr;
389 char out_buff[SHORT_STR];
391 proto_item *cap_item;
392 static proto_tree *cap_tree;
397 case FIELD_TIMESTAMP:
398 dataptr = tvb_get_ptr (tvb, offset, 8);
399 memset (out_buff, 0, SHORT_STR);
400 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
410 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
414 case FIELD_BEACON_INTERVAL:
415 dataptr = tvb_get_ptr (tvb, offset, 2);
416 temp_double = ((double) *((guint16 *) dataptr));
417 temp_double = temp_double * 1024 / 1000000;
418 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
419 temp_double,"Beacon Interval: %f [Seconds]",
425 dataptr = tvb_get_ptr (tvb, offset, 2);
426 temp16 = (guint16 *) dataptr;
428 cap_item = proto_tree_add_uint_format (tree, ff_capture,
431 "Capability Information: %04X",
433 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
434 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
436 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
438 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
440 if (ESS_SET (pntohs (temp16)) != 0) /* This is an AP */
441 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
442 ((pntohs (temp16) & 0xC) >> 2));
444 else /* This is a STA */
445 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
446 ((pntohs (temp16) & 0xC) >> 2));
451 dataptr = tvb_get_ptr (tvb, offset, 2);
452 temp16 =(guint16 *) dataptr;
453 proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2,
458 case FIELD_AUTH_TRANS_SEQ:
459 dataptr = tvb_get_ptr (tvb, offset, 2);
460 temp16 = (guint16 *)dataptr;
461 proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2,
466 case FIELD_CURRENT_AP_ADDR:
467 dataptr = tvb_get_ptr (tvb, offset, 6);
468 proto_tree_add_ether (tree, ff_current_ap, tvb, offset, 6, dataptr);
472 case FIELD_LISTEN_IVAL:
473 dataptr = tvb_get_ptr (tvb, offset, 2);
474 temp16 = (guint16 *) dataptr;
475 proto_tree_add_uint (tree, ff_listen_ival, tvb, offset, 2,
480 case FIELD_REASON_CODE:
481 dataptr = tvb_get_ptr (tvb, offset, 2);
482 temp16 = (guint16 *) dataptr;
483 proto_tree_add_uint (tree, ff_reason, tvb, offset, 2, pntohs (temp16));
488 dataptr = tvb_get_ptr (tvb, offset, 2);
489 temp16 = (guint16 *) dataptr;
490 proto_tree_add_uint (tree, ff_assoc_id, tvb, offset, 2, pntohs (temp16));
493 case FIELD_STATUS_CODE:
494 dataptr = tvb_get_ptr (tvb, offset, 2);
495 temp16 = (guint16 *) dataptr;
496 proto_tree_add_uint (tree, ff_status_code, tvb, offset, 2,
503 /* ************************************************************************* */
504 /* Dissect and add tagged (optional) fields to proto tree */
505 /* ************************************************************************* */
507 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
509 const guint8 *tag_info_ptr;
510 const guint8 *tag_data_ptr;
511 guint32 tag_no, tag_len;
513 char out_buff[SHORT_STR];
516 tag_info_ptr = tvb_get_ptr (tvb, offset, 2);
517 tag_no = tag_info_ptr[0];
518 tag_len = tag_info_ptr[1];
520 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
523 if ((tag_no >= 17) && (tag_no <= 31))
524 { /* Reserved for challenge text */
525 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
526 "Tag Number: %u (Reserved for challenge text)",
529 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
530 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
531 tag_len, "Not interpreted");
532 return (int) tag_len;
535 /* Next See if tag is reserved - if true, skip it! */
536 if (((tag_no >= 7) && (tag_no <= 15))
537 || ((tag_no >= 32) && (tag_no <= 255)))
539 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
540 "Tag Number: %u (Reserved tag number)",
543 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
545 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
546 tag_len, "Not interpreted");
547 return (int) tag_len;
551 switch (tag_info_ptr[0])
556 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
557 "Tag Number: %u (SSID parameter set)",
560 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
562 memset (out_buff, 0, SHORT_STR);
564 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
565 out_buff[tag_len + 1] = 0;
567 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
574 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
575 "Tag Number: %u (Supported Rates)", tag_no);
577 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
579 memset (out_buff, 0, SHORT_STR);
580 strcpy (out_buff, "Supported rates: ");
581 n = strlen (out_buff);
583 for (i = 0; i < tag_len; i++)
585 n += snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
586 (tag_data_ptr[i] & 0x7F) * 0.5,
587 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
589 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
591 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
597 case TAG_FH_PARAMETER:
598 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
599 "Tag Number: %u (FH Parameter set)",
602 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
603 memset (out_buff, 0, SHORT_STR);
605 snprintf (out_buff, SHORT_STR,
606 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
607 "Hop Index %2d", pntohs (tag_data_ptr), tag_data_ptr[2],
608 tag_data_ptr[3], tag_data_ptr[4]);
610 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
616 case TAG_DS_PARAMETER:
617 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
618 "Tag Number: %u (DS Parameter set)",
621 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
622 memset (out_buff, 0, SHORT_STR);
624 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
625 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
630 case TAG_CF_PARAMETER:
631 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
632 "Tag Number: %u (CF Parameter set)",
635 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
636 memset (out_buff, 0, SHORT_STR);
638 snprintf (out_buff, SHORT_STR,
639 "CFP count %u, CFP period %u, CFP max duration %u, "
640 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
641 pntohs (tag_data_ptr + 2), pntohs (tag_data_ptr + 4));
643 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
649 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
650 "Tag Number: %u ((TIM) Traffic Indication Map)",
653 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
654 memset (out_buff, 0, SHORT_STR);
655 snprintf (out_buff, SHORT_STR,
656 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
657 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
659 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
665 case TAG_IBSS_PARAMETER:
666 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
667 "Tag Number: %u (IBSS Parameter set)",
670 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
671 memset (out_buff, 0, SHORT_STR);
672 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
673 pntohs (tag_data_ptr));
675 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
681 case TAG_CHALLENGE_TEXT:
682 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
683 "Tag Number: %u (Challenge text)", tag_no);
685 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
686 memset (out_buff, 0, SHORT_STR);
687 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
688 proto_tree_add_string (tree, tag_interpretation, tvb, offset, tag_len,
702 /* ************************************************************************* */
703 /* Dissect 802.11 frame */
704 /* ************************************************************************* */
706 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
709 const guint8 *src = NULL, *dst = NULL;
711 proto_item *flag_item;
713 static proto_tree *hdr_tree;
714 static proto_tree *flag_tree;
715 static proto_tree *fixed_tree;
716 static proto_tree *tagged_tree;
717 static proto_tree *fc_tree;
718 guint16 cap_len, hdr_len;
723 int tagged_parameter_tree_len;
725 if (check_col (pinfo->fd, COL_PROTOCOL))
726 col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
727 if (check_col (pinfo->fd, COL_INFO))
728 col_clear (pinfo->fd, COL_INFO);
730 cap_len = tvb_length(tvb);
731 fcf = tvb_get_letohs (tvb, 0);
733 /* Add the FC to the current tree */
736 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
737 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
738 "IEEE 802.11 Header");
739 hdr_tree = proto_item_add_subtree (ti, ett_80211);
741 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
742 tvb_get_letohs (tvb, 0),
743 "Frame Control: 0x%04X",
744 tvb_get_letohs (tvb, 0));
746 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
749 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
750 COOK_PROT_VERSION (tvb_get_letohs (tvb, 0)));
752 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
753 COOK_FRAME_TYPE (tvb_get_letohs (tvb, 0)));
755 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
757 COOK_FRAME_SUBTYPE (tvb_get_letohs (tvb, 0)));
759 flags = COOK_FLAGS (tvb_get_letohs (tvb, 0));
762 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
763 flags, "Flags: 0x%X", flags);
765 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
767 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
768 COOK_DS_STATUS (flags));
770 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
773 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
775 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
777 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
780 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
782 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
784 if ((COMPOSE_FRAME_TYPE(fcf))==CTRL_PS_POLL)
785 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
786 COOK_ASSOC_ID(tvb_get_ntohs(tvb,2)));
789 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
790 tvb_get_ntohs (tvb, 2));
793 /* Perform tasks which are common to a certain frame type */
794 switch (COOK_FRAME_TYPE (fcf))
797 case MGT_FRAME: /* All management frames share a common header */
798 src = tvb_get_ptr (tvb, 10, 6);
799 dst = tvb_get_ptr (tvb, 4, 6);
802 if (check_col (pinfo->fd, COL_DEF_SRC))
803 col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X",
804 src[0], src[1], src[2], src[3], src[4], src[5]);
806 if (check_col (pinfo->fd, COL_DEF_DST))
807 col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X",
808 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
812 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
813 tvb_get_ptr (tvb, 4, 6));
815 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
816 tvb_get_ptr (tvb, 10, 6));
818 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
819 tvb_get_ptr (tvb, 16, 6));
821 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
822 COOK_FRAGMENT_NUMBER (tvb_get_letohs
825 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
826 COOK_SEQUENCE_NUMBER (tvb_get_letohs
828 cap_len = cap_len - MGT_FRAME_LEN - 4;
840 addr_type = COOK_ADDR_SELECTOR (fcf);
841 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
843 /* In order to show src/dst address we must always do the following */
848 src = tvb_get_ptr (tvb, 10, 6);
849 dst = tvb_get_ptr (tvb, 4, 6);
854 src = tvb_get_ptr (tvb, 16, 6);
855 dst = tvb_get_ptr (tvb, 4, 6);
860 src = tvb_get_ptr (tvb, 10, 6);
861 dst = tvb_get_ptr (tvb, 16, 6);
866 src = tvb_get_ptr (tvb, 24, 6);
867 dst = tvb_get_ptr (tvb, 16, 6);
871 if (check_col (pinfo->fd, COL_DEF_SRC))
872 col_add_fstr (pinfo->fd, COL_DEF_SRC,
873 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
874 src[0], src[1], src[2], src[3], src[4], src[5]);
876 if (check_col (pinfo->fd, COL_DEF_DST))
877 col_add_fstr (pinfo->fd, COL_DEF_DST,
878 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
879 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
881 /* Now if we have a tree we start adding stuff */
890 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
891 tvb_get_ptr (tvb, 4, 6));
892 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
893 tvb_get_ptr (tvb, 10, 6));
894 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
895 tvb_get_ptr (tvb, 16, 6));
896 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
897 COOK_FRAGMENT_NUMBER (tvb_get_ntohs
899 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
900 COOK_SEQUENCE_NUMBER (tvb_get_ntohs
906 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
907 tvb_get_ptr (tvb, 4, 6));
908 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
909 tvb_get_ptr (tvb, 10, 6));
910 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6,
911 tvb_get_ptr (tvb, 16, 6));
912 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
913 COOK_FRAGMENT_NUMBER (tvb_get_ntohs
915 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
916 COOK_SEQUENCE_NUMBER (tvb_get_ntohs
922 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
923 tvb_get_ptr (tvb, 4, 6));
924 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
925 tvb_get_ptr (tvb, 10, 6));
926 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
927 tvb_get_ptr (tvb, 16, 6));
928 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
929 COOK_FRAGMENT_NUMBER (tvb_get_ntohs
931 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
932 COOK_SEQUENCE_NUMBER (tvb_get_ntohs
938 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
939 tvb_get_ptr (tvb, 4, 6));
940 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
941 tvb_get_ptr (tvb, 10, 6));
942 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
943 tvb_get_ptr (tvb, 16, 6));
944 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
945 COOK_FRAGMENT_NUMBER (tvb_get_ntohs
947 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
948 COOK_SEQUENCE_NUMBER (tvb_get_ntohs
950 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6,
951 tvb_get_ptr (tvb, 24, 6));
960 switch (COMPOSE_FRAME_TYPE (fcf))
964 COL_SHOW_INFO (pinfo->fd, "Association Request");
967 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 4);
968 add_fixed_field (fixed_tree, tvb, MGT_FRAME_HDR_LEN,
970 add_fixed_field (fixed_tree, tvb, MGT_FRAME_HDR_LEN + 2,
973 next_idx = MGT_FRAME_HDR_LEN + 4; /* Size of fixed fields */
974 tagged_parameter_tree_len =
975 tvb_reported_length_remaining(tvb, next_idx + 4);
976 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
977 tagged_parameter_tree_len);
979 while (tagged_parameter_tree_len > 0) {
980 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
983 tagged_parameter_tree_len -= next_len;
991 COL_SHOW_INFO (pinfo->fd, "Association Response");
995 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 6);
996 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
997 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
999 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1002 next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
1004 tagged_parameter_tree_len =
1005 tvb_reported_length_remaining(tvb, next_idx + 4);
1006 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1007 tagged_parameter_tree_len);
1009 while (tagged_parameter_tree_len > 0) {
1010 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1012 next_idx +=next_len;
1013 tagged_parameter_tree_len -= next_len;
1019 case MGT_REASSOC_REQ:
1020 COL_SHOW_INFO (pinfo->fd, "Reassociation Request");
1023 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 10);
1024 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
1025 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1027 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1028 FIELD_CURRENT_AP_ADDR);
1030 next_idx = MGT_FRAME_LEN + 10; /* Size of fixed fields */
1031 tagged_parameter_tree_len =
1032 tvb_reported_length_remaining(tvb, next_idx + 4);
1033 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1034 tagged_parameter_tree_len);
1036 while (tagged_parameter_tree_len > 0) {
1037 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1039 next_idx +=next_len;
1040 tagged_parameter_tree_len -= next_len;
1045 case MGT_REASSOC_RESP:
1046 COL_SHOW_INFO (pinfo->fd, "Reassociation Response");
1049 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 10);
1050 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
1051 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1053 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1056 next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
1057 tagged_parameter_tree_len =
1058 tvb_reported_length_remaining(tvb, next_idx + 4);
1059 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1060 tagged_parameter_tree_len);
1062 while (tagged_parameter_tree_len > 0) {
1063 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1065 next_idx +=next_len;
1066 tagged_parameter_tree_len -= next_len;
1073 COL_SHOW_INFO (pinfo->fd, "Probe Request");
1076 next_idx = MGT_FRAME_LEN;
1077 tagged_parameter_tree_len =
1078 tvb_reported_length_remaining(tvb, next_idx + 4);
1079 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1080 tagged_parameter_tree_len);
1082 while (tagged_parameter_tree_len > 0) {
1083 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1085 next_idx +=next_len;
1086 tagged_parameter_tree_len -= next_len;
1092 case MGT_PROBE_RESP:
1093 COL_SHOW_INFO (pinfo->fd, "Probe Response");
1096 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 12);
1097 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_TIMESTAMP);
1098 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 8,
1099 FIELD_BEACON_INTERVAL);
1100 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 10,
1103 next_idx = MGT_FRAME_LEN + 12; /* Size of fixed fields */
1104 tagged_parameter_tree_len =
1105 tvb_reported_length_remaining(tvb, next_idx + 4);
1106 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1107 tagged_parameter_tree_len);
1109 while (tagged_parameter_tree_len > 0) {
1110 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1112 next_idx +=next_len;
1113 tagged_parameter_tree_len -= next_len;
1119 case MGT_BEACON: /* Dissect protocol payload fields */
1120 COL_SHOW_INFO (pinfo->fd, "Beacon frame");
1124 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 12);
1126 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_TIMESTAMP);
1128 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 8,
1129 FIELD_BEACON_INTERVAL);
1130 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 10,
1133 next_idx = MGT_FRAME_LEN + 12; /* Size of fixed fields */
1134 tagged_parameter_tree_len =
1135 tvb_reported_length_remaining(tvb, next_idx + 4);
1136 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1137 tagged_parameter_tree_len);
1139 while (tagged_parameter_tree_len > 0) {
1140 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1142 next_idx +=next_len;
1143 tagged_parameter_tree_len -= next_len;
1151 COL_SHOW_INFO (pinfo->fd, "ATIM");
1158 COL_SHOW_INFO (pinfo->fd, "Dissassociate");
1161 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, cap_len);
1162 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_REASON_CODE);
1166 case MGT_AUTHENTICATION:
1167 COL_SHOW_INFO (pinfo->fd, "Authentication");
1170 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 6);
1171 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_AUTH_ALG);
1172 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1173 FIELD_AUTH_TRANS_SEQ);
1174 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1177 next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
1179 tagged_parameter_tree_len =
1180 tvb_reported_length_remaining(tvb, next_idx + 4);
1181 if (tagged_parameter_tree_len != 0)
1183 tagged_tree = get_tagged_parameter_tree (tree,
1186 tagged_parameter_tree_len);
1188 while (tagged_parameter_tree_len > 0) {
1189 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1191 next_idx +=next_len;
1192 tagged_parameter_tree_len -= next_len;
1198 case MGT_DEAUTHENTICATION:
1199 COL_SHOW_INFO (pinfo->fd, "Deauthentication");
1202 fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 2);
1203 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_REASON_CODE);
1210 COL_SHOW_INFO (pinfo->fd, "Power-Save poll");
1212 src = tvb_get_ptr (tvb, 10, 6);
1213 dst = tvb_get_ptr (tvb, 4, 6);
1216 if (check_col (pinfo->fd, COL_DEF_SRC))
1217 col_add_fstr (pinfo->fd, COL_DEF_SRC,
1218 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (BSSID)",
1219 src[0], src[1], src[2], src[3], src[4], src[5]);
1221 if (check_col (pinfo->fd, COL_DEF_DST))
1222 col_add_fstr (pinfo->fd, COL_DEF_DST,
1223 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (TA)",
1224 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1228 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1229 tvb_get_ptr (tvb, 4, 6));
1231 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1232 tvb_get_ptr (tvb, 10, 6));
1240 COL_SHOW_INFO (pinfo->fd, "Request-to-send");
1241 src = tvb_get_ptr (tvb, 10, 6);
1242 dst = tvb_get_ptr (tvb, 4, 6);
1245 if (check_col (pinfo->fd, COL_DEF_SRC))
1246 col_add_fstr (pinfo->fd, COL_DEF_SRC,
1247 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (TA)",
1248 src[0], src[1], src[2], src[3], src[4], src[5]);
1250 if (check_col (pinfo->fd, COL_DEF_DST))
1251 col_add_fstr (pinfo->fd, COL_DEF_DST,
1252 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
1253 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1257 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1258 tvb_get_ptr (tvb, 4, 6));
1260 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1261 tvb_get_ptr (tvb, 10, 6));
1269 COL_SHOW_INFO (pinfo->fd, "Clear-to-send");
1271 dst = tvb_get_ptr (tvb, 4, 6);
1273 if (check_col (pinfo->fd, COL_DEF_DST))
1274 col_add_fstr (pinfo->fd, COL_DEF_DST,
1275 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
1276 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1280 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1281 tvb_get_ptr (tvb, 4, 6));
1288 case CTRL_ACKNOWLEDGEMENT:
1289 COL_SHOW_INFO (pinfo->fd, "Acknowledgement");
1291 dst = tvb_get_ptr (tvb, 4, 6);
1293 if (check_col (pinfo->fd, COL_DEF_DST))
1294 col_add_fstr (pinfo->fd, COL_DEF_DST,
1295 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
1296 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1299 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1300 tvb_get_ptr (tvb, 4, 6));
1306 COL_SHOW_INFO (pinfo->fd, "CF-End (Control-frame)");
1308 src = tvb_get_ptr (tvb, 10, 6);
1309 dst = tvb_get_ptr (tvb, 4, 6);
1312 if (check_col (pinfo->fd, COL_DEF_SRC))
1313 col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X (BSSID)",
1314 src[0], src[1], src[2], src[3], src[4], src[5]);
1316 if (check_col (pinfo->fd, COL_DEF_DST))
1317 col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X (RA)",
1318 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1322 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1323 tvb_get_ptr (tvb, 4, 6));
1324 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1325 tvb_get_ptr (tvb, 10, 6));
1331 case CTRL_CFP_ENDACK:
1332 COL_SHOW_INFO (pinfo->fd, "CF-End + CF-Ack (Control-frame)");
1334 src = tvb_get_ptr (tvb, 10, 6);
1335 dst = tvb_get_ptr (tvb, 4, 6);
1337 if (check_col (pinfo->fd, COL_DEF_SRC))
1338 col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X (BSSID)",
1339 src[0], src[1], src[2], src[3], src[4], src[5]);
1341 if (check_col (pinfo->fd, COL_DEF_DST))
1342 col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X (RA)",
1343 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1347 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1348 tvb_get_ptr (tvb, 4, 6));
1350 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1351 tvb_get_ptr (tvb, 10, 6));
1358 COL_SHOW_INFO (pinfo->fd, "Data");
1361 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
1363 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1364 call_dissector (llc_handle, next_tvb, pinfo, tree);
1371 COL_SHOW_INFO (pinfo->fd, "Data + CF-Acknowledgement");
1374 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
1376 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1377 call_dissector (llc_handle, next_tvb, pinfo, tree);
1384 COL_SHOW_INFO (pinfo->fd, "Data + CF-Poll");
1387 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
1388 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1389 call_dissector (llc_handle, next_tvb, pinfo, tree);
1395 case DATA_CF_ACK_POLL:
1396 COL_SHOW_INFO (pinfo->fd, "Data + CF-Acknowledgement/Poll");
1399 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
1400 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1401 call_dissector (llc_handle, next_tvb, pinfo, tree);
1407 case DATA_NULL_FUNCTION:
1408 COL_SHOW_INFO (pinfo->fd, "Null function (No data)");
1412 case DATA_CF_ACK_NOD:
1413 COL_SHOW_INFO (pinfo->fd, "Data + Acknowledgement(No data)");
1417 case DATA_CF_POLL_NOD:
1418 COL_SHOW_INFO (pinfo->fd, "Data + CF-Poll (No data)");
1422 case DATA_CF_ACK_POLL_NOD:
1423 COL_SHOW_INFO (pinfo->fd, "Data + CF-Acknowledgement/Poll (No data)");
1428 COL_SHOW_INFO (pinfo->fd, "Unrecognized (Reserved frame)");
1435 proto_register_wlan (void)
1438 static const value_string tofrom_ds[] = {
1439 {0, "Not leaving DS or network is operating in AD-HOC mode ( To DS: 0 From DS: 0)"},
1440 {1, "Frame is exiting DS (To DS: 0 From DS: 1)"},
1441 {2, "Frame is entering DS (To DS: 1 From DS: 0)"},
1442 {3, "Frame part of WDS (To DS: 1 From DS: 1)"},
1446 static const true_false_string tods_flag = {
1447 "TO DS: Should be false",
1451 static const true_false_string fromds_flag = {
1452 "FROM DS: Should be false",
1456 static const true_false_string more_frags = {
1457 "MSDU/MMPDU is fragmented",
1461 static const true_false_string retry_flags = {
1462 "Frame is being retransmitted",
1463 "Frame is not being retransmitted"
1466 static const true_false_string pm_flags = {
1467 "STA will go to sleep",
1471 static const true_false_string md_flags = {
1472 "Data is buffered for STA at AP",
1476 static const true_false_string wep_flags = {
1481 static const true_false_string order_flags = {
1486 static const true_false_string cf_ess_flags = {
1487 "Transmitter is an AP",
1488 "Transmitter is a STA"
1492 static const true_false_string cf_privacy_flags = {
1493 "AP/STA can support WEP",
1494 "AP/STA cannot support WEP"
1498 static const true_false_string cf_ibss_flags = {
1499 "Transmitter belongs to an IBSS",
1500 "Transmitter belongs to a BSS"
1503 static const value_string sta_cf_pollable[] = {
1504 {0x00, "Station is not CF-Pollable"},
1505 {0x02, "Station is CF-Pollable, "
1506 "not requesting to be placed on the CF-polling list"},
1507 {0x01, "Station is CF-Pollable, "
1508 "requesting to be placed on the CF-polling list"},
1509 {0x03, "Station is CF-Pollable, requesting never to be polled"},
1513 static const value_string ap_cf_pollable[] = {
1514 {0x00, "No point coordinator at AP"},
1515 {0x02, "Point coordinator at AP for delivery only (no polling)"},
1516 {0x01, "Point coordinator at AP for delivery and polling"},
1522 static const value_string auth_alg[] = {
1523 {0x00, "Open System"},
1524 {0x01, "Shared key"},
1528 static const value_string reason_codes[] = {
1530 {0x01, "Unspecified reason"},
1531 {0x02, "Previous authentication no longer valid"},
1532 {0x03, "Deauthenticated because sending STA is leaving (has left) "
1534 {0x04, "Disassociated due to inactivity"},
1535 {0x05, "Disassociated because AP is unable to handle all currently "
1536 "associated stations"},
1537 {0x06, "Class 2 frame received from nonauthenticated station"},
1538 {0x07, "Class 3 frame received from nonassociated station"},
1539 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1540 {0x09, "Station requesting (re)association is not authenticated with "
1541 "responding station"},
1546 static const value_string status_codes[] = {
1547 {0x00, "Successful"},
1548 {0x01, "Unspecified failure"},
1549 {0x0A, "Cannot support all requested capabilities in the "
1550 "Capability information field"},
1551 {0x0B, "Reassociation denied due to inability to confirm that "
1552 "association exists"},
1553 {0x0C, "Association denied due to reason outside the scope of this "
1556 {0x0D, "Responding station does not support the specified authentication "
1558 {0x0E, "Received an Authentication frame with authentication sequence "
1559 "transaction sequence number out of expected sequence"},
1560 {0x0F, "Authentication rejected because of challenge failure"},
1561 {0x10, "Authentication rejected due to timeout waiting for next "
1562 "frame in sequence"},
1563 {0x11, "Association denied because AP is unable to handle additional "
1564 "associated stations"},
1565 {0x12, "Association denied due to requesting station not supporting all "
1566 "of the datarates in the BSSBasicServiceSet Parameter"},
1572 static hf_register_info hf[] = {
1574 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
1575 "MAC Frame control"}},
1577 {&hf_fc_proto_version,
1578 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
1579 "MAC Protocol version"}}, /* 0 */
1582 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, NULL, 0,
1585 {&hf_fc_frame_subtype,
1586 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
1587 "Frame subtype"}}, /* 2 */
1590 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
1594 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, TFS (&tofrom_ds), 0,
1595 "Data-frame DS-traversal status"}}, /* 3 */
1598 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), 0x1,
1599 "To DS flag"}}, /* 4 */
1602 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), 0x2,
1603 "From DS flag"}}, /* 5 */
1606 {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), 0x4,
1607 "More Fragments flag"}}, /* 6 */
1610 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), 0x8,
1611 "Retransmission flag"}},
1614 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), 0x10,
1615 "Power management status"}},
1618 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), 0x20,
1622 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), 0x40,
1626 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), 0x80,
1627 "Strictly ordered flag"}},
1630 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
1631 "Association-ID field" }},
1634 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
1638 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
1639 "Destination Hardware address"}},
1642 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
1643 "Source Hardware address"}},
1646 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
1647 "Receiving Station Hardware Address"}},
1650 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
1651 "Transmitting Station Hardware Address"}},
1654 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
1655 "Basic Service Set ID"}},
1658 {"Fragment number", "wlan.frag", FT_UINT16, BASE_HEX, NULL, 0,
1659 "Fragment number"}},
1662 {"Sequence number", "wlan.seq", FT_UINT16, BASE_HEX, NULL, 0,
1663 "Fragment number"}},
1666 {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
1670 {"Timestamp", "wlan.fixed.timestamp", FT_STRING, BASE_NONE,
1674 {"Authentication Algorithm", "wlan.fixed.auth.alg",
1675 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, ""}},
1677 {&ff_beacon_interval,
1678 {"Beacon Interval", "wlan.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
1681 {&hf_fixed_parameters,
1682 {"Fixed parameters", "wlan.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
1685 {&hf_tagged_parameters,
1686 {"Tagged parameters", "wlan.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
1690 {"Capabilities", "wlan.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
1691 "Capability information"}},
1694 {"CFP participation capabilities", "wlan.fixed.capabilities.cfpoll.sta",
1695 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
1696 "CF-Poll capabilities for a STA"}},
1699 {"CFP participation capabilities", "wlan.fixed.capabilities.cfpoll.ap",
1700 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
1701 "CF-Poll capabilities for an AP"}},
1704 {"ESS capabilities", "wlan.fixed.capabilities.ess",
1705 FT_BOOLEAN, 1, TFS (&cf_ess_flags), 0x0001, "ESS capabilities"}},
1709 {"IBSS status", "wlan.fixed.capabilities.ibss",
1710 FT_BOOLEAN, 1, TFS (&cf_ibss_flags), 0x0002, "IBSS participation"}},
1713 {"Privacy", "wlan.fixed.capabilities.privacy",
1714 FT_BOOLEAN, 1, TFS (&cf_privacy_flags), 0x0010, "WEP support"}},
1718 {"Authentication SEQ", "wlan.fixed.auth_seq",
1719 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number"}},
1722 {"Association ID", "wlan.fixed.aid",
1723 FT_UINT16, BASE_HEX, NULL, 0, "Association ID"}},
1726 {"Listen Interval", "wlan.fixed.listen_ival",
1727 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval"}},
1730 {"Current AP", "wlan.fixed.current_ap",
1731 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP"}},
1734 {"Reason code", "wlan.fixed.reason_code",
1735 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
1736 "Reason for unsolicited notification"}},
1739 {"Status code", "wlan.fixed.status_code",
1740 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
1741 "Status of requested event"}},
1744 {"Tag", "wlan.tag.number",
1745 FT_UINT16, BASE_DEC, NULL, 0,
1749 {"Tag length", "wlan.tag.length",
1750 FT_UINT16, BASE_DEC, NULL, 0, "Length of tag"}},
1752 {&tag_interpretation,
1753 {"Tag interpretation", "wlan.tag.interpretation",
1754 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag"}}
1760 static gint *tree_array[] = { &ett_80211,
1763 &ett_fixed_parameters,
1764 &ett_tagged_parameters,
1768 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
1769 "IEEE 802.11", "wlan");
1770 proto_register_field_array (proto_wlan, hf, array_length (hf));
1771 proto_register_subtree_array (tree_array, array_length (tree_array));
1775 proto_reg_handoff_wlan(void)
1778 * Get a handle for the LLC dissector.
1780 llc_handle = find_dissector("llc");
1782 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,