diff options
author | Gilbert Ramirez <gram@alumni.rice.edu> | 2004-07-18 18:06:47 +0000 |
---|---|---|
committer | Gilbert Ramirez <gram@alumni.rice.edu> | 2004-07-18 18:06:47 +0000 |
commit | 669db206cb1f270046ad400fff7655e20c63e723 (patch) | |
tree | 4eff24a2e16c8963e497e1fc575f35e6af59bd26 /packet-ieee80211.c | |
parent | ae46c27a38700af669ef907491081f09df6f6b2c (diff) |
Move dissectors to epan/dissectors directory.
Also move ncp222.py, x11-fields, process-x11-fields.pl,
make-reg-dotc, and make-reg-dotc.py.
Adjust #include lines in files that include packet-*.h
files.
svn path=/trunk/; revision=11410
Diffstat (limited to 'packet-ieee80211.c')
-rw-r--r-- | packet-ieee80211.c | 3445 |
1 files changed, 0 insertions, 3445 deletions
diff --git a/packet-ieee80211.c b/packet-ieee80211.c deleted file mode 100644 index d6f86433a8..0000000000 --- a/packet-ieee80211.c +++ /dev/null @@ -1,3445 +0,0 @@ -/* packet-ieee80211.c - * Routines for Wireless LAN (IEEE 802.11) dissection - * Copyright 2000, Axis Communications AB - * Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com - * - * $Id$ - * - * Ethereal - Network traffic analyzer - * By Gerald Combs <gerald@ethereal.com> - * Copyright 1998 Gerald Combs - * - * Copied from README.developer - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Credits: - * - * The following people helped me by pointing out bugs etc. Thank you! - * - * Marco Molteni - * Lena-Marie Nilsson - * Magnus Hultman-Persson - */ - -/* - * 09/12/2003 - Added dissection of country information tag - * - * Ritchie<at>tipsybottle.com - * - * 03/22/2004 - Added dissection of RSN IE - * Jouni Malinen <jkmaline@cc.hut.fi> - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> - -#ifdef NEED_SNPRINTF_H -# include "snprintf.h" -#endif - -#include <string.h> -#include <glib.h> -#include <epan/bitswap.h> -#include <epan/proto.h> -#include <epan/packet.h> -#include <epan/resolv.h> -#include <epan/strutil.h> -#include "prefs.h" -#include "reassemble.h" -#include "packet-ipx.h" -#include "packet-llc.h" -#include "packet-ieee80211.h" -#include "etypes.h" -#include "crc32.h" - -/* Defragment fragmented 802.11 datagrams */ -static gboolean wlan_defragment = TRUE; - -/* Check for the presence of the 802.11 FCS */ -static gboolean wlan_check_fcs = FALSE; - -/* Ignore the WEP bit; assume packet is decrypted */ -static gboolean wlan_ignore_wep = FALSE; - -/* Tables for reassembly of fragments. */ -static GHashTable *wlan_fragment_table = NULL; -static GHashTable *wlan_reassembled_table = NULL; - -/* Stuff for the WEP decoder */ -static guint num_wepkeys = 0; -static guint8 **wep_keys = NULL; -static int *wep_keylens = NULL; -static void init_wepkeys(void); -static int wep_decrypt(guint8 *buf, guint32 len, int key_override); -static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len); -#define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;} - -/* #define USE_ENV */ -/* When this is set, an unlimited number of WEP keys can be set in the - environment: - - ETHEREAL_WEPKEYNUM=## - ETHEREAL_WEPKEY1=aa:bb:cc:dd:... - ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:... - - ... you get the idea. - - otherwise you're limited to specifying four keys in the preference system. - */ - -#ifndef USE_ENV -static char *wep_keystr[] = {NULL, NULL, NULL, NULL}; -#endif - -/* ************************************************************************* */ -/* Miscellaneous Constants */ -/* ************************************************************************* */ -#define SHORT_STR 256 - -/* ************************************************************************* */ -/* Define some very useful macros that are used to analyze frame types etc. */ -/* ************************************************************************* */ -#define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */ -#define COOK_PROT_VERSION(x) ((x) & 0x3) -#define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2) -#define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4) -#define COOK_ADDR_SELECTOR(x) ((x) & 0x300) -#define COOK_ASSOC_ID(x) ((x) & 0x3FFF) -#define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F) -#define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4) -#define COOK_QOS_PRIORITY(x) ((x) & 0x0007) -#define COOK_QOS_ACK_POLICY(x) (((x) & 0x0060) >> 5) -#define COOK_FLAGS(x) (((x) & 0xFF00) >> 8) -#define COOK_DS_STATUS(x) ((x) & 0x3) -#define COOK_WEP_KEY(x) (((x) & 0xC0) >> 6) - -#define KEY_EXTIV 0x20 -#define EXTIV_LEN 8 - -#define FLAG_TO_DS 0x01 -#define FLAG_FROM_DS 0x02 -#define FLAG_MORE_FRAGMENTS 0x04 -#define FLAG_RETRY 0x08 -#define FLAG_POWER_MGT 0x10 -#define FLAG_MORE_DATA 0x20 -#define FLAG_WEP 0x40 -#define FLAG_ORDER 0x80 - -#define IS_TO_DS(x) ((x) & FLAG_TO_DS) -#define IS_FROM_DS(x) ((x) & FLAG_FROM_DS) -#define HAVE_FRAGMENTS(x) ((x) & FLAG_MORE_FRAGMENTS) -#define IS_RETRY(x) ((x) & FLAG_RETRY) -#define POWER_MGT_STATUS(x) ((x) & FLAG_POWER_MGT) -#define HAS_MORE_DATA(x) ((x) & FLAG_MORE_DATA) -#define IS_WEP(x) (!wlan_ignore_wep && ((x) & FLAG_WEP)) -#define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER) - -#define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F))) -#define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19)) -#define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f)) -#define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f)) - - -/* ************************************************************************* */ -/* Constants used to identify cooked frame types */ -/* ************************************************************************* */ -#define MGT_FRAME 0x00 /* Frame type is management */ -#define CONTROL_FRAME 0x01 /* Frame type is control */ -#define DATA_FRAME 0x02 /* Frame type is Data */ - -#define DATA_SHORT_HDR_LEN 24 -#define DATA_LONG_HDR_LEN 30 -#define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */ - -#define MGT_ASSOC_REQ 0x00 /* Management - association request */ -#define MGT_ASSOC_RESP 0x01 /* Management - association response */ -#define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */ -#define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */ -#define MGT_PROBE_REQ 0x04 /* Management - Probe request */ -#define MGT_PROBE_RESP 0x05 /* Management - Probe response */ -#define MGT_BEACON 0x08 /* Management - Beacon frame */ -#define MGT_ATIM 0x09 /* Management - ATIM */ -#define MGT_DISASS 0x0A /* Management - Disassociation */ -#define MGT_AUTHENTICATION 0x0B /* Management - Authentication */ -#define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */ -#define MGT_ACTION 0x0D /* Management - Action */ - -#define CTRL_PS_POLL 0x1A /* Control - power-save poll */ -#define CTRL_RTS 0x1B /* Control - request to send */ -#define CTRL_CTS 0x1C /* Control - clear to send */ -#define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */ -#define CTRL_CFP_END 0x1E /* Control - contention-free period end */ -#define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */ - -#define DATA 0x20 /* Data - Data */ -#define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */ -#define DATA_CF_POLL 0x22 /* Data - Data + CF poll */ -#define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */ -#define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */ -#define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */ -#define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */ -#define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */ -#define DATA_QOS_DATA 0x28 /* Data - QoS Data */ -#define DATA_QOS_NULL 0x2c /* Data - QoS Null */ - -#define DATA_ADDR_T1 0 -#define DATA_ADDR_T2 (FLAG_FROM_DS << 8) -#define DATA_ADDR_T3 (FLAG_TO_DS << 8) -#define DATA_ADDR_T4 ((FLAG_TO_DS|FLAG_FROM_DS) << 8) - - -/* ************************************************************************* */ -/* Macros used to extract information about fixed fields */ -/* ************************************************************************* */ -#define ESS_SET(x) ((x) & 0x0001) -#define IBSS_SET(x) ((x) & 0x0002) - - - -/* ************************************************************************* */ -/* Logical field codes (dissector's encoding of fixed fields) */ -/* ************************************************************************* */ -#define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */ -#define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */ -#define FIELD_CAP_INFO 0x03 /* Add capability information tree */ -#define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */ -#define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */ -#define FIELD_CURRENT_AP_ADDR 0x06 -#define FIELD_LISTEN_IVAL 0x07 -#define FIELD_REASON_CODE 0x08 -#define FIELD_ASSOC_ID 0x09 -#define FIELD_STATUS_CODE 0x0A -#define FIELD_CATEGORY_CODE 0x0B /* Management action category */ -#define FIELD_ACTION_CODE 0x0C /* Management action code */ -#define FIELD_DIALOG_TOKEN 0x0D /* Management action dialog token */ -#define FIELD_WME_ACTION_CODE 0x0E /* Management notification action code */ -#define FIELD_WME_DIALOG_TOKEN 0x0F /* Management notification dialog token */ -#define FIELD_WME_STATUS_CODE 0x10 /* Management notification setup response status code */ - -/* ************************************************************************* */ -/* Logical field codes (IEEE 802.11 encoding of tags) */ -/* ************************************************************************* */ -#define TAG_SSID 0x00 -#define TAG_SUPP_RATES 0x01 -#define TAG_FH_PARAMETER 0x02 -#define TAG_DS_PARAMETER 0x03 -#define TAG_CF_PARAMETER 0x04 -#define TAG_TIM 0x05 -#define TAG_IBSS_PARAMETER 0x06 -#define TAG_COUNTRY_INFO 0x07 -#define TAG_FH_HOPPING_PARAMETER 0x08 -#define TAG_FH_HOPPING_TABLE 0x09 -#define TAG_CHALLENGE_TEXT 0x10 -#define TAG_ERP_INFO 0x2A -#define TAG_ERP_INFO_OLD 0x2F /* IEEE Std 802.11g/D4.0 */ -#define TAG_RSN_IE 0x30 -#define TAG_EXT_SUPP_RATES 0x32 -#define TAG_VENDOR_SPECIFIC_IE 0xDD - -#define WPA_OUI "\x00\x50\xF2" -#define RSN_OUI "\x00\x0F\xAC" -#define WME_OUI "\x00\x50\xF2" - -#define PMKID_LEN 16 - -/* ************************************************************************* */ -/* Frame types, and their names */ -/* ************************************************************************* */ -static const value_string frame_type_subtype_vals[] = { - {MGT_ASSOC_REQ, "Association Request"}, - {MGT_ASSOC_RESP, "Association Response"}, - {MGT_REASSOC_REQ, "Reassociation Request"}, - {MGT_REASSOC_RESP, "Reassociation Response"}, - {MGT_PROBE_REQ, "Probe Request"}, - {MGT_PROBE_RESP, "Probe Response"}, - {MGT_BEACON, "Beacon frame"}, - {MGT_ATIM, "ATIM"}, - {MGT_DISASS, "Dissassociate"}, - {MGT_AUTHENTICATION, "Authentication"}, - {MGT_DEAUTHENTICATION, "Deauthentication"}, - {MGT_ACTION, "Action"}, - {CTRL_PS_POLL, "Power-Save poll"}, - {CTRL_RTS, "Request-to-send"}, - {CTRL_CTS, "Clear-to-send"}, - {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"}, - {CTRL_CFP_END, "CF-End (Control-frame)"}, - {CTRL_CFP_ENDACK, "CF-End + CF-Ack (Control-frame)"}, - {DATA, "Data"}, - {DATA_CF_ACK, "Data + CF-Acknowledgement"}, - {DATA_CF_POLL, "Data + CF-Poll"}, - {DATA_CF_ACK_POLL, "Data + CF-Acknowledgement/Poll"}, - {DATA_NULL_FUNCTION, "Null function (No data)"}, - {DATA_CF_ACK_NOD, "Data + Acknowledgement (No data)"}, - {DATA_CF_POLL_NOD, "Data + CF-Poll (No data)"}, - {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"}, - {DATA_QOS_DATA, "QoS Data"}, - {DATA_QOS_NULL, "QoS Null (No data)"}, - {0, NULL} -}; - -/* ************************************************************************* */ -/* 802.1D Tag Names */ -/* ************************************************************************* */ -static const char *qos_tags[8] = { - "Best Effort", - "Background", - "Spare", - "Excellent Effort", - "Controlled Load", - "Video", - "Voice", - "Network Control" -}; - -/* ************************************************************************* */ -/* WME Access Category Names (by 802.1D Tag) */ -/* ************************************************************************* */ -static const char *qos_acs[8] = { - "Best Effort", - "Background", - "Background", - "Video", - "Video", - "Video", - "Voice", - "Voice" -}; - -/* ************************************************************************* */ -/* WME Access Category Names (by WME ACI) */ -/* ************************************************************************* */ -static const char *wme_acs[4] = { - "Best Effort", - "Background", - "Video", - "Voice", -}; - -static int proto_wlan = -1; - -/* ************************************************************************* */ -/* Header field info values for radio information */ -/* ************************************************************************* */ -static int hf_data_rate = -1; -static int hf_channel = -1; -static int hf_signal_strength = -1; - -/* ************************************************************************* */ -/* Header field info values for FC-field */ -/* ************************************************************************* */ -static int hf_fc_field = -1; -static int hf_fc_proto_version = -1; -static int hf_fc_frame_type = -1; -static int hf_fc_frame_subtype = -1; -static int hf_fc_frame_type_subtype = -1; - -static int hf_fc_flags = -1; -static int hf_fc_to_ds = -1; -static int hf_fc_from_ds = -1; -static int hf_fc_data_ds = -1; - -static int hf_fc_more_frag = -1; -static int hf_fc_retry = -1; -static int hf_fc_pwr_mgt = -1; -static int hf_fc_more_data = -1; -static int hf_fc_wep = -1; -static int hf_fc_order = -1; - - -/* ************************************************************************* */ -/* Header values for Duration/ID field */ -/* ************************************************************************* */ -static int hf_did_duration = -1; -static int hf_assoc_id = -1; - - -/* ************************************************************************* */ -/* Header values for different address-fields (all 4 of them) */ -/* ************************************************************************* */ -static int hf_addr_da = -1; /* Destination address subfield */ -static int hf_addr_sa = -1; /* Source address subfield */ -static int hf_addr_ra = -1; /* Receiver address subfield */ -static int hf_addr_ta = -1; /* Transmitter address subfield */ -static int hf_addr_bssid = -1; /* address is bssid */ - -static int hf_addr = -1; /* Source or destination address subfield */ - - -/* ************************************************************************* */ -/* Header values for QoS control field */ -/* ************************************************************************* */ -static int hf_qos_priority = -1; -static int hf_qos_ack_policy = -1; - -/* ************************************************************************* */ -/* Header values for sequence number field */ -/* ************************************************************************* */ -static int hf_frag_number = -1; -static int hf_seq_number = -1; - -/* ************************************************************************* */ -/* Header values for Frame Check field */ -/* ************************************************************************* */ -static int hf_fcs = -1; - -/* ************************************************************************* */ -/* Header values for reassembly */ -/* ************************************************************************* */ -static int hf_fragments = -1; -static int hf_fragment = -1; -static int hf_fragment_overlap = -1; -static int hf_fragment_overlap_conflict = -1; -static int hf_fragment_multiple_tails = -1; -static int hf_fragment_too_long_fragment = -1; -static int hf_fragment_error = -1; -static int hf_reassembled_in = -1; - - -static int proto_wlan_mgt = -1; -/* ************************************************************************* */ -/* Fixed fields found in mgt frames */ -/* ************************************************************************* */ -static int ff_auth_alg = -1; /* Authentication algorithm field */ -static int ff_auth_seq = -1; /* Authentication transaction sequence */ -static int ff_current_ap = -1; /* Current AP MAC address */ -static int ff_listen_ival = -1; /* Listen interval fixed field */ -static int ff_timestamp = -1; /* 64 bit timestamp */ -static int ff_beacon_interval = -1; /* 16 bit Beacon interval */ -static int ff_assoc_id = -1; /* 16 bit AID field */ -static int ff_reason = -1; /* 16 bit reason code */ -static int ff_status_code = -1; /* Status code */ -static int ff_category_code = -1; /* 8 bit Category code */ -static int ff_action_code = -1; /* 8 bit Action code */ -static int ff_dialog_token = -1; /* 8 bit Dialog token */ -static int ff_wme_action_code = -1; /* Management notification action code */ -static int ff_wme_status_code = -1; /* Management notification setup response status code */ - -/* ************************************************************************* */ -/* Flags found in the capability field (fixed field) */ -/* ************************************************************************* */ -static int ff_capture = -1; -static int ff_cf_ess = -1; -static int ff_cf_ibss = -1; -static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */ -static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */ -static int ff_cf_privacy = -1; -static int ff_cf_preamble = -1; -static int ff_cf_pbcc = -1; -static int ff_cf_agility = -1; -static int ff_short_slot_time = -1; -static int ff_dsss_ofdm = -1; - -/* ************************************************************************* */ -/* Tagged value format fields */ -/* ************************************************************************* */ -static int tag_number = -1; -static int tag_length = -1; -static int tag_interpretation = -1; - - - -static int hf_fixed_parameters = -1; /* Protocol payload for management frames */ -static int hf_tagged_parameters = -1; /* Fixed payload item */ -static int hf_wep_iv = -1; -static int hf_tkip_extiv = -1; -static int hf_ccmp_extiv = -1; -static int hf_wep_key = -1; -static int hf_wep_icv = -1; - - -static int rsn_cap = -1; -static int rsn_cap_preauth = -1; -static int rsn_cap_no_pairwise = -1; -static int rsn_cap_ptksa_replay_counter = -1; -static int rsn_cap_gtksa_replay_counter = -1; - -/* ************************************************************************* */ -/* Protocol trees */ -/* ************************************************************************* */ -static gint ett_80211 = -1; -static gint ett_proto_flags = -1; -static gint ett_cap_tree = -1; -static gint ett_fc_tree = -1; -static gint ett_fragments = -1; -static gint ett_fragment = -1; - -static gint ett_80211_mgt = -1; -static gint ett_fixed_parameters = -1; -static gint ett_tagged_parameters = -1; -static gint ett_qos_parameters = -1; -static gint ett_wep_parameters = -1; - -static gint ett_rsn_cap_tree = -1; - -static const fragment_items frag_items = { - &ett_fragment, - &ett_fragments, - &hf_fragments, - &hf_fragment, - &hf_fragment_overlap, - &hf_fragment_overlap_conflict, - &hf_fragment_multiple_tails, - &hf_fragment_too_long_fragment, - &hf_fragment_error, - &hf_reassembled_in, - "fragments" -}; - -static dissector_handle_t llc_handle; -static dissector_handle_t ipx_handle; -static dissector_handle_t eth_handle; -static dissector_handle_t data_handle; - -/* ************************************************************************* */ -/* Return the length of the current header (in bytes) */ -/* ************************************************************************* */ -static int -find_header_length (guint16 fcf) -{ - int len; - - switch (COOK_FRAME_TYPE (fcf)) { - - case MGT_FRAME: - return MGT_FRAME_HDR_LEN; - - case CONTROL_FRAME: - switch (COMPOSE_FRAME_TYPE (fcf)) { - - case CTRL_CTS: - case CTRL_ACKNOWLEDGEMENT: - return 10; - - case CTRL_RTS: - case CTRL_PS_POLL: - case CTRL_CFP_END: - case CTRL_CFP_ENDACK: - return 16; - } - return 4; /* XXX */ - - case DATA_FRAME: - len = (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN : - DATA_SHORT_HDR_LEN; - switch (COMPOSE_FRAME_TYPE (fcf)) { - - case DATA_QOS_DATA: - case DATA_QOS_NULL: - return len + 2; - - default: - return len; - } - default: - return 4; /* XXX */ - } -} - - -/* ************************************************************************* */ -/* This is the capture function used to update packet counts */ -/* ************************************************************************* */ -static void -capture_ieee80211_common (const guchar * pd, int offset, int len, - packet_counts * ld, gboolean fixed_length_header) -{ - guint16 fcf, hdr_length; - - if (!BYTES_ARE_IN_FRAME(offset, len, 2)) { - ld->other++; - return; - } - - fcf = pletohs (&pd[0]); - - if (IS_WEP(COOK_FLAGS(fcf))) - { - ld->other++; - return; - } - - switch (COMPOSE_FRAME_TYPE (fcf)) - { - - case DATA: /* We got a data frame */ - case DATA_CF_ACK: /* Data with ACK */ - case DATA_CF_POLL: - case DATA_CF_ACK_POLL: - case DATA_QOS_DATA: - if (fixed_length_header) - hdr_length = DATA_LONG_HDR_LEN; - else - hdr_length = find_header_length (fcf); - /* I guess some bridges take Netware Ethernet_802_3 frames, - which are 802.3 frames (with a length field rather than - a type field, but with no 802.2 header in the payload), - and just stick the payload into an 802.11 frame. I've seen - captures that show frames of that sort. - - This means we have to do the same check for Netware 802.3 - - or, if you will, "Netware 802.11" - that we do in the - Ethernet dissector, i.e. checking for 0xffff as the first - four bytes of the payload and, if we find it, treating it - as an IPX frame. */ - if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) { - ld->other++; - return; - } - if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) { - capture_ipx (ld); - } - else { - capture_llc (pd, offset + hdr_length, len, ld); - } - break; - - default: - ld->other++; - break; - } -} - -/* - * Handle 802.11 with a variable-length link-layer header. - */ -void -capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld) -{ - capture_ieee80211_common (pd, offset, len, ld, FALSE); -} - -/* - * Handle 802.11 with a fixed-length link-layer header (padded to the - * maximum length). - */ -void -capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld) -{ - capture_ieee80211_common (pd, offset, len, ld, TRUE); -} - - -/* ************************************************************************* */ -/* Add the subtree used to store the fixed parameters */ -/* ************************************************************************* */ -static proto_tree * -get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size) -{ - proto_item *fixed_fields; - fixed_fields = - proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start, - size, size, "Fixed parameters (%d bytes)", - size); - - return proto_item_add_subtree (fixed_fields, ett_fixed_parameters); -} - - -/* ************************************************************************* */ -/* Add the subtree used to store tagged parameters */ -/* ************************************************************************* */ -static proto_tree * -get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size) -{ - proto_item *tagged_fields; - - tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters, - tvb, - start, - size, - size, - "Tagged parameters (%d bytes)", - size); - - return proto_item_add_subtree (tagged_fields, ett_tagged_parameters); -} - - -/* ************************************************************************* */ -/* Dissect and add fixed mgmt fields to protocol tree */ -/* ************************************************************************* */ -static void -add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode) -{ - const guint8 *dataptr; - char out_buff[SHORT_STR]; - guint16 capability; - proto_item *cap_item; - static proto_tree *cap_tree; - double temp_double; - - switch (lfcode) - { - case FIELD_TIMESTAMP: - dataptr = tvb_get_ptr (tvb, offset, 8); - memset (out_buff, 0, SHORT_STR); - snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X", - dataptr[7], - dataptr[6], - dataptr[5], - dataptr[4], - dataptr[3], - dataptr[2], - dataptr[1], - dataptr[0]); - - proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff); - break; - - case FIELD_BEACON_INTERVAL: - temp_double = (double) tvb_get_letohs (tvb, offset); - temp_double = temp_double * 1024 / 1000000; - proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2, - temp_double,"Beacon Interval: %f [Seconds]", - temp_double); - break; - - - case FIELD_CAP_INFO: - capability = tvb_get_letohs (tvb, offset); - - cap_item = proto_tree_add_uint_format (tree, ff_capture, - tvb, offset, 2, - capability, - "Capability Information: 0x%04X", - capability); - cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree); - proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2, - capability); - proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2, - capability); - if (ESS_SET (capability) != 0) /* This is an AP */ - proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2, - capability); - - else /* This is a STA */ - proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2, - capability); - proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2, - capability); - proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2, - capability); - proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2, - capability); - proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2, - capability); - proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2, - capability); - proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2, - capability); - break; - - case FIELD_AUTH_ALG: - proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE); - break; - - case FIELD_AUTH_TRANS_SEQ: - proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE); - break; - - case FIELD_CURRENT_AP_ADDR: - proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE); - break; - - case FIELD_LISTEN_IVAL: - proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE); - break; - - case FIELD_REASON_CODE: - proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE); - break; - - case FIELD_ASSOC_ID: - proto_tree_add_uint(tree, ff_assoc_id, tvb, offset, 2, - COOK_ASSOC_ID(tvb_get_letohs(tvb,offset))); - /* proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE); */ - break; - - case FIELD_STATUS_CODE: - proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE); - break; - - case FIELD_CATEGORY_CODE: - proto_tree_add_item (tree, ff_category_code, tvb, offset, 1, TRUE); - break; - - case FIELD_ACTION_CODE: - proto_tree_add_item (tree, ff_action_code, tvb, offset, 1, TRUE); - break; - - case FIELD_DIALOG_TOKEN: - proto_tree_add_item (tree, ff_dialog_token, tvb, offset, 1, TRUE); - break; - - case FIELD_WME_ACTION_CODE: - proto_tree_add_item (tree, ff_wme_action_code, tvb, offset, 1, TRUE); - break; - - case FIELD_WME_STATUS_CODE: - proto_tree_add_item (tree, ff_wme_status_code, tvb, offset, 1, TRUE); - break; - } -} - -static char *wpa_cipher_str[] = -{ - "NONE", - "WEP (40-bit)", - "TKIP", - "AES (OCB)", - "AES (CCM)", - "WEP (104-bit)", -}; - -static char * -wpa_cipher_idx2str(guint idx) -{ - if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0])) - return wpa_cipher_str[idx]; - return "UNKNOWN"; -} - -static char *wpa_keymgmt_str[] = -{ - "NONE", - "WPA", - "PSK", -}; - -static char * -wpa_keymgmt_idx2str(guint idx) -{ - if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0])) - return wpa_keymgmt_str[idx]; - return "UNKNOWN"; -} - -static void -dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset, - guint32 tag_len, const guint8 *tag_val) -{ - guint32 tag_val_off = 0; - char out_buff[SHORT_STR], *pos; - guint i; - - /* Wi-Fi Protected Access (WPA) Information Element */ - if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) { - snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u", - tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4])); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff); - offset += 6; - tag_val_off += 6; - if (tag_val_off + 4 <= tag_len) { - /* multicast cipher suite */ - if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) { - snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s", - wpa_cipher_idx2str(tag_val[tag_val_off + 3])); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff); - offset += 4; - tag_val_off += 4; - /* unicast cipher suites */ - if (tag_val_off + 2 <= tag_len) { - snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", - pletohs(tag_val + tag_val_off)); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - i = 1; - while (tag_val_off + 4 <= tag_len) { - if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) { - snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s", - i, wpa_cipher_idx2str(tag_val[tag_val_off + 3])); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff); - offset += 4; - tag_val_off += 4; - i ++; - } - else - break; - } - /* authenticated key management suites */ - if (tag_val_off + 2 <= tag_len) { - snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", - pletohs(tag_val + tag_val_off)); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - i = 1; - while (tag_val_off + 4 <= tag_len) { - if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) { - snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s", - i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3])); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff); - offset += 4; - tag_val_off += 4; - i ++; - } - else - break; - } - } - } - } - } - if (tag_val_off < tag_len) - proto_tree_add_string(tree, tag_interpretation, tvb, - offset, tag_len - tag_val_off, "Not interpreted"); - } else if (tag_val_off + 7 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x00", 5)) { - /* Wireless Multimedia Enhancements (WME) Information Element */ - snprintf(out_buff, SHORT_STR, "WME IE: type %u, subtype %u, version %u, parameter set %u", - tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5], - tag_val[tag_val_off + 6]); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff); - } else if (tag_val_off + 24 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x01", 5)) { - /* Wireless Multimedia Enhancements (WME) Parameter Element */ - snprintf(out_buff, SHORT_STR, "WME PE: type %u, subtype %u, version %u, parameter set %u", - tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5], - tag_val[tag_val_off + 6]); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff); - offset += 8; - tag_val_off += 8; - for (i = 0; i < 4; i++) { - snprintf(out_buff, SHORT_STR, "WME AC Parameters: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u", - (tag_val[tag_val_off] & 0x60) >> 5, - wme_acs[(tag_val[tag_val_off] & 0x60) >> 5], - (tag_val[tag_val_off] & 0x10) ? "" : "not ", - tag_val[tag_val_off] & 0x0f, - tag_val[tag_val_off + 1] & 0x0f, - (tag_val[tag_val_off + 1] & 0xf0) >> 4, - tvb_get_letohs(tvb, offset + 2)); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff); - offset += 4; - tag_val_off += 4; - } - } else if (tag_val_off + 56 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x02", 5)) { - /* Wireless Multimedia Enhancements (WME) TSPEC Element */ - guint16 ts_info, msdu_size, surplus_bandwidth; - const char *direction[] = { "Uplink", "Downlink", "Reserved", "Bi-directional" }; - const value_string fields[] = { - {12, "Minimum Service Interval"}, - {16, "Maximum Service Interval"}, - {20, "Inactivity Interval"}, - {24, "Service Start Time"}, - {28, "Minimum Data Rate"}, - {32, "Mean Data Rate"}, - {36, "Maximum Burst Size"}, - {40, "Minimum PHY Rate"}, - {44, "Peak Data Rate"}, - {48, "Delay Bound"}, - {0, NULL} - }; - char *field; - - snprintf(out_buff, SHORT_STR, "WME TSPEC: type %u, subtype %u, version %u", - tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5]); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff); - offset += 6; - tag_val_off += 6; - - ts_info = tvb_get_letohs(tvb, offset); - snprintf(out_buff, SHORT_STR, "WME TS Info: Priority %u (%s) (%s), Contention-based access %sset, %s", - (ts_info >> 11) & 0x7, qos_tags[(ts_info >> 11) & 0x7], qos_acs[(ts_info >> 11) & 0x7], - (ts_info & 0x0080) ? "" : "not ", - direction[(ts_info >> 5) & 0x3]); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - - msdu_size = tvb_get_letohs(tvb, offset); - snprintf(out_buff, SHORT_STR, "WME TSPEC: %s MSDU Size %u", - (msdu_size & 0x8000) ? "Fixed" : "Nominal", msdu_size & 0x7fff); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - - snprintf(out_buff, SHORT_STR, "WME TSPEC: Maximum MSDU Size %u", tvb_get_letohs(tvb, offset)); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - - while ((field = val_to_str(tag_val_off, fields, NULL))) { - snprintf(out_buff, SHORT_STR, "WME TSPEC: %s %u", field, tvb_get_letohl(tvb, offset)); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff); - offset += 4; - tag_val_off += 4; - if (tag_val_off == 52) - break; - } - - surplus_bandwidth = tvb_get_letohs(tvb, offset); - snprintf(out_buff, SHORT_STR, "WME TSPEC: Surplus Bandwidth Allowance Factor %u.%u", - (surplus_bandwidth >> 13) & 0x7, (surplus_bandwidth & 0x1fff)); - offset += 2; - tag_val_off += 2; - - snprintf(out_buff, SHORT_STR, "WME TSPEC: Medium Time %u", tvb_get_letohs(tvb, offset)); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - } else if (tag_val_off + 4 <= tag_len && !memcmp(tag_val, RSN_OUI"\x04", 4)) { - /* IEEE 802.11i / Key Data Encapsulation / Data Type=4 - PMKID. - * This is only used within EAPOL-Key frame Key Data. */ - pos = out_buff; - pos += snprintf(pos, out_buff + SHORT_STR - pos, "RSN PMKID: "); - if (tag_len - 4 != PMKID_LEN) { - pos += snprintf(pos, out_buff + SHORT_STR - pos, - "(invalid PMKID len=%d, expected 16) ", tag_len - 4); - } - for (i = 0; i < tag_len - 4; i++) { - pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X", - tag_val[tag_val_off + 4 + i]); - } - proto_tree_add_string(tree, tag_interpretation, tvb, offset, - tag_len, out_buff); - } else - proto_tree_add_string(tree, tag_interpretation, - tvb, offset, tag_len, "Not interpreted"); -} - -static void -dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset, - guint32 tag_len, const guint8 *tag_val) -{ - guint32 tag_val_off = 0; - guint16 rsn_capab; - char out_buff[SHORT_STR]; - int i, j, count; - proto_item *cap_item; - proto_tree *cap_tree; - - if (tag_val_off + 2 > tag_len) { - proto_tree_add_string(tree, tag_interpretation, tvb, offset, tag_len, - "Not interpreted"); - return; - } - - snprintf(out_buff, SHORT_STR, "RSN IE, version %u", - pletohs(&tag_val[tag_val_off])); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - - offset += 2; - tag_val_off += 2; - - if (tag_val_off + 4 > tag_len) - goto done; - - /* multicast cipher suite */ - if (!memcmp(&tag_val[tag_val_off], RSN_OUI, 3)) { - snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s", - wpa_cipher_idx2str(tag_val[tag_val_off + 3])); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff); - offset += 4; - tag_val_off += 4; - } - - if (tag_val_off + 2 > tag_len) - goto done; - - /* unicast cipher suites */ - count = pletohs(tag_val + tag_val_off); - snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", count); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - i = 1; - while (tag_val_off + 4 <= tag_len && i <= count) { - if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0) - goto done; - snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s", - i, wpa_cipher_idx2str(tag_val[tag_val_off + 3])); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff); - offset += 4; - tag_val_off += 4; - i++; - } - - if (i <= count || tag_val_off + 2 > tag_len) - goto done; - - /* authenticated key management suites */ - count = pletohs(tag_val + tag_val_off); - snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", count); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - i = 1; - while (tag_val_off + 4 <= tag_len && i <= count) { - if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0) - goto done; - snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s", - i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3])); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff); - offset += 4; - tag_val_off += 4; - i++; - } - - if (i <= count || tag_val_off + 2 > tag_len) - goto done; - - rsn_capab = pletohs(&tag_val[tag_val_off]); - snprintf(out_buff, SHORT_STR, "RSN Capabilities 0x%04x", rsn_capab); - cap_item = proto_tree_add_uint_format(tree, rsn_cap, tvb, - offset, 2, rsn_capab, - "RSN Capabilities: 0x%04X", rsn_capab); - cap_tree = proto_item_add_subtree(cap_item, ett_rsn_cap_tree); - proto_tree_add_boolean(cap_tree, rsn_cap_preauth, tvb, offset, 2, - rsn_capab); - proto_tree_add_boolean(cap_tree, rsn_cap_no_pairwise, tvb, offset, 2, - rsn_capab); - proto_tree_add_uint(cap_tree, rsn_cap_ptksa_replay_counter, tvb, offset, 2, - rsn_capab); - proto_tree_add_uint(cap_tree, rsn_cap_gtksa_replay_counter, tvb, offset, 2, - rsn_capab); - offset += 2; - tag_val_off += 2; - - if (tag_val_off + 2 > tag_len) - goto done; - - count = pletohs(tag_val + tag_val_off); - snprintf(out_buff, SHORT_STR, "# of PMKIDs: %u", count); - proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff); - offset += 2; - tag_val_off += 2; - - /* PMKID List (16 * n octets) */ - for (i = 0; i < count; i++) { - char *pos; - if (tag_val_off + PMKID_LEN > tag_len) - goto done; - pos = out_buff; - pos += snprintf(pos, out_buff + SHORT_STR - pos, "PMKID %u: ", i); - for (j = 0; j < PMKID_LEN; j++) { - pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X", - tag_val[tag_val_off + j]); - } - proto_tree_add_string(tree, tag_interpretation, tvb, offset, - PMKID_LEN, out_buff); - offset += PMKID_LEN; - tag_val_off += PMKID_LEN; - } - - done: - if (tag_val_off < tag_len) - proto_tree_add_string(tree, tag_interpretation, tvb, offset, - tag_len - tag_val_off, "Not interpreted"); -} - -/* ************************************************************************* */ -/* Dissect and add tagged (optional) fields to proto tree */ -/* ************************************************************************* */ - -static const value_string tag_num_vals[] = { - { TAG_SSID, "SSID parameter set" }, - { TAG_SUPP_RATES, "Supported Rates" }, - { TAG_FH_PARAMETER, "FH Parameter set" }, - { TAG_DS_PARAMETER, "DS Parameter set" }, - { TAG_CF_PARAMETER, "CF Parameter set" }, - { TAG_TIM, "(TIM) Traffic Indication Map" }, - { TAG_IBSS_PARAMETER, "IBSS Parameter set" }, - { TAG_COUNTRY_INFO, "Country Information" }, - { TAG_FH_HOPPING_PARAMETER, "Hopping Pattern Parameters" }, - { TAG_CHALLENGE_TEXT, "Challenge text" }, - { TAG_ERP_INFO, "ERP Information" }, - { TAG_ERP_INFO_OLD, "ERP Information" }, - { TAG_RSN_IE, "RSN Information" }, - { TAG_EXT_SUPP_RATES, "Extended Supported Rates" }, - { TAG_VENDOR_SPECIFIC_IE, "Vendor Specific" }, - { 0, NULL } -}; - -static const value_string environment_vals[] = { - { 0x20, "Any" }, - { 0x4f, "Outdoor" }, - { 0x49, "Indoor" }, - { 0, NULL } -}; - -static int -add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset) -{ - const guint8 *tag_data_ptr; - guint32 tag_no, tag_len; - unsigned int i; - int n, ret; - char out_buff[SHORT_STR]; - - - tag_no = tvb_get_guint8(tvb, offset); - proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no, - "Tag Number: %u (%s)", - tag_no, - val_to_str(tag_no, tag_num_vals, - (tag_no >= 17 && tag_no <= 31) ? - "Reserved for challenge text" : - "Reserved tag number")); - - tag_len = tvb_get_guint8(tvb, offset + 1); - proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len); - - tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len); - - switch (tag_no) - { - - - case TAG_SSID: - memset (out_buff, 0, SHORT_STR); - - memcpy (out_buff, tag_data_ptr, (size_t) tag_len); - out_buff[tag_len + 1] = 0; - - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - break; - - - - case TAG_SUPP_RATES: - case TAG_EXT_SUPP_RATES: - memset (out_buff, 0, SHORT_STR); - strcpy (out_buff, "Supported rates: "); - n = strlen (out_buff); - - for (i = 0; i < tag_len && n < SHORT_STR; i++) - { - ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ", - (tag_data_ptr[i] & 0x7F) * 0.5, - (tag_data_ptr[i] & 0x80) ? "(B)" : ""); - if (ret == -1 || ret >= SHORT_STR - n) { - /* Some versions of snprintf return -1 if they'd truncate - the output. Others return <buf_size> or greater. */ - break; - } - n += ret; - } - if (n < SHORT_STR) - snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]"); - - out_buff[SHORT_STR-1] = '\0'; - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - break; - - - - case TAG_FH_PARAMETER: - memset (out_buff, 0, SHORT_STR); - - snprintf (out_buff, SHORT_STR, - "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, " - "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2], - tag_data_ptr[3], tag_data_ptr[4]); - - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - break; - - - - case TAG_DS_PARAMETER: - memset (out_buff, 0, SHORT_STR); - - snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]); - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - break; - - - case TAG_CF_PARAMETER: - memset (out_buff, 0, SHORT_STR); - - snprintf (out_buff, SHORT_STR, - "CFP count %u, CFP period %u, CFP max duration %u, " - "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1], - pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4)); - - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - break; - - - case TAG_TIM: - memset (out_buff, 0, SHORT_STR); - snprintf (out_buff, SHORT_STR, - "DTIM count %u, DTIM period %u, Bitmap control 0x%X, " - "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1], - tag_data_ptr[2]); - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - break; - - - - case TAG_IBSS_PARAMETER: - memset (out_buff, 0, SHORT_STR); - snprintf (out_buff, SHORT_STR, "ATIM window 0x%X", - pletohs (tag_data_ptr)); - - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - break; - - - case TAG_COUNTRY_INFO: - memset (out_buff, 0, SHORT_STR); - - snprintf (out_buff, SHORT_STR, "Country Code: %c%c, %s Environment", - tag_data_ptr[0], tag_data_ptr[1], - val_to_str(tag_data_ptr[2], environment_vals,"Unknown (0x%02x)")); - - n = strlen (out_buff); - - for (i = 3; (i + 3) <= tag_len && n < SHORT_STR; i += 3) - { - ret = snprintf(out_buff + n, SHORT_STR - n, - ", Start Channel: %u, Channels: %u, Max TX Power: %d dBm", - tag_data_ptr[i], tag_data_ptr[i + 1], - (gint)tag_data_ptr[i + 2]); - - if (ret == -1 || ret >= SHORT_STR - n) { - /* Some versions of snprintf return -1 if they'd truncate - the output. Others return <buf_size> or greater. */ - break; - } - n += ret; - } - - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,tag_len, out_buff); - break; - - - case TAG_FH_HOPPING_PARAMETER: - memset (out_buff, 0, SHORT_STR); - snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u", - tag_data_ptr[0], tag_data_ptr[1]); - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, tag_len, out_buff); - - - break; - - - case TAG_CHALLENGE_TEXT: - memset (out_buff, 0, SHORT_STR); - snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr); - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - - break; - - - - case TAG_ERP_INFO: - case TAG_ERP_INFO_OLD: - memset (out_buff, 0, SHORT_STR); - - snprintf (out_buff, SHORT_STR, - "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)", - tag_data_ptr[0], - tag_data_ptr[0] & 0x01 ? "" : "no ", - tag_data_ptr[0] & 0x02 ? "" : "do not ", - tag_data_ptr[0] & 0x04 ? "short or long": "long"); - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, out_buff); - - break; - - case TAG_VENDOR_SPECIFIC_IE: - dissect_vendor_specific_ie(tree, tvb, offset + 2, tag_len, - tag_data_ptr); - break; - - case TAG_RSN_IE: - dissect_rsn_ie(tree, tvb, offset + 2, tag_len, tag_data_ptr); - break; - - - default: - proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, - tag_len, "Not interpreted"); - break; - } - - return tag_len + 2; -} - -void -ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, proto_tree * tree, - int tagged_parameters_len) -{ - int next_len; - - while (tagged_parameters_len > 0) { - if ((next_len=add_tagged_field (tree, tvb, offset))==0) - break; - if (next_len > tagged_parameters_len) { - /* XXX - flag this as an error? */ - next_len = tagged_parameters_len; - } - offset += next_len; - tagged_parameters_len -= next_len; - } -} - -/* ************************************************************************* */ -/* Dissect 802.11 management frame */ -/* ************************************************************************* */ -static void -dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo, - proto_tree * tree) -{ - proto_item *ti = NULL; - proto_tree *mgt_tree; - proto_tree *fixed_tree; - proto_tree *tagged_tree; - int offset; - int tagged_parameter_tree_len; - - CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree); - - if (tree) - { - ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE); - mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt); - - switch (COMPOSE_FRAME_TYPE(fcf)) - { - - case MGT_ASSOC_REQ: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4); - add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO); - add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL); - - offset = 4; /* Size of fixed fields */ - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - break; - - - case MGT_ASSOC_RESP: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6); - add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO); - add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE); - add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID); - - offset = 6; /* Size of fixed fields */ - - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - break; - - - case MGT_REASSOC_REQ: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10); - add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO); - add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL); - add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR); - - offset = 10; /* Size of fixed fields */ - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - break; - - case MGT_REASSOC_RESP: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10); - add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO); - add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE); - add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID); - - offset = 6; /* Size of fixed fields */ - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - break; - - - case MGT_PROBE_REQ: - offset = 0; - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - break; - - - case MGT_PROBE_RESP: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12); - add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP); - add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL); - add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO); - - offset = 12; /* Size of fixed fields */ - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - break; - - - case MGT_BEACON: /* Dissect protocol payload fields */ - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12); - - add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP); - add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL); - add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO); - - offset = 12; /* Size of fixed fields */ - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - break; - - - case MGT_ATIM: - break; - - - case MGT_DISASS: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2); - add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE); - break; - - - case MGT_AUTHENTICATION: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6); - add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG); - add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ); - add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE); - - offset = 6; /* Size of fixed fields */ - - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - if (tagged_parameter_tree_len != 0) - { - tagged_tree = get_tagged_parameter_tree (mgt_tree, - tvb, - offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - } - break; - - - case MGT_DEAUTHENTICATION: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2); - add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE); - break; - - - case MGT_ACTION: - fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 3); - add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE); - - switch (tvb_get_guint8(tvb, 0)) - { - - case 17: /* Management notification frame */ - add_fixed_field (fixed_tree, tvb, 1, FIELD_WME_ACTION_CODE); - add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN); - add_fixed_field (fixed_tree, tvb, 3, FIELD_WME_STATUS_CODE); - - offset = 4; /* Size of fixed fields */ - - tagged_parameter_tree_len = - tvb_reported_length_remaining(tvb, offset); - if (tagged_parameter_tree_len != 0) - { - tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset, - tagged_parameter_tree_len); - - ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree, - tagged_parameter_tree_len); - } - break; - - default: /* Management action frame */ - add_fixed_field (fixed_tree, tvb, 1, FIELD_ACTION_CODE); - add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN); - break; - } - break; - } - } -} - -static void -set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type) -{ - if (check_col(pinfo->cinfo, COL_RES_DL_SRC)) - col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)", - get_ether_name(addr), type); - if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC)) - col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)", - ether_to_str(addr), type); -} - -static void -set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type) -{ - if (check_col(pinfo->cinfo, COL_RES_DL_DST)) - col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)", - get_ether_name(addr), type); - if (check_col(pinfo->cinfo, COL_UNRES_DL_DST)) - col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)", - ether_to_str(addr), type); -} - -typedef enum { - ENCAP_802_2, - ENCAP_IPX, - ENCAP_ETHERNET -} encap_t; - -/* ************************************************************************* */ -/* Dissect 802.11 frame */ -/* ************************************************************************* */ -static void -dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo, - proto_tree * tree, gboolean fixed_length_header, - gboolean has_radio_information, gint fcs_len, - gboolean wlan_broken_fc) -{ - guint16 fcf, flags, frame_type_subtype; - guint16 seq_control; - guint32 seq_number, frag_number; - gboolean more_frags; - const guint8 *src = NULL, *dst = NULL; - proto_item *ti = NULL; - proto_item *flag_item; - proto_item *fc_item; - proto_tree *hdr_tree = NULL; - proto_tree *flag_tree; - proto_tree *fc_tree; - guint16 hdr_len; - gboolean has_fcs; - gint len, reported_len, ivlen; - gboolean save_fragmented; - tvbuff_t *volatile next_tvb = NULL; - guint32 addr_type; - volatile encap_t encap_type; - guint8 octet1, octet2; - char out_buff[SHORT_STR]; - - if (check_col (pinfo->cinfo, COL_PROTOCOL)) - col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11"); - if (check_col (pinfo->cinfo, COL_INFO)) - col_clear (pinfo->cinfo, COL_INFO); - - /* Add the radio information, if present, to the column information */ - if (has_radio_information) { - if (check_col(pinfo->cinfo, COL_TX_RATE)) { - col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u", - pinfo->pseudo_header->ieee_802_11.data_rate / 2, - pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0); - } - if (check_col(pinfo->cinfo, COL_RSSI)) { - /* XX - this is a percentage, not a dBm or normalized or raw RSSI */ - col_add_fstr(pinfo->cinfo, COL_RSSI, "%u", - pinfo->pseudo_header->ieee_802_11.signal_level); - } - } - - fcf = tvb_get_letohs (tvb, 0); - if (wlan_broken_fc) { - /* Swap bytes */ - fcf = ((fcf & 0xff) << 8) | (((fcf & 0xff00) >> 8) & 0xff); - } - if (fixed_length_header) - hdr_len = DATA_LONG_HDR_LEN; - else - hdr_len = find_header_length (fcf); - frame_type_subtype = COMPOSE_FRAME_TYPE(fcf); - - if (check_col (pinfo->cinfo, COL_INFO)) - col_set_str (pinfo->cinfo, COL_INFO, - val_to_str(frame_type_subtype, frame_type_subtype_vals, - "Unrecognized (Reserved frame)")); - - flags = COOK_FLAGS (fcf); - more_frags = HAVE_FRAGMENTS (flags); - - /* Add the radio information, if present, and the FC to the current tree */ - if (tree) - { - ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len, - "IEEE 802.11"); - hdr_tree = proto_item_add_subtree (ti, ett_80211); - - if (has_radio_information) { - proto_tree_add_uint_format(hdr_tree, hf_data_rate, - tvb, 0, 0, - pinfo->pseudo_header->ieee_802_11.data_rate, - "Data Rate: %u.%u Mb/s", - pinfo->pseudo_header->ieee_802_11.data_rate / 2, - pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0); - - proto_tree_add_uint(hdr_tree, hf_channel, - tvb, 0, 0, - pinfo->pseudo_header->ieee_802_11.channel); - - proto_tree_add_uint_format(hdr_tree, hf_signal_strength, - tvb, 0, 0, - pinfo->pseudo_header->ieee_802_11.signal_level, - "Signal Strength: %u%%", - pinfo->pseudo_header->ieee_802_11.signal_level); - } - - proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype, - tvb, - wlan_broken_fc?1:0, 1, - frame_type_subtype); - - fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb, - 0, 2, - fcf, - "Frame Control: 0x%04X (%s)", - fcf, wlan_broken_fc?"Swapped":"Normal"); - - fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree); - - - proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb, - wlan_broken_fc?1:0, 1, - COOK_PROT_VERSION (fcf)); - - proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb, - wlan_broken_fc?1:0, 1, - COOK_FRAME_TYPE (fcf)); - - proto_tree_add_uint (fc_tree, hf_fc_frame_subtype, - tvb, - wlan_broken_fc?1:0, 1, - COOK_FRAME_SUBTYPE (fcf)); - - flag_item = - proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb, - wlan_broken_fc?0:1, 1, - flags, "Flags: 0x%X", flags); - - flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags); - - proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb, - wlan_broken_fc?0:1, 1, - COOK_DS_STATUS (flags)); - proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1, - flags); - proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1, - flags); - - proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb, - wlan_broken_fc?0:1, 1, - flags); - - proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb, - wlan_broken_fc?0:1, 1, flags); - - proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb, - wlan_broken_fc?0:1, 1, flags); - - proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb, - wlan_broken_fc?0:1, 1, - flags); - - proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb, - wlan_broken_fc?0:1, 1, flags); - - proto_tree_add_boolean (flag_tree, hf_fc_order, tvb, - wlan_broken_fc?0:1, 1, flags); - - if (frame_type_subtype == CTRL_PS_POLL) - proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2, - COOK_ASSOC_ID(tvb_get_letohs(tvb,2))); - - else - proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2, - tvb_get_letohs (tvb, 2)); - } - - /* - * Decode the part of the frame header that isn't the same for all - * frame types. - */ - seq_control = 0; - frag_number = 0; - seq_number = 0; - - switch (COOK_FRAME_TYPE (fcf)) - { - - case MGT_FRAME: - /* - * All management frame types have the same header. - */ - src = tvb_get_ptr (tvb, 10, 6); - dst = tvb_get_ptr (tvb, 4, 6); - - SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src); - SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src); - SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst); - SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst); - - seq_control = tvb_get_letohs(tvb, 22); - frag_number = COOK_FRAGMENT_NUMBER(seq_control); - seq_number = COOK_SEQUENCE_NUMBER(seq_control); - - if (tree) - { - proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst); - - proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src); - - /* add items for wlan.addr filter */ - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst); - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src); - - proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6, - tvb_get_ptr (tvb, 16, 6)); - - proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2, - frag_number); - - proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2, - seq_number); - } - break; - - case CONTROL_FRAME: - switch (frame_type_subtype) - { - - case CTRL_PS_POLL: - src = tvb_get_ptr (tvb, 10, 6); - dst = tvb_get_ptr (tvb, 4, 6); - - set_src_addr_cols(pinfo, src, "BSSID"); - set_dst_addr_cols(pinfo, dst, "BSSID"); - - if (tree) - { - proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst); - - proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src); - } - break; - - - case CTRL_RTS: - src = tvb_get_ptr (tvb, 10, 6); - dst = tvb_get_ptr (tvb, 4, 6); - - set_src_addr_cols(pinfo, src, "TA"); - set_dst_addr_cols(pinfo, dst, "RA"); - - if (tree) - { - proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst); - - proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src); - } - break; - - - case CTRL_CTS: - dst = tvb_get_ptr (tvb, 4, 6); - - set_dst_addr_cols(pinfo, dst, "RA"); - - if (tree) - proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst); - break; - - - case CTRL_ACKNOWLEDGEMENT: - dst = tvb_get_ptr (tvb, 4, 6); - - set_dst_addr_cols(pinfo, dst, "RA"); - - if (tree) - proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst); - break; - - - case CTRL_CFP_END: - src = tvb_get_ptr (tvb, 10, 6); - dst = tvb_get_ptr (tvb, 4, 6); - - set_src_addr_cols(pinfo, src, "BSSID"); - set_dst_addr_cols(pinfo, dst, "RA"); - - if (tree) - { - proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst); - proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src); - } - break; - - - case CTRL_CFP_ENDACK: - src = tvb_get_ptr (tvb, 10, 6); - dst = tvb_get_ptr (tvb, 4, 6); - - set_src_addr_cols(pinfo, src, "BSSID"); - set_dst_addr_cols(pinfo, dst, "RA"); - - if (tree) - { - proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst); - - proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src); - } - break; - } - break; - - case DATA_FRAME: - addr_type = COOK_ADDR_SELECTOR (fcf); - - /* In order to show src/dst address we must always do the following */ - switch (addr_type) - { - - case DATA_ADDR_T1: - src = tvb_get_ptr (tvb, 10, 6); - dst = tvb_get_ptr (tvb, 4, 6); - break; - - - case DATA_ADDR_T2: - src = tvb_get_ptr (tvb, 16, 6); - dst = tvb_get_ptr (tvb, 4, 6); - break; - - - case DATA_ADDR_T3: - src = tvb_get_ptr (tvb, 10, 6); - dst = tvb_get_ptr (tvb, 16, 6); - break; - - - case DATA_ADDR_T4: - src = tvb_get_ptr (tvb, 24, 6); - dst = tvb_get_ptr (tvb, 16, 6); - break; - } - - SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src); - SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src); - SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst); - SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst); - - seq_control = tvb_get_letohs(tvb, 22); - frag_number = COOK_FRAGMENT_NUMBER(seq_control); - seq_number = COOK_SEQUENCE_NUMBER(seq_control); - - /* Now if we have a tree we start adding stuff */ - if (tree) - { - - - switch (addr_type) - { - - case DATA_ADDR_T1: - proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst); - proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src); - proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6, - tvb_get_ptr (tvb, 16, 6)); - proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2, - frag_number); - proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2, - seq_number); - - /* add items for wlan.addr filter */ - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst); - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src); - break; - - - case DATA_ADDR_T2: - proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst); - proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, - tvb_get_ptr (tvb, 10, 6)); - proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src); - proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2, - frag_number); - proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2, - seq_number); - - /* add items for wlan.addr filter */ - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst); - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src); - break; - - - case DATA_ADDR_T3: - proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, - tvb_get_ptr (tvb, 4, 6)); - proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src); - proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst); - - proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2, - frag_number); - proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2, - seq_number); - - /* add items for wlan.addr filter */ - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src); - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst); - break; - - - case DATA_ADDR_T4: - proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, - tvb_get_ptr (tvb, 4, 6)); - proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, - tvb_get_ptr (tvb, 10, 6)); - proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst); - proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2, - frag_number); - proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2, - seq_number); - proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src); - - /* add items for wlan.addr filter */ - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst); - proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src); - break; - } - - } - break; - } - - len = tvb_length_remaining(tvb, hdr_len); - reported_len = tvb_reported_length_remaining(tvb, hdr_len); - - switch (fcs_len) - { - case 0: /* Definitely has no FCS */ - has_fcs = FALSE; - break; - - case 4: /* Definitely has an FCS */ - has_fcs = TRUE; - break; - - default: /* Don't know - use "wlan_check_fcs" */ - has_fcs = wlan_check_fcs; - break; - } - if (has_fcs) - { - /* - * Well, this packet should, in theory, have an FCS. - * Do we have the entire packet, and does it have enough data for - * the FCS? - */ - if (reported_len < 4) - { - /* - * The packet is claimed not to even have enough data for a 4-byte - * FCS. - * Pretend it doesn't have an FCS. - */ - ; - } - else if (len < reported_len) - { - /* - * The packet is claimed to have enough data for a 4-byte FCS, but - * we didn't capture all of the packet. - * Slice off the 4-byte FCS from the reported length, and trim the - * captured length so it's no more than the reported length; that - * will slice off what of the FCS, if any, is in the captured - * length. - */ - reported_len -= 4; - if (len > reported_len) - len = reported_len; - } - else - { - /* - * We have the entire packet, and it includes a 4-byte FCS. - * Slice it off, and put it into the tree. - */ - len -= 4; - reported_len -= 4; - if (tree) - { - guint32 fcs = crc32_802_tvb(tvb, hdr_len + len); - guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len); - if (fcs == sent_fcs) - proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb, - hdr_len + len, 4, sent_fcs, - "Frame check sequence: 0x%08x (correct)", sent_fcs); - else - proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb, - hdr_len + len, 4, sent_fcs, - "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)", - sent_fcs, fcs); - } - } - } - - if (tree && (frame_type_subtype == DATA_QOS_DATA || frame_type_subtype == DATA_QOS_NULL)) { - proto_item *qos_fields; - proto_tree *qos_tree; - - guint16 qos_control, qos_priority, qos_ack_policy; - - qos_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len - 2, 2, - "QoS parameters"); - qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters); - - qos_control = tvb_get_letohs(tvb, hdr_len - 2); - qos_priority = COOK_QOS_PRIORITY(qos_control); - qos_ack_policy = COOK_QOS_ACK_POLICY(qos_control); - proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb, - hdr_len - 2, 2, qos_priority, - "Priority: %d (%s) (%s)", - qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]); - proto_tree_add_uint_format (qos_tree, hf_qos_ack_policy, tvb, - hdr_len - 2, 2, qos_ack_policy, - "Ack Policy: %d (%sAcknowledge)", - qos_ack_policy, qos_ack_policy ? "Do not " : ""); - } - - /* - * Only management and data frames have a body, so we don't have - * anything more to do for other types of frames. - */ - switch (COOK_FRAME_TYPE (fcf)) - { - - case MGT_FRAME: - break; - - case DATA_FRAME: - /* - * No-data frames don't have a body. - */ - switch (frame_type_subtype) - { - - case DATA_NULL_FUNCTION: - case DATA_CF_ACK_NOD: - case DATA_CF_POLL_NOD: - case DATA_CF_ACK_POLL_NOD: - case DATA_QOS_NULL: - return; - } - break; - - default: - return; - } - - if (IS_WEP(COOK_FLAGS(fcf))) { - /* - * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt - * the data, if we have a matching key. Otherwise display it as data. - */ - gboolean can_decrypt = FALSE; - proto_tree *wep_tree = NULL; - guint32 iv; - guint8 key, keybyte; - - keybyte = tvb_get_guint8(tvb, hdr_len + 3); - key = COOK_WEP_KEY(keybyte); - if ((keybyte & KEY_EXTIV) && (len >= EXTIV_LEN)) { - /* Extended IV; this frame is likely encrypted with TKIP or CCMP */ - if (tree) { - proto_item *extiv_fields; - - extiv_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 8, - "TKIP/CCMP parameters"); - wep_tree = proto_item_add_subtree (extiv_fields, ett_wep_parameters); - /* It is unknown whether this is a TKIP or CCMP encrypted packet, so - * display both packet number alternatives unless the ExtIV can be - * determined to be possible only with one of the encryption protocols. - */ - if (tvb_get_guint8(tvb, hdr_len + 1) & 0x20) { - snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X", - tvb_get_letohl(tvb, hdr_len + 4), - tvb_get_guint8(tvb, hdr_len), - tvb_get_guint8(tvb, hdr_len + 2)); - proto_tree_add_string(wep_tree, hf_tkip_extiv, tvb, hdr_len, - EXTIV_LEN, out_buff); - } - if (tvb_get_guint8(tvb, hdr_len + 2) == 0) { - snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X", - tvb_get_letohl(tvb, hdr_len + 4), - tvb_get_guint8(tvb, hdr_len + 1), - tvb_get_guint8(tvb, hdr_len)); - proto_tree_add_string(wep_tree, hf_ccmp_extiv, tvb, hdr_len, - EXTIV_LEN, out_buff); - } - proto_tree_add_uint(wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key); - } - - /* Subtract out the length of the IV. */ - len -= EXTIV_LEN; - reported_len -= EXTIV_LEN; - ivlen = EXTIV_LEN; - /* It is unknown whether this is TKIP or CCMP, so let's not even try to - * parse TKIP Michael MIC+ICV or CCMP MIC. */ - } else { - /* No Ext. IV - WEP packet */ - /* - * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass - * them to "wep_decrypt()", rather than having "wep_decrypt()" extract - * them itself. - * - * Also, just pass the data *following* the WEP parameters as the - * buffer to decrypt. - */ - iv = tvb_get_letoh24(tvb, hdr_len); - if (tree) { - proto_item *wep_fields; - - wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4, - "WEP parameters"); - - wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters); - proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv); - } - if (tree) - proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key); - - /* Subtract out the length of the IV. */ - len -= 4; - reported_len -= 4; - ivlen = 4; - - /* - * Well, this packet should, in theory, have an ICV. - * Do we have the entire packet, and does it have enough data for - * the ICV? - */ - if (reported_len < 4) { - /* - * The packet is claimed not to even have enough data for a - * 4-byte ICV. - * Pretend it doesn't have an ICV. - */ - ; - } else if (len < reported_len) { - /* - * The packet is claimed to have enough data for a 4-byte ICV, - * but we didn't capture all of the packet. - * Slice off the 4-byte ICV from the reported length, and trim - * the captured length so it's no more than the reported length; - * that will slice off what of the ICV, if any, is in the - * captured length. - * - */ - reported_len -= 4; - if (len > reported_len) - len = reported_len; - } else { - /* - * We have the entire packet, and it includes a 4-byte ICV. - * Slice it off, and put it into the tree. - * - * We only support decrypting if we have the the ICV. - * - * XXX - the ICV is encrypted; we're putting the encrypted - * value, not the decrypted value, into the tree. - */ - len -= 4; - reported_len -= 4; - can_decrypt = TRUE; - } - } - - if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) { - /* - * WEP decode impossible or failed, treat payload as raw data - * and don't attempt fragment reassembly or further dissection. - */ - next_tvb = tvb_new_subset(tvb, hdr_len + ivlen, len, reported_len); - - if (tree && can_decrypt) - proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, - hdr_len + ivlen + len, 4, - tvb_get_ntohl(tvb, hdr_len + ivlen + len), - "WEP ICV: 0x%08x (not verified)", - tvb_get_ntohl(tvb, hdr_len + ivlen + len)); - - call_dissector(data_handle, next_tvb, pinfo, tree); - return; - } else { - - if (tree) - proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb, - hdr_len + ivlen + len, 4, - tvb_get_ntohl(tvb, hdr_len + ivlen + len), - "WEP ICV: 0x%08x (correct)", - tvb_get_ntohl(tvb, hdr_len + ivlen + len)); - - add_new_data_source(pinfo, next_tvb, "Decrypted WEP data"); - } - - /* - * WEP decryption successful! - * - * Use the tvbuff we got back from the decryption; the data starts at - * the beginning. The lengths are already correct for the decoded WEP - * payload. - */ - hdr_len = 0; - - } else { - /* - * Not a WEP-encrypted frame; just use the data from the tvbuff - * handed to us. - * - * The payload starts at "hdr_len" (i.e., just past the 802.11 - * MAC header), the length of data in the tvbuff following the - * 802.11 header is "len", and the length of data in the packet - * following the 802.11 header is "reported_len". - */ - next_tvb = tvb; - } - - /* - * Do defragmentation if "wlan_defragment" is true, and we have more - * fragments or this isn't the first fragment. - * - * We have to do some special handling to catch frames that - * have the "More Fragments" indicator not set but that - * don't show up as reassembled and don't have any other - * fragments present. Some networking interfaces appear - * to do reassembly even when you're capturing raw packets - * *and* show the reassembled packet without the "More - * Fragments" indicator set *but* with a non-zero fragment - * number. - * - * "fragment_add_seq_802_11()" handles that; we want to call it - * even if we have a short frame, so that it does those checks - if - * the frame is short, it doesn't do reassembly on it. - * - * (This could get some false positives if we really *did* only - * capture the last fragment of a fragmented packet, but that's - * life.) - */ - save_fragmented = pinfo->fragmented; - if (wlan_defragment && (more_frags || frag_number != 0)) { - fragment_data *fd_head; - - /* - * If we've already seen this frame, look it up in the - * table of reassembled packets, otherwise add it to - * whatever reassembly is in progress, if any, and see - * if it's done. - */ - fd_head = fragment_add_seq_802_11(next_tvb, hdr_len, pinfo, seq_number, - wlan_fragment_table, - wlan_reassembled_table, - frag_number, - reported_len, - more_frags); - next_tvb = process_reassembled_data(tvb, hdr_len, pinfo, - "Reassembled 802.11", fd_head, - &frag_items, NULL, hdr_tree); - } else { - /* - * If this is the first fragment, dissect its contents, otherwise - * just show it as a fragment. - */ - if (frag_number != 0) { - /* Not the first fragment - don't dissect it. */ - next_tvb = NULL; - } else { - /* First fragment, or not fragmented. Dissect what we have here. */ - - /* Get a tvbuff for the payload. */ - next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len); - - /* - * If this is the first fragment, but not the only fragment, - * tell the next protocol that. - */ - if (more_frags) - pinfo->fragmented = TRUE; - else - pinfo->fragmented = FALSE; - } - } - - if (next_tvb == NULL) { - /* Just show this as an incomplete fragment. */ - if (check_col(pinfo->cinfo, COL_INFO)) - col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame"); - next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len); - call_dissector(data_handle, next_tvb, pinfo, tree); - pinfo->fragmented = save_fragmented; - return; - } - - switch (COOK_FRAME_TYPE (fcf)) - { - - case MGT_FRAME: - dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree); - break; - - - case DATA_FRAME: - /* I guess some bridges take Netware Ethernet_802_3 frames, - which are 802.3 frames (with a length field rather than - a type field, but with no 802.2 header in the payload), - and just stick the payload into an 802.11 frame. I've seen - captures that show frames of that sort. - - We also handle some odd form of encapsulation in which a - complete Ethernet frame is encapsulated within an 802.11 - data frame, with no 802.2 header. This has been seen - from some hardware. - - So, if the packet doesn't start with 0xaa 0xaa: - - we first use the same scheme that linux-wlan-ng does to detect - those encapsulated Ethernet frames, namely looking to see whether - the frame either starts with 6 octets that match the destination - address from the 802.11 header or has 6 octets that match the - source address from the 802.11 header following the first 6 octets, - and, if so, treat it as an encapsulated Ethernet frame; - - otherwise, we use the same scheme that we use in the Ethernet - dissector to recognize Netware 802.3 frames, namely checking - whether the packet starts with 0xff 0xff and, if so, treat it - as an encapsulated IPX frame. */ - encap_type = ENCAP_802_2; - TRY { - octet1 = tvb_get_guint8(next_tvb, 0); - octet2 = tvb_get_guint8(next_tvb, 1); - if (octet1 != 0xaa || octet2 != 0xaa) { - src = tvb_get_ptr (next_tvb, 6, 6); - dst = tvb_get_ptr (next_tvb, 0, 6); - if (memcmp(src, pinfo->dl_src.data, 6) == 0 || - memcmp(dst, pinfo->dl_dst.data, 6) == 0) - encap_type = ENCAP_ETHERNET; - else if (octet1 == 0xff && octet2 == 0xff) - encap_type = ENCAP_IPX; - } - } - CATCH2(BoundsError, ReportedBoundsError) { - ; /* do nothing */ - - } - ENDTRY; - - switch (encap_type) { - - case ENCAP_802_2: - call_dissector(llc_handle, next_tvb, pinfo, tree); - break; - - case ENCAP_ETHERNET: - call_dissector(eth_handle, next_tvb, pinfo, tree); - break; - - case ENCAP_IPX: - call_dissector(ipx_handle, next_tvb, pinfo, tree); - break; - } - break; - } - pinfo->fragmented = save_fragmented; -} - -/* - * Dissect 802.11 with a variable-length link-layer header. - */ -static void -dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) -{ - dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, - pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE); -} - -/* - * Dissect 802.11 with a variable-length link-layer header and a pseudo- - * header containing radio information. - */ -static void -dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) -{ - dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE, - pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE); -} - -/* - * Dissect 802.11 with a variable-length link-layer header and a byte-swapped - * control field (some hardware sends out LWAPP-encapsulated 802.11 - * packets with the control field byte swapped). - */ -static void -dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) -{ - dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE, TRUE); -} - -/* - * Dissect 802.11 with a fixed-length link-layer header (padded to the - * maximum length). - */ -static void -dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) -{ - dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE, FALSE); -} - -static void -wlan_defragment_init(void) -{ - fragment_table_init(&wlan_fragment_table); - reassembled_table_init(&wlan_reassembled_table); -} - -void -proto_register_ieee80211 (void) -{ - static const value_string frame_type[] = { - {MGT_FRAME, "Management frame"}, - {CONTROL_FRAME, "Control frame"}, - {DATA_FRAME, "Data frame"}, - {0, NULL} - }; - - static const value_string tofrom_ds[] = { - {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"}, - {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"}, - {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"}, - {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"}, - {0, NULL} - }; - - static const true_false_string tods_flag = { - "Frame is entering DS", - "Frame is not entering DS" - }; - - static const true_false_string fromds_flag = { - "Frame is exiting DS", - "Frame is not exiting DS" - }; - - static const true_false_string more_frags = { - "More fragments follow", - "This is the last fragment" - }; - - static const true_false_string retry_flags = { - "Frame is being retransmitted", - "Frame is not being retransmitted" - }; - - static const true_false_string pm_flags = { - "STA will go to sleep", - "STA will stay up" - }; - - static const true_false_string md_flags = { - "Data is buffered for STA at AP", - "No data buffered" - }; - - static const true_false_string wep_flags = { - "WEP is enabled", - "WEP is disabled" - }; - - static const true_false_string order_flags = { - "Strictly ordered", - "Not strictly ordered" - }; - - static const true_false_string cf_ess_flags = { - "Transmitter is an AP", - "Transmitter is a STA" - }; - - - static const true_false_string cf_privacy_flags = { - "AP/STA can support WEP", - "AP/STA cannot support WEP" - }; - - static const true_false_string cf_preamble_flags = { - "Short preamble allowed", - "Short preamble not allowed" - }; - - static const true_false_string cf_pbcc_flags = { - "PBCC modulation allowed", - "PBCC modulation not allowed" - }; - - static const true_false_string cf_agility_flags = { - "Channel agility in use", - "Channel agility not in use" - }; - - static const true_false_string short_slot_time_flags = { - "Short slot time in use", - "Short slot time not in use" - }; - - static const true_false_string dsss_ofdm_flags = { - "DSSS-OFDM modulation allowed", - "DSSS-OFDM modulation not allowed" - }; - - - static const true_false_string cf_ibss_flags = { - "Transmitter belongs to an IBSS", - "Transmitter belongs to a BSS" - }; - - static const value_string sta_cf_pollable[] = { - {0x00, "Station is not CF-Pollable"}, - {0x02, "Station is CF-Pollable, " - "not requesting to be placed on the CF-polling list"}, - {0x01, "Station is CF-Pollable, " - "requesting to be placed on the CF-polling list"}, - {0x03, "Station is CF-Pollable, requesting never to be polled"}, - {0, NULL} - }; - - static const value_string ap_cf_pollable[] = { - {0x00, "No point coordinator at AP"}, - {0x02, "Point coordinator at AP for delivery only (no polling)"}, - {0x01, "Point coordinator at AP for delivery and polling"}, - {0x03, "Reserved"}, - {0, NULL} - }; - - - static const value_string auth_alg[] = { - {0x00, "Open System"}, - {0x01, "Shared key"}, - {0, NULL} - }; - - static const value_string reason_codes[] = { - {0x00, "Reserved"}, - {0x01, "Unspecified reason"}, - {0x02, "Previous authentication no longer valid"}, - {0x03, "Deauthenticated because sending STA is leaving (has left) " - "IBSS or ESS"}, - {0x04, "Disassociated due to inactivity"}, - {0x05, "Disassociated because AP is unable to handle all currently " - "associated stations"}, - {0x06, "Class 2 frame received from nonauthenticated station"}, - {0x07, "Class 3 frame received from nonassociated station"}, - {0x08, "Disassociated because sending STA is leaving (has left) BSS"}, - {0x09, "Station requesting (re)association is not authenticated with " - "responding station"}, - {0x0D, "Invalid Information Element"}, - {0x0E, "Michael MIC failure"}, - {0x0F, "4-Way Handshake timeout"}, - {0x10, "Group key update timeout"}, - {0x11, "Information element in 4-Way Handshake different from " - "(Re)Association Request/Probe Response/Beacon"}, - {0x12, "Group Cipher is not valid"}, - {0x13, "Pairwise Cipher is not valid"}, - {0x14, "AKMP is not valid"}, - {0x15, "Unsupported RSN IE version"}, - {0x16, "Invalid RSN IE Capabilities"}, - {0x17, "IEEE 802.1X Authentication failed"}, - {0x18, "Cipher suite is rejected per security policy"}, - {0x00, NULL} - }; - - - static const value_string status_codes[] = { - {0x00, "Successful"}, - {0x01, "Unspecified failure"}, - {0x0A, "Cannot support all requested capabilities in the " - "Capability information field"}, - {0x0B, "Reassociation denied due to inability to confirm that " - "association exists"}, - {0x0C, "Association denied due to reason outside the scope of this " - "standard"}, - - {0x0D, "Responding station does not support the specified authentication " - "algorithm"}, - {0x0E, "Received an Authentication frame with authentication sequence " - "transaction sequence number out of expected sequence"}, - {0x0F, "Authentication rejected because of challenge failure"}, - {0x10, "Authentication rejected due to timeout waiting for next " - "frame in sequence"}, - {0x11, "Association denied because AP is unable to handle additional " - "associated stations"}, - {0x12, "Association denied due to requesting station not supporting all " - "of the datarates in the BSSBasicServiceSet Parameter"}, - {0x13, "Association denied due to requesting station not supporting " - "short preamble operation"}, - {0x14, "Association denied due to requesting station not supporting " - "PBCC encoding"}, - {0x15, "Association denied due to requesting station not supporting " - "channel agility"}, - {0x19, "Association denied due to requesting station not supporting " - "short slot operation"}, - {0x1A, "Association denied due to requesting station not supporting " - "DSSS-OFDM operation"}, - {0x28, "Invalid Information Element"}, - {0x29, "Group Cipher is not valid"}, - {0x2A, "Pairwise Cipher is not valid"}, - {0x2B, "AKMP is not valid"}, - {0x2C, "Unsupported RSN IE version"}, - {0x2D, "Invalid RSN IE Capabilities"}, - {0x2E, "Cipher suite is rejected per security policy"}, - {0x00, NULL} - }; - - static const value_string category_codes[] = { - {0x11, "Management notification frame"}, - {0x00, NULL} - }; - - static const value_string action_codes[] = { - {0x00, NULL} - }; - - static const value_string wme_action_codes[] = { - {0x00, "Setup request"}, - {0x01, "Setup response"}, - {0x02, "Teardown"}, - {0x00, NULL} - }; - - static const value_string wme_status_codes[] = { - {0x00, "Admission accepted"}, - {0x01, "Invalid parameters"}, - {0x03, "Refused"}, - {0x00, NULL} - }; - - static hf_register_info hf[] = { - {&hf_data_rate, - {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0, - "Data rate (.5 Mb/s units)", HFILL }}, - - {&hf_channel, - {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0, - "Radio channel", HFILL }}, - - {&hf_signal_strength, - {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0, - "Signal strength (percentage)", HFILL }}, - - {&hf_fc_field, - {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0, - "MAC Frame control", HFILL }}, - - {&hf_fc_proto_version, - {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0, - "MAC Protocol version", HFILL }}, /* 0 */ - - {&hf_fc_frame_type, - {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0, - "Frame type", HFILL }}, - - {&hf_fc_frame_subtype, - {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0, - "Frame subtype", HFILL }}, /* 2 */ - - {&hf_fc_frame_type_subtype, - {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0, - "Type and subtype combined", HFILL }}, - - {&hf_fc_flags, - {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0, - "Protocol flags", HFILL }}, - - {&hf_fc_data_ds, - {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0, - "Data-frame DS-traversal status", HFILL }}, /* 3 */ - - {&hf_fc_to_ds, - {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS, - "To DS flag", HFILL }}, /* 4 */ - - {&hf_fc_from_ds, - {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS, - "From DS flag", HFILL }}, /* 5 */ - - {&hf_fc_more_frag, - {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS, - "More Fragments flag", HFILL }}, /* 6 */ - - {&hf_fc_retry, - {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY, - "Retransmission flag", HFILL }}, - - {&hf_fc_pwr_mgt, - {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT, - "Power management status", HFILL }}, - - {&hf_fc_more_data, - {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA, - "More data flag", HFILL }}, - - {&hf_fc_wep, - {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP, - "WEP flag", HFILL }}, - - {&hf_fc_order, - {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER, - "Strictly ordered flag", HFILL }}, - - {&hf_assoc_id, - {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0, - "Association-ID field", HFILL }}, - - {&hf_did_duration, - {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0, - "Duration field", HFILL }}, - - {&hf_addr_da, - {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0, - "Destination Hardware Address", HFILL }}, - - {&hf_addr_sa, - {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0, - "Source Hardware Address", HFILL }}, - - { &hf_addr, - {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0, - "Source or Destination Hardware Address", HFILL }}, - - {&hf_addr_ra, - {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0, - "Receiving Station Hardware Address", HFILL }}, - - {&hf_addr_ta, - {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0, - "Transmitting Station Hardware Address", HFILL }}, - - {&hf_addr_bssid, - {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0, - "Basic Service Set ID", HFILL }}, - - {&hf_frag_number, - {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0, - "Fragment number", HFILL }}, - - {&hf_seq_number, - {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0, - "Sequence number", HFILL }}, - - {&hf_qos_priority, - {"Priority", "wlan.qos.priority", FT_UINT16, BASE_DEC, NULL, 0, - "802.1D Tag", HFILL }}, - - {&hf_qos_ack_policy, - {"Ack Policy", "wlan.qos.ack", FT_UINT16, BASE_DEC, NULL, 0, - "Ack Policy", HFILL }}, - - {&hf_fcs, - {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX, - NULL, 0, "FCS", HFILL }}, - - {&hf_fragment_overlap, - {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE, - NULL, 0x0, "Fragment overlaps with other fragments", HFILL }}, - - {&hf_fragment_overlap_conflict, - {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "Overlapping fragments contained conflicting data", HFILL }}, - - {&hf_fragment_multiple_tails, - {"Multiple tail fragments found", "wlan.fragment.multipletails", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "Several tails were found when defragmenting the packet", HFILL }}, - - {&hf_fragment_too_long_fragment, - {"Fragment too long", "wlan.fragment.toolongfragment", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "Fragment contained data past end of packet", HFILL }}, - - {&hf_fragment_error, - {"Defragmentation error", "wlan.fragment.error", - FT_FRAMENUM, BASE_NONE, NULL, 0x0, - "Defragmentation error due to illegal fragments", HFILL }}, - - {&hf_fragment, - {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, - "802.11 Fragment", HFILL }}, - - {&hf_fragments, - {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0, - "802.11 Fragments", HFILL }}, - - {&hf_reassembled_in, - {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, - "This 802.11 packet is reassembled in this frame", HFILL }}, - - {&hf_wep_iv, - {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0, - "Initialization Vector", HFILL }}, - - {&hf_tkip_extiv, - {"TKIP Ext. Initialization Vector", "wlan.tkip.extiv", FT_STRING, - BASE_HEX, NULL, 0, "TKIP Extended Initialization Vector", HFILL }}, - - {&hf_ccmp_extiv, - {"CCMP Ext. Initialization Vector", "wlan.ccmp.extiv", FT_STRING, - BASE_HEX, NULL, 0, "CCMP Extended Initialization Vector", HFILL }}, - - {&hf_wep_key, - {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0, - "Key", HFILL }}, - - {&hf_wep_icv, - {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0, - "WEP ICV", HFILL }}, - }; - - static const true_false_string rsn_preauth_flags = { - "Transmitter supports pre-authentication", - "Transmitter does not support pre-authentication" - }; - - static const true_false_string rsn_no_pairwise_flags = { - "Transmitter cannot support WEP default key 0 simultaneously with " - "Pairwise key", - "Transmitter can support WEP default key 0 simultaneously with " - "Pairwise key" - }; - - static const value_string rsn_cap_replay_counter[] = { - {0x00, "1 replay counter per PTKSA/GTKSA/STAKeySA"}, - {0x01, "2 replay counters per PTKSA/GTKSA/STAKeySA"}, - {0x02, "4 replay counters per PTKSA/GTKSA/STAKeySA"}, - {0x03, "16 replay counters per PTKSA/GTKSA/STAKeySA"}, - {0, NULL} - }; - - static hf_register_info ff[] = { - {&ff_timestamp, - {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE, - NULL, 0, "", HFILL }}, - - {&ff_auth_alg, - {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg", - FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }}, - - {&ff_beacon_interval, - {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0, - "", HFILL }}, - - {&hf_fixed_parameters, - {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0, - "", HFILL }}, - - {&hf_tagged_parameters, - {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0, - "", HFILL }}, - - {&ff_capture, - {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0, - "Capability information", HFILL }}, - - {&ff_cf_ess, - {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess", - FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }}, - - {&ff_cf_ibss, - {"IBSS status", "wlan_mgt.fixed.capabilities.ibss", - FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }}, - - {&ff_cf_sta_poll, - {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta", - FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C, - "CF-Poll capabilities for a STA", HFILL }}, - - {&ff_cf_ap_poll, - {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap", - FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C, - "CF-Poll capabilities for an AP", HFILL }}, - - {&ff_cf_privacy, - {"Privacy", "wlan_mgt.fixed.capabilities.privacy", - FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }}, - - {&ff_cf_preamble, - {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble", - FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }}, - - {&ff_cf_pbcc, - {"PBCC", "wlan_mgt.fixed.capabilities.pbcc", - FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }}, - - {&ff_cf_agility, - {"Channel Agility", "wlan_mgt.fixed.capabilities.agility", - FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }}, - - {&ff_short_slot_time, - {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time", - FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time", - HFILL }}, - - {&ff_dsss_ofdm, - {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm", - FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation", - HFILL }}, - - {&ff_auth_seq, - {"Authentication SEQ", "wlan_mgt.fixed.auth_seq", - FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }}, - - {&ff_assoc_id, - {"Association ID", "wlan_mgt.fixed.aid", - FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }}, - - {&ff_listen_ival, - {"Listen Interval", "wlan_mgt.fixed.listen_ival", - FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }}, - - {&ff_current_ap, - {"Current AP", "wlan_mgt.fixed.current_ap", - FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }}, - - {&ff_reason, - {"Reason code", "wlan_mgt.fixed.reason_code", - FT_UINT16, BASE_HEX, VALS (&reason_codes), 0, - "Reason for unsolicited notification", HFILL }}, - - {&ff_status_code, - {"Status code", "wlan_mgt.fixed.status_code", - FT_UINT16, BASE_HEX, VALS (&status_codes), 0, - "Status of requested event", HFILL }}, - - {&ff_category_code, - {"Category code", "wlan_mgt.fixed.category_code", - FT_UINT16, BASE_HEX, VALS (&category_codes), 0, - "Management action category", HFILL }}, - - {&ff_action_code, - {"Action code", "wlan_mgt.fixed.action_code", - FT_UINT16, BASE_HEX, VALS (&action_codes), 0, - "Management action code", HFILL }}, - - {&ff_dialog_token, - {"Dialog token", "wlan_mgt.fixed.dialog_token", - FT_UINT16, BASE_HEX, NULL, 0, "Management action dialog token", HFILL }}, - - {&ff_wme_action_code, - {"Action code", "wlan_mgt.fixed.action_code", - FT_UINT16, BASE_HEX, VALS (&wme_action_codes), 0, - "Management notification action code", HFILL }}, - - {&ff_wme_status_code, - {"Status code", "wlan_mgt.fixed.status_code", - FT_UINT16, BASE_HEX, VALS (&wme_status_codes), 0, - "Management notification setup response status code", HFILL }}, - - {&tag_number, - {"Tag", "wlan_mgt.tag.number", - FT_UINT8, BASE_DEC, VALS(tag_num_vals), 0, - "Element ID", HFILL }}, - - {&tag_length, - {"Tag length", "wlan_mgt.tag.length", - FT_UINT8, BASE_DEC, NULL, 0, "Length of tag", HFILL }}, - - {&tag_interpretation, - {"Tag interpretation", "wlan_mgt.tag.interpretation", - FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }}, - - {&rsn_cap, - {"RSN Capabilities", "wlan_mgt.rsn.capabilities", FT_UINT16, BASE_HEX, - NULL, 0, "RSN Capability information", HFILL }}, - - {&rsn_cap_preauth, - {"RSN Pre-Auth capabilities", "wlan_mgt.rsn.capabilities.preauth", - FT_BOOLEAN, 16, TFS (&rsn_preauth_flags), 0x0001, - "RSN Pre-Auth capabilities", HFILL }}, - - {&rsn_cap_no_pairwise, - {"RSN No Pairwise capabilities", "wlan_mgt.rsn.capabilities.no_pairwise", - FT_BOOLEAN, 16, TFS (&rsn_no_pairwise_flags), 0x0002, - "RSN No Pairwise capabilities", HFILL }}, - - {&rsn_cap_ptksa_replay_counter, - {"RSN PTKSA Replay Counter capabilities", - "wlan_mgt.rsn.capabilities.ptksa_replay_counter", - FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x000C, - "RSN PTKSA Replay Counter capabilities", HFILL }}, - - {&rsn_cap_gtksa_replay_counter, - {"RSN GTKSA Replay Counter capabilities", - "wlan_mgt.rsn.capabilities.gtksa_replay_counter", - FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x0030, - "RSN GTKSA Replay Counter capabilities", HFILL }}, - }; - - static gint *tree_array[] = { - &ett_80211, - &ett_fc_tree, - &ett_proto_flags, - &ett_fragments, - &ett_fragment, - &ett_80211_mgt, - &ett_fixed_parameters, - &ett_tagged_parameters, - &ett_qos_parameters, - &ett_wep_parameters, - &ett_cap_tree, - &ett_rsn_cap_tree, - }; - module_t *wlan_module; - - static const enum_val_t wep_keys_options[] = { - {"0", "0", 0}, - {"1", "1", 1}, - {"2", "2", 2}, - {"3", "3", 3}, - {"4", "4", 4}, - {NULL, NULL, -1}, - }; - - - proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN", - "IEEE 802.11", "wlan"); - proto_register_field_array (proto_wlan, hf, array_length (hf)); - proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame", - "802.11 MGT", "wlan_mgt"); - proto_register_field_array (proto_wlan_mgt, ff, array_length (ff)); - proto_register_subtree_array (tree_array, array_length (tree_array)); - - register_dissector("wlan", dissect_ieee80211, proto_wlan); - register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan); - register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan); - register_init_routine(wlan_defragment_init); - - /* Register configuration options */ - wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys); - prefs_register_bool_preference(wlan_module, "defragment", - "Reassemble fragmented 802.11 datagrams", - "Whether fragmented 802.11 datagrams should be reassembled", - &wlan_defragment); - - prefs_register_bool_preference(wlan_module, "check_fcs", - "Assume packets have FCS", - "Some 802.11 cards include the FCS at the end of a packet, others do not.", - &wlan_check_fcs); - - prefs_register_bool_preference(wlan_module, "ignore_wep", - "Ignore the WEP bit", - "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.", - &wlan_ignore_wep); - -#ifndef USE_ENV - prefs_register_enum_preference(wlan_module, "wep_keys", - "WEP key count", - "How many WEP keys do we have to choose from? (0 to disable, up to 4)", - &num_wepkeys, wep_keys_options, FALSE); - - prefs_register_string_preference(wlan_module, "wep_key1", - "WEP key #1", - "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", - &wep_keystr[0]); - prefs_register_string_preference(wlan_module, "wep_key2", - "WEP key #2", - "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", - &wep_keystr[1]); - prefs_register_string_preference(wlan_module, "wep_key3", - "WEP key #3", - "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", - &wep_keystr[2]); - prefs_register_string_preference(wlan_module, "wep_key4", - "WEP key #4", - "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", - &wep_keystr[3]); -#endif -} - -void -proto_reg_handoff_ieee80211(void) -{ - dissector_handle_t ieee80211_handle; - dissector_handle_t ieee80211_radio_handle; - - /* - * Get handles for the LLC, IPX and Ethernet dissectors. - */ - llc_handle = find_dissector("llc"); - ipx_handle = find_dissector("ipx"); - eth_handle = find_dissector("eth"); - data_handle = find_dissector("data"); - - ieee80211_handle = find_dissector("wlan"); - dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle); - ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio, - proto_wlan); - dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO, - ieee80211_radio_handle); -} - -static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) { - const guint8 *enc_data; - guint8 *tmp = NULL; - int i; - tvbuff_t *decr_tvb = NULL; - - if (num_wepkeys < 1) - return NULL; - - enc_data = tvb_get_ptr(tvb, offset, len); - - if ((tmp = g_malloc(len)) == NULL) - return NULL; /* krap! */ - - /* try once with the key index in the packet, then look through our list. */ - for (i = -1; i < (int) num_wepkeys; i++) { - /* copy the encrypted data over to the tmp buffer */ -#if 0 - printf("trying %d\n", i); -#endif - memcpy(tmp, enc_data, len); - if (wep_decrypt(tmp, len, i) == 0) { - - /* decrypt successful, let's set up a new data tvb. */ - decr_tvb = tvb_new_real_data(tmp, len-8, len-8); - tvb_set_free_cb(decr_tvb, g_free); - tvb_set_child_real_data_tvbuff(tvb, decr_tvb); - - goto done; - } - } - - done: - if ((!decr_tvb) && (tmp)) g_free(tmp); - -#if 0 - printf("de-wep %p\n", decr_tvb); -#endif - - return decr_tvb; -} - - -/* de-weps the block. if successful, buf* will point to the data start. */ -static int wep_decrypt(guint8 *buf, guint32 len, int key_override) { - guint32 i, j, k, crc, keylen; - guint8 s[256], key[128], c_crc[4]; - guint8 keyidx, *dpos, *cpos; - - /* Needs to be at least 8 bytes of payload */ - if (len < 8) - return -1; - - /* initialize the first bytes of the key from the IV */ - key[0] = buf[0]; - key[1] = buf[1]; - key[2] = buf[2]; - keyidx = COOK_WEP_KEY(buf[3]); - - if (key_override >= 0) - keyidx = key_override; - - if (keyidx >= num_wepkeys) - return -1; - - keylen = wep_keylens[keyidx]; - - if (keylen == 0) - return -1; - if (wep_keys[keyidx] == NULL) - return -1; - - keylen+=3; /* add in ICV bytes */ - - /* copy the rest of the key over from the designated key */ - memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]); - -#if 0 - 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]); -#endif - - /* set up the RC4 state */ - for (i = 0; i < 256; i++) - s[i] = i; - j = 0; - for (i = 0; i < 256; i++) { - j = (j + s[i] + key[i % keylen]) & 0xff; - SSWAP(i,j); - } - - /* Apply the RC4 to the data, update the CRC32 */ - cpos = buf+4; - dpos = buf; - crc = ~0; - i = j = 0; - for (k = 0; k < (len -8); k++) { - i = (i+1) & 0xff; - j = (j+s[i]) & 0xff; - SSWAP(i,j); -#if 0 - printf("%d -- %02x ", k, *dpos); -#endif - *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff]; -#if 0 - printf("%02x\n", *dpos); -#endif - crc = crc32_ccitt_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8); - } - crc = ~crc; - - /* now let's check the crc */ - c_crc[0] = crc; - c_crc[1] = crc >> 8; - c_crc[2] = crc >> 16; - c_crc[3] = crc >> 24; - - for (k = 0; k < 4; k++) { - i = (i + 1) & 0xff; - j = (j+s[i]) & 0xff; - SSWAP(i,j); -#if 0 - printf("-- %02x %02x\n", *dpos, c_crc[k]); -#endif - if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k]) - return -1; /* ICV mismatch */ - } - - return 0; -} - -static void init_wepkeys(void) { - char *tmp; - guint i; - GByteArray *bytes; - gboolean res; - -#ifdef USE_ENV - guint8 buf[128]; - - tmp = getenv("ETHEREAL_WEPKEYNUM"); - if (!tmp) { - num_wepkeys = 0; - return; - } - num_wepkeys = atoi(tmp); -#else - if (num_wepkeys > 4) - num_wepkeys = 4; -#endif - - if (num_wepkeys < 1) - return; - - if (wep_keys) - g_free(wep_keys); - - if (wep_keylens) - g_free(wep_keylens); - - wep_keys = g_malloc(num_wepkeys * sizeof(guint8*)); - wep_keylens = g_malloc(num_wepkeys * sizeof(int)); - bytes = g_byte_array_new(); - - for (i = 0 ; i < num_wepkeys; i++) { - wep_keys[i] = NULL; - wep_keylens[i] = 0; - -#ifdef USE_ENV - sprintf(buf, "ETHEREAL_WEPKEY%d", i+1); - tmp = getenv(buf); -#else - tmp = wep_keystr[i]; -#endif - - if (tmp) { -#if 0 -#ifdef USE_ENV - printf("%s -- %s\n", buf, tmp); -#else - printf("%d -- %s\n", i+1, tmp); -#endif -#endif - - if (wep_keys[i]) { - g_free(wep_keys[i]); - } - - res = hex_str_to_bytes(tmp, bytes, FALSE); - if (res && bytes->len > 0) { - if (bytes->len > 32) { - bytes->len = 32; - } - wep_keys[i] = g_malloc(32 * sizeof(guint8)); - memset(wep_keys[i], 0, 32 * sizeof(guint8)); - memcpy(wep_keys[i], bytes->data, bytes->len * sizeof(guint8)); - wep_keylens[i] = bytes->len; -#if 0 - printf("%d: %d bytes\n", i, bytes->len); - printf("%d: %s\n", i, bytes_to_str(bytes->data, bytes->len)); -#endif - } else { -#if 0 - printf("res: %d bytes->len: %d\n", res, bytes->len); -#endif - g_warning("Could not parse WEP key %d: %s", i + 1, tmp); - } - } - } - g_byte_array_free(bytes, TRUE); -} |