dd7a5dc30189049a0a8dae7890d0263a37affb58
[obnox/wireshark/wip.git] / packet-ieee80211.c
1 /* packet-ieee80211.c
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
5  *
6  * $Id: packet-ieee80211.c,v 1.93 2003/08/26 05:09:56 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from README.developer
13  *
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.
18  *
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.
23  *
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.
27  *
28  * Credits:
29  *
30  * The following people helped me by pointing out bugs etc. Thank you!
31  *
32  * Marco Molteni
33  * Lena-Marie Nilsson
34  * Magnus Hultman-Persson
35  */
36
37 #ifdef HAVE_CONFIG_H
38 # include "config.h"
39 #endif
40
41 #include <stdio.h>
42 #include <stdlib.h>
43
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
46 #endif
47
48 #include <string.h>
49 #include <glib.h>
50 #include <epan/bitswap.h>
51 #include <epan/proto.h>
52 #include <epan/packet.h>
53 #include <epan/resolv.h>
54 #include "prefs.h"
55 #include "reassemble.h"
56 #include "packet-ipx.h"
57 #include "packet-llc.h"
58 #include "packet-ieee80211.h"
59 #include "etypes.h"
60 #include "crc32.h"
61
62 /* Defragment fragmented 802.11 datagrams */
63 static gboolean wlan_defragment = TRUE;
64
65 /* Check for the presence of the 802.11 FCS */
66 static gboolean wlan_check_fcs = FALSE;
67
68 /* Ignore the WEP bit; assume packet is decrypted */
69 static gboolean wlan_ignore_wep = FALSE;
70
71 /* Tables for reassembly of fragments. */
72 static GHashTable *wlan_fragment_table = NULL;
73 static GHashTable *wlan_reassembled_table = NULL;
74
75 /* Stuff for the WEP decoder */
76 static guint num_wepkeys = 0;
77 static guint8 **wep_keys = NULL;
78 static int *wep_keylens = NULL;
79 static void init_wepkeys(void);
80 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
81 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
82 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
83
84 /* #define USE_ENV */
85 /* When this is set, an unlimited number of WEP keys can be set in the
86    environment:
87
88    ETHEREAL_WEPKEYNUM=##
89    ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
90    ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
91
92    ... you get the idea.
93
94    otherwise you're limited to specifying four keys in the preference system.
95  */
96
97 #ifndef USE_ENV
98 static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
99 #endif
100
101 /* ************************************************************************* */
102 /*                          Miscellaneous Constants                          */
103 /* ************************************************************************* */
104 #define SHORT_STR 256
105
106 /* ************************************************************************* */
107 /*  Define some very useful macros that are used to analyze frame types etc. */
108 /* ************************************************************************* */
109 #define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4))      /* Create key to (sub)type */
110 #define COOK_PROT_VERSION(x)  ((x) & 0x3)
111 #define COOK_FRAME_TYPE(x)    (((x) & 0xC) >> 2)
112 #define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
113 #define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
114 #define COOK_ASSOC_ID(x)      ((x) & 0x3FFF)
115 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
116 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
117 #define COOK_FLAGS(x)           (((x) & 0xFF00) >> 8)
118 #define COOK_DS_STATUS(x)       ((x) & 0x3)
119 #define COOK_WEP_KEY(x)       (((x) & 0xC0) >> 6)
120
121 #define FLAG_TO_DS              0x01
122 #define FLAG_FROM_DS            0x02
123 #define FLAG_MORE_FRAGMENTS     0x04
124 #define FLAG_RETRY              0x08
125 #define FLAG_POWER_MGT          0x10
126 #define FLAG_MORE_DATA          0x20
127 #define FLAG_WEP                0x40
128 #define FLAG_ORDER              0x80
129
130 #define IS_TO_DS(x)            ((x) & FLAG_TO_DS)
131 #define IS_FROM_DS(x)          ((x) & FLAG_FROM_DS)
132 #define HAVE_FRAGMENTS(x)      ((x) & FLAG_MORE_FRAGMENTS)
133 #define IS_RETRY(x)            ((x) & FLAG_RETRY)
134 #define POWER_MGT_STATUS(x)    ((x) & FLAG_POWER_MGT)
135 #define HAS_MORE_DATA(x)       ((x) & FLAG_MORE_DATA)
136 #define IS_WEP(x)              (!wlan_ignore_wep && ((x) & FLAG_WEP))
137 #define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
138
139 #define MGT_RESERVED_RANGE(x)  (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
140 #define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
141 #define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
142 #define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
143
144
145 /* ************************************************************************* */
146 /*              Constants used to identify cooked frame types                */
147 /* ************************************************************************* */
148 #define MGT_FRAME            0x00       /* Frame type is management */
149 #define CONTROL_FRAME        0x01       /* Frame type is control */
150 #define DATA_FRAME           0x02       /* Frame type is Data */
151
152 #define DATA_SHORT_HDR_LEN     24
153 #define DATA_LONG_HDR_LEN      30
154 #define MGT_FRAME_HDR_LEN      24       /* Length of Managment frame-headers */
155
156 #define MGT_ASSOC_REQ        0x00       /* Management - association request        */
157 #define MGT_ASSOC_RESP       0x01       /* Management - association response       */
158 #define MGT_REASSOC_REQ      0x02       /* Management - reassociation request      */
159 #define MGT_REASSOC_RESP     0x03       /* Management - reassociation response     */
160 #define MGT_PROBE_REQ        0x04       /* Management - Probe request              */
161 #define MGT_PROBE_RESP       0x05       /* Management - Probe response             */
162 #define MGT_BEACON           0x08       /* Management - Beacon frame               */
163 #define MGT_ATIM             0x09       /* Management - ATIM                       */
164 #define MGT_DISASS           0x0A       /* Management - Disassociation             */
165 #define MGT_AUTHENTICATION   0x0B       /* Management - Authentication             */
166 #define MGT_DEAUTHENTICATION 0x0C       /* Management - Deauthentication           */
167
168 #define CTRL_PS_POLL         0x1A       /* Control - power-save poll               */
169 #define CTRL_RTS             0x1B       /* Control - request to send               */
170 #define CTRL_CTS             0x1C       /* Control - clear to send                 */
171 #define CTRL_ACKNOWLEDGEMENT 0x1D       /* Control - acknowledgement               */
172 #define CTRL_CFP_END         0x1E       /* Control - contention-free period end    */
173 #define CTRL_CFP_ENDACK      0x1F       /* Control - contention-free period end/ack */
174
175 #define DATA                 0x20       /* Data - Data                             */
176 #define DATA_CF_ACK          0x21       /* Data - Data + CF acknowledge            */
177 #define DATA_CF_POLL         0x22       /* Data - Data + CF poll                   */
178 #define DATA_CF_ACK_POLL     0x23       /* Data - Data + CF acknowledge + CF poll  */
179 #define DATA_NULL_FUNCTION   0x24       /* Data - Null function (no data)          */
180 #define DATA_CF_ACK_NOD      0x25       /* Data - CF ack (no data)                 */
181 #define DATA_CF_POLL_NOD     0x26       /* Data - Data + CF poll (No data)         */
182 #define DATA_CF_ACK_POLL_NOD 0x27       /* Data - CF ack + CF poll (no data)       */
183
184 #define DATA_ADDR_T1         0
185 #define DATA_ADDR_T2         (FLAG_FROM_DS << 8)
186 #define DATA_ADDR_T3         (FLAG_TO_DS << 8)
187 #define DATA_ADDR_T4         ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
188
189
190 /* ************************************************************************* */
191 /*          Macros used to extract information about fixed fields            */
192 /* ************************************************************************* */
193 #define ESS_SET(x) ((x) & 0x0001)
194 #define IBSS_SET(x) ((x) & 0x0002)
195
196
197
198 /* ************************************************************************* */
199 /*        Logical field codes (dissector's encoding of fixed fields)         */
200 /* ************************************************************************* */
201 #define FIELD_TIMESTAMP       0x01      /* 64-bit timestamp                       */
202 #define FIELD_BEACON_INTERVAL 0x02      /* 16-bit beacon interval                 */
203 #define FIELD_CAP_INFO        0x03      /* Add capability information tree        */
204 #define FIELD_AUTH_ALG        0x04      /* Authentication algorithm used          */
205 #define FIELD_AUTH_TRANS_SEQ  0x05      /* Authentication sequence number         */
206 #define FIELD_CURRENT_AP_ADDR 0x06
207 #define FIELD_LISTEN_IVAL     0x07
208 #define FIELD_REASON_CODE     0x08
209 #define FIELD_ASSOC_ID        0x09
210 #define FIELD_STATUS_CODE     0x0A
211
212 /* ************************************************************************* */
213 /*        Logical field codes (IEEE 802.11 encoding of tags)                 */
214 /* ************************************************************************* */
215 #define TAG_SSID           0x00
216 #define TAG_SUPP_RATES     0x01
217 #define TAG_FH_PARAMETER   0x02
218 #define TAG_DS_PARAMETER   0x03
219 #define TAG_CF_PARAMETER   0x04
220 #define TAG_TIM            0x05
221 #define TAG_IBSS_PARAMETER 0x06
222 #define TAG_CHALLENGE_TEXT 0x10
223 #define TAG_ERP_INFO       0x2A
224 #define TAG_ERP_INFO_OLD   0x2F /* IEEE Std 802.11g/D4.0 */
225 #define TAG_EXT_SUPP_RATES 0x32
226 #define TAG_VENDOR_SPECIFIC_IE     0xDD
227
228 #define WPA_OUI "\x00\x50\xF2"
229
230 /* ************************************************************************* */
231 /*                         Frame types, and their names                      */
232 /* ************************************************************************* */
233 static const value_string frame_type_subtype_vals[] = {
234         {MGT_ASSOC_REQ,        "Association Request"},
235         {MGT_ASSOC_RESP,       "Association Response"},
236         {MGT_REASSOC_REQ,      "Reassociation Request"},
237         {MGT_REASSOC_RESP,     "Reassociation Response"},
238         {MGT_PROBE_REQ,        "Probe Request"},
239         {MGT_PROBE_RESP,       "Probe Response"},
240         {MGT_BEACON,           "Beacon frame"},
241         {MGT_ATIM,             "ATIM"},
242         {MGT_DISASS,           "Dissassociate"},
243         {MGT_AUTHENTICATION,   "Authentication"},
244         {MGT_DEAUTHENTICATION, "Deauthentication"},
245         {CTRL_PS_POLL,         "Power-Save poll"},
246         {CTRL_RTS,             "Request-to-send"},
247         {CTRL_CTS,             "Clear-to-send"},
248         {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
249         {CTRL_CFP_END,         "CF-End (Control-frame)"},
250         {CTRL_CFP_ENDACK,      "CF-End + CF-Ack (Control-frame)"},
251         {DATA,                 "Data"},
252         {DATA_CF_ACK,          "Data + CF-Acknowledgement"},
253         {DATA_CF_POLL,         "Data + CF-Poll"},
254         {DATA_CF_ACK_POLL,     "Data + CF-Acknowledgement/Poll"},
255         {DATA_NULL_FUNCTION,   "Null function (No data)"},
256         {DATA_CF_ACK_NOD,      "Data + Acknowledgement (No data)"},
257         {DATA_CF_POLL_NOD,     "Data + CF-Poll (No data)"},
258         {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
259         {0,                    NULL}
260 };
261
262 static int proto_wlan = -1;
263
264 /* ************************************************************************* */
265 /*                Header field info values for radio information             */
266 /* ************************************************************************* */
267 static int hf_data_rate = -1;
268 static int hf_channel = -1;
269 static int hf_signal_strength = -1;
270
271 /* ************************************************************************* */
272 /*                Header field info values for FC-field                      */
273 /* ************************************************************************* */
274 static int hf_fc_field = -1;
275 static int hf_fc_proto_version = -1;
276 static int hf_fc_frame_type = -1;
277 static int hf_fc_frame_subtype = -1;
278 static int hf_fc_frame_type_subtype = -1;
279
280 static int hf_fc_flags = -1;
281 static int hf_fc_to_ds = -1;
282 static int hf_fc_from_ds = -1;
283 static int hf_fc_data_ds = -1;
284
285 static int hf_fc_more_frag = -1;
286 static int hf_fc_retry = -1;
287 static int hf_fc_pwr_mgt = -1;
288 static int hf_fc_more_data = -1;
289 static int hf_fc_wep = -1;
290 static int hf_fc_order = -1;
291
292
293 /* ************************************************************************* */
294 /*                   Header values for Duration/ID field                     */
295 /* ************************************************************************* */
296 static int hf_did_duration = -1;
297 static int hf_assoc_id = -1;
298
299
300 /* ************************************************************************* */
301 /*         Header values for different address-fields (all 4 of them)        */
302 /* ************************************************************************* */
303 static int hf_addr_da = -1;     /* Destination address subfield */
304 static int hf_addr_sa = -1;     /* Source address subfield */
305 static int hf_addr_ra = -1;     /* Receiver address subfield */
306 static int hf_addr_ta = -1;     /* Transmitter address subfield */
307 static int hf_addr_bssid = -1;  /* address is bssid */
308
309 static int hf_addr = -1;        /* Source or destination address subfield */
310
311
312 /* ************************************************************************* */
313 /*                Header values for sequence number field                    */
314 /* ************************************************************************* */
315 static int hf_frag_number = -1;
316 static int hf_seq_number = -1;
317
318 /* ************************************************************************* */
319 /*                   Header values for Frame Check field                     */
320 /* ************************************************************************* */
321 static int hf_fcs = -1;
322
323 /* ************************************************************************* */
324 /*                   Header values for reassembly                            */
325 /* ************************************************************************* */
326 static int hf_fragments = -1;
327 static int hf_fragment = -1;
328 static int hf_fragment_overlap = -1;
329 static int hf_fragment_overlap_conflict = -1;
330 static int hf_fragment_multiple_tails = -1;
331 static int hf_fragment_too_long_fragment = -1;
332 static int hf_fragment_error = -1;
333 static int hf_reassembled_in = -1;
334
335
336 static int proto_wlan_mgt = -1;
337 /* ************************************************************************* */
338 /*                      Fixed fields found in mgt frames                     */
339 /* ************************************************************************* */
340 static int ff_auth_alg = -1;    /* Authentication algorithm field            */
341 static int ff_auth_seq = -1;    /* Authentication transaction sequence       */
342 static int ff_current_ap = -1;  /* Current AP MAC address                    */
343 static int ff_listen_ival = -1; /* Listen interval fixed field               */
344 static int ff_timestamp = -1;   /* 64 bit timestamp                          */
345 static int ff_beacon_interval = -1;     /* 16 bit Beacon interval            */
346 static int ff_assoc_id = -1;    /* 16 bit AID field                          */
347 static int ff_reason = -1;      /* 16 bit reason code                        */
348 static int ff_status_code = -1; /* Status code                               */
349
350 /* ************************************************************************* */
351 /*            Flags found in the capability field (fixed field)              */
352 /* ************************************************************************* */
353 static int ff_capture = -1;
354 static int ff_cf_ess = -1;
355 static int ff_cf_ibss = -1;
356 static int ff_cf_sta_poll = -1; /* CF pollable status for a STA            */
357 static int ff_cf_ap_poll = -1;  /* CF pollable status for an AP            */
358 static int ff_cf_privacy = -1;
359 static int ff_cf_preamble = -1;
360 static int ff_cf_pbcc = -1;
361 static int ff_cf_agility = -1;
362 static int ff_short_slot_time = -1;
363 static int ff_dsss_ofdm = -1;
364
365 /* ************************************************************************* */
366 /*                       Tagged value format fields                          */
367 /* ************************************************************************* */
368 static int tag_number = -1;
369 static int tag_length = -1;
370 static int tag_interpretation = -1;
371
372
373
374 static int hf_fixed_parameters = -1;    /* Protocol payload for management frames */
375 static int hf_tagged_parameters = -1;   /* Fixed payload item */
376 static int hf_wep_iv = -1;
377 static int hf_wep_key = -1;
378 static int hf_wep_icv = -1;
379
380 /* ************************************************************************* */
381 /*                               Protocol trees                              */
382 /* ************************************************************************* */
383 static gint ett_80211 = -1;
384 static gint ett_proto_flags = -1;
385 static gint ett_cap_tree = -1;
386 static gint ett_fc_tree = -1;
387 static gint ett_fragments = -1;
388 static gint ett_fragment = -1;
389
390 static gint ett_80211_mgt = -1;
391 static gint ett_fixed_parameters = -1;
392 static gint ett_tagged_parameters = -1;
393 static gint ett_wep_parameters = -1;
394
395 static const fragment_items frag_items = {
396         &ett_fragment,
397         &ett_fragments,
398         &hf_fragments,
399         &hf_fragment,
400         &hf_fragment_overlap,
401         &hf_fragment_overlap_conflict,
402         &hf_fragment_multiple_tails,
403         &hf_fragment_too_long_fragment,
404         &hf_fragment_error,
405         &hf_reassembled_in,
406         "fragments"
407 };
408
409 static dissector_handle_t llc_handle;
410 static dissector_handle_t ipx_handle;
411 static dissector_handle_t data_handle;
412
413 /* ************************************************************************* */
414 /*            Return the length of the current header (in bytes)             */
415 /* ************************************************************************* */
416 static int
417 find_header_length (guint16 fcf)
418 {
419   switch (COOK_FRAME_TYPE (fcf)) {
420
421   case MGT_FRAME:
422     return MGT_FRAME_HDR_LEN;
423
424   case CONTROL_FRAME:
425     switch (COMPOSE_FRAME_TYPE (fcf)) {
426
427     case CTRL_CTS:
428     case CTRL_ACKNOWLEDGEMENT:
429       return 10;
430
431     case CTRL_RTS:
432     case CTRL_PS_POLL:
433     case CTRL_CFP_END:
434     case CTRL_CFP_ENDACK:
435       return 16;
436     }
437     return 4;   /* XXX */
438
439   case DATA_FRAME:
440     return (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
441                                                        DATA_SHORT_HDR_LEN;
442   default:
443     return 4;   /* XXX */
444   }
445 }
446
447
448 /* ************************************************************************* */
449 /*          This is the capture function used to update packet counts        */
450 /* ************************************************************************* */
451 static void
452 capture_ieee80211_common (const guchar * pd, int offset, int len,
453                           packet_counts * ld, gboolean fixed_length_header)
454 {
455   guint16 fcf, hdr_length;
456
457   if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
458     ld->other++;
459     return;
460   }
461
462   fcf = pletohs (&pd[0]);
463
464   if (IS_WEP(COOK_FLAGS(fcf)))
465     {
466       ld->other++;
467       return;
468     }
469
470   switch (COMPOSE_FRAME_TYPE (fcf))
471     {
472
473     case DATA:                  /* We got a data frame */
474     case DATA_CF_ACK:           /* Data with ACK */
475     case DATA_CF_POLL:
476     case DATA_CF_ACK_POLL:
477       if (fixed_length_header)
478         hdr_length = DATA_LONG_HDR_LEN;
479       else
480         hdr_length = find_header_length (fcf);
481       /* I guess some bridges take Netware Ethernet_802_3 frames,
482          which are 802.3 frames (with a length field rather than
483          a type field, but with no 802.2 header in the payload),
484          and just stick the payload into an 802.11 frame.  I've seen
485          captures that show frames of that sort.
486
487          This means we have to do the same check for Netware 802.3 -
488          or, if you will, "Netware 802.11" - that we do in the
489          Ethernet dissector, i.e. checking for 0xffff as the first
490          four bytes of the payload and, if we find it, treating it
491          as an IPX frame. */
492       if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
493         ld->other++;
494         return;
495       }
496       if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
497         capture_ipx (ld);
498       }
499       else {
500         capture_llc (pd, offset + hdr_length, len, ld);
501       }
502       break;
503
504     default:
505       ld->other++;
506       break;
507     }
508 }
509
510 /*
511  * Handle 802.11 with a variable-length link-layer header.
512  */
513 void
514 capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
515 {
516   capture_ieee80211_common (pd, offset, len, ld, FALSE);
517 }
518
519 /*
520  * Handle 802.11 with a fixed-length link-layer header (padded to the
521  * maximum length).
522  */
523 void
524 capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
525 {
526   capture_ieee80211_common (pd, offset, len, ld, TRUE);
527 }
528
529
530 /* ************************************************************************* */
531 /*          Add the subtree used to store the fixed parameters               */
532 /* ************************************************************************* */
533 static proto_tree *
534 get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
535 {
536   proto_item *fixed_fields;
537   fixed_fields =
538     proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
539                                 size, size, "Fixed parameters (%d bytes)",
540                                 size);
541
542   return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
543 }
544
545
546 /* ************************************************************************* */
547 /*            Add the subtree used to store tagged parameters                */
548 /* ************************************************************************* */
549 static proto_tree *
550 get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
551 {
552   proto_item *tagged_fields;
553
554   tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
555                                               tvb,
556                                               start,
557                                               size,
558                                               size,
559                                               "Tagged parameters (%d bytes)",
560                                               size);
561
562   return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
563 }
564
565
566 /* ************************************************************************* */
567 /*              Dissect and add fixed mgmt fields to protocol tree           */
568 /* ************************************************************************* */
569 static void
570 add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
571 {
572   const guint8 *dataptr;
573   char out_buff[SHORT_STR];
574   guint16 capability;
575   proto_item *cap_item;
576   static proto_tree *cap_tree;
577   double temp_double;
578
579   switch (lfcode)
580     {
581     case FIELD_TIMESTAMP:
582       dataptr = tvb_get_ptr (tvb, offset, 8);
583       memset (out_buff, 0, SHORT_STR);
584       snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
585                 dataptr[7],
586                 dataptr[6],
587                 dataptr[5],
588                 dataptr[4],
589                 dataptr[3],
590                 dataptr[2],
591                 dataptr[1],
592                 dataptr[0]);
593
594       proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
595       break;
596
597     case FIELD_BEACON_INTERVAL:
598       temp_double = (double) tvb_get_letohs (tvb, offset);
599       temp_double = temp_double * 1024 / 1000000;
600       proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
601                                     temp_double,"Beacon Interval: %f [Seconds]",
602                                     temp_double);
603       break;
604
605
606     case FIELD_CAP_INFO:
607       capability = tvb_get_letohs (tvb, offset);
608
609       cap_item = proto_tree_add_uint_format (tree, ff_capture,
610                                              tvb, offset, 2,
611                                              capability,
612                                              "Capability Information: 0x%04X",
613                                              capability);
614       cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
615       proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
616                               capability);
617       proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
618                               capability);
619       if (ESS_SET (capability) != 0)    /* This is an AP */
620         proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
621                              capability);
622
623       else                      /* This is a STA */
624         proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
625                              capability);
626       proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
627                               capability);
628       proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
629                               capability);
630       proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
631                               capability);
632       proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
633                               capability);
634       proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
635                               capability);
636       proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
637                               capability);
638       break;
639
640     case FIELD_AUTH_ALG:
641       proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
642       break;
643
644     case FIELD_AUTH_TRANS_SEQ:
645       proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
646       break;
647
648     case FIELD_CURRENT_AP_ADDR:
649       proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
650       break;
651
652     case FIELD_LISTEN_IVAL:
653       proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
654       break;
655
656     case FIELD_REASON_CODE:
657       proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
658       break;
659
660     case FIELD_ASSOC_ID:
661       proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE);
662       break;
663
664     case FIELD_STATUS_CODE:
665       proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
666       break;
667     }
668 }
669
670 static char *wpa_cipher_str[] = 
671 {
672   "NONE",
673   "WEP (40-bit)",
674   "TKIP",
675   "AES (OCB)",
676   "AES (CCM)",
677   "WEP (104-bit)",
678 };
679
680 static char *
681 wpa_cipher_idx2str(guint idx)
682 {
683   if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
684     return wpa_cipher_str[idx];
685   return "UNKNOWN";
686 }
687
688 static char *wpa_keymgmt_str[] = 
689 {
690   "NONE",
691   "WPA",
692   "PSK",
693 };
694
695 static char *
696 wpa_keymgmt_idx2str(guint idx)
697 {
698   if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
699     return wpa_keymgmt_str[idx];
700   return "UNKNOWN";
701 }
702
703 void 
704 dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
705                 int tag_number, int tag_length, int tag_interpretation)
706 {
707       guint8 tag_no;
708       guint32 tag_len;
709       const guint8 *tag_val;
710       guint32 tag_val_off = 0;
711       char out_buff[SHORT_STR];
712       int i;
713         
714       tag_no = tvb_get_guint8(tvb, offset);
715       tag_len = tvb_get_guint8(tvb, offset + 1);
716       tag_val = tvb_get_ptr(tvb, offset + 2, tag_len);
717   
718       proto_tree_add_uint(tree, tag_number, tvb, offset, 1, tag_no);
719       offset += 1;
720       
721       proto_tree_add_uint(tree, tag_length, tvb, offset, 1, tag_len);
722       offset += 1;
723
724       if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
725         snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
726                   tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
727         proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
728         offset += 6;
729         tag_val_off += 6;
730         if (tag_val_off + 4 <= tag_len) {
731           /* multicast cipher suite */
732           if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
733             snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s", 
734                       wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
735             proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
736             offset += 4;
737             tag_val_off += 4;
738             /* unicast cipher suites */
739             if (tag_val_off + 2 <= tag_len) {
740               snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
741                         pletohs(tag_val + tag_val_off));
742               proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
743               offset += 2;
744               tag_val_off += 2;
745               i = 1;
746               while (tag_val_off + 4 <= tag_len) {
747                 if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
748                   snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s", 
749                             i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
750                   proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
751                   offset += 4;
752                   tag_val_off += 4;
753                   i ++;
754                 }
755                 else
756                   break;
757               }
758               /* authenticated key management suites */
759               if (tag_val_off + 2 <= tag_len) {
760                 snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
761                           pletohs(tag_val + tag_val_off));
762                 proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
763                 offset += 2;
764                 tag_val_off += 2;
765                 i = 1;
766                 while (tag_val_off + 4 <= tag_len) {
767                   if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
768                     snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s", 
769                               i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
770                     proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
771                     offset += 4;
772                     tag_val_off += 4;
773                     i ++;
774                   }
775                   else
776                     break;
777                 }
778               }
779             }
780           }
781         }
782         if (tag_val_off < tag_len)
783           proto_tree_add_string(tree, tag_interpretation, tvb,
784                                  offset, tag_len - tag_val_off, "Not interpreted");
785       }
786       else
787         proto_tree_add_string(tree, tag_interpretation, 
788                         tvb, offset, tag_len, "Not interpreted");
789 }
790
791 /* ************************************************************************* */
792 /*           Dissect and add tagged (optional) fields to proto tree          */
793 /* ************************************************************************* */
794 static int
795 add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
796 {
797   const guint8 *tag_data_ptr;
798   guint32 tag_no, tag_len;
799   unsigned int i;
800   int n, ret;
801   char out_buff[SHORT_STR];
802
803
804   tag_no = tvb_get_guint8(tvb, offset);
805   tag_len = tvb_get_guint8(tvb, offset + 1);
806
807   tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
808
809
810   if ((tag_no >= 17) && (tag_no <= 31))
811     {                           /* Reserved for challenge text */
812       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
813                                   "Tag Number: %u (Reserved for challenge text)",
814                                   tag_no);
815
816       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
817       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
818                              tag_len, "Not interpreted");
819       return (int) tag_len + 2;
820     }
821
822   /* Next See if tag is reserved - if true, skip it! */
823   if (((tag_no >= 7) && (tag_no <= 15))
824       || ((tag_no >= 32) && (tag_no <= 255) && (tag_no != TAG_ERP_INFO) &&
825           (tag_no != TAG_EXT_SUPP_RATES) &&
826           (tag_no != TAG_ERP_INFO_OLD) && (tag_no != TAG_VENDOR_SPECIFIC_IE)))
827     {
828       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
829                                   "Tag Number: %u (Reserved tag number)",
830                                   tag_no);
831
832       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
833
834       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
835                              tag_len, "Not interpreted");
836       return (int) tag_len + 2;
837     }
838
839
840   switch (tag_no)
841     {
842
843
844     case TAG_SSID:
845       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
846                                   "Tag Number: %u (SSID parameter set)",
847                                   tag_no);
848
849       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
850
851       memset (out_buff, 0, SHORT_STR);
852
853       memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
854       out_buff[tag_len + 1] = 0;
855
856       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
857                              tag_len, out_buff);
858       break;
859
860
861
862     case TAG_SUPP_RATES:
863     case TAG_EXT_SUPP_RATES:
864       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
865                                   "Tag Number: %u (%sSupported Rates)",
866                                   tag_no,
867                                   tag_no == TAG_EXT_SUPP_RATES ? "Extended " :
868                                   "");
869
870       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
871
872       memset (out_buff, 0, SHORT_STR);
873       strcpy (out_buff, "Supported rates: ");
874       n = strlen (out_buff);
875
876       for (i = 0; i < tag_len && n < SHORT_STR; i++)
877         {
878             ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
879                            (tag_data_ptr[i] & 0x7F) * 0.5,
880                            (tag_data_ptr[i] & 0x80) ? "(B)" : "");
881             if (ret == -1 || ret >= SHORT_STR - n) {
882               /* Some versions of snprintf return -1 if they'd truncate
883                  the output. Others return <buf_size> or greater.  */
884               break;
885             }
886             n += ret;
887         }
888       if (n < SHORT_STR)
889         snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
890
891       out_buff[SHORT_STR-1] = '\0';
892       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
893                              tag_len, out_buff);
894       break;
895
896
897
898     case TAG_FH_PARAMETER:
899       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
900                                   "Tag Number: %u (FH Parameter set)",
901                                   tag_no);
902
903       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
904       memset (out_buff, 0, SHORT_STR);
905
906       snprintf (out_buff, SHORT_STR,
907                 "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
908                 "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
909                 tag_data_ptr[3], tag_data_ptr[4]);
910
911       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
912                              tag_len, out_buff);
913       break;
914
915
916
917     case TAG_DS_PARAMETER:
918       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
919                                   "Tag Number: %u (DS Parameter set)",
920                                   tag_no);
921
922       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
923       memset (out_buff, 0, SHORT_STR);
924
925       snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
926       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
927                              tag_len, out_buff);
928       break;
929
930
931     case TAG_CF_PARAMETER:
932       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
933                                   "Tag Number: %u (CF Parameter set)",
934                                   tag_no);
935
936       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
937       memset (out_buff, 0, SHORT_STR);
938
939       snprintf (out_buff, SHORT_STR,
940                 "CFP count %u, CFP period %u, CFP max duration %u, "
941                 "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
942                 pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
943
944       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
945                              tag_len, out_buff);
946       break;
947
948
949     case TAG_TIM:
950       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
951                                   "Tag Number: %u ((TIM) Traffic Indication Map)",
952                                   tag_no);
953
954       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
955       memset (out_buff, 0, SHORT_STR);
956       snprintf (out_buff, SHORT_STR,
957                 "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
958                 "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
959                 tag_data_ptr[2]);
960       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
961                              tag_len, out_buff);
962       break;
963
964
965
966     case TAG_IBSS_PARAMETER:
967       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
968                                   "Tag Number: %u (IBSS Parameter set)",
969                                   tag_no);
970
971       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
972       memset (out_buff, 0, SHORT_STR);
973       snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
974                 pletohs (tag_data_ptr));
975
976       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
977                              tag_len, out_buff);
978       break;
979
980
981
982     case TAG_CHALLENGE_TEXT:
983       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
984                                   "Tag Number: %u (Challenge text)", tag_no);
985
986       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
987       memset (out_buff, 0, SHORT_STR);
988       snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
989       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
990                              tag_len, out_buff);
991
992       break;
993
994
995
996     case TAG_ERP_INFO:
997     case TAG_ERP_INFO_OLD:
998       proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
999                                   "Tag Number: %u (ERP Information)",
1000                                   tag_no);
1001
1002       proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
1003       memset (out_buff, 0, SHORT_STR);
1004
1005       snprintf (out_buff, SHORT_STR,
1006                 "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)",
1007                 tag_data_ptr[0],
1008                 tag_data_ptr[0] & 0x01 ? "" : "no ",
1009                 tag_data_ptr[0] & 0x02 ? "" : "do not ",
1010                 tag_data_ptr[0] & 0x04 ? "short or long": "long");
1011       proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
1012                              tag_len, out_buff);
1013
1014       break;
1015
1016     case TAG_VENDOR_SPECIFIC_IE:
1017       dissect_vendor_specific_ie(tree, tvb, offset, tag_number, tag_length, tag_interpretation);
1018       break;
1019
1020
1021     default:
1022       return 0;
1023     }
1024
1025   return tag_len + 2;
1026 }
1027
1028 /* ************************************************************************* */
1029 /*                     Dissect 802.11 management frame                       */
1030 /* ************************************************************************* */
1031 static void
1032 dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
1033         proto_tree * tree)
1034 {
1035   proto_item *ti = NULL;
1036   proto_tree *mgt_tree;
1037   proto_tree *fixed_tree;
1038   proto_tree *tagged_tree;
1039   guint32 next_idx;
1040   guint32 next_len;
1041   int tagged_parameter_tree_len;
1042
1043   CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
1044
1045   if (tree)
1046     {
1047       ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
1048       mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
1049
1050       switch (COMPOSE_FRAME_TYPE(fcf))
1051         {
1052
1053         case MGT_ASSOC_REQ:
1054           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
1055           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1056           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1057
1058           next_idx = 4; /* Size of fixed fields */
1059           tagged_parameter_tree_len =
1060               tvb_reported_length_remaining(tvb, next_idx);
1061           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1062                                                    tagged_parameter_tree_len);
1063
1064           while (tagged_parameter_tree_len > 0) {
1065             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1066               break;
1067             next_idx +=next_len;
1068             tagged_parameter_tree_len -= next_len;
1069           }
1070           break;
1071
1072
1073         case MGT_ASSOC_RESP:
1074           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1075           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1076           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1077           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1078
1079           next_idx = 6; /* Size of fixed fields */
1080
1081           tagged_parameter_tree_len =
1082               tvb_reported_length_remaining(tvb, next_idx);
1083           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1084                                                    tagged_parameter_tree_len);
1085
1086           while (tagged_parameter_tree_len > 0) {
1087             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1088               break;
1089             next_idx +=next_len;
1090             tagged_parameter_tree_len -= next_len;
1091           }
1092           break;
1093
1094
1095         case MGT_REASSOC_REQ:
1096           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1097           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1098           add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
1099           add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
1100
1101           next_idx = 10;        /* Size of fixed fields */
1102           tagged_parameter_tree_len =
1103               tvb_reported_length_remaining(tvb, next_idx);
1104           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1105                                                    tagged_parameter_tree_len);
1106
1107           while (tagged_parameter_tree_len > 0) {
1108             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1109               break;
1110             next_idx +=next_len;
1111             tagged_parameter_tree_len -= next_len;
1112           }
1113           break;
1114
1115         case MGT_REASSOC_RESP:
1116           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
1117           add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
1118           add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
1119           add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
1120
1121           next_idx = 6; /* Size of fixed fields */
1122           tagged_parameter_tree_len =
1123               tvb_reported_length_remaining(tvb, next_idx);
1124           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1125                                                    tagged_parameter_tree_len);
1126
1127           while (tagged_parameter_tree_len > 0) {
1128             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1129               break;
1130             next_idx +=next_len;
1131             tagged_parameter_tree_len -= next_len;
1132           }
1133           break;
1134
1135
1136         case MGT_PROBE_REQ:
1137           next_idx = 0;
1138           tagged_parameter_tree_len =
1139               tvb_reported_length_remaining(tvb, next_idx);
1140           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1141                                                    tagged_parameter_tree_len);
1142
1143           while (tagged_parameter_tree_len > 0) {
1144             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1145               break;
1146             next_idx +=next_len;
1147             tagged_parameter_tree_len -= next_len;
1148           }
1149           break;
1150
1151
1152         case MGT_PROBE_RESP:
1153           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1154           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1155           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1156           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1157
1158           next_idx = 12;        /* Size of fixed fields */
1159           tagged_parameter_tree_len =
1160               tvb_reported_length_remaining(tvb, next_idx);
1161           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1162                                                    tagged_parameter_tree_len);
1163
1164           while (tagged_parameter_tree_len > 0) {
1165             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1166               break;
1167             next_idx +=next_len;
1168             tagged_parameter_tree_len -= next_len;
1169           }
1170           break;
1171
1172
1173         case MGT_BEACON:                /* Dissect protocol payload fields  */
1174           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
1175
1176           add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
1177           add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
1178           add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
1179
1180           next_idx = 12;        /* Size of fixed fields */
1181           tagged_parameter_tree_len =
1182               tvb_reported_length_remaining(tvb, next_idx);
1183           tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, next_idx,
1184                                                    tagged_parameter_tree_len);
1185
1186           while (tagged_parameter_tree_len > 0) {
1187             if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1188               break;
1189             next_idx +=next_len;
1190             tagged_parameter_tree_len -= next_len;
1191           }
1192           break;
1193
1194
1195         case MGT_ATIM:
1196           break;
1197
1198
1199         case MGT_DISASS:
1200           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1201           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1202           break;
1203
1204
1205         case MGT_AUTHENTICATION:
1206           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
1207           add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
1208           add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
1209           add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
1210
1211           next_idx = 6; /* Size of fixed fields */
1212
1213           tagged_parameter_tree_len =
1214                   tvb_reported_length_remaining(tvb, next_idx);
1215           if (tagged_parameter_tree_len != 0)
1216             {
1217               tagged_tree = get_tagged_parameter_tree (mgt_tree,
1218                                                        tvb,
1219                                                        next_idx,
1220                                                        tagged_parameter_tree_len);
1221
1222               while (tagged_parameter_tree_len > 0) {
1223                 if ((next_len=add_tagged_field (tagged_tree, tvb, next_idx))==0)
1224                   break;
1225                 next_idx +=next_len;
1226                 tagged_parameter_tree_len -= next_len;
1227               }
1228             }
1229           break;
1230
1231
1232         case MGT_DEAUTHENTICATION:
1233           fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
1234           add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
1235           break;
1236         }
1237     }
1238 }
1239
1240 static void
1241 set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1242 {
1243   if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
1244     col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
1245                     get_ether_name(addr), type);
1246   if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
1247     col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
1248                      ether_to_str(addr), type);
1249 }
1250
1251 static void
1252 set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
1253 {
1254   if (check_col(pinfo->cinfo, COL_RES_DL_DST))
1255     col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
1256                      get_ether_name(addr), type);
1257   if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
1258     col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
1259                      ether_to_str(addr), type);
1260 }
1261
1262 /* ************************************************************************* */
1263 /*                          Dissect 802.11 frame                             */
1264 /* ************************************************************************* */
1265 static void
1266 dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
1267                           proto_tree * tree, gboolean fixed_length_header,
1268                           gboolean has_radio_information, gboolean has_no_fcs)
1269 {
1270   guint16 fcf, flags, frame_type_subtype;
1271   guint16 seq_control;
1272   guint32 seq_number, frag_number;
1273   gboolean more_frags;
1274   const guint8 *src = NULL, *dst = NULL;
1275   proto_item *ti = NULL;
1276   proto_item *flag_item;
1277   proto_item *fc_item;
1278   proto_tree *hdr_tree = NULL;
1279   proto_tree *flag_tree;
1280   proto_tree *fc_tree;
1281   guint16 hdr_len;
1282   gint len, reported_len;
1283   gboolean save_fragmented;
1284   tvbuff_t *volatile next_tvb = NULL;
1285   guint32 addr_type;
1286   volatile gboolean is_802_2;
1287
1288   if (check_col (pinfo->cinfo, COL_PROTOCOL))
1289     col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
1290   if (check_col (pinfo->cinfo, COL_INFO))
1291     col_clear (pinfo->cinfo, COL_INFO);
1292
1293   fcf = tvb_get_letohs (tvb, 0);
1294   if (fixed_length_header)
1295     hdr_len = DATA_LONG_HDR_LEN;
1296   else
1297     hdr_len = find_header_length (fcf);
1298   frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
1299
1300   if (check_col (pinfo->cinfo, COL_INFO))
1301       col_set_str (pinfo->cinfo, COL_INFO,
1302           val_to_str(frame_type_subtype, frame_type_subtype_vals,
1303               "Unrecognized (Reserved frame)"));
1304
1305   flags = COOK_FLAGS (fcf);
1306   more_frags = HAVE_FRAGMENTS (flags);
1307
1308   /* Add the radio information, if present, and the FC to the current tree */
1309   if (tree)
1310     {
1311       ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
1312                                            "IEEE 802.11");
1313       hdr_tree = proto_item_add_subtree (ti, ett_80211);
1314
1315       if (has_radio_information) {
1316         proto_tree_add_uint_format(hdr_tree, hf_data_rate,
1317                                    tvb, 0, 0,
1318                                    pinfo->pseudo_header->ieee_802_11.data_rate,
1319                                    "Data Rate: %g mb/s",
1320                                    .5*pinfo->pseudo_header->ieee_802_11.data_rate);
1321
1322         proto_tree_add_uint(hdr_tree, hf_channel,
1323                             tvb, 0, 0,
1324                             pinfo->pseudo_header->ieee_802_11.channel);
1325
1326         proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
1327                                    tvb, 0, 0,
1328                                    pinfo->pseudo_header->ieee_802_11.signal_level,
1329                                    "Signal Strength: %u%%",
1330                                    pinfo->pseudo_header->ieee_802_11.signal_level);
1331       }
1332
1333       proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
1334                            tvb, 0, 1,
1335                            frame_type_subtype);
1336
1337       fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, 0, 2,
1338                                             fcf,
1339                                             "Frame Control: 0x%04X",
1340                                             fcf);
1341
1342       fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
1343
1344
1345       proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, 0, 1,
1346                            COOK_PROT_VERSION (fcf));
1347
1348       proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, 0, 1,
1349                            COOK_FRAME_TYPE (fcf));
1350
1351       proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
1352                            tvb, 0, 1,
1353                            COOK_FRAME_SUBTYPE (fcf));
1354
1355       flag_item =
1356         proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, 1, 1,
1357                                     flags, "Flags: 0x%X", flags);
1358
1359       flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
1360
1361       proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, 1, 1,
1362                            COOK_DS_STATUS (flags));
1363       proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1, 
1364                                      flags);
1365       proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1, 
1366                                      flags);
1367
1368       proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, 1, 1,
1369                               flags);
1370
1371       proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, 1, 1, flags);
1372
1373       proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, 1, 1, flags);
1374
1375       proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, 1, 1,
1376                               flags);
1377
1378       proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, 1, 1, flags);
1379
1380       proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, 1, 1, flags);
1381
1382       if (frame_type_subtype == CTRL_PS_POLL)
1383         proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
1384                             COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
1385
1386       else
1387           proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
1388                                tvb_get_letohs (tvb, 2));
1389     }
1390
1391   /*
1392    * Decode the part of the frame header that isn't the same for all
1393    * frame types.
1394    */
1395   seq_control = 0;
1396   frag_number = 0;
1397   seq_number = 0;
1398
1399   switch (COOK_FRAME_TYPE (fcf))
1400     {
1401
1402     case MGT_FRAME:
1403       /*
1404        * All management frame types have the same header.
1405        */
1406       src = tvb_get_ptr (tvb, 10, 6);
1407       dst = tvb_get_ptr (tvb, 4, 6);
1408
1409       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1410       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1411       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1412       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1413
1414       seq_control = tvb_get_letohs(tvb, 22);
1415       frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1416       seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1417
1418       if (tree)
1419         {
1420           proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1421
1422           proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1423
1424           /* add items for wlan.addr filter */
1425           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1426           proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1427
1428           proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1429                                 tvb_get_ptr (tvb, 16, 6));
1430
1431           proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1432                                frag_number);
1433
1434           proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1435                                seq_number);
1436         }
1437       break;
1438
1439     case CONTROL_FRAME:
1440       switch (frame_type_subtype)
1441         {
1442
1443         case CTRL_PS_POLL:
1444           src = tvb_get_ptr (tvb, 10, 6);
1445           dst = tvb_get_ptr (tvb, 4, 6);
1446
1447           set_src_addr_cols(pinfo, src, "BSSID");
1448           set_dst_addr_cols(pinfo, dst, "BSSID");
1449
1450           if (tree)
1451             {
1452               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
1453
1454               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1455             }
1456           break;
1457
1458
1459         case CTRL_RTS:
1460           src = tvb_get_ptr (tvb, 10, 6);
1461           dst = tvb_get_ptr (tvb, 4, 6);
1462
1463           set_src_addr_cols(pinfo, src, "TA");
1464           set_dst_addr_cols(pinfo, dst, "RA");
1465
1466           if (tree)
1467             {
1468               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1469
1470               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
1471             }
1472           break;
1473
1474
1475         case CTRL_CTS:
1476           dst = tvb_get_ptr (tvb, 4, 6);
1477
1478           set_dst_addr_cols(pinfo, dst, "RA");
1479
1480           if (tree)
1481             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1482           break;
1483
1484
1485         case CTRL_ACKNOWLEDGEMENT:
1486           dst = tvb_get_ptr (tvb, 4, 6);
1487
1488           set_dst_addr_cols(pinfo, dst, "RA");
1489
1490           if (tree)
1491             proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1492           break;
1493
1494
1495         case CTRL_CFP_END:
1496           src = tvb_get_ptr (tvb, 10, 6);
1497           dst = tvb_get_ptr (tvb, 4, 6);
1498
1499           set_src_addr_cols(pinfo, src, "BSSID");
1500           set_dst_addr_cols(pinfo, dst, "RA");
1501
1502           if (tree)
1503             {
1504               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1505               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1506             }
1507           break;
1508
1509
1510         case CTRL_CFP_ENDACK:
1511           src = tvb_get_ptr (tvb, 10, 6);
1512           dst = tvb_get_ptr (tvb, 4, 6);
1513
1514           set_src_addr_cols(pinfo, src, "BSSID");
1515           set_dst_addr_cols(pinfo, dst, "RA");
1516
1517           if (tree)
1518             {
1519               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
1520
1521               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
1522             }
1523           break;
1524         }
1525       break;
1526
1527     case DATA_FRAME:
1528       addr_type = COOK_ADDR_SELECTOR (fcf);
1529
1530       /* In order to show src/dst address we must always do the following */
1531       switch (addr_type)
1532         {
1533
1534         case DATA_ADDR_T1:
1535           src = tvb_get_ptr (tvb, 10, 6);
1536           dst = tvb_get_ptr (tvb, 4, 6);
1537           break;
1538
1539
1540         case DATA_ADDR_T2:
1541           src = tvb_get_ptr (tvb, 16, 6);
1542           dst = tvb_get_ptr (tvb, 4, 6);
1543           break;
1544
1545
1546         case DATA_ADDR_T3:
1547           src = tvb_get_ptr (tvb, 10, 6);
1548           dst = tvb_get_ptr (tvb, 16, 6);
1549           break;
1550
1551
1552         case DATA_ADDR_T4:
1553           src = tvb_get_ptr (tvb, 24, 6);
1554           dst = tvb_get_ptr (tvb, 16, 6);
1555           break;
1556         }
1557
1558       SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
1559       SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
1560       SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
1561       SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
1562
1563       seq_control = tvb_get_letohs(tvb, 22);
1564       frag_number = COOK_FRAGMENT_NUMBER(seq_control);
1565       seq_number = COOK_SEQUENCE_NUMBER(seq_control);
1566
1567       /* Now if we have a tree we start adding stuff */
1568       if (tree)
1569         {
1570
1571
1572           switch (addr_type)
1573             {
1574
1575             case DATA_ADDR_T1:
1576               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1577               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1578               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
1579                                     tvb_get_ptr (tvb, 16, 6));
1580               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1581                                    frag_number);
1582               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1583                                    seq_number);
1584
1585               /* add items for wlan.addr filter */
1586               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1587               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1588               break;
1589
1590
1591             case DATA_ADDR_T2:
1592               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
1593               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
1594                                     tvb_get_ptr (tvb, 10, 6));
1595               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
1596               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1597                                    frag_number);
1598               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1599                                    seq_number);
1600
1601               /* add items for wlan.addr filter */
1602               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
1603               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
1604               break;
1605
1606
1607             case DATA_ADDR_T3:
1608               proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
1609                                     tvb_get_ptr (tvb, 4, 6));
1610               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
1611               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1612
1613               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1614                                    frag_number);
1615               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1616                                    seq_number);
1617
1618               /* add items for wlan.addr filter */
1619               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
1620               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1621               break;
1622
1623
1624             case DATA_ADDR_T4:
1625               proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
1626                                     tvb_get_ptr (tvb, 4, 6));
1627               proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
1628                                     tvb_get_ptr (tvb, 10, 6));
1629               proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
1630               proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
1631                                    frag_number);
1632               proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
1633                                    seq_number);
1634               proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
1635
1636               /* add items for wlan.addr filter */
1637               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
1638               proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
1639               break;
1640             }
1641
1642         }
1643       break;
1644     }
1645
1646   len = tvb_length_remaining(tvb, hdr_len);
1647   reported_len = tvb_reported_length_remaining(tvb, hdr_len);
1648
1649   if (!has_no_fcs && (wlan_check_fcs))
1650     {
1651       /*
1652        * Well, this packet should, in theory, have an FCS.
1653        * Do we have the entire packet, and does it have enough data for
1654        * the FCS?
1655        */
1656       if (reported_len < 4)
1657         {
1658           /*
1659            * The packet is claimed not to even have enough data for a 4-byte
1660            * FCS.
1661            * Pretend it doesn't have an FCS.
1662            */
1663           ;
1664         }
1665       else if (len < reported_len)
1666         {
1667           /*
1668            * The packet is claimed to have enough data for a 4-byte FCS, but
1669            * we didn't capture all of the packet.
1670            * Slice off the 4-byte FCS from the reported length, and trim the
1671            * captured length so it's no more than the reported length; that
1672            * will slice off what of the FCS, if any, is in the captured
1673            * length.
1674            */
1675           reported_len -= 4;
1676           if (len > reported_len)
1677             len = reported_len;
1678         }
1679       else
1680         {
1681           /*
1682            * We have the entire packet, and it includes a 4-byte FCS.
1683            * Slice it off, and put it into the tree.
1684            */
1685           len -= 4;
1686           reported_len -= 4;
1687           if (tree)
1688             {
1689               guint32 fcs = crc32(tvb_get_ptr(tvb, 0, hdr_len + len), hdr_len + len);
1690               guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
1691               if (fcs == sent_fcs)
1692                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1693                         hdr_len + len, 4, sent_fcs,
1694                         "Frame check sequence: 0x%08x (correct)", sent_fcs);
1695               else
1696                 proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
1697                         hdr_len + len, 4, sent_fcs,
1698                         "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
1699                         sent_fcs, fcs);
1700             }
1701         }
1702     }
1703
1704   /*
1705    * Only management and data frames have a body, so we don't have
1706    * anything more to do for other types of frames.
1707    */
1708   switch (COOK_FRAME_TYPE (fcf))
1709     {
1710
1711     case MGT_FRAME:
1712       break;
1713
1714     case DATA_FRAME:
1715       /*
1716        * No-data frames don't have a body.
1717        */
1718       switch (frame_type_subtype)
1719         {
1720
1721         case DATA_NULL_FUNCTION:
1722         case DATA_CF_ACK_NOD:
1723         case DATA_CF_POLL_NOD:
1724         case DATA_CF_ACK_POLL_NOD:
1725           return;
1726         }
1727         break;
1728
1729     default:
1730       return;
1731     }
1732
1733   if (IS_WEP(COOK_FLAGS(fcf))) {
1734     /*
1735      * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
1736      * the data, if we have a matching key.  Otherwise display it as data.
1737      */
1738     gboolean can_decrypt = FALSE;
1739     proto_tree *wep_tree = NULL;
1740     guint32 iv;
1741     guint8 key;
1742
1743     /*
1744      * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
1745      * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
1746      * them itself.
1747      *
1748      * Also, just pass the data *following* the WEP parameters as the
1749      * buffer to decrypt.
1750      */
1751     iv = tvb_get_letoh24(tvb, hdr_len);
1752     if (tree) {
1753       proto_item *wep_fields;
1754
1755       wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
1756                                            "WEP parameters");
1757
1758       wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
1759       proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
1760     }
1761     key = COOK_WEP_KEY (tvb_get_guint8 (tvb, hdr_len + 3));
1762     if (tree)
1763       proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
1764
1765     /* Subtract out the length of the IV. */
1766     len -= 4;
1767     reported_len -= 4;
1768
1769     /*
1770      * Well, this packet should, in theory, have an ICV.
1771      * Do we have the entire packet, and does it have enough data for
1772      * the ICV?
1773      */
1774     if (reported_len < 4) {
1775       /*
1776        * The packet is claimed not to even have enough data for a
1777        * 4-byte ICV.
1778        * Pretend it doesn't have an ICV.
1779        */
1780       ;
1781     } else if (len < reported_len) {
1782       /*
1783        * The packet is claimed to have enough data for a 4-byte ICV,
1784        * but we didn't capture all of the packet.
1785        * Slice off the 4-byte ICV from the reported length, and trim
1786        * the captured length so it's no more than the reported length;
1787        * that will slice off what of the ICV, if any, is in the
1788        * captured length.
1789        *
1790        */
1791       reported_len -= 4;
1792       if (len > reported_len)
1793         len = reported_len;
1794     } else {
1795       /*
1796        * We have the entire packet, and it includes a 4-byte ICV.
1797        * Slice it off, and put it into the tree.
1798        *
1799        * We only support decrypting if we have the the ICV.
1800        *
1801        * XXX - the ICV is encrypted; we're putting the encrypted
1802        * value, not the decrypted value, into the tree.
1803        */
1804       len -= 4;
1805       reported_len -= 4;
1806       can_decrypt = TRUE;
1807     }
1808
1809     if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
1810       /*
1811        * WEP decode impossible or failed, treat payload as raw data
1812        * and don't attempt fragment reassembly or further dissection.
1813        */
1814       next_tvb = tvb_new_subset(tvb, hdr_len + 4, len, reported_len);
1815
1816       if (tree && can_decrypt)
1817         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
1818                                     hdr_len + 4 + len, 4, 
1819                                     tvb_get_ntohl(tvb, hdr_len + 4 + len),
1820                                     "WEP ICV: 0x%08x (not verified)", 
1821                                     tvb_get_ntohl(tvb, hdr_len + 4 + len));
1822
1823       call_dissector(data_handle, next_tvb, pinfo, tree);
1824       return;
1825     } else {
1826
1827       if (tree)
1828         proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, 
1829                                     hdr_len + 4 + len, 4, 
1830                                     tvb_get_ntohl(tvb, hdr_len + 4 + len),
1831                                     "WEP ICV: 0x%08x (correct)", 
1832                                     tvb_get_ntohl(tvb, hdr_len + 4 + len));
1833
1834       add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
1835     }
1836
1837     /*
1838      * WEP decryption successful!
1839      *
1840      * Use the tvbuff we got back from the decryption; the data starts at
1841      * the beginning.  The lengths are already correct for the decoded WEP
1842      * payload.
1843      */
1844     hdr_len = 0;
1845
1846   } else {
1847     /*
1848      * Not a WEP-encrypted frame; just use the data from the tvbuff
1849      * handed to us.
1850      *
1851      * The payload starts at "hdr_len" (i.e., just past the 802.11
1852      * MAC header), the length of data in the tvbuff following the
1853      * 802.11 header is "len", and the length of data in the packet
1854      * following the 802.11 header is "reported_len".
1855      */
1856     next_tvb = tvb;
1857   }
1858
1859   /*
1860    * Do defragmentation if "wlan_defragment" is true, and we have more
1861    * fragments or this isn't the first fragment.
1862    *
1863    * We have to do some special handling to catch frames that
1864    * have the "More Fragments" indicator not set but that
1865    * don't show up as reassembled and don't have any other
1866    * fragments present.  Some networking interfaces appear
1867    * to do reassembly even when you're capturing raw packets
1868    * *and* show the reassembled packet without the "More
1869    * Fragments" indicator set *but* with a non-zero fragment
1870    * number.
1871    *
1872    * "fragment_add_seq_check()" handles that; we want to call it
1873    * even if we have a short frame, so that it does those checks - if
1874    * the frame is short, it doesn't do reassembly on it.
1875    *
1876    * (This could get some false positives if we really *did* only
1877    * capture the last fragment of a fragmented packet, but that's
1878    * life.)
1879    */
1880   save_fragmented = pinfo->fragmented;
1881   if (wlan_defragment && (more_frags || frag_number != 0)) {
1882     fragment_data *fd_head;
1883
1884     /*
1885      * If we've already seen this frame, look it up in the
1886      * table of reassembled packets, otherwise add it to
1887      * whatever reassembly is in progress, if any, and see
1888      * if it's done.
1889      */
1890     fd_head = fragment_add_seq_check(next_tvb, hdr_len, pinfo, seq_number,
1891                                      wlan_fragment_table,
1892                                      wlan_reassembled_table,
1893                                      frag_number,
1894                                      reported_len,
1895                                      more_frags);
1896     if (fd_head != NULL) {
1897       /*
1898        * Either this is reassembled or it wasn't fragmented
1899        * (see comment above about some networking interfaces).
1900        * In either case, it's now in the table of reassembled
1901        * packets.
1902        *
1903        * If the "fragment_data" structure doesn't have a list of
1904        * fragments, we assume it's a placeholder to mark those
1905        * not-really-fragmented packets, and just treat this as
1906        * a non-fragmented frame.
1907        */
1908       if (fd_head->next != NULL) {
1909         next_tvb = process_reassembled_data(tvb, pinfo, "Reassembled 802.11",
1910                 fd_head, &frag_items, NULL, hdr_tree);
1911       } else {
1912         /*
1913          * Not fragmented, really.
1914          * Show it as a regular frame.
1915          */
1916         next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1917       }
1918
1919       /* It's not fragmented. */
1920       pinfo->fragmented = FALSE;
1921     } else {
1922       /* We don't have the complete reassembled payload. */
1923       next_tvb = NULL;
1924     }
1925   } else {
1926     /*
1927      * If this is the first fragment, dissect its contents, otherwise
1928      * just show it as a fragment.
1929      */
1930     if (frag_number != 0) {
1931       /* Not the first fragment - don't dissect it. */
1932       next_tvb = NULL;
1933     } else {
1934       /* First fragment, or not fragmented.  Dissect what we have here. */
1935
1936       /* Get a tvbuff for the payload. */
1937       next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
1938
1939       /*
1940        * If this is the first fragment, but not the only fragment,
1941        * tell the next protocol that.
1942        */
1943       if (more_frags)
1944         pinfo->fragmented = TRUE;
1945       else
1946         pinfo->fragmented = FALSE;
1947     }
1948   }
1949
1950   if (next_tvb == NULL) {
1951     /* Just show this as an incomplete fragment. */
1952     if (check_col(pinfo->cinfo, COL_INFO))
1953       col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
1954     next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
1955     call_dissector(data_handle, next_tvb, pinfo, tree);
1956     pinfo->fragmented = save_fragmented;
1957     return;
1958   }
1959
1960   switch (COOK_FRAME_TYPE (fcf))
1961     {
1962
1963     case MGT_FRAME:
1964       dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
1965       break;
1966
1967
1968     case DATA_FRAME:
1969       /* I guess some bridges take Netware Ethernet_802_3 frames,
1970          which are 802.3 frames (with a length field rather than
1971          a type field, but with no 802.2 header in the payload),
1972          and just stick the payload into an 802.11 frame.  I've seen
1973          captures that show frames of that sort.
1974
1975          This means we have to do the same check for Netware 802.3 -
1976          or, if you will, "Netware 802.11" - that we do in the
1977          Ethernet dissector, i.e. checking for 0xffff as the first
1978          four bytes of the payload and, if we find it, treating it
1979          as an IPX frame. */
1980       is_802_2 = TRUE;
1981       TRY {
1982         if (tvb_get_ntohs(next_tvb, 0) == 0xffff)
1983           is_802_2 = FALSE;
1984       }
1985       CATCH2(BoundsError, ReportedBoundsError) {
1986             ; /* do nothing */
1987
1988       }
1989       ENDTRY;
1990
1991       if (is_802_2)
1992         call_dissector(llc_handle, next_tvb, pinfo, tree);
1993       else
1994         call_dissector(ipx_handle, next_tvb, pinfo, tree);
1995       break;
1996     }
1997   pinfo->fragmented = save_fragmented;
1998 }
1999
2000 /*
2001  * Dissect 802.11 with a variable-length link-layer header.
2002  */
2003 static void
2004 dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2005 {
2006   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE);
2007 }
2008
2009 /*
2010  * Dissect 802.11 with a variable-length link-layer header and a pseudo-
2011  * header containing radio information.
2012  */
2013 static void
2014 dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2015 {
2016   /* These packets do NOT have a FCS present */
2017   dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE, TRUE);
2018 }
2019
2020 /*
2021  * Dissect 802.11 with a fixed-length link-layer header (padded to the
2022  * maximum length).
2023  */
2024 static void
2025 dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
2026 {
2027   dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE);
2028 }
2029
2030 static void
2031 wlan_defragment_init(void)
2032 {
2033   fragment_table_init(&wlan_fragment_table);
2034   reassembled_table_init(&wlan_reassembled_table);
2035 }
2036
2037 void
2038 proto_register_ieee80211 (void)
2039 {
2040   static const value_string frame_type[] = {
2041     {MGT_FRAME,     "Management frame"},
2042     {CONTROL_FRAME, "Control frame"},
2043     {DATA_FRAME,    "Data frame"},
2044     {0,             NULL}
2045   };
2046
2047   static const value_string tofrom_ds[] = {
2048     {0,                       "Not leaving DS or network is operating in AD-HOC mode (To DS: 0  From DS: 0)"},
2049     {FLAG_TO_DS,              "Frame is entering DS (To DS: 1  From DS: 0)"},
2050     {FLAG_FROM_DS,            "Frame is exiting DS (To DS: 0  From DS: 1)"},
2051     {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1  From DS: 1)"},
2052     {0, NULL}
2053   };
2054
2055   static const true_false_string tods_flag = {
2056     "Frame is entering DS",
2057     "Frame is not entering DS"
2058   };
2059
2060   static const true_false_string fromds_flag = {
2061     "Frame is exiting DS",
2062     "Frame is not exiting DS"
2063   };
2064
2065   static const true_false_string more_frags = {
2066     "More fragments follow",
2067     "This is the last fragment"
2068   };
2069
2070   static const true_false_string retry_flags = {
2071     "Frame is being retransmitted",
2072     "Frame is not being retransmitted"
2073   };
2074
2075   static const true_false_string pm_flags = {
2076     "STA will go to sleep",
2077     "STA will stay up"
2078   };
2079
2080   static const true_false_string md_flags = {
2081     "Data is buffered for STA at AP",
2082     "No data buffered"
2083   };
2084
2085   static const true_false_string wep_flags = {
2086     "WEP is enabled",
2087     "WEP is disabled"
2088   };
2089
2090   static const true_false_string order_flags = {
2091     "Strictly ordered",
2092     "Not strictly ordered"
2093   };
2094
2095   static const true_false_string cf_ess_flags = {
2096     "Transmitter is an AP",
2097     "Transmitter is a STA"
2098   };
2099
2100
2101   static const true_false_string cf_privacy_flags = {
2102     "AP/STA can support WEP",
2103     "AP/STA cannot support WEP"
2104   };
2105
2106   static const true_false_string cf_preamble_flags = {
2107     "Short preamble allowed",
2108     "Short preamble not allowed"
2109   };
2110
2111   static const true_false_string cf_pbcc_flags = {
2112     "PBCC modulation allowed",
2113     "PBCC modulation not allowed"
2114   };
2115
2116   static const true_false_string cf_agility_flags = {
2117     "Channel agility in use",
2118     "Channel agility not in use"
2119   };
2120
2121   static const true_false_string short_slot_time_flags = {
2122     "Short slot time in use",
2123     "Short slot time not in use"
2124   };
2125
2126   static const true_false_string dsss_ofdm_flags = {
2127     "DSSS-OFDM modulation allowed",
2128     "DSSS-OFDM modulation not allowed"
2129   };
2130
2131
2132   static const true_false_string cf_ibss_flags = {
2133     "Transmitter belongs to an IBSS",
2134     "Transmitter belongs to a BSS"
2135   };
2136
2137   static const value_string sta_cf_pollable[] = {
2138     {0x00, "Station is not CF-Pollable"},
2139     {0x02, "Station is CF-Pollable, "
2140      "not requesting to be placed on the  CF-polling list"},
2141     {0x01, "Station is CF-Pollable, "
2142      "requesting to be placed on the CF-polling list"},
2143     {0x03, "Station is CF-Pollable, requesting never to be polled"},
2144     {0, NULL}
2145   };
2146
2147   static const value_string ap_cf_pollable[] = {
2148     {0x00, "No point coordinator at AP"},
2149     {0x02, "Point coordinator at AP for delivery only (no polling)"},
2150     {0x01, "Point coordinator at AP for delivery and polling"},
2151     {0x03, "Reserved"},
2152     {0, NULL}
2153   };
2154
2155
2156   static const value_string auth_alg[] = {
2157     {0x00, "Open System"},
2158     {0x01, "Shared key"},
2159     {0, NULL}
2160   };
2161
2162   static const value_string reason_codes[] = {
2163     {0x00, "Reserved"},
2164     {0x01, "Unspecified reason"},
2165     {0x02, "Previous authentication no longer valid"},
2166     {0x03, "Deauthenticated because sending STA is leaving (has left) "
2167      "IBSS or ESS"},
2168     {0x04, "Disassociated due to inactivity"},
2169     {0x05, "Disassociated because AP is unable to handle all currently "
2170      "associated stations"},
2171     {0x06, "Class 2 frame received from nonauthenticated station"},
2172     {0x07, "Class 3 frame received from nonassociated station"},
2173     {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
2174     {0x09, "Station requesting (re)association is not authenticated with "
2175      "responding station"},
2176     {0x00, NULL}
2177   };
2178
2179
2180   static const value_string status_codes[] = {
2181     {0x00, "Successful"},
2182     {0x01, "Unspecified failure"},
2183     {0x0A, "Cannot support all requested capabilities in the "
2184      "Capability information field"},
2185     {0x0B, "Reassociation denied due to inability to confirm that "
2186      "association exists"},
2187     {0x0C, "Association denied due to reason outside the scope of this "
2188      "standard"},
2189
2190     {0x0D, "Responding station does not support the specified authentication "
2191      "algorithm"},
2192     {0x0E, "Received an Authentication frame with authentication sequence "
2193      "transaction sequence number out of expected sequence"},
2194     {0x0F, "Authentication rejected because of challenge failure"},
2195     {0x10, "Authentication rejected due to timeout waiting for next "
2196      "frame in sequence"},
2197     {0x11, "Association denied because AP is unable to handle additional "
2198      "associated stations"},
2199     {0x12, "Association denied due to requesting station not supporting all "
2200      "of the datarates in the BSSBasicServiceSet Parameter"},
2201     {0x13, "Association denied due to requesting station not supporting "
2202      "short preamble operation"},
2203     {0x14, "Association denied due to requesting station not supporting "
2204      "PBCC encoding"},
2205     {0x15, "Association denied due to requesting station not supporting "
2206      "channel agility"},
2207     {0x19, "Association denied due to requesting station not supporting "
2208      "short slot operation"},
2209     {0x1A, "Association denied due to requesting station not supporting "
2210      "DSSS-OFDM operation"},
2211     {0x00, NULL}
2212   };
2213
2214   static hf_register_info hf[] = {
2215     {&hf_data_rate,
2216      {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
2217       "Data rate (.5 Mb/s units)", HFILL }},
2218
2219     {&hf_channel,
2220      {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
2221       "Radio channel", HFILL }},
2222
2223     {&hf_signal_strength,
2224      {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
2225       "Signal strength (percentage)", HFILL }},
2226
2227     {&hf_fc_field,
2228      {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
2229       "MAC Frame control", HFILL }},
2230
2231     {&hf_fc_proto_version,
2232      {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
2233       "MAC Protocol version", HFILL }}, /* 0 */
2234
2235     {&hf_fc_frame_type,
2236      {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
2237       "Frame type", HFILL }},
2238
2239     {&hf_fc_frame_subtype,
2240      {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
2241       "Frame subtype", HFILL }},        /* 2 */
2242
2243     {&hf_fc_frame_type_subtype,
2244      {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
2245       "Type and subtype combined", HFILL }},
2246
2247     {&hf_fc_flags,
2248      {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
2249       "Protocol flags", HFILL }},
2250
2251     {&hf_fc_data_ds,
2252      {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
2253       "Data-frame DS-traversal status", HFILL }},       /* 3 */
2254
2255     {&hf_fc_to_ds,
2256      {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
2257       "To DS flag", HFILL }},           /* 4 */
2258
2259     {&hf_fc_from_ds,
2260      {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
2261       "From DS flag", HFILL }},         /* 5 */
2262
2263     {&hf_fc_more_frag,
2264      {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
2265       "More Fragments flag", HFILL }},  /* 6 */
2266
2267     {&hf_fc_retry,
2268      {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
2269       "Retransmission flag", HFILL }},
2270
2271     {&hf_fc_pwr_mgt,
2272      {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
2273       "Power management status", HFILL }},
2274
2275     {&hf_fc_more_data,
2276      {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
2277       "More data flag", HFILL }},
2278
2279     {&hf_fc_wep,
2280      {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
2281       "WEP flag", HFILL }},
2282
2283     {&hf_fc_order,
2284      {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
2285       "Strictly ordered flag", HFILL }},
2286
2287     {&hf_assoc_id,
2288      {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
2289       "Association-ID field", HFILL }},
2290
2291     {&hf_did_duration,
2292      {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
2293       "Duration field", HFILL }},
2294
2295     {&hf_addr_da,
2296      {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
2297       "Destination Hardware Address", HFILL }},
2298
2299     {&hf_addr_sa,
2300      {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
2301       "Source Hardware Address", HFILL }},
2302
2303     { &hf_addr,
2304       {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
2305        "Source or Destination Hardware Address", HFILL }},
2306
2307     {&hf_addr_ra,
2308      {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
2309       "Receiving Station Hardware Address", HFILL }},
2310
2311     {&hf_addr_ta,
2312      {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
2313       "Transmitting Station Hardware Address", HFILL }},
2314
2315     {&hf_addr_bssid,
2316      {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
2317       "Basic Service Set ID", HFILL }},
2318
2319     {&hf_frag_number,
2320      {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
2321       "Fragment number", HFILL }},
2322
2323     {&hf_seq_number,
2324      {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
2325       "Sequence number", HFILL }},
2326
2327     {&hf_fcs,
2328      {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
2329       NULL, 0, "FCS", HFILL }},
2330
2331     {&hf_fragment_overlap,
2332       {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
2333        NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2334
2335     {&hf_fragment_overlap_conflict,
2336       {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
2337        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2338        "Overlapping fragments contained conflicting data", HFILL }},
2339
2340     {&hf_fragment_multiple_tails,
2341       {"Multiple tail fragments found", "wlan.fragment.multipletails",
2342        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2343        "Several tails were found when defragmenting the packet", HFILL }},
2344
2345     {&hf_fragment_too_long_fragment,
2346       {"Fragment too long", "wlan.fragment.toolongfragment",
2347        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2348        "Fragment contained data past end of packet", HFILL }},
2349
2350     {&hf_fragment_error,
2351       {"Defragmentation error", "wlan.fragment.error",
2352        FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2353        "Defragmentation error due to illegal fragments", HFILL }},
2354
2355     {&hf_fragment,
2356       {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2357        "802.11 Fragment", HFILL }},
2358
2359     {&hf_fragments,
2360       {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2361        "802.11 Fragments", HFILL }},
2362
2363     {&hf_reassembled_in,
2364       {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2365        "This 802.11 packet is reassembled in this frame", HFILL }},
2366
2367     {&hf_wep_iv,
2368      {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
2369       "Initialization Vector", HFILL }},
2370
2371     {&hf_wep_key,
2372      {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
2373       "Key", HFILL }},
2374
2375     {&hf_wep_icv,
2376      {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
2377       "WEP ICV", HFILL }},
2378   };
2379
2380   static hf_register_info ff[] = {
2381     {&ff_timestamp,
2382      {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
2383       NULL, 0, "", HFILL }},
2384
2385     {&ff_auth_alg,
2386      {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
2387       FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
2388
2389     {&ff_beacon_interval,
2390      {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
2391       "", HFILL }},
2392
2393     {&hf_fixed_parameters,
2394      {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
2395       "", HFILL }},
2396
2397     {&hf_tagged_parameters,
2398      {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
2399       "", HFILL }},
2400
2401     {&ff_capture,
2402      {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
2403       "Capability information", HFILL }},
2404
2405     {&ff_cf_ess,
2406      {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
2407       FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
2408
2409     {&ff_cf_ibss,
2410      {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
2411       FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
2412
2413     {&ff_cf_sta_poll,
2414      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
2415       FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C,
2416       "CF-Poll capabilities for a STA", HFILL }},
2417
2418     {&ff_cf_ap_poll,
2419      {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
2420       FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C,
2421       "CF-Poll capabilities for an AP", HFILL }},
2422
2423     {&ff_cf_privacy,
2424      {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
2425       FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
2426
2427     {&ff_cf_preamble,
2428      {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
2429       FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
2430
2431     {&ff_cf_pbcc,
2432      {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
2433       FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
2434
2435     {&ff_cf_agility,
2436      {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
2437       FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
2438
2439     {&ff_short_slot_time,
2440      {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
2441       FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
2442       HFILL }},
2443
2444     {&ff_dsss_ofdm,
2445      {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
2446       FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
2447       HFILL }},
2448
2449     {&ff_auth_seq,
2450      {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
2451       FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
2452
2453     {&ff_assoc_id,
2454      {"Association ID", "wlan_mgt.fixed.aid",
2455       FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
2456
2457     {&ff_listen_ival,
2458      {"Listen Interval", "wlan_mgt.fixed.listen_ival",
2459       FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
2460
2461     {&ff_current_ap,
2462      {"Current AP", "wlan_mgt.fixed.current_ap",
2463       FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
2464
2465     {&ff_reason,
2466      {"Reason code", "wlan_mgt.fixed.reason_code",
2467       FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
2468       "Reason for unsolicited notification", HFILL }},
2469
2470     {&ff_status_code,
2471      {"Status code", "wlan_mgt.fixed.status_code",
2472       FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
2473       "Status of requested event", HFILL }},
2474
2475     {&tag_number,
2476      {"Tag", "wlan_mgt.tag.number",
2477       FT_UINT16, BASE_DEC, NULL, 0,
2478       "Element ID", HFILL }},
2479
2480     {&tag_length,
2481      {"Tag length", "wlan_mgt.tag.length",
2482       FT_UINT16, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
2483
2484     {&tag_interpretation,
2485      {"Tag interpretation", "wlan_mgt.tag.interpretation",
2486       FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}
2487
2488   };
2489
2490   static gint *tree_array[] = {
2491     &ett_80211,
2492     &ett_fc_tree,
2493     &ett_proto_flags,
2494     &ett_fragments,
2495     &ett_fragment,
2496     &ett_80211_mgt,
2497     &ett_fixed_parameters,
2498     &ett_tagged_parameters,
2499     &ett_wep_parameters,
2500     &ett_cap_tree,
2501   };
2502   module_t *wlan_module;
2503
2504   static const enum_val_t wep_keys_options[] = {
2505     {"0", 0},
2506     {"1", 1},
2507     {"2", 2},
2508     {"3", 3},
2509     {"4", 4},
2510     {NULL, -1},
2511   };
2512
2513
2514   proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
2515                                         "IEEE 802.11", "wlan");
2516   proto_register_field_array (proto_wlan, hf, array_length (hf));
2517   proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
2518                                         "802.11 MGT", "wlan_mgt");
2519   proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
2520   proto_register_subtree_array (tree_array, array_length (tree_array));
2521
2522   register_dissector("wlan", dissect_ieee80211, proto_wlan);
2523   register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
2524   register_init_routine(wlan_defragment_init);
2525
2526   /* Register configuration options */
2527   wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);
2528   prefs_register_bool_preference(wlan_module, "defragment",
2529         "Reassemble fragmented 802.11 datagrams",
2530         "Whether fragmented 802.11 datagrams should be reassembled",
2531         &wlan_defragment);
2532
2533   prefs_register_bool_preference(wlan_module, "check_fcs",
2534                                  "Assume packets have FCS",
2535                                  "Some 802.11 cards include the FCS at the end of a packet, others do not.",
2536                                  &wlan_check_fcs);
2537
2538   prefs_register_bool_preference(wlan_module, "ignore_wep",
2539                                  "Ignore the WEP bit",
2540                                  "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
2541                                  &wlan_ignore_wep);
2542
2543 #ifndef USE_ENV
2544   prefs_register_enum_preference(wlan_module, "wep_keys",
2545                                  "WEP key count",
2546                                  "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
2547                                  &num_wepkeys, wep_keys_options, FALSE);
2548
2549   prefs_register_string_preference(wlan_module, "wep_key1",
2550                                    "WEP key #1",
2551                                    "First WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
2552                                    &wep_keystr[0]);
2553   prefs_register_string_preference(wlan_module, "wep_key2",
2554                                    "WEP key #2",
2555                                    "Second WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
2556                                    &wep_keystr[1]);
2557   prefs_register_string_preference(wlan_module, "wep_key3",
2558                                    "WEP key #3",
2559                                    "Third WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
2560                                    &wep_keystr[2]);
2561   prefs_register_string_preference(wlan_module, "wep_key4",
2562                                    "WEP key #4",
2563                                    "Fourth WEP key (A:B:C:D:E) [40bit] (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
2564                                    &wep_keystr[3]);
2565 #endif
2566 }
2567
2568 void
2569 proto_reg_handoff_ieee80211(void)
2570 {
2571   dissector_handle_t ieee80211_handle;
2572   dissector_handle_t ieee80211_radio_handle;
2573
2574   /*
2575    * Get handles for the LLC and IPX dissectors.
2576    */
2577   llc_handle = find_dissector("llc");
2578   ipx_handle = find_dissector("ipx");
2579   data_handle = find_dissector("data");
2580
2581   ieee80211_handle = find_dissector("wlan");
2582   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
2583   ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
2584                                                    proto_wlan);
2585   dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
2586                 ieee80211_radio_handle);
2587 }
2588
2589 static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
2590   guint8 *tmp = NULL;
2591   int i;
2592   tvbuff_t *decr_tvb = NULL;
2593
2594   if (num_wepkeys < 1)
2595     return NULL;
2596
2597   if ((tmp = g_malloc(len)) == NULL)
2598     return NULL;  /* krap! */
2599
2600   /* try once with the key index in the packet, then look through our list. */
2601   for (i = -1; i < (int) num_wepkeys; i++) {
2602     /* copy the encrypted data over to the tmp buffer */
2603 #if 0
2604     printf("trying %d\n", i);
2605 #endif
2606     tvb_memcpy(tvb, tmp, offset, len);
2607     if (wep_decrypt(tmp, len, i) == 0) {
2608
2609       /* decrypt successful, let's set up a new data tvb. */
2610       decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
2611       tvb_set_free_cb(decr_tvb, g_free);
2612       tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
2613
2614       goto done;
2615     }
2616   }
2617
2618  done:
2619   if ((!decr_tvb) && (tmp))    g_free(tmp);
2620
2621 #if 0
2622   printf("de-wep %p\n", decr_tvb);
2623 #endif
2624
2625   return decr_tvb;
2626 }
2627
2628
2629 /* de-weps the block.  if successful, buf* will point to the data start. */
2630 static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
2631   guint32 i, j, k, crc, keylen;
2632   guint8 s[256], key[128], c_crc[4];
2633   guint8 keyidx, *dpos, *cpos;
2634
2635   /* Needs to be at least 8 bytes of payload */
2636   if (len < 8)
2637     return -1;
2638
2639   /* initialize the first bytes of the key from the IV */
2640   key[0] = buf[0];
2641   key[1] = buf[1];
2642   key[2] = buf[2];
2643   keyidx = COOK_WEP_KEY(buf[3]);
2644
2645   if (key_override >= 0)
2646     keyidx = key_override;
2647
2648   if (keyidx >= num_wepkeys)
2649     return -1;
2650
2651   keylen = wep_keylens[keyidx];
2652
2653   if (keylen == 0)
2654     return -1;
2655   if (wep_keys[keyidx] == NULL)
2656     return -1;
2657
2658   keylen+=3;  /* add in ICV bytes */
2659
2660   /* copy the rest of the key over from the designated key */
2661   memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
2662
2663 #if 0
2664   printf("%d: %02x %02x %02x (%d %d) %02x:%02x:%02x:%02x:%02x\n", len, key[0], key[1], key[2], keyidx, keylen, key[3], key[4], key[5], key[6], key[7]);
2665 #endif
2666
2667   /* set up the RC4 state */
2668   for (i = 0; i < 256; i++)
2669     s[i] = i;
2670   j = 0;
2671   for (i = 0; i < 256; i++) {
2672     j = (j + s[i] + key[i % keylen]) & 0xff;
2673     SSWAP(i,j);
2674   }
2675
2676   /* Apply the RC4 to the data, update the CRC32 */
2677   cpos = buf+4;
2678   dpos = buf;
2679   crc = ~0;
2680   i = j = 0;
2681   for (k = 0; k < (len -8); k++) {
2682     i = (i+1) & 0xff;
2683     j = (j+s[i]) & 0xff;
2684     SSWAP(i,j);
2685 #if 0
2686     printf("%d -- %02x ", k, *dpos);
2687 #endif
2688     *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
2689 #if 0
2690     printf("%02x\n", *dpos);
2691 #endif
2692     crc = crc32_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
2693   }
2694   crc = ~crc;
2695
2696   /* now let's check the crc */
2697   c_crc[0] = crc;
2698   c_crc[1] = crc >> 8;
2699   c_crc[2] = crc >> 16;
2700   c_crc[3] = crc >> 24;
2701
2702   for (k = 0; k < 4; k++) {
2703     i = (i + 1) & 0xff;
2704     j = (j+s[i]) & 0xff;
2705     SSWAP(i,j);
2706 #if 0
2707     printf("-- %02x %02x\n", *dpos, c_crc[k]);
2708 #endif
2709     if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
2710       return -1; /* ICV mismatch */
2711   }
2712
2713   return 0;
2714 }
2715
2716 static void init_wepkeys(void) {
2717   char *tmp, *tmp2;
2718   guint8 *tmp3;
2719   guint i, j;
2720
2721 #ifdef USE_ENV
2722   guint8 buf[128];
2723
2724   tmp = getenv("ETHEREAL_WEPKEYNUM");
2725   if (!tmp) {
2726     num_wepkeys = 0;
2727     return;
2728   }
2729   num_wepkeys = atoi(tmp);
2730 #else
2731   if (num_wepkeys > 4)
2732     num_wepkeys = 4;
2733 #endif
2734
2735   if (num_wepkeys < 1)
2736     return;
2737
2738   if (wep_keys)
2739     g_free(wep_keys);
2740
2741   if (wep_keylens)
2742     g_free(wep_keylens);
2743
2744   wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
2745   wep_keylens = g_malloc(num_wepkeys * sizeof(int));
2746
2747   for (i = 0 ; i < num_wepkeys; i++) {
2748     wep_keys[i] = NULL;
2749     wep_keylens[i] = 0;
2750
2751 #ifdef USE_ENV
2752     sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
2753     tmp = getenv(buf);
2754 #else
2755     tmp = wep_keystr[i];
2756 #endif
2757
2758     if (tmp) {
2759       j = 0;
2760 #if 0
2761 #ifdef USE_ENV
2762       printf("%s -- %s\n", buf, tmp);
2763 #else
2764       printf("%d -- %s\n", i+1, tmp);
2765 #endif
2766 #endif
2767
2768       if (wep_keys[i])
2769         g_free(wep_keys[i]);
2770       wep_keys[i] = g_malloc(32 * sizeof(guint8));
2771       memset(wep_keys[i], 0, 32 * sizeof(guint8));
2772       tmp3 = wep_keys[i];
2773       while ((tmp != NULL) && (*tmp != 0)) {
2774         tmp3[j] = strtoul(tmp, &tmp2, 16) & 0xff;
2775 #if 0
2776         printf("%d %d -- %02x\n", i, j, tmp3[j]);
2777 #endif
2778         tmp = tmp2;
2779         wep_keylens[i]++;
2780
2781         if ((tmp != NULL) && (*tmp == ':'))
2782           tmp++;
2783         j++;
2784       }
2785     }
2786
2787   }
2788
2789   return;
2790 }