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.20 2001/06/08 06:01:06 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 & 0x200)) && ((x & 0x100)))
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_IV(x) (x & 0xFFFFFF)
91 #define COOK_WEP_KEY(x) ((x & 0xC0000000) >> 30)
92 #define COL_SHOW_INFO(fd,info) if (check_col(fd,COL_INFO)) \
93 col_add_str(fd,COL_INFO,info);
94 #define COL_SHOW_INFO_CONST(fd,info) if (check_col(fd,COL_INFO)) \
95 col_set_str(fd,COL_INFO,info);
97 #define IS_TO_DS(x) ((x & 0x1))
98 #define IS_FROM_DS(x) ((x & 0x2))
99 #define HAVE_FRAGMENTS(x) ((x & 0x4))
100 #define IS_RETRY(x) ((x & 0x8))
101 #define POWER_MGT_STATUS(x) ((x & 0x10))
102 #define HAS_MORE_DATA(x) ((x & 0x20))
103 #define IS_WEP(x) ((x & 0x40))
104 #define IS_STRICTLY_ORDERED(x) ((x & 0x80))
106 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
107 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
108 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
109 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
112 /* ************************************************************************* */
113 /* Constants used to identify cooked frame types */
114 /* ************************************************************************* */
115 #define MGT_FRAME 0x00 /* Frame type is management */
116 #define CONTROL_FRAME 0x01 /* Frame type is control */
117 #define DATA_FRAME 0x02 /* Frame type is Data */
119 #define DATA_SHORT_HDR_LEN 24
120 #define DATA_LONG_HDR_LEN 30
121 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
123 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
124 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
125 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
126 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
127 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
128 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
129 #define MGT_BEACON 0x08 /* Management - Beacon frame */
130 #define MGT_ATIM 0x09 /* Management - ATIM */
131 #define MGT_DISASS 0x0A /* Management - Disassociation */
132 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
133 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
135 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
136 #define CTRL_RTS 0x1B /* Control - request to send */
137 #define CTRL_CTS 0x1C /* Control - clear to send */
138 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
139 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
140 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
142 #define DATA 0x20 /* Data - Data */
143 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
144 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
145 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
146 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
147 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
148 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
149 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
151 #define DATA_ADDR_T1 0x0000
152 #define DATA_ADDR_T2 0x0100
153 #define DATA_ADDR_T3 0x0200
154 #define DATA_ADDR_T4 0x0300
157 /* ************************************************************************* */
158 /* Macros used to extract information about fixed fields */
159 /* ************************************************************************* */
160 #define ESS_SET(x) ((x & 0x0001))
161 #define IBSS_SET(x) ((x & 0x0002))
165 /* ************************************************************************* */
166 /* Logical field codes (dissector's encoding of fixed fields) */
167 /* ************************************************************************* */
168 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
169 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
170 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
171 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
172 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
173 #define FIELD_CURRENT_AP_ADDR 0x06
174 #define FIELD_LISTEN_IVAL 0x07
175 #define FIELD_REASON_CODE 0x08
176 #define FIELD_ASSOC_ID 0x09
177 #define FIELD_STATUS_CODE 0x0A
179 /* ************************************************************************* */
180 /* Logical field codes (IEEE 802.11 encoding of tags) */
181 /* ************************************************************************* */
182 #define TAG_SSID 0x00
183 #define TAG_SUPP_RATES 0x01
184 #define TAG_FH_PARAMETER 0x02
185 #define TAG_DS_PARAMETER 0x03
186 #define TAG_CF_PARAMETER 0x04
188 #define TAG_IBSS_PARAMETER 0x06
189 #define TAG_CHALLENGE_TEXT 0x10
192 static int proto_wlan = -1;
193 /* ************************************************************************* */
194 /* Header field info values for FC-field */
195 /* ************************************************************************* */
196 static int hf_fc_field = -1;
197 static int hf_fc_proto_version = -1;
198 static int hf_fc_frame_type = -1;
199 static int hf_fc_frame_subtype = -1;
201 static int hf_fc_flags = -1;
202 static int hf_fc_to_ds = -1;
203 static int hf_fc_from_ds = -1;
204 static int hf_fc_data_ds = -1;
206 static int hf_fc_more_frag = -1;
207 static int hf_fc_retry = -1;
208 static int hf_fc_pwr_mgt = -1;
209 static int hf_fc_more_data = -1;
210 static int hf_fc_wep = -1;
211 static int hf_fc_order = -1;
214 /* ************************************************************************* */
215 /* Header values for Duration/ID field */
216 /* ************************************************************************* */
217 static int hf_did_duration = -1;
218 static int hf_assoc_id = -1;
221 /* ************************************************************************* */
222 /* Header values for different address-fields (all 4 of them) */
223 /* ************************************************************************* */
224 static int hf_addr_da = -1; /* Destination address subfield */
225 static int hf_addr_sa = -1; /* Source address subfield */
226 static int hf_addr_ra = -1; /* Receiver address subfield */
227 static int hf_addr_ta = -1; /* Transmitter address subfield */
228 static int hf_addr_bssid = -1; /* address is bssid */
232 /* ************************************************************************* */
233 /* Header values for sequence number field */
234 /* ************************************************************************* */
235 static int hf_frag_number = -1;
236 static int hf_seq_number = -1;
238 /* ************************************************************************* */
239 /* Header values for Frame Check field */
240 /* ************************************************************************* */
241 static int hf_fcs = -1;
244 /* ************************************************************************* */
245 /* Fixed fields found in mgt frames */
246 /* ************************************************************************* */
247 static int ff_auth_alg = -1; /* Authentication algorithm field */
248 static int ff_auth_seq = -1; /* Authentication transaction sequence */
249 static int ff_current_ap = -1; /* Current AP MAC address */
250 static int ff_listen_ival = -1; /* Listen interval fixed field */
251 static int ff_timestamp = -1; /* 64 bit timestamp */
252 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
253 static int ff_assoc_id = -1; /* 16 bit AID field */
254 static int ff_reason = -1; /* 16 bit reason code */
255 static int ff_status_code = -1; /* Status code */
257 /* ************************************************************************* */
258 /* Flags found in the capability field (fixed field) */
259 /* ************************************************************************* */
260 static int ff_capture = -1;
261 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
262 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
263 static int ff_cf_ess = -1;
264 static int ff_cf_ibss = -1;
265 static int ff_cf_privacy = -1;
266 static int ff_cf_preamble = -1;
267 static int ff_cf_pbcc = -1;
268 static int ff_cf_agility = -1;
270 /* ************************************************************************* */
271 /* Tagged value format fields */
272 /* ************************************************************************* */
273 static int tag_number = -1;
274 static int tag_length = -1;
275 static int tag_interpretation = -1;
279 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
280 static int hf_tagged_parameters = -1; /* Fixed payload item */
281 static int hf_wep_parameters = -1;
282 static int hf_wep_iv = -1;
283 static int hf_wep_key = -1;
284 static int hf_wep_crc = -1;
286 /* ************************************************************************* */
288 /* ************************************************************************* */
289 static gint ett_80211 = -1;
290 static gint ett_proto_flags = -1;
291 static gint ett_cap_tree = -1;
292 static gint ett_fc_tree = -1;
293 static gint ett_fixed_parameters = -1;
294 static gint ett_tagged_parameters = -1;
295 static gint ett_wep_parameters = -1;
297 static dissector_handle_t llc_handle;
299 /* ************************************************************************* */
300 /* Return the length of the current header (in bytes) */
301 /* ************************************************************************* */
303 find_header_length (const u_char * pd, int offset)
305 guint16 frame_control;
307 frame_control = pntohs (pd);
308 return ((IS_FROM_DS(frame_control))
309 && (IS_TO_DS(frame_control))) ? 30 : 24;
313 /* ************************************************************************* */
314 /* This is the capture function used to update packet counts */
315 /* ************************************************************************* */
317 capture_ieee80211 (const u_char * pd, int offset, packet_counts * ld)
319 guint16 fcf, hdr_length;
321 fcf = pletohs (&pd[0]);
324 hdr_length = MGT_FRAME_HDR_LEN; /* Set the header length of the frame */
326 if (IS_WEP(COOK_FLAGS(fcf)))
332 switch (COMPOSE_FRAME_TYPE (fcf))
335 case DATA: /* We got a data frame */
336 hdr_length = find_header_length (pd, offset);
337 capture_llc (pd, offset + hdr_length, ld);
340 case DATA_CF_ACK: /* Data with ACK */
341 hdr_length = find_header_length (pd, offset);
342 capture_llc (pd, offset + hdr_length, ld);
346 hdr_length = find_header_length (pd, offset);
347 capture_llc (pd, offset + hdr_length, ld);
350 case DATA_CF_ACK_POLL:
351 hdr_length = find_header_length (pd, offset);
352 capture_llc (pd, offset + hdr_length, ld);
363 /* ************************************************************************* */
364 /* Add the subtree used to store the fixed parameters */
365 /* ************************************************************************* */
367 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
369 proto_item *fixed_fields;
371 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
372 size, size, "Fixed parameters (%d bytes)",
375 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
379 /* ************************************************************************* */
380 /* Add the subtree used to store tagged parameters */
381 /* ************************************************************************* */
383 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
385 proto_item *tagged_fields;
387 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
392 "Tagged parameters (%d bytes)",
395 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
399 /* ************************************************************************* */
400 /* Add the subtree used to store WEP parameters */
401 /* ************************************************************************* */
403 get_wep_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
405 proto_item *wep_fields;
406 proto_tree *wep_tree;
407 int crc_offset = size - 4;
409 wep_fields = proto_tree_add_string_format(tree, hf_wep_parameters, tvb,
410 0, 4, 0, "WEP parameters");
412 wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
413 proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, start, 3,
414 COOK_WEP_IV (tvb_get_letohl (tvb, start)));
416 proto_tree_add_uint (wep_tree, hf_wep_key, tvb, start + 3, 1,
417 COOK_WEP_KEY (tvb_get_letohl (tvb, start)));
419 if (tvb_bytes_exist(tvb, start + crc_offset, 4))
420 proto_tree_add_uint (wep_tree, hf_wep_crc, tvb, start + crc_offset, 4,
421 tvb_get_ntohl (tvb, start + crc_offset));
424 /* ************************************************************************* */
425 /* Dissect and add fixed mgmt fields to protocol tree */
426 /* ************************************************************************* */
428 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
430 const guint8 *dataptr;
431 char out_buff[SHORT_STR];
433 proto_item *cap_item;
434 static proto_tree *cap_tree;
439 case FIELD_TIMESTAMP:
440 dataptr = tvb_get_ptr (tvb, offset, 8);
441 memset (out_buff, 0, SHORT_STR);
442 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
452 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
456 case FIELD_BEACON_INTERVAL:
457 dataptr = tvb_get_ptr (tvb, offset, 2);
458 temp_double = ((double) *((guint16 *) dataptr));
459 temp_double = temp_double * 1024 / 1000000;
460 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
461 temp_double,"Beacon Interval: %f [Seconds]",
467 dataptr = tvb_get_ptr (tvb, offset, 2);
468 temp16 = (guint16 *) dataptr;
470 cap_item = proto_tree_add_uint_format (tree, ff_capture,
473 "Capability Information: %04X",
475 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
476 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
478 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
480 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
482 proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 1,
484 proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 1,
486 proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 1,
488 if (ESS_SET (pletohs (temp16)) != 0) /* This is an AP */
489 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
490 ((pletohs (temp16) & 0xC) >> 2));
492 else /* This is a STA */
493 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
494 ((pletohs (temp16) & 0xC) >> 2));
499 dataptr = tvb_get_ptr (tvb, offset, 2);
500 temp16 =(guint16 *) dataptr;
501 proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2,
506 case FIELD_AUTH_TRANS_SEQ:
507 dataptr = tvb_get_ptr (tvb, offset, 2);
508 temp16 = (guint16 *)dataptr;
509 proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2,
514 case FIELD_CURRENT_AP_ADDR:
515 dataptr = tvb_get_ptr (tvb, offset, 6);
516 proto_tree_add_ether (tree, ff_current_ap, tvb, offset, 6, dataptr);
520 case FIELD_LISTEN_IVAL:
521 dataptr = tvb_get_ptr (tvb, offset, 2);
522 temp16 = (guint16 *) dataptr;
523 proto_tree_add_uint (tree, ff_listen_ival, tvb, offset, 2,
528 case FIELD_REASON_CODE:
529 dataptr = tvb_get_ptr (tvb, offset, 2);
530 temp16 = (guint16 *) dataptr;
531 proto_tree_add_uint (tree, ff_reason, tvb, offset, 2, pletohs (temp16));
536 dataptr = tvb_get_ptr (tvb, offset, 2);
537 temp16 = (guint16 *) dataptr;
538 proto_tree_add_uint (tree, ff_assoc_id, tvb, offset, 2, pletohs (temp16));
541 case FIELD_STATUS_CODE:
542 dataptr = tvb_get_ptr (tvb, offset, 2);
543 temp16 = (guint16 *) dataptr;
544 proto_tree_add_uint (tree, ff_status_code, tvb, offset, 2,
551 /* ************************************************************************* */
552 /* Dissect and add tagged (optional) fields to proto tree */
553 /* ************************************************************************* */
555 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
557 const guint8 *tag_info_ptr;
558 const guint8 *tag_data_ptr;
559 guint32 tag_no, tag_len;
561 char out_buff[SHORT_STR];
564 tag_info_ptr = tvb_get_ptr (tvb, offset, 2);
565 tag_no = tag_info_ptr[0];
566 tag_len = tag_info_ptr[1];
568 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
571 if ((tag_no >= 17) && (tag_no <= 31))
572 { /* Reserved for challenge text */
573 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
574 "Tag Number: %u (Reserved for challenge text)",
577 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
578 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
579 tag_len, "Not interpreted");
580 return (int) tag_len + 2;
583 /* Next See if tag is reserved - if true, skip it! */
584 if (((tag_no >= 7) && (tag_no <= 15))
585 || ((tag_no >= 32) && (tag_no <= 255)))
587 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
588 "Tag Number: %u (Reserved tag number)",
591 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
593 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
594 tag_len, "Not interpreted");
595 return (int) tag_len + 2;
599 switch (tag_info_ptr[0])
604 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
605 "Tag Number: %u (SSID parameter set)",
608 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
610 memset (out_buff, 0, SHORT_STR);
612 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
613 out_buff[tag_len + 1] = 0;
615 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
622 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
623 "Tag Number: %u (Supported Rates)", tag_no);
625 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
627 memset (out_buff, 0, SHORT_STR);
628 strcpy (out_buff, "Supported rates: ");
629 n = strlen (out_buff);
631 for (i = 0; i < tag_len; i++)
633 n += snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
634 (tag_data_ptr[i] & 0x7F) * 0.5,
635 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
637 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
639 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
645 case TAG_FH_PARAMETER:
646 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
647 "Tag Number: %u (FH Parameter set)",
650 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
651 memset (out_buff, 0, SHORT_STR);
653 snprintf (out_buff, SHORT_STR,
654 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
655 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
656 tag_data_ptr[3], tag_data_ptr[4]);
658 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
664 case TAG_DS_PARAMETER:
665 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
666 "Tag Number: %u (DS Parameter set)",
669 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
670 memset (out_buff, 0, SHORT_STR);
672 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
673 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
678 case TAG_CF_PARAMETER:
679 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
680 "Tag Number: %u (CF Parameter set)",
683 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
684 memset (out_buff, 0, SHORT_STR);
686 snprintf (out_buff, SHORT_STR,
687 "CFP count %u, CFP period %u, CFP max duration %u, "
688 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
689 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
691 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
697 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
698 "Tag Number: %u ((TIM) Traffic Indication Map)",
701 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
702 memset (out_buff, 0, SHORT_STR);
703 snprintf (out_buff, SHORT_STR,
704 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
705 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
707 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
713 case TAG_IBSS_PARAMETER:
714 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
715 "Tag Number: %u (IBSS Parameter set)",
718 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
719 memset (out_buff, 0, SHORT_STR);
720 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
721 pletohs (tag_data_ptr));
723 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
729 case TAG_CHALLENGE_TEXT:
730 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
731 "Tag Number: %u (Challenge text)", tag_no);
733 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
734 memset (out_buff, 0, SHORT_STR);
735 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
736 proto_tree_add_string (tree, tag_interpretation, tvb, offset, tag_len,
750 /* ************************************************************************* */
751 /* Dissect 802.11 frame */
752 /* ************************************************************************* */
754 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
757 const guint8 *src = NULL, *dst = NULL;
759 proto_item *flag_item;
761 static proto_tree *hdr_tree;
762 static proto_tree *flag_tree;
763 static proto_tree *fixed_tree;
764 static proto_tree *tagged_tree;
765 static proto_tree *fc_tree;
766 guint16 cap_len, hdr_len;
771 int tagged_parameter_tree_len;
773 if (check_col (pinfo->fd, COL_PROTOCOL))
774 col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
775 if (check_col (pinfo->fd, COL_INFO))
776 col_clear (pinfo->fd, COL_INFO);
778 cap_len = tvb_length(tvb);
779 fcf = tvb_get_letohs (tvb, 0);
781 /* Add the FC to the current tree */
784 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
785 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
786 "IEEE 802.11 Header");
787 hdr_tree = proto_item_add_subtree (ti, ett_80211);
789 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
791 "Frame Control: 0x%04X",
794 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
797 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
798 COOK_PROT_VERSION (fcf));
800 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
801 COOK_FRAME_TYPE (fcf));
803 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
805 COOK_FRAME_SUBTYPE (fcf));
807 flags = COOK_FLAGS (fcf);
810 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
811 flags, "Flags: 0x%X", flags);
813 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
815 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
816 COOK_DS_STATUS (flags));
818 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
821 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
823 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
825 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
828 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
830 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
832 if ((COMPOSE_FRAME_TYPE(fcf))==CTRL_PS_POLL)
833 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
834 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
837 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
838 tvb_get_letohs (tvb, 2));
841 /* Perform tasks which are common to a certain frame type */
842 switch (COOK_FRAME_TYPE (fcf))
845 case MGT_FRAME: /* All management frames share a common header */
846 src = tvb_get_ptr (tvb, 10, 6);
847 dst = tvb_get_ptr (tvb, 4, 6);
850 if (check_col (pinfo->fd, COL_DEF_SRC))
851 col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X",
852 src[0], src[1], src[2], src[3], src[4], src[5]);
854 if (check_col (pinfo->fd, COL_DEF_DST))
855 col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X",
856 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
860 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
861 tvb_get_ptr (tvb, 4, 6));
863 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
864 tvb_get_ptr (tvb, 10, 6));
866 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
867 tvb_get_ptr (tvb, 16, 6));
869 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
870 COOK_FRAGMENT_NUMBER (tvb_get_letohs
873 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
874 COOK_SEQUENCE_NUMBER (tvb_get_letohs
876 cap_len = cap_len - MGT_FRAME_LEN - 4;
888 addr_type = COOK_ADDR_SELECTOR (fcf);
889 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
891 /* In order to show src/dst address we must always do the following */
896 src = tvb_get_ptr (tvb, 10, 6);
897 dst = tvb_get_ptr (tvb, 4, 6);
902 src = tvb_get_ptr (tvb, 16, 6);
903 dst = tvb_get_ptr (tvb, 4, 6);
908 src = tvb_get_ptr (tvb, 10, 6);
909 dst = tvb_get_ptr (tvb, 16, 6);
914 src = tvb_get_ptr (tvb, 24, 6);
915 dst = tvb_get_ptr (tvb, 16, 6);
919 if (check_col (pinfo->fd, COL_DEF_SRC))
920 col_add_fstr (pinfo->fd, COL_DEF_SRC,
921 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
922 src[0], src[1], src[2], src[3], src[4], src[5]);
924 if (check_col (pinfo->fd, COL_DEF_DST))
925 col_add_fstr (pinfo->fd, COL_DEF_DST,
926 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
927 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
929 /* Now if we have a tree we start adding stuff */
938 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
939 tvb_get_ptr (tvb, 4, 6));
940 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
941 tvb_get_ptr (tvb, 10, 6));
942 proto_tree_add_ether (hdr_tree, hf_addr_bssid, 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_letohs
947 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
948 COOK_SEQUENCE_NUMBER (tvb_get_letohs
954 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
955 tvb_get_ptr (tvb, 4, 6));
956 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
957 tvb_get_ptr (tvb, 10, 6));
958 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6,
959 tvb_get_ptr (tvb, 16, 6));
960 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
961 COOK_FRAGMENT_NUMBER (tvb_get_letohs
963 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
964 COOK_SEQUENCE_NUMBER (tvb_get_letohs
970 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
971 tvb_get_ptr (tvb, 4, 6));
972 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
973 tvb_get_ptr (tvb, 10, 6));
974 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
975 tvb_get_ptr (tvb, 16, 6));
976 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
977 COOK_FRAGMENT_NUMBER (tvb_get_letohs
979 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
980 COOK_SEQUENCE_NUMBER (tvb_get_letohs
986 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
987 tvb_get_ptr (tvb, 4, 6));
988 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
989 tvb_get_ptr (tvb, 10, 6));
990 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
991 tvb_get_ptr (tvb, 16, 6));
992 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
993 COOK_FRAGMENT_NUMBER (tvb_get_letohs
995 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
996 COOK_SEQUENCE_NUMBER (tvb_get_letohs
998 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6,
999 tvb_get_ptr (tvb, 24, 6));
1008 switch (COMPOSE_FRAME_TYPE (fcf))
1012 COL_SHOW_INFO_CONST (pinfo->fd, "Association Request");
1015 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 4);
1016 add_fixed_field (fixed_tree, tvb, MGT_FRAME_HDR_LEN,
1018 add_fixed_field (fixed_tree, tvb, MGT_FRAME_HDR_LEN + 2,
1021 next_idx = MGT_FRAME_HDR_LEN + 4; /* Size of fixed fields */
1022 tagged_parameter_tree_len =
1023 tvb_reported_length_remaining(tvb, next_idx + 4);
1024 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1025 tagged_parameter_tree_len);
1027 while (tagged_parameter_tree_len > 0) {
1028 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1030 next_idx +=next_len;
1031 tagged_parameter_tree_len -= next_len;
1038 case MGT_ASSOC_RESP:
1039 COL_SHOW_INFO_CONST (pinfo->fd, "Association Response");
1043 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 6);
1044 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
1045 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1047 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1050 next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
1052 tagged_parameter_tree_len =
1053 tvb_reported_length_remaining(tvb, next_idx + 4);
1054 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1055 tagged_parameter_tree_len);
1057 while (tagged_parameter_tree_len > 0) {
1058 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1060 next_idx +=next_len;
1061 tagged_parameter_tree_len -= next_len;
1067 case MGT_REASSOC_REQ:
1068 COL_SHOW_INFO_CONST (pinfo->fd, "Reassociation Request");
1071 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 10);
1072 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
1073 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1075 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1076 FIELD_CURRENT_AP_ADDR);
1078 next_idx = MGT_FRAME_LEN + 10; /* Size of fixed fields */
1079 tagged_parameter_tree_len =
1080 tvb_reported_length_remaining(tvb, next_idx + 4);
1081 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1082 tagged_parameter_tree_len);
1084 while (tagged_parameter_tree_len > 0) {
1085 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1087 next_idx +=next_len;
1088 tagged_parameter_tree_len -= next_len;
1093 case MGT_REASSOC_RESP:
1094 COL_SHOW_INFO_CONST (pinfo->fd, "Reassociation Response");
1097 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 10);
1098 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
1099 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1101 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1104 next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
1105 tagged_parameter_tree_len =
1106 tvb_reported_length_remaining(tvb, next_idx + 4);
1107 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1108 tagged_parameter_tree_len);
1110 while (tagged_parameter_tree_len > 0) {
1111 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1113 next_idx +=next_len;
1114 tagged_parameter_tree_len -= next_len;
1121 COL_SHOW_INFO_CONST (pinfo->fd, "Probe Request");
1124 next_idx = MGT_FRAME_LEN;
1125 tagged_parameter_tree_len =
1126 tvb_reported_length_remaining(tvb, next_idx + 4);
1127 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1128 tagged_parameter_tree_len);
1130 while (tagged_parameter_tree_len > 0) {
1131 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1133 next_idx +=next_len;
1134 tagged_parameter_tree_len -= next_len;
1140 case MGT_PROBE_RESP:
1141 COL_SHOW_INFO_CONST (pinfo->fd, "Probe Response");
1144 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 12);
1145 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_TIMESTAMP);
1146 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 8,
1147 FIELD_BEACON_INTERVAL);
1148 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 10,
1151 next_idx = MGT_FRAME_LEN + 12; /* Size of fixed fields */
1152 tagged_parameter_tree_len =
1153 tvb_reported_length_remaining(tvb, next_idx + 4);
1154 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1155 tagged_parameter_tree_len);
1157 while (tagged_parameter_tree_len > 0) {
1158 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1160 next_idx +=next_len;
1161 tagged_parameter_tree_len -= next_len;
1167 case MGT_BEACON: /* Dissect protocol payload fields */
1168 COL_SHOW_INFO_CONST (pinfo->fd, "Beacon frame");
1172 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 12);
1174 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_TIMESTAMP);
1176 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 8,
1177 FIELD_BEACON_INTERVAL);
1178 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 10,
1181 next_idx = MGT_FRAME_LEN + 12; /* Size of fixed fields */
1182 tagged_parameter_tree_len =
1183 tvb_reported_length_remaining(tvb, next_idx + 4);
1184 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1185 tagged_parameter_tree_len);
1187 while (tagged_parameter_tree_len > 0) {
1188 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1190 next_idx +=next_len;
1191 tagged_parameter_tree_len -= next_len;
1199 COL_SHOW_INFO_CONST (pinfo->fd, "ATIM");
1206 COL_SHOW_INFO_CONST (pinfo->fd, "Dissassociate");
1209 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, cap_len);
1210 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_REASON_CODE);
1214 case MGT_AUTHENTICATION:
1215 COL_SHOW_INFO_CONST (pinfo->fd, "Authentication");
1216 if (IS_WEP(COOK_FLAGS(fcf)))
1218 int pkt_len = tvb_reported_length (tvb);
1219 int cap_len = tvb_length (tvb);
1222 get_wep_parameter_tree (tree, tvb, MGT_FRAME_LEN, pkt_len);
1223 pkt_len = MAX (pkt_len - 8 - MGT_FRAME_LEN, 0);
1224 cap_len = MIN (pkt_len, MAX (cap_len - 8 - MGT_FRAME_LEN, 0));
1225 next_tvb = tvb_new_subset (tvb, MGT_FRAME_LEN + 4, cap_len, pkt_len);
1226 dissect_data (next_tvb, 0, pinfo, tree);
1232 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 6);
1233 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_AUTH_ALG);
1234 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1235 FIELD_AUTH_TRANS_SEQ);
1236 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1239 next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
1241 tagged_parameter_tree_len =
1242 tvb_reported_length_remaining(tvb, next_idx + 4);
1243 if (tagged_parameter_tree_len != 0)
1245 tagged_tree = get_tagged_parameter_tree (tree,
1248 tagged_parameter_tree_len);
1250 while (tagged_parameter_tree_len > 0) {
1251 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1253 next_idx +=next_len;
1254 tagged_parameter_tree_len -= next_len;
1261 case MGT_DEAUTHENTICATION:
1262 COL_SHOW_INFO_CONST (pinfo->fd, "Deauthentication");
1265 fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 2);
1266 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_REASON_CODE);
1273 COL_SHOW_INFO_CONST (pinfo->fd, "Power-Save poll");
1275 src = tvb_get_ptr (tvb, 10, 6);
1276 dst = tvb_get_ptr (tvb, 4, 6);
1279 if (check_col (pinfo->fd, COL_DEF_SRC))
1280 col_add_fstr (pinfo->fd, COL_DEF_SRC,
1281 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (BSSID)",
1282 src[0], src[1], src[2], src[3], src[4], src[5]);
1284 if (check_col (pinfo->fd, COL_DEF_DST))
1285 col_add_fstr (pinfo->fd, COL_DEF_DST,
1286 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (TA)",
1287 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1291 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1292 tvb_get_ptr (tvb, 4, 6));
1294 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1295 tvb_get_ptr (tvb, 10, 6));
1303 COL_SHOW_INFO_CONST (pinfo->fd, "Request-to-send");
1304 src = tvb_get_ptr (tvb, 10, 6);
1305 dst = tvb_get_ptr (tvb, 4, 6);
1308 if (check_col (pinfo->fd, COL_DEF_SRC))
1309 col_add_fstr (pinfo->fd, COL_DEF_SRC,
1310 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (TA)",
1311 src[0], src[1], src[2], src[3], src[4], src[5]);
1313 if (check_col (pinfo->fd, COL_DEF_DST))
1314 col_add_fstr (pinfo->fd, COL_DEF_DST,
1315 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
1316 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1320 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1321 tvb_get_ptr (tvb, 4, 6));
1323 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1324 tvb_get_ptr (tvb, 10, 6));
1332 COL_SHOW_INFO_CONST (pinfo->fd, "Clear-to-send");
1334 dst = tvb_get_ptr (tvb, 4, 6);
1336 if (check_col (pinfo->fd, COL_DEF_DST))
1337 col_add_fstr (pinfo->fd, COL_DEF_DST,
1338 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
1339 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1343 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1344 tvb_get_ptr (tvb, 4, 6));
1351 case CTRL_ACKNOWLEDGEMENT:
1352 COL_SHOW_INFO_CONST (pinfo->fd, "Acknowledgement");
1354 dst = tvb_get_ptr (tvb, 4, 6);
1356 if (check_col (pinfo->fd, COL_DEF_DST))
1357 col_add_fstr (pinfo->fd, COL_DEF_DST,
1358 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (RA)",
1359 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1362 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1363 tvb_get_ptr (tvb, 4, 6));
1369 COL_SHOW_INFO_CONST (pinfo->fd, "CF-End (Control-frame)");
1371 src = tvb_get_ptr (tvb, 10, 6);
1372 dst = tvb_get_ptr (tvb, 4, 6);
1375 if (check_col (pinfo->fd, COL_DEF_SRC))
1376 col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X (BSSID)",
1377 src[0], src[1], src[2], src[3], src[4], src[5]);
1379 if (check_col (pinfo->fd, COL_DEF_DST))
1380 col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X (RA)",
1381 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1385 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1386 tvb_get_ptr (tvb, 4, 6));
1387 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1388 tvb_get_ptr (tvb, 10, 6));
1394 case CTRL_CFP_ENDACK:
1395 COL_SHOW_INFO_CONST (pinfo->fd, "CF-End + CF-Ack (Control-frame)");
1397 src = tvb_get_ptr (tvb, 10, 6);
1398 dst = tvb_get_ptr (tvb, 4, 6);
1400 if (check_col (pinfo->fd, COL_DEF_SRC))
1401 col_add_fstr (pinfo->fd, COL_DEF_SRC, "%X:%X:%X:%X:%X:%X (BSSID)",
1402 src[0], src[1], src[2], src[3], src[4], src[5]);
1404 if (check_col (pinfo->fd, COL_DEF_DST))
1405 col_add_fstr (pinfo->fd, COL_DEF_DST, "%X:%X:%X:%X:%X:%X (RA)",
1406 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
1410 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1411 tvb_get_ptr (tvb, 4, 6));
1413 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1414 tvb_get_ptr (tvb, 10, 6));
1421 COL_SHOW_INFO_CONST (pinfo->fd, "Data");
1422 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
1424 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1426 if (IS_WEP(COOK_FLAGS(fcf)))
1428 int pkt_len = tvb_reported_length (next_tvb);
1429 int cap_len = tvb_length (next_tvb);
1432 get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
1433 pkt_len = MAX (pkt_len - 8, 0);
1434 cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
1435 next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
1436 dissect_data (next_tvb, 0, pinfo, tree);
1439 call_dissector (llc_handle, next_tvb, pinfo, tree);
1445 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Acknowledgement");
1446 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
1448 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1450 if (IS_WEP(COOK_FLAGS(fcf)))
1452 int pkt_len = tvb_reported_length (next_tvb);
1453 int cap_len = tvb_length (next_tvb);
1456 get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
1457 pkt_len = MAX (pkt_len - 8, 0);
1458 cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
1459 next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
1460 dissect_data (next_tvb, 0, pinfo, tree);
1463 call_dissector (llc_handle, next_tvb, pinfo, tree);
1469 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Poll");
1470 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
1471 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1473 if (IS_WEP(COOK_FLAGS(fcf)))
1475 int pkt_len = tvb_reported_length (next_tvb);
1476 int cap_len = tvb_length (next_tvb);
1479 get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
1480 pkt_len = MAX (pkt_len - 8, 0);
1481 cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
1482 next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
1483 dissect_data (next_tvb, 0, pinfo, tree);
1486 call_dissector (llc_handle, next_tvb, pinfo, tree);
1491 case DATA_CF_ACK_POLL:
1492 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Acknowledgement/Poll");
1493 hdr_len = find_header_length (tvb_get_ptr (tvb, 0, cap_len), 0);
1494 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1496 if (IS_WEP(COOK_FLAGS(fcf)))
1498 int pkt_len = tvb_reported_length (next_tvb);
1499 int cap_len = tvb_length (next_tvb);
1502 get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
1503 pkt_len = MAX (pkt_len - 8, 0);
1504 cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
1505 next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
1506 dissect_data (next_tvb, 0, pinfo, tree);
1509 call_dissector (llc_handle, next_tvb, pinfo, tree);
1514 case DATA_NULL_FUNCTION:
1515 COL_SHOW_INFO_CONST (pinfo->fd, "Null function (No data)");
1519 case DATA_CF_ACK_NOD:
1520 COL_SHOW_INFO_CONST (pinfo->fd, "Data + Acknowledgement(No data)");
1524 case DATA_CF_POLL_NOD:
1525 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Poll (No data)");
1529 case DATA_CF_ACK_POLL_NOD:
1530 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Acknowledgement/Poll (No data)");
1535 COL_SHOW_INFO_CONST (pinfo->fd, "Unrecognized (Reserved frame)");
1542 proto_register_wlan (void)
1545 static const value_string tofrom_ds[] = {
1546 {0, "Not leaving DS or network is operating in AD-HOC mode ( To DS: 0 From DS: 0)"},
1547 {1, "Frame is exiting DS (To DS: 0 From DS: 1)"},
1548 {2, "Frame is entering DS (To DS: 1 From DS: 0)"},
1549 {3, "Frame part of WDS (To DS: 1 From DS: 1)"},
1553 static const true_false_string tods_flag = {
1554 "TO DS: Should be false",
1558 static const true_false_string fromds_flag = {
1559 "FROM DS: Should be false",
1563 static const true_false_string more_frags = {
1564 "MSDU/MMPDU is fragmented",
1568 static const true_false_string retry_flags = {
1569 "Frame is being retransmitted",
1570 "Frame is not being retransmitted"
1573 static const true_false_string pm_flags = {
1574 "STA will go to sleep",
1578 static const true_false_string md_flags = {
1579 "Data is buffered for STA at AP",
1583 static const true_false_string wep_flags = {
1588 static const true_false_string order_flags = {
1593 static const true_false_string cf_ess_flags = {
1594 "Transmitter is an AP",
1595 "Transmitter is a STA"
1599 static const true_false_string cf_privacy_flags = {
1600 "AP/STA can support WEP",
1601 "AP/STA cannot support WEP"
1604 static const true_false_string cf_preamble_flags = {
1605 "Short preamble allowed",
1606 "Short preamble not allowed"
1609 static const true_false_string cf_pbcc_flags = {
1610 "PBCC modulation allowed",
1611 "PBCC modulation not allowed"
1614 static const true_false_string cf_agility_flags = {
1615 "Channel agility in use",
1616 "Channel agility not in use"
1620 static const true_false_string cf_ibss_flags = {
1621 "Transmitter belongs to an IBSS",
1622 "Transmitter belongs to a BSS"
1625 static const value_string sta_cf_pollable[] = {
1626 {0x00, "Station is not CF-Pollable"},
1627 {0x02, "Station is CF-Pollable, "
1628 "not requesting to be placed on the CF-polling list"},
1629 {0x01, "Station is CF-Pollable, "
1630 "requesting to be placed on the CF-polling list"},
1631 {0x03, "Station is CF-Pollable, requesting never to be polled"},
1635 static const value_string ap_cf_pollable[] = {
1636 {0x00, "No point coordinator at AP"},
1637 {0x02, "Point coordinator at AP for delivery only (no polling)"},
1638 {0x01, "Point coordinator at AP for delivery and polling"},
1644 static const value_string auth_alg[] = {
1645 {0x00, "Open System"},
1646 {0x01, "Shared key"},
1650 static const value_string reason_codes[] = {
1652 {0x01, "Unspecified reason"},
1653 {0x02, "Previous authentication no longer valid"},
1654 {0x03, "Deauthenticated because sending STA is leaving (has left) "
1656 {0x04, "Disassociated due to inactivity"},
1657 {0x05, "Disassociated because AP is unable to handle all currently "
1658 "associated stations"},
1659 {0x06, "Class 2 frame received from nonauthenticated station"},
1660 {0x07, "Class 3 frame received from nonassociated station"},
1661 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1662 {0x09, "Station requesting (re)association is not authenticated with "
1663 "responding station"},
1668 static const value_string status_codes[] = {
1669 {0x00, "Successful"},
1670 {0x01, "Unspecified failure"},
1671 {0x0A, "Cannot support all requested capabilities in the "
1672 "Capability information field"},
1673 {0x0B, "Reassociation denied due to inability to confirm that "
1674 "association exists"},
1675 {0x0C, "Association denied due to reason outside the scope of this "
1678 {0x0D, "Responding station does not support the specified authentication "
1680 {0x0E, "Received an Authentication frame with authentication sequence "
1681 "transaction sequence number out of expected sequence"},
1682 {0x0F, "Authentication rejected because of challenge failure"},
1683 {0x10, "Authentication rejected due to timeout waiting for next "
1684 "frame in sequence"},
1685 {0x11, "Association denied because AP is unable to handle additional "
1686 "associated stations"},
1687 {0x12, "Association denied due to requesting station not supporting all "
1688 "of the datarates in the BSSBasicServiceSet Parameter"},
1694 static hf_register_info hf[] = {
1696 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
1697 "MAC Frame control"}},
1699 {&hf_fc_proto_version,
1700 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
1701 "MAC Protocol version"}}, /* 0 */
1704 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, NULL, 0,
1707 {&hf_fc_frame_subtype,
1708 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
1709 "Frame subtype"}}, /* 2 */
1712 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
1716 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, TFS (&tofrom_ds), 0,
1717 "Data-frame DS-traversal status"}}, /* 3 */
1720 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), 0x1,
1721 "To DS flag"}}, /* 4 */
1724 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), 0x2,
1725 "From DS flag"}}, /* 5 */
1728 {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), 0x4,
1729 "More Fragments flag"}}, /* 6 */
1732 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), 0x8,
1733 "Retransmission flag"}},
1736 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), 0x10,
1737 "Power management status"}},
1740 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), 0x20,
1744 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), 0x40,
1748 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), 0x80,
1749 "Strictly ordered flag"}},
1752 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
1753 "Association-ID field" }},
1756 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
1760 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
1761 "Destination Hardware address"}},
1764 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
1765 "Source Hardware address"}},
1768 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
1769 "Receiving Station Hardware Address"}},
1772 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
1773 "Transmitting Station Hardware Address"}},
1776 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
1777 "Basic Service Set ID"}},
1780 {"Fragment number", "wlan.frag", FT_UINT16, BASE_HEX, NULL, 0,
1781 "Fragment number"}},
1784 {"Sequence number", "wlan.seq", FT_UINT16, BASE_HEX, NULL, 0,
1785 "Fragment number"}},
1788 {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
1792 {"Timestamp", "wlan.fixed.timestamp", FT_STRING, BASE_NONE,
1796 {"Authentication Algorithm", "wlan.fixed.auth.alg",
1797 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, ""}},
1799 {&ff_beacon_interval,
1800 {"Beacon Interval", "wlan.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
1803 {&hf_fixed_parameters,
1804 {"Fixed parameters", "wlan.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
1807 {&hf_tagged_parameters,
1808 {"Tagged parameters", "wlan.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
1811 {&hf_wep_parameters,
1812 {"WEP parameters", "wlan.wep.all", FT_STRING, BASE_NONE, NULL, 0,
1816 {"Initialization Vector", "wlan.wep.iv", FT_UINT32, BASE_HEX, NULL, 0,
1817 "Initialization Vector"}},
1820 {"Key", "wlan.wep.key", FT_UINT32, BASE_DEC, NULL, 0,
1824 {"WEP CRC (not verified)", "wlan.wep.crc", FT_UINT32, BASE_HEX, NULL, 0,
1828 {"Capabilities", "wlan.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
1829 "Capability information"}},
1832 {"CFP participation capabilities", "wlan.fixed.capabilities.cfpoll.sta",
1833 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
1834 "CF-Poll capabilities for a STA"}},
1837 {"CFP participation capabilities", "wlan.fixed.capabilities.cfpoll.ap",
1838 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
1839 "CF-Poll capabilities for an AP"}},
1842 {"ESS capabilities", "wlan.fixed.capabilities.ess",
1843 FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities"}},
1847 {"IBSS status", "wlan.fixed.capabilities.ibss",
1848 FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation"}},
1851 {"Privacy", "wlan.fixed.capabilities.privacy",
1852 FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support"}},
1855 {"Short Preamble", "wlan.fixed.capabilities.preamble",
1856 FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble"}},
1859 {"PBCC", "wlan.fixed.capabilities.pbcc",
1860 FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation"}},
1863 {"Channel Agility", "wlan.fixed.capabilities.agility",
1864 FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility"}},
1868 {"Authentication SEQ", "wlan.fixed.auth_seq",
1869 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number"}},
1872 {"Association ID", "wlan.fixed.aid",
1873 FT_UINT16, BASE_HEX, NULL, 0, "Association ID"}},
1876 {"Listen Interval", "wlan.fixed.listen_ival",
1877 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval"}},
1880 {"Current AP", "wlan.fixed.current_ap",
1881 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP"}},
1884 {"Reason code", "wlan.fixed.reason_code",
1885 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
1886 "Reason for unsolicited notification"}},
1889 {"Status code", "wlan.fixed.status_code",
1890 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
1891 "Status of requested event"}},
1894 {"Tag", "wlan.tag.number",
1895 FT_UINT16, BASE_DEC, NULL, 0,
1899 {"Tag length", "wlan.tag.length",
1900 FT_UINT16, BASE_DEC, NULL, 0, "Length of tag"}},
1902 {&tag_interpretation,
1903 {"Tag interpretation", "wlan.tag.interpretation",
1904 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag"}}
1910 static gint *tree_array[] = { &ett_80211,
1913 &ett_fixed_parameters,
1914 &ett_tagged_parameters,
1915 &ett_wep_parameters,
1919 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
1920 "IEEE 802.11", "wlan");
1921 proto_register_field_array (proto_wlan, hf, array_length (hf));
1922 proto_register_subtree_array (tree_array, array_length (tree_array));
1926 proto_reg_handoff_wlan(void)
1929 * Get a handle for the LLC dissector.
1931 llc_handle = find_dissector("llc");
1933 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,