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.26 2001/06/20 06:22:33 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * Copied from README.developer
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 * The following people helped me by pointing out bugs etc. Thank you!
34 * Magnus Hultman-Persson
45 #ifdef HAVE_SYS_TYPES_H
46 # include <sys/types.h>
49 #ifdef HAVE_NETINET_IN_H
50 # include <netinet/in.h>
53 #ifdef NEED_SNPRINTF_H
59 # include "snprintf.h"
68 #include "packet-llc.h"
69 #include "packet-ieee80211.h"
72 /* ************************************************************************* */
73 /* Miscellaneous Constants */
74 /* ************************************************************************* */
76 #define MGT_FRAME_LEN 24
78 /* ************************************************************************* */
79 /* Define some very useful macros that are used to analyze frame types etc. */
80 /* ************************************************************************* */
81 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */
82 #define COOK_PROT_VERSION(x) ((x) & 0x3)
83 #define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2)
84 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
85 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
86 #define COOK_ASSOC_ID(x) ((x) & 0x3FFF)
87 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
88 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
89 #define COOK_FLAGS(x) (((x) & 0xFF00) >> 8)
90 #define COOK_DS_STATUS(x) ((x) & 0x3)
91 #define COOK_WEP_IV(x) ((x) & 0xFFFFFF)
92 #define COOK_WEP_KEY(x) (((x) & 0xC0000000) >> 30)
93 #define COL_SHOW_INFO(fd,info) if (check_col(fd,COL_INFO)) \
94 col_add_str(fd,COL_INFO,info);
95 #define COL_SHOW_INFO_CONST(fd,info) if (check_col(fd,COL_INFO)) \
96 col_set_str(fd,COL_INFO,info);
98 #define IS_TO_DS(x) ((x) & 0x01)
99 #define IS_FROM_DS(x) ((x) & 0x02)
100 #define HAVE_FRAGMENTS(x) ((x) & 0x04)
101 #define IS_RETRY(x) ((x) & 0x08)
102 #define POWER_MGT_STATUS(x) ((x) & 0x10)
103 #define HAS_MORE_DATA(x) ((x) & 0x20)
104 #define IS_WEP(x) ((x) & 0x40)
105 #define IS_STRICTLY_ORDERED(x) ((x) & 0x80)
107 #define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
108 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
109 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
110 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
113 /* ************************************************************************* */
114 /* Constants used to identify cooked frame types */
115 /* ************************************************************************* */
116 #define MGT_FRAME 0x00 /* Frame type is management */
117 #define CONTROL_FRAME 0x01 /* Frame type is control */
118 #define DATA_FRAME 0x02 /* Frame type is Data */
120 #define DATA_SHORT_HDR_LEN 24
121 #define DATA_LONG_HDR_LEN 30
122 #define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
124 #define MGT_ASSOC_REQ 0x00 /* Management - association request */
125 #define MGT_ASSOC_RESP 0x01 /* Management - association response */
126 #define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
127 #define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
128 #define MGT_PROBE_REQ 0x04 /* Management - Probe request */
129 #define MGT_PROBE_RESP 0x05 /* Management - Probe response */
130 #define MGT_BEACON 0x08 /* Management - Beacon frame */
131 #define MGT_ATIM 0x09 /* Management - ATIM */
132 #define MGT_DISASS 0x0A /* Management - Disassociation */
133 #define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
134 #define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
136 #define CTRL_PS_POLL 0x1A /* Control - power-save poll */
137 #define CTRL_RTS 0x1B /* Control - request to send */
138 #define CTRL_CTS 0x1C /* Control - clear to send */
139 #define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
140 #define CTRL_CFP_END 0x1E /* Control - contention-free period end */
141 #define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
143 #define DATA 0x20 /* Data - Data */
144 #define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
145 #define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
146 #define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
147 #define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
148 #define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
149 #define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
150 #define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
152 #define DATA_ADDR_T1 0x0000
153 #define DATA_ADDR_T2 0x0100
154 #define DATA_ADDR_T3 0x0200
155 #define DATA_ADDR_T4 0x0300
158 /* ************************************************************************* */
159 /* Macros used to extract information about fixed fields */
160 /* ************************************************************************* */
161 #define ESS_SET(x) ((x) & 0x0001)
162 #define IBSS_SET(x) ((x) & 0x0002)
166 /* ************************************************************************* */
167 /* Logical field codes (dissector's encoding of fixed fields) */
168 /* ************************************************************************* */
169 #define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
170 #define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
171 #define FIELD_CAP_INFO 0x03 /* Add capability information tree */
172 #define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
173 #define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
174 #define FIELD_CURRENT_AP_ADDR 0x06
175 #define FIELD_LISTEN_IVAL 0x07
176 #define FIELD_REASON_CODE 0x08
177 #define FIELD_ASSOC_ID 0x09
178 #define FIELD_STATUS_CODE 0x0A
180 /* ************************************************************************* */
181 /* Logical field codes (IEEE 802.11 encoding of tags) */
182 /* ************************************************************************* */
183 #define TAG_SSID 0x00
184 #define TAG_SUPP_RATES 0x01
185 #define TAG_FH_PARAMETER 0x02
186 #define TAG_DS_PARAMETER 0x03
187 #define TAG_CF_PARAMETER 0x04
189 #define TAG_IBSS_PARAMETER 0x06
190 #define TAG_CHALLENGE_TEXT 0x10
193 static int proto_wlan = -1;
194 /* ************************************************************************* */
195 /* Header field info values for FC-field */
196 /* ************************************************************************* */
197 static int hf_fc_field = -1;
198 static int hf_fc_proto_version = -1;
199 static int hf_fc_frame_type = -1;
200 static int hf_fc_frame_subtype = -1;
202 static int hf_fc_flags = -1;
203 static int hf_fc_to_ds = -1;
204 static int hf_fc_from_ds = -1;
205 static int hf_fc_data_ds = -1;
207 static int hf_fc_more_frag = -1;
208 static int hf_fc_retry = -1;
209 static int hf_fc_pwr_mgt = -1;
210 static int hf_fc_more_data = -1;
211 static int hf_fc_wep = -1;
212 static int hf_fc_order = -1;
215 /* ************************************************************************* */
216 /* Header values for Duration/ID field */
217 /* ************************************************************************* */
218 static int hf_did_duration = -1;
219 static int hf_assoc_id = -1;
222 /* ************************************************************************* */
223 /* Header values for different address-fields (all 4 of them) */
224 /* ************************************************************************* */
225 static int hf_addr_da = -1; /* Destination address subfield */
226 static int hf_addr_sa = -1; /* Source address subfield */
227 static int hf_addr_ra = -1; /* Receiver address subfield */
228 static int hf_addr_ta = -1; /* Transmitter address subfield */
229 static int hf_addr_bssid = -1; /* address is bssid */
233 /* ************************************************************************* */
234 /* Header values for sequence number field */
235 /* ************************************************************************* */
236 static int hf_frag_number = -1;
237 static int hf_seq_number = -1;
239 /* ************************************************************************* */
240 /* Header values for Frame Check field */
241 /* ************************************************************************* */
242 static int hf_fcs = -1;
245 /* ************************************************************************* */
246 /* Fixed fields found in mgt frames */
247 /* ************************************************************************* */
248 static int ff_auth_alg = -1; /* Authentication algorithm field */
249 static int ff_auth_seq = -1; /* Authentication transaction sequence */
250 static int ff_current_ap = -1; /* Current AP MAC address */
251 static int ff_listen_ival = -1; /* Listen interval fixed field */
252 static int ff_timestamp = -1; /* 64 bit timestamp */
253 static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
254 static int ff_assoc_id = -1; /* 16 bit AID field */
255 static int ff_reason = -1; /* 16 bit reason code */
256 static int ff_status_code = -1; /* Status code */
258 /* ************************************************************************* */
259 /* Flags found in the capability field (fixed field) */
260 /* ************************************************************************* */
261 static int ff_capture = -1;
262 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
263 static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
264 static int ff_cf_ess = -1;
265 static int ff_cf_ibss = -1;
266 static int ff_cf_privacy = -1;
267 static int ff_cf_preamble = -1;
268 static int ff_cf_pbcc = -1;
269 static int ff_cf_agility = -1;
271 /* ************************************************************************* */
272 /* Tagged value format fields */
273 /* ************************************************************************* */
274 static int tag_number = -1;
275 static int tag_length = -1;
276 static int tag_interpretation = -1;
280 static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
281 static int hf_tagged_parameters = -1; /* Fixed payload item */
282 static int hf_wep_parameters = -1;
283 static int hf_wep_iv = -1;
284 static int hf_wep_key = -1;
285 static int hf_wep_crc = -1;
287 /* ************************************************************************* */
289 /* ************************************************************************* */
290 static gint ett_80211 = -1;
291 static gint ett_proto_flags = -1;
292 static gint ett_cap_tree = -1;
293 static gint ett_fc_tree = -1;
294 static gint ett_fixed_parameters = -1;
295 static gint ett_tagged_parameters = -1;
296 static gint ett_wep_parameters = -1;
298 static dissector_handle_t llc_handle;
300 /* ************************************************************************* */
301 /* Return the length of the current header (in bytes) */
302 /* ************************************************************************* */
304 find_header_length (guint16 fcf)
306 return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? 30 : 24;
310 /* ************************************************************************* */
311 /* This is the capture function used to update packet counts */
312 /* ************************************************************************* */
314 capture_ieee80211 (const u_char * pd, int offset, packet_counts * ld)
316 guint16 fcf, hdr_length;
318 fcf = pletohs (&pd[0]);
320 if (IS_WEP(COOK_FLAGS(fcf)))
326 switch (COMPOSE_FRAME_TYPE (fcf))
329 case DATA: /* We got a data frame */
330 hdr_length = find_header_length (fcf);
331 capture_llc (pd, offset + hdr_length, ld);
334 case DATA_CF_ACK: /* Data with ACK */
335 hdr_length = find_header_length (fcf);
336 capture_llc (pd, offset + hdr_length, ld);
340 hdr_length = find_header_length (fcf);
341 capture_llc (pd, offset + hdr_length, ld);
344 case DATA_CF_ACK_POLL:
345 hdr_length = find_header_length (fcf);
346 capture_llc (pd, offset + hdr_length, ld);
357 /* ************************************************************************* */
358 /* Add the subtree used to store the fixed parameters */
359 /* ************************************************************************* */
361 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
363 proto_item *fixed_fields;
365 proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
366 size, size, "Fixed parameters (%d bytes)",
369 return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
373 /* ************************************************************************* */
374 /* Add the subtree used to store tagged parameters */
375 /* ************************************************************************* */
377 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
379 proto_item *tagged_fields;
381 tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
386 "Tagged parameters (%d bytes)",
389 return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
393 /* ************************************************************************* */
394 /* Add the subtree used to store WEP parameters */
395 /* ************************************************************************* */
397 get_wep_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
399 proto_item *wep_fields;
400 proto_tree *wep_tree;
401 int crc_offset = size - 4;
403 wep_fields = proto_tree_add_string_format(tree, hf_wep_parameters, tvb,
404 0, 4, 0, "WEP parameters");
406 wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
407 proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, start, 3,
408 COOK_WEP_IV (tvb_get_letohl (tvb, start)));
410 proto_tree_add_uint (wep_tree, hf_wep_key, tvb, start + 3, 1,
411 COOK_WEP_KEY (tvb_get_letohl (tvb, start)));
413 if (tvb_bytes_exist(tvb, start + crc_offset, 4))
414 proto_tree_add_uint (wep_tree, hf_wep_crc, tvb, start + crc_offset, 4,
415 tvb_get_ntohl (tvb, start + crc_offset));
418 /* ************************************************************************* */
419 /* Dissect and add fixed mgmt fields to protocol tree */
420 /* ************************************************************************* */
422 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
424 const guint8 *dataptr;
425 char out_buff[SHORT_STR];
427 proto_item *cap_item;
428 static proto_tree *cap_tree;
433 case FIELD_TIMESTAMP:
434 dataptr = tvb_get_ptr (tvb, offset, 8);
435 memset (out_buff, 0, SHORT_STR);
436 snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
446 proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
450 case FIELD_BEACON_INTERVAL:
451 dataptr = tvb_get_ptr (tvb, offset, 2);
452 temp_double = ((double) *((guint16 *) dataptr));
453 temp_double = temp_double * 1024 / 1000000;
454 proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
455 temp_double,"Beacon Interval: %f [Seconds]",
461 dataptr = tvb_get_ptr (tvb, offset, 2);
462 temp16 = (guint16 *) dataptr;
464 cap_item = proto_tree_add_uint_format (tree, ff_capture,
467 "Capability Information: 0x%04X",
469 cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
470 proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 1,
472 proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 1,
474 proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 1,
476 proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 1,
478 proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 1,
480 proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 1,
482 if (ESS_SET (pletohs (temp16)) != 0) /* This is an AP */
483 proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
484 ((pletohs (temp16) & 0xC) >> 2));
486 else /* This is a STA */
487 proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
488 ((pletohs (temp16) & 0xC) >> 2));
493 dataptr = tvb_get_ptr (tvb, offset, 2);
494 temp16 =(guint16 *) dataptr;
495 proto_tree_add_uint (tree, ff_auth_alg, tvb, offset, 2,
500 case FIELD_AUTH_TRANS_SEQ:
501 dataptr = tvb_get_ptr (tvb, offset, 2);
502 temp16 = (guint16 *)dataptr;
503 proto_tree_add_uint (tree, ff_auth_seq, tvb, offset, 2,
508 case FIELD_CURRENT_AP_ADDR:
509 dataptr = tvb_get_ptr (tvb, offset, 6);
510 proto_tree_add_ether (tree, ff_current_ap, tvb, offset, 6, dataptr);
514 case FIELD_LISTEN_IVAL:
515 dataptr = tvb_get_ptr (tvb, offset, 2);
516 temp16 = (guint16 *) dataptr;
517 proto_tree_add_uint (tree, ff_listen_ival, tvb, offset, 2,
522 case FIELD_REASON_CODE:
523 dataptr = tvb_get_ptr (tvb, offset, 2);
524 temp16 = (guint16 *) dataptr;
525 proto_tree_add_uint (tree, ff_reason, tvb, offset, 2, pletohs (temp16));
530 dataptr = tvb_get_ptr (tvb, offset, 2);
531 temp16 = (guint16 *) dataptr;
532 proto_tree_add_uint (tree, ff_assoc_id, tvb, offset, 2, pletohs (temp16));
535 case FIELD_STATUS_CODE:
536 dataptr = tvb_get_ptr (tvb, offset, 2);
537 temp16 = (guint16 *) dataptr;
538 proto_tree_add_uint (tree, ff_status_code, tvb, offset, 2,
545 /* ************************************************************************* */
546 /* Dissect and add tagged (optional) fields to proto tree */
547 /* ************************************************************************* */
549 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
551 const guint8 *tag_info_ptr;
552 const guint8 *tag_data_ptr;
553 guint32 tag_no, tag_len;
556 char out_buff[SHORT_STR];
559 tag_info_ptr = tvb_get_ptr (tvb, offset, 2);
560 tag_no = tag_info_ptr[0];
561 tag_len = tag_info_ptr[1];
563 tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
566 if ((tag_no >= 17) && (tag_no <= 31))
567 { /* Reserved for challenge text */
568 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
569 "Tag Number: %u (Reserved for challenge text)",
572 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
573 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
574 tag_len, "Not interpreted");
575 return (int) tag_len + 2;
578 /* Next See if tag is reserved - if true, skip it! */
579 if (((tag_no >= 7) && (tag_no <= 15))
580 || ((tag_no >= 32) && (tag_no <= 255)))
582 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
583 "Tag Number: %u (Reserved tag number)",
586 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
588 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
589 tag_len, "Not interpreted");
590 return (int) tag_len + 2;
594 switch (tag_info_ptr[0])
599 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
600 "Tag Number: %u (SSID parameter set)",
603 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
605 memset (out_buff, 0, SHORT_STR);
607 memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
608 out_buff[tag_len + 1] = 0;
610 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
617 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
618 "Tag Number: %u (Supported Rates)", tag_no);
620 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
622 memset (out_buff, 0, SHORT_STR);
623 strcpy (out_buff, "Supported rates: ");
624 n = strlen (out_buff);
626 for (i = 0; i < tag_len; i++)
628 n += snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
629 (tag_data_ptr[i] & 0x7F) * 0.5,
630 (tag_data_ptr[i] & 0x80) ? "(B)" : "");
632 snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
634 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
640 case TAG_FH_PARAMETER:
641 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
642 "Tag Number: %u (FH Parameter set)",
645 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
646 memset (out_buff, 0, SHORT_STR);
648 snprintf (out_buff, SHORT_STR,
649 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
650 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
651 tag_data_ptr[3], tag_data_ptr[4]);
653 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
659 case TAG_DS_PARAMETER:
660 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
661 "Tag Number: %u (DS Parameter set)",
664 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
665 memset (out_buff, 0, SHORT_STR);
667 snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
668 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
673 case TAG_CF_PARAMETER:
674 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
675 "Tag Number: %u (CF Parameter set)",
678 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
679 memset (out_buff, 0, SHORT_STR);
681 snprintf (out_buff, SHORT_STR,
682 "CFP count %u, CFP period %u, CFP max duration %u, "
683 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
684 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
686 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
692 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
693 "Tag Number: %u ((TIM) Traffic Indication Map)",
696 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
697 memset (out_buff, 0, SHORT_STR);
698 snprintf (out_buff, SHORT_STR,
699 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
700 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
702 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
708 case TAG_IBSS_PARAMETER:
709 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
710 "Tag Number: %u (IBSS Parameter set)",
713 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
714 memset (out_buff, 0, SHORT_STR);
715 snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
716 pletohs (tag_data_ptr));
718 proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
724 case TAG_CHALLENGE_TEXT:
725 proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
726 "Tag Number: %u (Challenge text)", tag_no);
728 proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
729 memset (out_buff, 0, SHORT_STR);
730 snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
731 proto_tree_add_string (tree, tag_interpretation, tvb, offset, tag_len,
744 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
746 if (check_col(pinfo->fd, COL_RES_DL_SRC))
747 col_add_fstr(pinfo->fd, COL_RES_DL_SRC, "%s (%s)",
748 get_ether_name(addr), type);
749 if (check_col(pinfo->fd, COL_UNRES_DL_SRC))
750 col_add_fstr(pinfo->fd, COL_UNRES_DL_SRC, "%s (%s)",
751 ether_to_str(addr), type);
755 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
757 if (check_col(pinfo->fd, COL_RES_DL_DST))
758 col_add_fstr(pinfo->fd, COL_RES_DL_DST, "%s (%s)",
759 get_ether_name(addr), type);
760 if (check_col(pinfo->fd, COL_UNRES_DL_DST))
761 col_add_fstr(pinfo->fd, COL_UNRES_DL_DST, "%s (%s)",
762 ether_to_str(addr), type);
765 /* ************************************************************************* */
766 /* Dissect 802.11 frame */
767 /* ************************************************************************* */
769 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
772 const guint8 *src = NULL, *dst = NULL;
774 proto_item *flag_item;
776 static proto_tree *hdr_tree;
777 static proto_tree *flag_tree;
778 static proto_tree *fixed_tree;
779 static proto_tree *tagged_tree;
780 static proto_tree *fc_tree;
781 guint16 cap_len, hdr_len;
786 int tagged_parameter_tree_len;
788 if (check_col (pinfo->fd, COL_PROTOCOL))
789 col_set_str (pinfo->fd, COL_PROTOCOL, "IEEE 802.11");
790 if (check_col (pinfo->fd, COL_INFO))
791 col_clear (pinfo->fd, COL_INFO);
793 cap_len = tvb_length(tvb);
794 fcf = tvb_get_letohs (tvb, 0);
795 hdr_len = find_header_length (fcf);
797 /* Add the FC to the current tree */
800 ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
801 "IEEE 802.11 Header");
802 hdr_tree = proto_item_add_subtree (ti, ett_80211);
804 fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
806 "Frame Control: 0x%04X",
809 fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
812 proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
813 COOK_PROT_VERSION (fcf));
815 proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
816 COOK_FRAME_TYPE (fcf));
818 proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
820 COOK_FRAME_SUBTYPE (fcf));
822 flags = COOK_FLAGS (fcf);
825 proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
826 flags, "Flags: 0x%X", flags);
828 flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
830 proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
831 COOK_DS_STATUS (flags));
833 proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
836 proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
838 proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
840 proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
843 proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
845 proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
847 if ((COMPOSE_FRAME_TYPE(fcf))==CTRL_PS_POLL)
848 proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
849 COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
852 proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
853 tvb_get_letohs (tvb, 2));
856 /* Perform tasks which are common to a certain frame type */
857 switch (COOK_FRAME_TYPE (fcf))
860 case MGT_FRAME: /* All management frames share a common header */
861 src = tvb_get_ptr (tvb, 10, 6);
862 dst = tvb_get_ptr (tvb, 4, 6);
864 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
865 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
866 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
867 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
871 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
872 tvb_get_ptr (tvb, 4, 6));
874 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
875 tvb_get_ptr (tvb, 10, 6));
877 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
878 tvb_get_ptr (tvb, 16, 6));
880 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
881 COOK_FRAGMENT_NUMBER (tvb_get_letohs
884 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
885 COOK_SEQUENCE_NUMBER (tvb_get_letohs
887 cap_len = cap_len - MGT_FRAME_LEN - 4;
899 addr_type = COOK_ADDR_SELECTOR (fcf);
901 /* In order to show src/dst address we must always do the following */
906 src = tvb_get_ptr (tvb, 10, 6);
907 dst = tvb_get_ptr (tvb, 4, 6);
912 src = tvb_get_ptr (tvb, 16, 6);
913 dst = tvb_get_ptr (tvb, 4, 6);
918 src = tvb_get_ptr (tvb, 10, 6);
919 dst = tvb_get_ptr (tvb, 16, 6);
924 src = tvb_get_ptr (tvb, 24, 6);
925 dst = tvb_get_ptr (tvb, 16, 6);
929 SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
930 SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
931 SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
932 SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
934 /* Now if we have a tree we start adding stuff */
943 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
944 tvb_get_ptr (tvb, 4, 6));
945 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
946 tvb_get_ptr (tvb, 10, 6));
947 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
948 tvb_get_ptr (tvb, 16, 6));
949 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
950 COOK_FRAGMENT_NUMBER (tvb_get_letohs
952 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
953 COOK_SEQUENCE_NUMBER (tvb_get_letohs
959 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6,
960 tvb_get_ptr (tvb, 4, 6));
961 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
962 tvb_get_ptr (tvb, 10, 6));
963 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6,
964 tvb_get_ptr (tvb, 16, 6));
965 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
966 COOK_FRAGMENT_NUMBER (tvb_get_letohs
968 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
969 COOK_SEQUENCE_NUMBER (tvb_get_letohs
975 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
976 tvb_get_ptr (tvb, 4, 6));
977 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6,
978 tvb_get_ptr (tvb, 10, 6));
979 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
980 tvb_get_ptr (tvb, 16, 6));
981 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
982 COOK_FRAGMENT_NUMBER (tvb_get_letohs
984 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
985 COOK_SEQUENCE_NUMBER (tvb_get_letohs
991 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
992 tvb_get_ptr (tvb, 4, 6));
993 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
994 tvb_get_ptr (tvb, 10, 6));
995 proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6,
996 tvb_get_ptr (tvb, 16, 6));
997 proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
998 COOK_FRAGMENT_NUMBER (tvb_get_letohs
1000 proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1001 COOK_SEQUENCE_NUMBER (tvb_get_letohs
1003 proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6,
1004 tvb_get_ptr (tvb, 24, 6));
1013 switch (COMPOSE_FRAME_TYPE (fcf))
1017 COL_SHOW_INFO_CONST (pinfo->fd, "Association Request");
1020 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 4);
1021 add_fixed_field (fixed_tree, tvb, MGT_FRAME_HDR_LEN,
1023 add_fixed_field (fixed_tree, tvb, MGT_FRAME_HDR_LEN + 2,
1026 next_idx = MGT_FRAME_HDR_LEN + 4; /* Size of fixed fields */
1027 tagged_parameter_tree_len =
1028 tvb_reported_length_remaining(tvb, next_idx + 4);
1029 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1030 tagged_parameter_tree_len);
1032 while (tagged_parameter_tree_len > 0) {
1033 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1035 next_idx +=next_len;
1036 tagged_parameter_tree_len -= next_len;
1043 case MGT_ASSOC_RESP:
1044 COL_SHOW_INFO_CONST (pinfo->fd, "Association Response");
1048 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 6);
1049 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
1050 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1052 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1055 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;
1072 case MGT_REASSOC_REQ:
1073 COL_SHOW_INFO_CONST (pinfo->fd, "Reassociation Request");
1076 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 10);
1077 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
1078 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1080 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1081 FIELD_CURRENT_AP_ADDR);
1083 next_idx = MGT_FRAME_LEN + 10; /* Size of fixed fields */
1084 tagged_parameter_tree_len =
1085 tvb_reported_length_remaining(tvb, next_idx + 4);
1086 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1087 tagged_parameter_tree_len);
1089 while (tagged_parameter_tree_len > 0) {
1090 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1092 next_idx +=next_len;
1093 tagged_parameter_tree_len -= next_len;
1098 case MGT_REASSOC_RESP:
1099 COL_SHOW_INFO_CONST (pinfo->fd, "Reassociation Response");
1102 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 10);
1103 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_CAP_INFO);
1104 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1106 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1109 next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
1110 tagged_parameter_tree_len =
1111 tvb_reported_length_remaining(tvb, next_idx + 4);
1112 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1113 tagged_parameter_tree_len);
1115 while (tagged_parameter_tree_len > 0) {
1116 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1118 next_idx +=next_len;
1119 tagged_parameter_tree_len -= next_len;
1126 COL_SHOW_INFO_CONST (pinfo->fd, "Probe Request");
1129 next_idx = MGT_FRAME_LEN;
1130 tagged_parameter_tree_len =
1131 tvb_reported_length_remaining(tvb, next_idx + 4);
1132 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1133 tagged_parameter_tree_len);
1135 while (tagged_parameter_tree_len > 0) {
1136 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1138 next_idx +=next_len;
1139 tagged_parameter_tree_len -= next_len;
1145 case MGT_PROBE_RESP:
1146 COL_SHOW_INFO_CONST (pinfo->fd, "Probe Response");
1149 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 12);
1150 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_TIMESTAMP);
1151 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 8,
1152 FIELD_BEACON_INTERVAL);
1153 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 10,
1156 next_idx = MGT_FRAME_LEN + 12; /* Size of fixed fields */
1157 tagged_parameter_tree_len =
1158 tvb_reported_length_remaining(tvb, next_idx + 4);
1159 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1160 tagged_parameter_tree_len);
1162 while (tagged_parameter_tree_len > 0) {
1163 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1165 next_idx +=next_len;
1166 tagged_parameter_tree_len -= next_len;
1172 case MGT_BEACON: /* Dissect protocol payload fields */
1173 COL_SHOW_INFO_CONST (pinfo->fd, "Beacon frame");
1177 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 12);
1179 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_TIMESTAMP);
1181 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 8,
1182 FIELD_BEACON_INTERVAL);
1183 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 10,
1186 next_idx = MGT_FRAME_LEN + 12; /* Size of fixed fields */
1187 tagged_parameter_tree_len =
1188 tvb_reported_length_remaining(tvb, next_idx + 4);
1189 tagged_tree = get_tagged_parameter_tree (tree, tvb, next_idx,
1190 tagged_parameter_tree_len);
1192 while (tagged_parameter_tree_len > 0) {
1193 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1195 next_idx +=next_len;
1196 tagged_parameter_tree_len -= next_len;
1204 COL_SHOW_INFO_CONST (pinfo->fd, "ATIM");
1211 COL_SHOW_INFO_CONST (pinfo->fd, "Dissassociate");
1214 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, cap_len);
1215 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_REASON_CODE);
1219 case MGT_AUTHENTICATION:
1220 COL_SHOW_INFO_CONST (pinfo->fd, "Authentication");
1221 if (IS_WEP(COOK_FLAGS(fcf)))
1223 int pkt_len = tvb_reported_length (tvb);
1224 int cap_len = tvb_length (tvb);
1227 get_wep_parameter_tree (tree, tvb, MGT_FRAME_LEN, pkt_len);
1228 pkt_len = MAX (pkt_len - 8 - MGT_FRAME_LEN, 0);
1229 cap_len = MIN (pkt_len, MAX (cap_len - 8 - MGT_FRAME_LEN, 0));
1230 next_tvb = tvb_new_subset (tvb, MGT_FRAME_LEN + 4, cap_len, pkt_len);
1231 dissect_data (next_tvb, 0, pinfo, tree);
1237 fixed_tree = get_fixed_parameter_tree (tree, tvb, MGT_FRAME_LEN, 6);
1238 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_AUTH_ALG);
1239 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 2,
1240 FIELD_AUTH_TRANS_SEQ);
1241 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN + 4,
1244 next_idx = MGT_FRAME_LEN + 6; /* Size of fixed fields */
1246 tagged_parameter_tree_len =
1247 tvb_reported_length_remaining(tvb, next_idx + 4);
1248 if (tagged_parameter_tree_len != 0)
1250 tagged_tree = get_tagged_parameter_tree (tree,
1253 tagged_parameter_tree_len);
1255 while (tagged_parameter_tree_len > 0) {
1256 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1258 next_idx +=next_len;
1259 tagged_parameter_tree_len -= next_len;
1266 case MGT_DEAUTHENTICATION:
1267 COL_SHOW_INFO_CONST (pinfo->fd, "Deauthentication");
1270 fixed_tree = get_fixed_parameter_tree (hdr_tree, tvb, MGT_FRAME_LEN, 2);
1271 add_fixed_field (fixed_tree, tvb, MGT_FRAME_LEN, FIELD_REASON_CODE);
1278 COL_SHOW_INFO_CONST (pinfo->fd, "Power-Save poll");
1280 src = tvb_get_ptr (tvb, 10, 6);
1281 dst = tvb_get_ptr (tvb, 4, 6);
1283 set_src_addr_cols(pinfo, src, "BSSID");
1284 set_dst_addr_cols(pinfo, dst, "BSSID");
1288 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1289 tvb_get_ptr (tvb, 4, 6));
1291 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1292 tvb_get_ptr (tvb, 10, 6));
1300 COL_SHOW_INFO_CONST (pinfo->fd, "Request-to-send");
1301 src = tvb_get_ptr (tvb, 10, 6);
1302 dst = tvb_get_ptr (tvb, 4, 6);
1304 set_src_addr_cols(pinfo, src, "TA");
1305 set_dst_addr_cols(pinfo, dst, "RA");
1309 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1310 tvb_get_ptr (tvb, 4, 6));
1312 proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1313 tvb_get_ptr (tvb, 10, 6));
1321 COL_SHOW_INFO_CONST (pinfo->fd, "Clear-to-send");
1323 dst = tvb_get_ptr (tvb, 4, 6);
1325 set_dst_addr_cols(pinfo, dst, "RA");
1329 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1330 tvb_get_ptr (tvb, 4, 6));
1337 case CTRL_ACKNOWLEDGEMENT:
1338 COL_SHOW_INFO_CONST (pinfo->fd, "Acknowledgement");
1340 dst = tvb_get_ptr (tvb, 4, 6);
1342 set_dst_addr_cols(pinfo, dst, "RA");
1345 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1346 tvb_get_ptr (tvb, 4, 6));
1352 COL_SHOW_INFO_CONST (pinfo->fd, "CF-End (Control-frame)");
1354 src = tvb_get_ptr (tvb, 10, 6);
1355 dst = tvb_get_ptr (tvb, 4, 6);
1357 set_src_addr_cols(pinfo, src, "BSSID");
1358 set_dst_addr_cols(pinfo, dst, "RA");
1362 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1363 tvb_get_ptr (tvb, 4, 6));
1364 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1365 tvb_get_ptr (tvb, 10, 6));
1371 case CTRL_CFP_ENDACK:
1372 COL_SHOW_INFO_CONST (pinfo->fd, "CF-End + CF-Ack (Control-frame)");
1374 src = tvb_get_ptr (tvb, 10, 6);
1375 dst = tvb_get_ptr (tvb, 4, 6);
1377 set_src_addr_cols(pinfo, src, "BSSID");
1378 set_dst_addr_cols(pinfo, dst, "RA");
1382 proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1383 tvb_get_ptr (tvb, 4, 6));
1385 proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1386 tvb_get_ptr (tvb, 10, 6));
1393 COL_SHOW_INFO_CONST (pinfo->fd, "Data");
1395 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1397 if (IS_WEP(COOK_FLAGS(fcf)))
1399 int pkt_len = tvb_reported_length (next_tvb);
1400 int cap_len = tvb_length (next_tvb);
1403 get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
1404 pkt_len = MAX (pkt_len - 8, 0);
1405 cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
1406 next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
1407 dissect_data (next_tvb, 0, pinfo, tree);
1410 call_dissector (llc_handle, next_tvb, pinfo, tree);
1416 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Acknowledgement");
1418 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1420 if (IS_WEP(COOK_FLAGS(fcf)))
1422 int pkt_len = tvb_reported_length (next_tvb);
1423 int cap_len = tvb_length (next_tvb);
1426 get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
1427 pkt_len = MAX (pkt_len - 8, 0);
1428 cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
1429 next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
1430 dissect_data (next_tvb, 0, pinfo, tree);
1433 call_dissector (llc_handle, next_tvb, pinfo, tree);
1439 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Poll");
1440 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1442 if (IS_WEP(COOK_FLAGS(fcf)))
1444 int pkt_len = tvb_reported_length (next_tvb);
1445 int cap_len = tvb_length (next_tvb);
1448 get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
1449 pkt_len = MAX (pkt_len - 8, 0);
1450 cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
1451 next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
1452 dissect_data (next_tvb, 0, pinfo, tree);
1455 call_dissector (llc_handle, next_tvb, pinfo, tree);
1460 case DATA_CF_ACK_POLL:
1461 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Acknowledgement/Poll");
1462 next_tvb = tvb_new_subset (tvb, hdr_len, -1, -1);
1464 if (IS_WEP(COOK_FLAGS(fcf)))
1466 int pkt_len = tvb_reported_length (next_tvb);
1467 int cap_len = tvb_length (next_tvb);
1470 get_wep_parameter_tree (tree, next_tvb, 0, pkt_len);
1471 pkt_len = MAX (pkt_len - 8, 0);
1472 cap_len = MIN (pkt_len, MAX (cap_len - 8, 0));
1473 next_tvb = tvb_new_subset (tvb, hdr_len + 4, cap_len, pkt_len);
1474 dissect_data (next_tvb, 0, pinfo, tree);
1477 call_dissector (llc_handle, next_tvb, pinfo, tree);
1482 case DATA_NULL_FUNCTION:
1483 COL_SHOW_INFO_CONST (pinfo->fd, "Null function (No data)");
1487 case DATA_CF_ACK_NOD:
1488 COL_SHOW_INFO_CONST (pinfo->fd, "Data + Acknowledgement (No data)");
1492 case DATA_CF_POLL_NOD:
1493 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Poll (No data)");
1497 case DATA_CF_ACK_POLL_NOD:
1498 COL_SHOW_INFO_CONST (pinfo->fd, "Data + CF-Acknowledgement/Poll (No data)");
1503 COL_SHOW_INFO_CONST (pinfo->fd, "Unrecognized (Reserved frame)");
1510 proto_register_wlan (void)
1513 static const value_string tofrom_ds[] = {
1514 {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
1515 {1, "Frame is exiting DS (To DS: 0 From DS: 1)"},
1516 {2, "Frame is entering DS (To DS: 1 From DS: 0)"},
1517 {3, "Frame part of WDS (To DS: 1 From DS: 1)"},
1521 static const true_false_string tods_flag = {
1522 "TO DS: Should be false",
1526 static const true_false_string fromds_flag = {
1527 "FROM DS: Should be false",
1531 static const true_false_string more_frags = {
1532 "MSDU/MMPDU is fragmented",
1536 static const true_false_string retry_flags = {
1537 "Frame is being retransmitted",
1538 "Frame is not being retransmitted"
1541 static const true_false_string pm_flags = {
1542 "STA will go to sleep",
1546 static const true_false_string md_flags = {
1547 "Data is buffered for STA at AP",
1551 static const true_false_string wep_flags = {
1556 static const true_false_string order_flags = {
1558 "Not strictly ordered"
1561 static const true_false_string cf_ess_flags = {
1562 "Transmitter is an AP",
1563 "Transmitter is a STA"
1567 static const true_false_string cf_privacy_flags = {
1568 "AP/STA can support WEP",
1569 "AP/STA cannot support WEP"
1572 static const true_false_string cf_preamble_flags = {
1573 "Short preamble allowed",
1574 "Short preamble not allowed"
1577 static const true_false_string cf_pbcc_flags = {
1578 "PBCC modulation allowed",
1579 "PBCC modulation not allowed"
1582 static const true_false_string cf_agility_flags = {
1583 "Channel agility in use",
1584 "Channel agility not in use"
1588 static const true_false_string cf_ibss_flags = {
1589 "Transmitter belongs to an IBSS",
1590 "Transmitter belongs to a BSS"
1593 static const value_string sta_cf_pollable[] = {
1594 {0x00, "Station is not CF-Pollable"},
1595 {0x02, "Station is CF-Pollable, "
1596 "not requesting to be placed on the CF-polling list"},
1597 {0x01, "Station is CF-Pollable, "
1598 "requesting to be placed on the CF-polling list"},
1599 {0x03, "Station is CF-Pollable, requesting never to be polled"},
1603 static const value_string ap_cf_pollable[] = {
1604 {0x00, "No point coordinator at AP"},
1605 {0x02, "Point coordinator at AP for delivery only (no polling)"},
1606 {0x01, "Point coordinator at AP for delivery and polling"},
1612 static const value_string auth_alg[] = {
1613 {0x00, "Open System"},
1614 {0x01, "Shared key"},
1618 static const value_string reason_codes[] = {
1620 {0x01, "Unspecified reason"},
1621 {0x02, "Previous authentication no longer valid"},
1622 {0x03, "Deauthenticated because sending STA is leaving (has left) "
1624 {0x04, "Disassociated due to inactivity"},
1625 {0x05, "Disassociated because AP is unable to handle all currently "
1626 "associated stations"},
1627 {0x06, "Class 2 frame received from nonauthenticated station"},
1628 {0x07, "Class 3 frame received from nonassociated station"},
1629 {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
1630 {0x09, "Station requesting (re)association is not authenticated with "
1631 "responding station"},
1636 static const value_string status_codes[] = {
1637 {0x00, "Successful"},
1638 {0x01, "Unspecified failure"},
1639 {0x0A, "Cannot support all requested capabilities in the "
1640 "Capability information field"},
1641 {0x0B, "Reassociation denied due to inability to confirm that "
1642 "association exists"},
1643 {0x0C, "Association denied due to reason outside the scope of this "
1646 {0x0D, "Responding station does not support the specified authentication "
1648 {0x0E, "Received an Authentication frame with authentication sequence "
1649 "transaction sequence number out of expected sequence"},
1650 {0x0F, "Authentication rejected because of challenge failure"},
1651 {0x10, "Authentication rejected due to timeout waiting for next "
1652 "frame in sequence"},
1653 {0x11, "Association denied because AP is unable to handle additional "
1654 "associated stations"},
1655 {0x12, "Association denied due to requesting station not supporting all "
1656 "of the datarates in the BSSBasicServiceSet Parameter"},
1662 static hf_register_info hf[] = {
1664 {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
1665 "MAC Frame control", HFILL }},
1667 {&hf_fc_proto_version,
1668 {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
1669 "MAC Protocol version", HFILL }}, /* 0 */
1672 {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, NULL, 0,
1673 "Frame type", HFILL }},
1675 {&hf_fc_frame_subtype,
1676 {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
1677 "Frame subtype", HFILL }}, /* 2 */
1680 {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
1681 "Protocol flags", HFILL }},
1684 {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
1685 "Data-frame DS-traversal status", HFILL }}, /* 3 */
1688 {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), 0x1,
1689 "To DS flag", HFILL }}, /* 4 */
1692 {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), 0x2,
1693 "From DS flag", HFILL }}, /* 5 */
1696 {"Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), 0x4,
1697 "More Fragments flag", HFILL }}, /* 6 */
1700 {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), 0x8,
1701 "Retransmission flag", HFILL }},
1704 {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), 0x10,
1705 "Power management status", HFILL }},
1708 {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), 0x20,
1709 "More data flag", HFILL }},
1712 {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), 0x40,
1713 "WEP flag", HFILL }},
1716 {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), 0x80,
1717 "Strictly ordered flag", HFILL }},
1720 {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
1721 "Association-ID field", HFILL }},
1724 {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
1725 "Duration field", HFILL }},
1728 {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
1729 "Destination Hardware address", HFILL }},
1732 {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
1733 "Source Hardware address", HFILL }},
1736 {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
1737 "Receiving Station Hardware Address", HFILL }},
1740 {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
1741 "Transmitting Station Hardware Address", HFILL }},
1744 {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
1745 "Basic Service Set ID", HFILL }},
1748 {"Fragment number", "wlan.frag", FT_UINT16, BASE_HEX, NULL, 0,
1749 "Fragment number", HFILL }},
1752 {"Sequence number", "wlan.seq", FT_UINT16, BASE_HEX, NULL, 0,
1753 "Fragment number", HFILL }},
1756 {"Frame Check Sequence (not verified)", "wlan.fcs", FT_UINT32, BASE_HEX,
1757 NULL, 0, "", HFILL }},
1760 {"Timestamp", "wlan.fixed.timestamp", FT_STRING, BASE_NONE,
1761 NULL, 0, "", HFILL }},
1764 {"Authentication Algorithm", "wlan.fixed.auth.alg",
1765 FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
1767 {&ff_beacon_interval,
1768 {"Beacon Interval", "wlan.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
1771 {&hf_fixed_parameters,
1772 {"Fixed parameters", "wlan.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
1775 {&hf_tagged_parameters,
1776 {"Tagged parameters", "wlan.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
1779 {&hf_wep_parameters,
1780 {"WEP parameters", "wlan.wep.all", FT_STRING, BASE_NONE, NULL, 0,
1784 {"Initialization Vector", "wlan.wep.iv", FT_UINT32, BASE_HEX, NULL, 0,
1785 "Initialization Vector", HFILL }},
1788 {"Key", "wlan.wep.key", FT_UINT32, BASE_DEC, NULL, 0,
1792 {"WEP CRC (not verified)", "wlan.wep.crc", FT_UINT32, BASE_HEX, NULL, 0,
1793 "WEP CRC", HFILL }},
1796 {"Capabilities", "wlan.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
1797 "Capability information", HFILL }},
1800 {"CFP participation capabilities", "wlan.fixed.capabilities.cfpoll.sta",
1801 FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0,
1802 "CF-Poll capabilities for a STA", HFILL }},
1805 {"CFP participation capabilities", "wlan.fixed.capabilities.cfpoll.ap",
1806 FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0,
1807 "CF-Poll capabilities for an AP", HFILL }},
1810 {"ESS capabilities", "wlan.fixed.capabilities.ess",
1811 FT_BOOLEAN, 8, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
1815 {"IBSS status", "wlan.fixed.capabilities.ibss",
1816 FT_BOOLEAN, 8, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
1819 {"Privacy", "wlan.fixed.capabilities.privacy",
1820 FT_BOOLEAN, 8, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
1823 {"Short Preamble", "wlan.fixed.capabilities.preamble",
1824 FT_BOOLEAN, 8, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
1827 {"PBCC", "wlan.fixed.capabilities.pbcc",
1828 FT_BOOLEAN, 8, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
1831 {"Channel Agility", "wlan.fixed.capabilities.agility",
1832 FT_BOOLEAN, 8, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
1836 {"Authentication SEQ", "wlan.fixed.auth_seq",
1837 FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
1840 {"Association ID", "wlan.fixed.aid",
1841 FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
1844 {"Listen Interval", "wlan.fixed.listen_ival",
1845 FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
1848 {"Current AP", "wlan.fixed.current_ap",
1849 FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
1852 {"Reason code", "wlan.fixed.reason_code",
1853 FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
1854 "Reason for unsolicited notification", HFILL }},
1857 {"Status code", "wlan.fixed.status_code",
1858 FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
1859 "Status of requested event", HFILL }},
1862 {"Tag", "wlan.tag.number",
1863 FT_UINT16, BASE_DEC, NULL, 0,
1864 "Element ID", HFILL }},
1867 {"Tag length", "wlan.tag.length",
1868 FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
1870 {&tag_interpretation,
1871 {"Tag interpretation", "wlan.tag.interpretation",
1872 FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
1878 static gint *tree_array[] = { &ett_80211,
1881 &ett_fixed_parameters,
1882 &ett_tagged_parameters,
1883 &ett_wep_parameters,
1887 proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
1888 "IEEE 802.11", "wlan");
1889 proto_register_field_array (proto_wlan, hf, array_length (hf));
1890 proto_register_subtree_array (tree_array, array_length (tree_array));
1894 proto_reg_handoff_wlan(void)
1897 * Get a handle for the LLC dissector.
1899 llc_handle = find_dissector("llc");
1901 dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, dissect_ieee80211,