aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ieee802154.c
diff options
context:
space:
mode:
authorJaap Keuter <jaap.keuter@xs4all.nl>2010-03-11 07:50:45 +0000
committerJaap Keuter <jaap.keuter@xs4all.nl>2010-03-11 07:50:45 +0000
commite0cef3d9f9a714517032f0ec20a8794bfe279dc4 (patch)
tree3da7eb14755cf159a58bcc8c9131936162b91ced /epan/dissectors/packet-ieee802154.c
parente1b68812865ac511f095e4a0f58bf52cbb36d150 (diff)
From Owen Kirby:
This patch adds a hash table that stores any short-to-extended address mappings that the dissector finds for later use during packet decryption. I've also added a UAT so the user can manually add address pairs if needed. svn path=/trunk/; revision=32166
Diffstat (limited to 'epan/dissectors/packet-ieee802154.c')
-rw-r--r--epan/dissectors/packet-ieee802154.c199
1 files changed, 195 insertions, 4 deletions
diff --git a/epan/dissectors/packet-ieee802154.c b/epan/dissectors/packet-ieee802154.c
index a45e0a7813..ddb9bf2347 100644
--- a/epan/dissectors/packet-ieee802154.c
+++ b/epan/dissectors/packet-ieee802154.c
@@ -79,6 +79,7 @@
#include <epan/expert.h>
#include <epan/addr_resolv.h>
#include <epan/prefs.h>
+#include <epan/uat.h>
#include <epan/strutil.h>
/* Use libgcrypt for cipher libraries. */
@@ -107,11 +108,110 @@ static const gchar *ieee802154_key_str = NULL;
static gboolean ieee802154_key_valid;
static guint8 ieee802154_key[IEEE802154_CIPHER_SIZE];
-/* Function declarations */
+/*-------------------------------------
+ * Address Hash Table
+ *-------------------------------------
+ */
+static GHashTable * ieee802154_addr_table = NULL;
+
+/* Value used for the hash table. */
+typedef struct {
+ guint64 addr;
+ //guint32 frame_counter; /* TODO for frame counter sequence checks. Any other security state to save across packets? */
+} ieee802154_long_addr;
+
+/* Keys used for the hash table. */
+typedef struct {
+ guint16 addr;
+ guint16 pan;
+} ieee802154_short_addr;
+
+/* Key hash function. */
+static guint
+ieee802154_addr_hash(gconstpointer key)
+{
+ return (((ieee802154_short_addr *)key)->addr) | (((ieee802154_short_addr *)key)->pan << 16);
+}
+
+/* Key equals function. */
+static gboolean
+ieee802154_addr_equals(gconstpointer a, gconstpointer b)
+{
+ return (((ieee802154_short_addr *)a)->addr == ((ieee802154_short_addr *)b)->addr) &&
+ (((ieee802154_short_addr *)a)->pan == ((ieee802154_short_addr *)b)->pan);
+}
+
+/* Function to update the address table. */
+/* TODO: Make this a public function, in case other layers expose short-to-extended address pairs. */
+static void ieee802154_addr_update(guint16 short_addr, guint16 pan, guint64 long_addr)
+{
+ ieee802154_short_addr addr16;
+ ieee802154_long_addr * addr64;
+ addr16.addr = short_addr;
+ addr16.pan = pan;
+ addr64 = g_hash_table_lookup(ieee802154_addr_table, &addr16);
+ if (addr64) {
+ addr64->addr = long_addr;
+ }
+ else {
+ addr64 = se_alloc(sizeof(ieee802154_long_addr));
+ addr64->addr = long_addr;
+ g_hash_table_insert(ieee802154_addr_table, se_memdup(&addr16, sizeof(addr16)), addr64);
+ }
+} /* ieee802154_addr_update */
+
+/*-------------------------------------
+ * Static Address Mapping UAT
+ *-------------------------------------
+ */
+/* UAT entry structure. */
+typedef struct {
+ guchar * eui64;
+ guint eui64_len;
+ guint addr16;
+ guint pan;
+} static_addr_t;
+
+/* UAT variables */
+static uat_t * static_addr_uat = NULL;
+static static_addr_t * static_addrs = NULL;
+static guint num_static_addrs = 0;
+
+/* Sanity-checks a UAT record. */
+static void
+addr_uat_update_cb(void* r, const char** err)
+{
+ static_addr_t * map = r;
+ /* Ensure a valid short address */
+ if (map->addr16 >= IEEE802154_NO_ADDR16) {
+ *err = "Invalid short address";
+ }
+ /* Ensure a valid PAN identifier. */
+ if (map->pan >= IEEE802154_BCAST_PAN) {
+ *err = "Invalid PAN identifier";
+ }
+ /* Ensure a valid EUI-64 length */
+ if (map->eui64_len != sizeof(guint64)) {
+ *err = "Invalid EUI-64";
+ }
+} /* ieee802154_addr_uat_update_cb */
+
+/* Field callbacks. */
+UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
+UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
+UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
+
+/*-------------------------------------
+ * Dissector Function Prototypes
+ *-------------------------------------
+ */
/* Register Functions. Loads the dissector into Wireshark. */
void proto_reg_handoff_ieee802154 (void);
void proto_register_ieee802154 (void);
+static void proto_init_ieee802154 (void);
+/* TODO: cleanup. */
+
/* Dissection Routines. */
static void dissect_ieee802154_nonask_phy (tvbuff_t *, packet_info *, proto_tree *);
static void dissect_ieee802154 (tvbuff_t *, packet_info *, proto_tree *);
@@ -1476,6 +1576,11 @@ dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
}
}
+ /* Update the address table. */
+ if ((status == IEEE802154_CMD_ASRSP_AS_SUCCESS) && (short_addr != IEEE802154_NO_ADDR16)) {
+ ieee802154_addr_update(short_addr, packet->dst_pan, packet->dst.addr64);
+ }
+
/* Call the data dissector for any leftover bytes. */
if (tvb_length(tvb) > offset) {
call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
@@ -1593,6 +1698,10 @@ dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
col_append_fstr(pinfo->cinfo, COL_INFO, ", Addr: 0x%04x", short_addr);
}
offset += 2;
+ /* Update the address table. */
+ if ((short_addr != IEEE802154_NO_ADDR16) && (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) {
+ ieee802154_addr_update(short_addr, packet->dst_pan, packet->dst.addr64);
+ }
/* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
if (tvb_bytes_exist(tvb, offset, 1)) {
@@ -1744,12 +1853,28 @@ dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ie
*
* Also need to find the extended address of the sender.
*/
- /* Get the extended source address. */
if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
+ /* The source EUI-64 is included in the headers. */
srcAddr = packet->src.addr64;
}
+ else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
+ ieee802154_short_addr addr16;
+ ieee802154_long_addr * addr64;
+
+ /* Try to lookup the EUI-64 from the address table. */
+ addr16.addr = packet->src.addr16;
+ addr16.pan = packet->src_pan;
+ addr64 = (ieee802154_long_addr *)g_hash_table_lookup(ieee802154_addr_table, &addr16);
+ if (!addr64) {
+ /* Lookup failed. */
+ *status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
+ return NULL;
+ }
+ /* Lookup successful. */
+ srcAddr = addr64->addr;
+ }
else {
- /* TODO: Implement a lookup table or something. */
+ /* No addressing is present in the headers. We're screwed. */
*status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
return NULL;
}
@@ -2082,6 +2207,7 @@ ccm_cbc_mac(const gchar *key _U_, const gchar *iv _U_, const gchar *a _U_, gint
*/
void proto_register_ieee802154(void)
{
+ /* Protocol fields */
static hf_register_info hf_phy[] = {
/* PHY level */
@@ -2098,7 +2224,6 @@ void proto_register_ieee802154(void)
NULL, HFILL }},
};
-
static hf_register_info hf[] = {
{ &hf_ieee802154_frame_type,
{ "Frame Type", "wpan.frame_type", FT_UINT16, BASE_HEX, VALS(ieee802154_frame_types), IEEE802154_FCF_TYPE_MASK,
@@ -2327,6 +2452,7 @@ void proto_register_ieee802154(void)
"Key Index for processing of the protected frame", HFILL }}
};
+ /* Subtrees */
static gint *ett[] = {
&ett_ieee802154_nonask_phy,
&ett_ieee802154_nonask_phy_phr,
@@ -2344,8 +2470,22 @@ void proto_register_ieee802154(void)
&ett_ieee802154_pendaddr
};
+ /* Preferences. */
module_t *ieee802154_module;
+ static uat_field_t addr_uat_flds[] = {
+ UAT_FLD_HEX(addr_uat,addr16,"Short Address",
+ "16-bit short address in hexadecimal."),
+ UAT_FLD_HEX(addr_uat,pan,"PAN Identifier",
+ "16-bit PAN identifier in hexadecimal."),
+ UAT_FLD_BUFFER(addr_uat,eui64,"EUI-64",
+ "64-bit extended unique identifier."),
+ UAT_END_FIELDS
+ };
+
+ /* Register the init routine. */
+ register_init_routine(proto_init_ieee802154);
+
/* Register Protocol name and description. */
proto_ieee802154 = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN", "IEEE 802.15.4", "wpan");
proto_ieee802154_nonask_phy = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN non-ASK PHY", "IEEE 802.15.4 non-ASK PHY", "wpan-nonask-phy");
@@ -2372,6 +2512,25 @@ void proto_register_ieee802154(void)
"Dissect data only if FCS is ok.",
&ieee802154_fcs_ok);
+ /* Create a UAT for static address mappings. */
+ static_addr_uat = uat_new("Static Addresses",
+ sizeof(static_addr_t), /* record size */
+ "802154_addresses", /* filename */
+ TRUE, /* from_profile */
+ (void*) &static_addrs, /* data_ptr */
+ &num_static_addrs, /* numitems_ptr */
+ UAT_CAT_GENERAL, /* category */
+ NULL, /* help */
+ NULL, /* copy callback */
+ addr_uat_update_cb, /* update callback */
+ NULL, /* free callback */
+ NULL, /* post update callback */
+ addr_uat_flds); /* UAT field definitions */
+ prefs_register_uat_preference(ieee802154_module, "static_addr",
+ "Static Addresses",
+ "A table of static address mappings between 16-bit short addressing and EUI-64 addresses",
+ static_addr_uat);
+
/* Register preferences for a decryption key */
/* TODO: Implement a UAT for multiple keys, and with more advanced key management. */
prefs_register_string_preference(ieee802154_module, "802154_key", "Decryption key",
@@ -2438,3 +2597,35 @@ void proto_reg_handoff_ieee802154(void)
dissector_add("ethertype", ieee802154_ethertype, ieee802154_handle);
} /* proto_reg_handoff_ieee802154 */
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_init_ieee802154
+ * DESCRIPTION
+ * Init routine for the IEEE 802.15.4 dissector. Creates a
+ * hash table for mapping 16-bit to 64-bit addresses and
+ * populates it with static address pairs from a UAT
+ * preference table.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+static void
+proto_init_ieee802154(void)
+{
+ guint i;
+
+ /* Destroy the hash table, if it exists. */
+ if (ieee802154_addr_table)
+ g_hash_table_destroy(ieee802154_addr_table);
+
+ /* (Re)create the hash table. */
+ ieee802154_addr_table = g_hash_table_new(ieee802154_addr_hash, ieee802154_addr_equals);
+
+ /* Re-load the hash table from the static address UAT. */
+ for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
+ ieee802154_addr_update((guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan, pntoh64(static_addrs[i].eui64));
+ } /* for */
+} /* proto_init_ieee802154 */
+