aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ieee802154.c
diff options
context:
space:
mode:
authorOwen Kirby <osk@exegin.com>2014-04-17 23:33:42 -0400
committerAnders Broman <a.broman58@gmail.com>2014-05-22 15:05:33 +0000
commit177c6556f719d9533437a24fa7e89ff23c842651 (patch)
tree9d569115da991032c2c83af6c28f89b9e1d19655 /epan/dissectors/packet-ieee802154.c
parent19c1989cfad21b3aee52a9183751d1847e2e3211 (diff)
Tighten heuristic checks for IEEE 802.15.4 protocols, and add Decode-As by PANID for when we still get it wrong.
Change-Id: Icc2b274d2478a9426da881998bbbbfb3bf34ec4a Reviewed-on: https://code.wireshark.org/review/1167 Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-ieee802154.c')
-rw-r--r--epan/dissectors/packet-ieee802154.c272
1 files changed, 171 insertions, 101 deletions
diff --git a/epan/dissectors/packet-ieee802154.c b/epan/dissectors/packet-ieee802154.c
index c02ce07d81..31302a288e 100644
--- a/epan/dissectors/packet-ieee802154.c
+++ b/epan/dissectors/packet-ieee802154.c
@@ -66,6 +66,7 @@
#include <glib.h>
#include <epan/wmem/wmem.h>
+#include <epan/decode_as.h>
#include <epan/packet.h>
#include <epan/exceptions.h>
#include <wsutil/pint.h>
@@ -175,6 +176,7 @@ static void dissect_ieee802154_fcf (tvbuff_t *, packet_info *, proto_tr
static void dissect_ieee802154_superframe (tvbuff_t *, packet_info *, proto_tree *, guint *);
static void dissect_ieee802154_gtsinfo (tvbuff_t *, packet_info *, proto_tree *, guint *);
static void dissect_ieee802154_pendaddr (tvbuff_t *, packet_info *, proto_tree *, guint *);
+static void dissect_ieee802154_command (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
static void dissect_ieee802154_assoc_req (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
static void dissect_ieee802154_assoc_rsp (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
static void dissect_ieee802154_disassoc (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
@@ -295,8 +297,15 @@ static expert_field ei_ieee802154_decrypt_error = EI_INIT;
static expert_field ei_ieee802154_dst = EI_INIT;
static expert_field ei_ieee802154_src = EI_INIT;
-/* Dissector handles */
+/*
+ * Dissector handles
+ * - beacon dissection is always heuristic.
+ * - the PANID table is for stateful dissectors only (ie: Decode-As)
+ * - otherwise, data dissectors fall back to the heuristic dissectors.
+ */
static dissector_handle_t data_handle;
+static dissector_table_t panid_dissector_table;
+static heur_dissector_list_t ieee802154_beacon_subdissector_list;
static heur_dissector_list_t ieee802154_heur_subdissector_list;
/* Name Strings */
@@ -381,7 +390,6 @@ static gboolean ieee802154_extend_auth = TRUE;
#define IEEE802154_CRC_XOROUT 0xFFFF
#define ieee802154_crc_tvb(tvb, offset) (crc16_ccitt_tvb_seed(tvb, offset, IEEE802154_CRC_SEED) ^ IEEE802154_CRC_XOROUT)
-
/*FUNCTION:------------------------------------------------------
* NAME
* dissect_ieee802154_fcf
@@ -768,10 +776,14 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
}
offset += 2;
}
- else {
- /* Set the panID field in case the intra-pan condition was met. */
+ /* Set the panID field in case the intra-pan condition was met. */
+ else if (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) {
packet->src_pan = packet->dst_pan;
}
+ /* If all else fails, consider it a broadcast PANID. */
+ else {
+ packet->src_pan = IEEE802154_BCAST_PAN;
+ }
if (ieee_hints) {
ieee_hints->src_pan = packet->src_pan;
@@ -1068,108 +1080,40 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
saved_proto = pinfo->current_proto;
/* Try to dissect the payload. */
TRY {
- if ((packet->frame_type == IEEE802154_FCF_BEACON) ||
- (packet->frame_type == IEEE802154_FCF_DATA)) {
- /* Beacon and Data packets contain a payload. */
- if ((fcs_ok || !ieee802154_fcs_ok) && (tvb_reported_length(payload_tvb)>0)) {
- /* Attempt heuristic subdissection. */
- if (!dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) {
- /* Could not subdissect, call the data dissector instead. */
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- }
- }
- else {
- /* If no sub-dissector was called, call the data dissector. */
+ switch (packet->frame_type) {
+ case IEEE802154_FCF_BEACON:
+ if (!dissector_try_heuristic(ieee802154_beacon_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) {
+ /* Could not subdissect, call the data dissector instead. */
call_dissector(data_handle, payload_tvb, pinfo, tree);
}
- }
- /* If the packet is a command, try to dissect the payload. */
- else if (packet->frame_type == IEEE802154_FCF_CMD) {
- switch (packet->command_id) {
- case IEEE802154_CMD_ASRQ:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
- dissect_ieee802154_assoc_req(payload_tvb, pinfo, ieee802154_tree, packet);
- break;
-
- case IEEE802154_CMD_ASRSP:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
- dissect_ieee802154_assoc_rsp(payload_tvb, pinfo, ieee802154_tree, packet);
- break;
-
- case IEEE802154_CMD_DISAS:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
- dissect_ieee802154_disassoc(payload_tvb, pinfo, ieee802154_tree, packet);
- break;
-
- case IEEE802154_CMD_DATA_RQ:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
- /* No payload expected. */
- break;
-
- case IEEE802154_CMD_PANID_ERR:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
- /* No payload expected. */
- break;
-
- case IEEE802154_CMD_ORPH_NOTIF:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
- (packet->dst16 == IEEE802154_BCAST_ADDR) &&
- (packet->src_pan == IEEE802154_BCAST_PAN) &&
- (packet->dst_pan == IEEE802154_BCAST_PAN));
- /* No payload expected. */
- break;
-
- case IEEE802154_CMD_BCN_RQ:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
- (packet->dst16 == IEEE802154_BCAST_ADDR) &&
- (packet->dst_pan == IEEE802154_BCAST_PAN));
- /* No payload expected. */
- break;
-
- case IEEE802154_CMD_COORD_REAL:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_pan == IEEE802154_BCAST_PAN) &&
- (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
- if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
- /* If directed to a 16-bit address, check that it is being broadcast. */
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id, packet->dst16 == IEEE802154_BCAST_ADDR);
- }
- dissect_ieee802154_realign(payload_tvb, pinfo, ieee802154_tree, packet);
+ break;
+ case IEEE802154_FCF_CMD:
+ dissect_ieee802154_command(payload_tvb, pinfo, ieee802154_tree, packet);
+ break;
+ case IEEE802154_FCF_DATA:
+ /* Sanity-check. */
+ if ((!fcs_ok && ieee802154_fcs_ok) || !tvb_reported_length(payload_tvb)) {
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
break;
-
- case IEEE802154_CMD_GTS_REQ:
- /* Check that the addressing is correct for this command type. */
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
- (packet->src16 != IEEE802154_BCAST_ADDR) &&
- (packet->src16 != IEEE802154_NO_ADDR16));
- dissect_ieee802154_gtsreq(payload_tvb, pinfo, ieee802154_tree, packet);
+ }
+ /* Try the PANID dissector table for stateful dissection. */
+ if (dissector_try_uint_new(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, TRUE, packet)) {
break;
-
- default:
- /* Unknown Command */
- call_dissector(data_handle, payload_tvb, pinfo, ieee802154_tree);
+ }
+ /* Try again with the destination PANID (if different) */
+ if (((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
+ (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
+ (packet->dst_pan != packet->src_pan) &&
+ dissector_try_uint_new(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, TRUE, packet)) {
break;
- } /* switch */
- }
- /* Otherwise, dump whatever is left over to the data dissector. */
- else {
+ }
+ /* Try heuristic dissection. */
+ if (dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, packet)) break;
+ /* Fall-through to dump undissectable payloads. */
+ default:
+ /* Could not subdissect, call the data dissector instead. */
call_dissector(data_handle, payload_tvb, pinfo, tree);
- }
+ } /* switch */
}
CATCH_ALL {
/*
@@ -1753,6 +1697,103 @@ dissect_ieee802154_gtsreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
/*FUNCTION:------------------------------------------------------
* NAME
+ * dissect_ieee802154_command
+ * DESCRIPTION
+ * Subdissector routine all commands.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_info *pinfo - pointer to packet information fields (unused).
+ * proto_tree *tree - pointer to protocol tree.
+ * ieee802154_packet *packet - IEEE 802.15.4 packet information (unused).
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+static void
+dissect_ieee802154_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
+{
+ switch (packet->command_id) {
+ case IEEE802154_CMD_ASRQ:
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
+ (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
+ (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
+ dissect_ieee802154_assoc_req(tvb, pinfo, tree, packet);
+ break;
+
+ case IEEE802154_CMD_ASRSP:
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
+ (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
+ (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
+ dissect_ieee802154_assoc_rsp(tvb, pinfo, tree, packet);
+ break;
+
+ case IEEE802154_CMD_DISAS:
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
+ (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
+ (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
+ dissect_ieee802154_disassoc(tvb, pinfo, tree, packet);
+ return;
+
+ case IEEE802154_CMD_DATA_RQ:
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
+ /* No payload expected. */
+ break;
+
+ case IEEE802154_CMD_PANID_ERR:
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
+ (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
+ (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
+ /* No payload expected. */
+ break;
+
+ case IEEE802154_CMD_ORPH_NOTIF:
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
+ (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
+ (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
+ (packet->dst16 == IEEE802154_BCAST_ADDR) &&
+ (packet->src_pan == IEEE802154_BCAST_PAN) &&
+ (packet->dst_pan == IEEE802154_BCAST_PAN));
+ /* No payload expected. */
+ break;
+
+ case IEEE802154_CMD_BCN_RQ:
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
+ (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
+ (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
+ (packet->dst16 == IEEE802154_BCAST_ADDR) &&
+ (packet->dst_pan == IEEE802154_BCAST_PAN));
+ /* No payload expected. */
+ break;
+
+ case IEEE802154_CMD_COORD_REAL:
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
+ (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
+ (packet->dst_pan == IEEE802154_BCAST_PAN) &&
+ (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
+ if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
+ /* If directed to a 16-bit address, check that it is being broadcast. */
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->dst16 == IEEE802154_BCAST_ADDR);
+ }
+ dissect_ieee802154_realign(tvb, pinfo, tree, packet);
+ return;
+
+ case IEEE802154_CMD_GTS_REQ:
+ /* Check that the addressing is correct for this command type. */
+ IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
+ (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
+ (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
+ (packet->src16 != IEEE802154_BCAST_ADDR) &&
+ (packet->src16 != IEEE802154_NO_ADDR16));
+ dissect_ieee802154_gtsreq(tvb, pinfo, tree, packet);
+ return;
+ } /* switch */
+
+ /* Dump unexpected, or unknown command payloads. */
+ call_dissector(data_handle, tvb, pinfo, tree);
+} /* dissect_ieee802154_command */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
* dissect_ieee802154_decrypt
* DESCRIPTION
* IEEE 802.15.4 decryption algorithm. Tries to find the
@@ -2338,7 +2379,6 @@ gboolean ieee802154_long_addr_invalidate(guint64 long_addr, guint fnum)
return FALSE;
} /* ieee802154_long_addr_invalidate */
-
/*FUNCTION:------------------------------------------------------
* NAME
* proto_init_ieee802154
@@ -2374,6 +2414,23 @@ proto_init_ieee802154(void)
} /* for */
} /* proto_init_ieee802154 */
+/* Returns the prompt string for the Decode-As dialog. */
+static void ieee802154_da_prompt(packet_info *pinfo _U_, gchar* result)
+{
+ ieee802154_hints_t *hints;
+ hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
+ proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
+ g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN 0x%04x as", hints->src_pan);
+} /* iee802154_da_prompt */
+
+/* Returns the value to index the panid decode table with (source PAN)*/
+static gpointer ieee802154_da_value(packet_info *pinfo _U_)
+{
+ ieee802154_hints_t *hints;
+ hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
+ proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
+ return GUINT_TO_POINTER(hints->src_pan);
+} /* iee802154_da_value */
/*FUNCTION:------------------------------------------------------
* NAME
@@ -2693,6 +2750,14 @@ void proto_register_ieee802154(void)
UAT_END_FIELDS
};
+ static build_valid_func ieee802154_da_build_value[1] = {ieee802154_da_value};
+ static decode_as_value_t ieee802154_da_values = {ieee802154_da_prompt, 1, ieee802154_da_build_value};
+ static decode_as_t ieee802154_da = {
+ IEEE802154_PROTOABBREV_WPAN, "PAN", IEEE802154_PROTOABBREV_WPAN_PANID,
+ 1, 0, &ieee802154_da_values, NULL, NULL,
+ decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL
+ };
+
/* Register the init routine. */
register_init_routine(proto_init_ieee802154);
@@ -2765,13 +2830,18 @@ void proto_register_ieee802154(void)
&ieee802154_extend_auth);
/* Register the subdissector list */
+ panid_dissector_table = register_dissector_table(IEEE802154_PROTOABBREV_WPAN_PANID, "IEEE 802.15.4 PANID", FT_UINT16, BASE_HEX);
register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN, &ieee802154_heur_subdissector_list);
+ register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN_BEACON, &ieee802154_beacon_subdissector_list);
/* Register dissectors with Wireshark. */
register_dissector(IEEE802154_PROTOABBREV_WPAN, dissect_ieee802154, proto_ieee802154);
register_dissector("wpan_nofcs", dissect_ieee802154_nofcs, proto_ieee802154);
register_dissector("wpan_cc24xx", dissect_ieee802154_cc24xx, proto_ieee802154);
register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
+
+ /* Register a Decode-As handler. */
+ register_decode_as(&ieee802154_da);
} /* proto_register_ieee802154 */