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