* Copyright 2000, Axis Communications AB
* Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com
*
- * $Id: packet-ieee80211.c,v 1.81 2003/01/22 19:39:25 guy Exp $
+ * $Id: packet-ieee80211.c,v 1.91 2003/06/05 22:10:49 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#define TAG_TIM 0x05
#define TAG_IBSS_PARAMETER 0x06
#define TAG_CHALLENGE_TEXT 0x10
-#define TAG_ERP_INFO 0x2F
+#define TAG_ERP_INFO 0x2A
+#define TAG_ERP_INFO_OLD 0x2F /* IEEE Std 802.11g/D4.0 */
#define TAG_EXT_SUPP_RATES 0x32
+#define TAG_VENDOR_SPECIFIC_IE 0xDD
+
+#define WPA_OUI "\x00\x50\xF2"
/* ************************************************************************* */
/* Frame types, and their names */
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;
&hf_fragment_multiple_tails,
&hf_fragment_too_long_fragment,
&hf_fragment_error,
+ &hf_reassembled_in,
"fragments"
};
}
}
+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";
+}
+
+void
+dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
+ int tag_number, int tag_length, int tag_interpretation)
+{
+ guint8 tag_no;
+ guint32 tag_len;
+ const guint8 *tag_val;
+ guint32 tag_val_off = 0;
+ char out_buff[SHORT_STR];
+ int i;
+
+ tag_no = tvb_get_guint8(tvb, offset);
+ tag_len = tvb_get_guint8(tvb, offset + 1);
+ tag_val = tvb_get_ptr(tvb, offset + 2, tag_len);
+
+ proto_tree_add_uint(tree, tag_number, tvb, offset, 1, tag_no);
+ offset += 1;
+
+ proto_tree_add_uint(tree, tag_length, tvb, offset, 1, tag_len);
+ offset += 1;
+
+ 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
+ proto_tree_add_string(tree, tag_interpretation,
+ tvb, offset, tag_len, "Not interpreted");
+}
/* ************************************************************************* */
/* Dissect and add tagged (optional) fields to proto tree */
/* Next See if tag is reserved - if true, skip it! */
if (((tag_no >= 7) && (tag_no <= 15))
|| ((tag_no >= 32) && (tag_no <= 255) && (tag_no != TAG_ERP_INFO) &&
- (tag_no != TAG_EXT_SUPP_RATES)))
+ (tag_no != TAG_EXT_SUPP_RATES) &&
+ (tag_no != TAG_ERP_INFO_OLD) && (tag_no != TAG_VENDOR_SPECIFIC_IE)))
{
proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
"Tag Number: %u (Reserved tag number)",
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) {
+ if (ret == -1 || ret >= SHORT_STR - n) {
/* Some versions of snprintf return -1 if they'd truncate
- the output. */
+ 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_ERP_INFO:
+ case TAG_ERP_INFO_OLD:
proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
"Tag Number: %u (ERP Information)",
tag_no);
memset (out_buff, 0, SHORT_STR);
snprintf (out_buff, SHORT_STR,
- "ERP info: 0x%x (%sNon-ERP STAs, %suse protection)",
+ "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] & 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, tag_number, tag_length, tag_interpretation);
+ break;
default:
wlan_fragment_table,
wlan_reassembled_table,
frag_number,
- len,
+ reported_len,
more_frags);
if (fd_head != NULL) {
/*
* a non-fragmented frame.
*/
if (fd_head->next != NULL) {
- next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
- tvb_set_child_real_data_tvbuff(tvb, next_tvb);
- add_new_data_source(pinfo, next_tvb, "Reassembled 802.11");
-
- /* Show all fragments. */
- show_fragment_seq_tree(fd_head, &frag_items, hdr_tree, pinfo, next_tvb);
+ next_tvb = process_reassembled_data(tvb, pinfo, "Reassembled 802.11",
+ fd_head, &frag_items, NULL, hdr_tree);
} else {
/*
* Not fragmented, really.
"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"},
{0x00, NULL}
};
{"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 }},
}
done:
- if ((!decr_tvb) && (tmp)) free(tmp);
+ if ((!decr_tvb) && (tmp)) g_free(tmp);
#if 0
printf("de-wep %p\n", decr_tvb);
return 0;
}
-/* XXX need to verify these malloc()s succeed */
-
static void init_wepkeys(void) {
char *tmp, *tmp2;
guint8 *tmp3;
if (wep_keylens != NULL)
return;
- wep_keys = malloc(num_wepkeys * sizeof(guint8*));
- wep_keylens = malloc(num_wepkeys * sizeof(int));
+ wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
+ wep_keylens = g_malloc(num_wepkeys * sizeof(int));
for (i = 0 ; i < num_wepkeys; i++) {
wep_keys[i] = NULL;
#endif
#endif
- wep_keys[i] = malloc(32 * sizeof(guint8));
+ wep_keys[i] = g_malloc(32 * sizeof(guint8));
memset(wep_keys[i], 0, 32 * sizeof(guint8));
tmp3 = wep_keys[i];
while ((tmp != NULL) && (*tmp != 0)) {