aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2010-10-26 05:42:24 +0000
committerAnders Broman <anders.broman@ericsson.com>2010-10-26 05:42:24 +0000
commit26f0f7bc7a921b2096ae13544e04cc900efbad33 (patch)
treecf0b7371cfeaf8b1326cd86baf39beba169b5efa
parent161076b23bfedde54994776f77d2716c9dc2e916 (diff)
From Fred Fierling:
Multi-key Support and Extended Address Mapping for ZigBee Dissectors https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5331 svn path=/trunk/; revision=34647
-rw-r--r--epan/dissectors/packet-6lowpan.c8
-rw-r--r--epan/dissectors/packet-ieee802154.c501
-rw-r--r--epan/dissectors/packet-ieee802154.h63
-rw-r--r--epan/dissectors/packet-zbee-aps.c140
-rw-r--r--epan/dissectors/packet-zbee-aps.h58
-rw-r--r--epan/dissectors/packet-zbee-nwk.c443
-rw-r--r--epan/dissectors/packet-zbee-nwk.h32
-rw-r--r--epan/dissectors/packet-zbee-security.c722
-rw-r--r--epan/dissectors/packet-zbee-security.h14
-rw-r--r--epan/dissectors/packet-zbee.h10
10 files changed, 1346 insertions, 645 deletions
diff --git a/epan/dissectors/packet-6lowpan.c b/epan/dissectors/packet-6lowpan.c
index f2525b0e3b..7cd4054bdb 100644
--- a/epan/dissectors/packet-6lowpan.c
+++ b/epan/dissectors/packet-6lowpan.c
@@ -516,14 +516,14 @@ lowpan_dlsrc_to_ifcid(packet_info *pinfo, guint8 *ifcid)
/* Derive the IID from the IEEE 802.15.4 packet structure. */
if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
guint64 addr;
- addr = pntoh64(&packet->src.addr64);
+ addr = pntoh64(&packet->src64);
memcpy(ifcid, &addr, LOWPAN_IFC_ID_LEN);
/* RFC2464: Invert the U/L bit when using an EUI64 address. */
ifcid[0] ^= 0x02;
return TRUE;
}
if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
- lowpan_addr16_to_ifcid(packet->src.addr16, ifcid);
+ lowpan_addr16_to_ifcid(packet->src16, ifcid);
return TRUE;
}
@@ -561,14 +561,14 @@ lowpan_dldst_to_ifcid(packet_info *pinfo, guint8 *ifcid)
/* Derive the IID from the IEEE 802.15.4 packet structure. */
if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
guint64 addr;
- addr = pntoh64(&packet->dst.addr64);
+ addr = pntoh64(&packet->dst64);
memcpy(ifcid, &addr, LOWPAN_IFC_ID_LEN);
/* RFC2464: Invert the U/L bit when using an EUI64 address. */
ifcid[0] ^= 0x02;
return TRUE;
}
if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
- lowpan_addr16_to_ifcid(packet->dst.addr16, ifcid);
+ lowpan_addr16_to_ifcid(packet->dst16, ifcid);
return TRUE;
}
diff --git a/epan/dissectors/packet-ieee802154.c b/epan/dissectors/packet-ieee802154.c
index 9d230807bd..efa1e25aaf 100644
--- a/epan/dissectors/packet-ieee802154.c
+++ b/epan/dissectors/packet-ieee802154.c
@@ -100,7 +100,7 @@ static unsigned int ieee802154_ethertype = 0x809A;
/* boolean value set if the FCS field is using the TI CC24xx format */
static gboolean ieee802154_cc24xx = FALSE;
-/* boolean value set if the FCS must be oke before data is dissected */
+/* boolean value set if the FCS must be ok before payload is dissected */
static gboolean ieee802154_fcs_ok = TRUE;
/* User string with the decryption key. */
@@ -109,56 +109,10 @@ static gboolean ieee802154_key_valid;
static guint8 ieee802154_key[IEEE802154_CIPHER_SIZE];
/*-------------------------------------
- * Address Hash Table
+ * Address Hash Tables
*-------------------------------------
*/
-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 ieee802154_addr_t ieee802154_addr = { 0, NULL, NULL };
/*-------------------------------------
* Static Address Mapping UAT
@@ -192,7 +146,7 @@ addr_uat_update_cb(void* r, const char** err)
}
/* Ensure a valid EUI-64 length */
if (map->eui64_len != sizeof(guint64)) {
- *err = "Invalid EUI-64";
+ *err = "Invalid EUI-64 length";
}
} /* ieee802154_addr_uat_update_cb */
@@ -243,10 +197,11 @@ typedef enum {
DECRYPT_PACKET_MIC_CHECK_FAILED,
} ws_decrypt_status;
-static tvbuff_t * dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *, ws_decrypt_status *);
-static void ccm_init_block (gchar * block, gboolean adata, gint M, guint64 addr, guint32 counter, ieee802154_security_level level, gint ctr_val);
-static gboolean ccm_ctr_encrypt (const gchar *key, const gchar *iv, gchar *mic, gchar *data, gint length);
-static gboolean ccm_cbc_mac (const gchar * key, const gchar *iv, const gchar *a, gint a_len, const gchar *m, gint m_len, gchar *mic);
+static tvbuff_t * dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *,
+ ws_decrypt_status *);
+static void ccm_init_block (gchar *, gboolean, gint, guint64, guint32, ieee802154_security_level, gint);
+static gboolean ccm_ctr_encrypt (const gchar *, const gchar *, gchar *, gchar *, gint);
+static gboolean ccm_cbc_mac (const gchar *, const gchar *, const gchar *, gint, const gchar *, gint, gchar *);
/* Initialize Protocol and Registered fields */
static int proto_ieee802154_nonask_phy = -1;
@@ -268,8 +223,9 @@ static int hf_ieee802154_dst_pan = -1;
static int hf_ieee802154_dst_addr16 = -1;
static int hf_ieee802154_dst_addr64 = -1;
static int hf_ieee802154_src_panID = -1;
-static int hf_ieee802154_src_addr16 = -1;
-static int hf_ieee802154_src_addr64 = -1;
+static int hf_ieee802154_src16 = -1;
+static int hf_ieee802154_src64 = -1;
+static int hf_ieee802154_src64_origin = -1;
static int hf_ieee802154_fcs = -1;
static int hf_ieee802154_rssi = -1;
static int hf_ieee802154_fcs_ok = -1;
@@ -704,23 +660,36 @@ dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static void
dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint options)
{
- tvbuff_t *volatile payload_tvb;
- proto_tree *volatile ieee802154_tree = NULL;
- proto_item *volatile proto_root = NULL;
- proto_item *ti;
- void *pd_save;
-
- guint offset = 0;
- volatile gboolean fcs_ok = TRUE;
- const char *saved_proto;
- ieee802154_packet *packet = ep_alloc(sizeof(ieee802154_packet));
- ws_decrypt_status status;
+ tvbuff_t *volatile payload_tvb;
+ proto_tree *volatile ieee802154_tree = NULL;
+ proto_item *volatile proto_root = NULL;
+ proto_item *ti;
+ void *pd_save;
+
+ guint offset = 0;
+ volatile gboolean fcs_ok = TRUE;
+ const char *saved_proto;
+ ws_decrypt_status status;
+
+ ieee802154_packet *packet = ep_alloc(sizeof(ieee802154_packet));
+ ieee802154_short_addr addr16;
+ ieee802154_hints_t *ieee_hints;
/* Link our packet info structure into the private data field for the
* Network-Layer heuristic subdissectors. */
pd_save = pinfo->private_data;
pinfo->private_data = packet;
+ packet->short_table = ieee802154_addr.short_table;
+
+ /* Allocate frame data with hints for upper layers */
+ if(!pinfo->fd->flags.visited){
+ ieee_hints = se_alloc0(sizeof(ieee802154_hints_t));
+ p_add_proto_data(pinfo->fd, proto_ieee802154, ieee_hints);
+ } else {
+ ieee_hints = p_get_proto_data(pinfo->fd, proto_ieee802154);
+ }
+
/* Create the protocol tree. */
if (tree) {
proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_length(tvb), "IEEE 802.15.4");
@@ -782,17 +751,24 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
gchar *dst_addr = ep_alloc(32);
/* Get the address. */
- packet->dst.addr16 = tvb_get_letohs(tvb, offset);
+ packet->dst16 = tvb_get_letohs(tvb, offset);
/* Display the destination address. */
- if(packet->dst.addr16==IEEE802154_BCAST_ADDR) g_snprintf(dst_addr, 32, "Broadcast");
- else g_snprintf(dst_addr, 32, "0x%04x", packet->dst.addr16);
+ if ( packet->dst16 == IEEE802154_BCAST_ADDR ) {
+ g_snprintf(dst_addr, 32, "Broadcast");
+ }
+ else {
+ g_snprintf(dst_addr, 32, "0x%04x", packet->dst16);
+ }
+
SET_ADDRESS(&pinfo->dl_dst, AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr);
SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr);
+
if (tree) {
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_addr16, tvb, offset, 2, packet->dst.addr16);
+ proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_addr16, tvb, offset, 2, packet->dst16);
proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
}
+
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
}
@@ -804,14 +780,14 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
gchar *dst, *dst_oui;
/* Get the address */
- packet->dst.addr64 = tvb_get_letoh64(tvb, offset);
+ packet->dst64 = tvb_get_letoh64(tvb, offset);
/* print the address strings. */
- dst = print_eui64(packet->dst.addr64);
- dst_oui = print_eui64_oui(packet->dst.addr64);
+ dst = print_eui64(packet->dst64);
+ dst_oui = print_eui64_oui(packet->dst64);
/* Copy and convert the address to network byte order. */
- *(guint64 *)(addr) = pntoh64(&(packet->dst.addr64));
+ *(guint64 *)(addr) = pntoh64(&(packet->dst64));
/* Display the destination address. */
/* NOTE: OUI resolution doesn't happen when displaying EUI64 addresses
@@ -821,7 +797,8 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
SET_ADDRESS(&pinfo->dl_dst, AT_EUI64, 8, addr);
SET_ADDRESS(&pinfo->dst, AT_EUI64, 8, addr);
if (tree) {
- proto_tree_add_uint64_format_value(ieee802154_tree, hf_ieee802154_dst_addr64, tvb, offset, 8, packet->dst.addr64, "%s (%s)", dst_oui, dst);
+ proto_tree_add_uint64_format_value(ieee802154_tree, hf_ieee802154_dst_addr64, tvb, offset,
+ 8, packet->dst64, "%s (%s)", dst_oui, dst);
proto_item_append_text(proto_root, ", Dst: %s", dst_oui);
}
if (check_col(pinfo->cinfo, COL_INFO)) {
@@ -843,7 +820,8 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
if ( ((packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) || (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) || (!packet->intra_pan)) ) {
/* Source PAN is present, extract it and add it to the tree. */
- packet->src_pan = tvb_get_letohs(tvb, offset);
+ ieee_hints->src_pan = packet->src_pan = tvb_get_letohs(tvb, offset);
+
if (tree) {
proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_panID, tvb, offset, 2, packet->src_pan);
}
@@ -851,28 +829,63 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
}
else {
/* Set the panID field in case the intra-pan condition was met. */
- packet->src_pan = packet->dst_pan;
+ ieee_hints->src_pan = packet->src_pan = packet->dst_pan;
}
- /* Get source address if present. */
+ /* Get short source address if present. */
if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
/* Dynamic (not stack) memory required for address column. */
gchar *src_addr = ep_alloc(32);
/* Get the address. */
- packet->src.addr16 = tvb_get_letohs(tvb, offset);
+ packet->src16 = tvb_get_letohs(tvb, offset);
/* Update the Address fields. */
- if(packet->src.addr16==IEEE802154_BCAST_ADDR) g_snprintf(src_addr, 32, "Broadcast");
- else g_snprintf(src_addr, 32, "0x%04x", packet->src.addr16);
+ if (packet->src16==IEEE802154_BCAST_ADDR) {
+ g_snprintf(src_addr, 32, "Broadcast");
+ }
+ else {
+ g_snprintf(src_addr, 32, "0x%04x", packet->src16);
+
+ if (!pinfo->fd->flags.visited) {
+ /* If we know our extended source address from previous packets,
+ * provide a pointer to it in a hint for upper layers */
+ addr16.addr = packet->src16;
+ addr16.pan = packet->src_pan;
+
+ if (ieee_hints) {
+ ieee_hints->src16 = packet->src16;
+ ieee_hints->map_rec = (ieee802154_map_rec *)
+ g_hash_table_lookup(ieee802154_addr.short_table, &addr16);
+ }
+ }
+ }
+
SET_ADDRESS(&pinfo->dl_src, AT_STRINGZ, (int)strlen(src_addr)+1, src_addr);
SET_ADDRESS(&pinfo->src, AT_STRINGZ, (int)strlen(src_addr)+1, src_addr);
/* Add the addressing info to the tree. */
if (tree) {
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_addr16, tvb, offset, 2, packet->src.addr16);
+ proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src16, tvb, offset, 2, packet->src16);
proto_item_append_text(proto_root, ", Src: %s", src_addr);
+
+ if (ieee_hints && ieee_hints->map_rec) {
+ /* Display inferred source address info */
+ ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 0,
+ ieee_hints->map_rec->addr64);
+ PROTO_ITEM_SET_GENERATED(ti);
+
+ if ( ieee_hints->map_rec->start_fnum ) {
+ ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
+ ieee_hints->map_rec->start_fnum);
+ }
+ else {
+ ti = proto_tree_add_text(ieee802154_tree, tvb, 0, 0, "Origin: Pre-configured");
+ }
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
}
+
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
}
@@ -884,14 +897,14 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
gchar *src, *src_oui;
/* Get the address. */
- packet->src.addr64 = tvb_get_letoh64(tvb, offset);
+ packet->src64 = tvb_get_letoh64(tvb, offset);
/* Print the address strings. */
- src = print_eui64(packet->src.addr64);
- src_oui = print_eui64_oui(packet->src.addr64);
+ src = print_eui64(packet->src64);
+ src_oui = print_eui64_oui(packet->src64);
/* Copy and convert the address to network byte order. */
- *(guint64 *)(addr) = pntoh64(&(packet->src.addr64));
+ *(guint64 *)(addr) = pntoh64(&(packet->src64));
/* Display the source address. */
/* NOTE: OUI resolution doesn't happen when displaying EUI64 addresses
@@ -901,9 +914,11 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
SET_ADDRESS(&pinfo->dl_src, AT_EUI64, 8, addr);
SET_ADDRESS(&pinfo->src, AT_EUI64, 8, addr);
if (tree) {
- proto_tree_add_uint64_format_value(ieee802154_tree, hf_ieee802154_src_addr64, tvb, offset, 8, packet->src.addr64, "%s (%s)", src_oui, src);
+ proto_tree_add_uint64_format_value(ieee802154_tree, hf_ieee802154_src64, tvb, offset,
+ 8, packet->src64, "%s (%s)", src_oui, src);
proto_item_append_text(proto_root, ", Src: %s", src_oui);
}
+
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_oui);
}
@@ -945,14 +960,14 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
if (packet->security_enable && (packet->version == 1)) {
proto_tree *header_tree, *field_tree;
guint8 security_control;
- guint aux_length = 5; /* Minimum length of the auxilliary header. */
+ guint aux_length = 5; /* Minimum length of the auxiliary header. */
/* Parse the security control field. */
security_control = tvb_get_guint8(tvb, offset);
packet->security_level = (security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
packet->key_id_mode = (security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT;
- /* Compute the length of the auxilliar header and create a subtree. */
+ /* Compute the length of the auxiliary header and create a subtree. */
if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
@@ -1161,7 +1176,7 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
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->dst.addr16 == IEEE802154_BCAST_ADDR) &&
+ (packet->dst16 == IEEE802154_BCAST_ADDR) &&
(packet->src_pan == IEEE802154_BCAST_PAN) &&
(packet->dst_pan == IEEE802154_BCAST_PAN));
/* No payload expected. */
@@ -1171,7 +1186,7 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
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->dst.addr16 == IEEE802154_BCAST_ADDR) &&
+ (packet->dst16 == IEEE802154_BCAST_ADDR) &&
(packet->dst_pan == IEEE802154_BCAST_PAN));
/* No payload expected. */
break;
@@ -1183,7 +1198,7 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
(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->dst.addr16 == IEEE802154_BCAST_ADDR);
+ 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;
@@ -1193,8 +1208,8 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
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->src.addr16 != IEEE802154_BCAST_ADDR) &&
- (packet->src.addr16 != IEEE802154_NO_ADDR16));
+ (packet->src16 != IEEE802154_BCAST_ADDR) &&
+ (packet->src16 != IEEE802154_NO_ADDR16));
dissect_ieee802154_gtsreq(payload_tvb, pinfo, ieee802154_tree, packet);
break;
@@ -1537,7 +1552,8 @@ dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
/* Create a subtree for this command frame. */
if (tree) {
- ti = proto_tree_add_text(tree, tvb, offset, 3, "%s", val_to_str(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
+ ti = proto_tree_add_text(tree, tvb, offset, 3, "%s", val_to_str(packet->command_id,
+ ieee802154_cmd_names, "Unknown Command"));
subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
}
@@ -1578,7 +1594,8 @@ 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);
+ ieee802154_addr_update(&ieee802154_addr, short_addr, packet->dst_pan, packet->dst64,
+ proto_ieee802154, pinfo->fd->num);
}
/* Call the data dissector for any leftover bytes. */
@@ -1614,7 +1631,7 @@ dissect_ieee802154_disassoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
}
- /* Get and display the dissasociation reason. */
+ /* Get and display the disassociation reason. */
reason = tvb_get_guint8(tvb, 0);
if (tree) {
ti = proto_tree_add_uint(subtree, hf_ieee802154_disassoc_reason, tvb, 0, 1, reason);
@@ -1633,6 +1650,15 @@ dissect_ieee802154_disassoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
} /* switch */
}
+ if (!pinfo->fd->flags.visited) {
+ /* Update the address tables */
+ if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT ) {
+ ieee802154_long_addr_invalidate(packet->dst64, pinfo->fd->num);
+ } else if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT ) {
+ ieee802154_short_addr_invalidate(packet->dst16, packet->dst_pan, pinfo->fd->num);
+ }
+ }
+
/* Call the data dissector for any leftover bytes. */
if (tvb_length(tvb) > 1) {
call_dissector(data_handle, tvb_new_subset(tvb, 1, -1, -1), pinfo, tree);
@@ -1700,7 +1726,8 @@ dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
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);
+ ieee802154_addr_update(&ieee802154_addr, short_addr, packet->dst_pan, packet->dst64,
+ proto_ieee802154, pinfo->fd->num);
}
/* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
@@ -1752,7 +1779,8 @@ dissect_ieee802154_gtsreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
/* Create a subtree for this command frame. */
if (tree) {
- ti = proto_tree_add_text(tree, tvb, 0, 1, "%s", val_to_str(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
+ ti = proto_tree_add_text(tree, tvb, 0, 1, "%s", val_to_str(packet->command_id, ieee802154_cmd_names,
+ "Unknown Command"));
subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
}
@@ -1812,6 +1840,9 @@ dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ie
guint M = IEEE802154_MIC_LENGTH(packet->security_level);
gint captured_len;
gint reported_len;
+ ieee802154_hints_t *ieee_hints;
+
+ ieee_hints = p_get_proto_data(pinfo->fd, proto_ieee802154);
/* Get the captured and on-the-wire length of the payload. */
reported_len = tvb_reported_length_remaining(tvb, offset) - IEEE802154_FCS_LEN - M;
@@ -1855,26 +1886,14 @@ dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ie
*/
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;
+ srcAddr = packet->src64;
+ }
+ else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
+ /* Use the hint */
+ srcAddr = ieee_hints->map_rec->addr64;
}
else {
- /* No addressing is present in the headers. We're screwed. */
+ /* Lookup failed. */
*status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
return NULL;
}
@@ -2194,6 +2213,175 @@ ccm_cbc_mac(const gchar *key _U_, const gchar *iv _U_, const gchar *a _U_, gint
#endif
} /* ccm_cbc_mac */
+/* Key hash function. */
+guint ieee802154_short_addr_hash(gconstpointer key)
+{
+ return (((ieee802154_short_addr *)key)->addr) | (((ieee802154_short_addr *)key)->pan << 16);
+}
+
+/* Key equal function. */
+gboolean ieee802154_short_addr_equal(gconstpointer a, gconstpointer b)
+{
+ return (((ieee802154_short_addr *)a)->pan == ((ieee802154_short_addr *)b)->pan) &&
+ (((ieee802154_short_addr *)a)->addr == ((ieee802154_short_addr *)b)->addr);
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * ieee802154_addr_update
+ * DESCRIPTION
+ * Creates a record that maps the given short address and pan
+ * to a long (extended) address. Typically called when a
+ * successful association reponse is received.
+ * PARAMETERS
+ * guint16 short_addr - 16-bit short address
+ * guint16 pan - 16-bit PAN id
+ * guint64 long_addr - 64-bit long (extended) address
+ * guint - Frame number this mapping became valid
+ * RETURNS
+ * TRUE - Record was updated
+ * FALSE - Couldn't find it
+ *---------------------------------------------------------------
+ */
+ieee802154_map_rec *ieee802154_addr_update(ieee802154_addr_t *ieee802154_addr,
+ guint16 short_addr, guint16 pan, guint64 long_addr, int proto, guint fnum)
+{
+ ieee802154_short_addr addr16;
+ ieee802154_map_rec *p_map_rec;
+ gpointer old_key;
+
+ /* Look up short address hash */
+ addr16.pan = pan;
+ addr16.addr = short_addr;
+ p_map_rec = g_hash_table_lookup(ieee802154_addr->short_table, &addr16);
+
+ /* Update mapping record */
+ if (p_map_rec) {
+ /* record already exists */
+ if ( p_map_rec->addr64 == long_addr ) {
+ /* no change */
+ return p_map_rec;
+ }
+ else {
+ /* mark current mapping record invalid */
+ p_map_rec->end_fnum = fnum;
+ }
+ }
+
+ /* create a new mapping record */
+ p_map_rec = se_alloc(sizeof(ieee802154_map_rec));
+ p_map_rec->proto = proto;
+ p_map_rec->start_fnum = fnum;
+ p_map_rec->end_fnum = 0;
+ p_map_rec->addr64 = long_addr;
+
+ /* link new mapping record to addr hash tables */
+ if ( g_hash_table_lookup_extended(ieee802154_addr->short_table, &addr16, &old_key, NULL) ) {
+ /* update short addr hash table, reusing pointer to old key */
+ g_hash_table_insert(ieee802154_addr->short_table, &old_key, p_map_rec);
+ } else {
+ /* create new hash entry */
+ g_hash_table_insert(ieee802154_addr->short_table, se_memdup(&addr16, sizeof(addr16)), p_map_rec);
+ }
+
+ if ( g_hash_table_lookup_extended(ieee802154_addr->long_table, &long_addr, &old_key, NULL) ) {
+ /* update long addr hash table, reusing pointer to old key */
+ g_hash_table_insert(ieee802154_addr->long_table, &old_key, p_map_rec);
+ } else {
+ /* create new hash entry */
+ g_hash_table_insert(ieee802154_addr->long_table, se_memdup(&long_addr, sizeof(long_addr)), p_map_rec);
+ }
+
+ return p_map_rec;
+} /* ieee802154_addr_update */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * ieee802154_short_addr_invalidate
+ * DESCRIPTION
+ * Marks a mapping record associated with device with short_addr
+ * as invalid at a certain frame number, typically when a
+ * dissassociation occurs.
+ * PARAMETERS
+ * guint16 short_addr - 16-bit short address
+ * guint16 pan - 16-bit PAN id
+ * guint - Frame number when mapping became invalid
+ * RETURNS
+ * TRUE - Record was updated
+ * FALSE - Couldn't find it
+ *---------------------------------------------------------------
+ */
+gboolean ieee802154_short_addr_invalidate(guint16 short_addr, guint16 pan, guint fnum)
+{
+ ieee802154_short_addr addr16;
+ ieee802154_map_rec *map_rec;
+
+ addr16.pan = pan;
+ addr16.addr = short_addr;
+
+ map_rec = g_hash_table_lookup(ieee802154_addr.short_table, &addr16);
+ if ( map_rec ) {
+ /* indicates this mapping is invalid at frame fnum */
+ map_rec->end_fnum = fnum;
+ return TRUE;
+ }
+
+ return FALSE;
+} /* ieee802154_short_addr_invalidate */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * ieee802154_long_addr_invalidate
+ * DESCRIPTION
+ * Marks a mapping record associated with device with long_addr
+ * as invalid at a certain frame number, typically when a
+ * dissassociation occurs.
+ * PARAMETERS
+ * guint64 long_addr - 16-bit short address
+ * guint - Frame number when mapping became invalid
+ * RETURNS
+ * TRUE - If record was updated
+ * FALSE - If record wasn't updated
+ *---------------------------------------------------------------
+ */
+gboolean ieee802154_long_addr_invalidate(guint64 long_addr, guint fnum)
+{
+ ieee802154_map_rec *map_rec;
+
+ map_rec = g_hash_table_lookup(ieee802154_addr.long_table, &long_addr);
+ if ( map_rec ) {
+ /* indicates this mapping is invalid at frame fnum */
+ map_rec->end_fnum = fnum;
+ return TRUE;
+ }
+
+ return FALSE;
+} /* ieee802154_long_addr_invalidate */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_tree_add_eui64
+ * DESCRIPTION
+ * Helper function to display an EUI-64 address to the tree.
+ * PARAMETERS
+ * proto_tree *tree
+ * int hfindex
+ * tvbuff_t *tvb
+ * gint start
+ * gint length
+ * guint64 value;
+ * RETURNS
+ * proto_item *
+ *---------------------------------------------------------------
+ */
+proto_item *
+proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, gint64 value)
+{
+ header_field_info *hf = proto_registrar_get_nth(hfindex);
+ return proto_tree_add_uint64_format(tree, hfindex, tvb, start, length, value, "%s: %s (%s)",
+ hf->name, print_eui64_oui(value), print_eui64(value));
+}
+
/*FUNCTION:------------------------------------------------------
* NAME
* proto_register_ieee802154
@@ -2220,14 +2408,14 @@ void proto_register_ieee802154(void)
NULL, HFILL }},
{ &hf_ieee802154_nonask_phy_length,
- { "Frame Length", "wpan-nonask-phy.frame_length", FT_UINT8, BASE_HEX, NULL, IEEE802154_PHY_LENGTH_MASK,
- NULL, HFILL }},
+ { "Frame Length", "wpan-nonask-phy.frame_length", FT_UINT8, BASE_HEX, NULL,
+ IEEE802154_PHY_LENGTH_MASK, 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,
- NULL, HFILL }},
+ { "Frame Type", "wpan.frame_type", FT_UINT16, BASE_HEX, VALS(ieee802154_frame_types),
+ IEEE802154_FCF_TYPE_MASK, NULL, HFILL }},
{ &hf_ieee802154_security,
{ "Security Enabled", "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEC_EN,
@@ -2250,12 +2438,12 @@ void proto_register_ieee802154(void)
NULL, HFILL }},
{ &hf_ieee802154_dst_addr_mode,
- { "Destination Addressing Mode", "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes), IEEE802154_FCF_DADDR_MASK,
- NULL, HFILL }},
+ { "Destination Addressing Mode", "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
+ IEEE802154_FCF_DADDR_MASK, NULL, HFILL }},
{ &hf_ieee802154_src_addr_mode,
- { "Source Addressing Mode", "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes), IEEE802154_FCF_SADDR_MASK,
- NULL, HFILL }},
+ { "Source Addressing Mode", "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
+ IEEE802154_FCF_SADDR_MASK, NULL, HFILL }},
{ &hf_ieee802154_version,
{ "Frame Version", "wpan.version", FT_UINT16, BASE_DEC, NULL, IEEE802154_FCF_VERSION,
@@ -2277,12 +2465,16 @@ void proto_register_ieee802154(void)
{ "Source PAN", "wpan.src_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
- { &hf_ieee802154_src_addr16,
- { "Source", "wpan.src_addr16", FT_UINT16, BASE_HEX, NULL, 0x0,
+ { &hf_ieee802154_src16,
+ { "Source", "wpan.src16", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_ieee802154_src64,
+ { "Extended Source", "wpan.src64", FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
- { &hf_ieee802154_src_addr64,
- { "Source", "wpan.src_addr64", FT_UINT64, BASE_HEX, NULL, 0x0,
+ { &hf_ieee802154_src64_origin,
+ { "Origin", "wpan.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
{ &hf_ieee802154_fcs,
@@ -2386,7 +2578,8 @@ void proto_register_ieee802154(void)
"Specifies the transmission interval of the beacons.", HFILL }},
{ &hf_ieee802154_superframe_order,
- { "Superframe Interval", "wpan.superframe_order", FT_UINT16, BASE_DEC, NULL, IEEE802154_SUPERFRAME_ORDER_MASK,
+ { "Superframe Interval", "wpan.superframe_order", FT_UINT16, BASE_DEC, NULL,
+ IEEE802154_SUPERFRAME_ORDER_MASK,
"Specifies the length of time the coordinator will interact with the PAN.", HFILL }},
{ &hf_ieee802154_cap,
@@ -2428,11 +2621,12 @@ void proto_register_ieee802154(void)
/* Auxiliary Security Header Fields */
/*----------------------------------*/
{ &hf_ieee802154_security_level,
- { "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names), IEEE802154_AUX_SEC_LEVEL_MASK,
- "The Security Level of the frame", HFILL }},
+ { "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names),
+ IEEE802154_AUX_SEC_LEVEL_MASK, "The Security Level of the frame", HFILL }},
{ &hf_ieee802154_key_id_mode,
- { "Key Identifier Mode", "wpan.aux_sec.key_id_mode", FT_UINT8, BASE_HEX, VALS(ieee802154_key_id_mode_names), IEEE802154_AUX_KEY_ID_MODE_MASK,
+ { "Key Identifier Mode", "wpan.aux_sec.key_id_mode", FT_UINT8, BASE_HEX, VALS(ieee802154_key_id_mode_names),
+ IEEE802154_AUX_KEY_ID_MODE_MASK,
"The scheme to use by the recipient to lookup the key in its key table", HFILL }},
{ &hf_ieee802154_aux_sec_reserved,
@@ -2487,8 +2681,10 @@ void proto_register_ieee802154(void)
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");
+ proto_ieee802154 = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN", "IEEE 802.15.4",
+ IEEE802154_PROTOABBREV_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");
/* Register header fields and subtrees. */
proto_register_field_array(proto_ieee802154, hf, array_length(hf));
@@ -2498,7 +2694,7 @@ void proto_register_ieee802154(void)
/* add a user preference to set the 802.15.4 ethertype */
ieee802154_module = prefs_register_protocol(proto_ieee802154,
- proto_reg_handoff_ieee802154);
+ proto_reg_handoff_ieee802154);
prefs_register_uint_preference(ieee802154_module, "802154_ethertype",
"802.15.4 Ethertype (in hex)",
"(Hexadecimal) Ethertype used to indicate IEEE 802.15.4 frame.",
@@ -2508,8 +2704,8 @@ void proto_register_ieee802154(void)
"Set if the FCS field is in TI CC24xx format.",
&ieee802154_cc24xx);
prefs_register_bool_preference(ieee802154_module, "802154_fcs_ok",
- "Dissect data only if FCS is ok",
- "Dissect data only if FCS is ok.",
+ "Dissect only good FCS",
+ "Dissect payload only if FCS is valid.",
&ieee802154_fcs_ok);
/* Create a UAT for static address mappings. */
@@ -2537,10 +2733,10 @@ void proto_register_ieee802154(void)
"128-bit decryption key in hexadecimal format", (const char **)&ieee802154_key_str);
/* Register the subdissector list */
- register_heur_dissector_list("wpan", &ieee802154_heur_subdissector_list);
+ register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN, &ieee802154_heur_subdissector_list);
/* Register dissectors with Wireshark. */
- register_dissector("wpan", dissect_ieee802154, proto_ieee802154);
+ 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);
@@ -2571,7 +2767,7 @@ void proto_reg_handoff_ieee802154(void)
if (!prefs_initialized){
/* Get the dissector handles. */
- ieee802154_handle = find_dissector("wpan");
+ ieee802154_handle = find_dissector(IEEE802154_PROTOABBREV_WPAN);
ieee802154_nonask_phy_handle = find_dissector("wpan-nonask-phy");
ieee802154_nofcs_handle = find_dissector("wpan_nofcs");
data_handle = find_dissector("data");
@@ -2604,9 +2800,9 @@ void proto_reg_handoff_ieee802154(void)
* 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
+ * Init routine for the IEEE 802.15.4 dissector. Creates hash
+ * tables for mapping between 16-bit to 64-bit addresses and
+ * populates them with static address pairs from a UAT
* preference table.
* PARAMETERS
* none
@@ -2619,16 +2815,17 @@ proto_init_ieee802154(void)
{
guint i;
- /* Destroy the hash table, if it exists. */
- if (ieee802154_addr_table)
- g_hash_table_destroy(ieee802154_addr_table);
+ /* Destroy hash tables, if they exist. */
+ if (ieee802154_addr.short_table) g_hash_table_destroy(ieee802154_addr.short_table);
+ if (ieee802154_addr.long_table) g_hash_table_destroy(ieee802154_addr.long_table);
- /* (Re)create the hash table. */
- ieee802154_addr_table = g_hash_table_new(ieee802154_addr_hash, ieee802154_addr_equals);
+ /* Create the hash tables. */
+ ieee802154_addr.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
+ ieee802154_addr.long_table = g_hash_table_new(g_int64_hash, g_int64_equal);
/* 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));
+ ieee802154_addr_update(&ieee802154_addr,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
+ pntoh64(static_addrs[i].eui64), proto_ieee802154, IEEE802154_USER_MAPPING);
} /* for */
} /* proto_init_ieee802154 */
-
diff --git a/epan/dissectors/packet-ieee802154.h b/epan/dissectors/packet-ieee802154.h
index 428f573359..8cbce7aa4b 100644
--- a/epan/dissectors/packet-ieee802154.h
+++ b/epan/dissectors/packet-ieee802154.h
@@ -27,6 +27,9 @@
#ifndef PACKET_IEEE802154_H
#define PACKET_IEEE802154_H
+/* Protocol Abbreviation */
+#define IEEE802154_PROTOABBREV_WPAN "wpan"
+
/* Packet Overhead from MAC header + footer (excluding addressing) */
#define IEEE802154_MAX_FRAME_LEN 127
#define IEEE802154_FCS_LEN 2
@@ -48,7 +51,7 @@
#define IEEE802154_CMD_ASRSP_PAN_FULL 0x01
#define IEEE802154_CMD_ASRSP_PAN_DENIED 0x02
-/* Bit Masks for Capability Information Feild
+/* Bit Masks for Capability Information Field
Included in Association Req. command */
#define IEEE802154_CMD_CINFO_ALT_PAN_COORD 0x01
#define IEEE802154_CMD_CINFO_DEVICE_TYPE 0x02
@@ -99,7 +102,7 @@
#define IEEE802154_FCF_SEC_EN 0x0008
#define IEEE802154_FCF_FRAME_PND 0x0010
#define IEEE802154_FCF_ACK_REQ 0x0020
-#define IEEE802154_FCF_INTRA_PAN 0x0040
+#define IEEE802154_FCF_INTRA_PAN 0x0040 /* known as PAN ID Compression in IEEE 802.15.4-2006 */
#define IEEE802154_FCF_DADDR_MASK 0x0C00 /* destination addressing mask */
#define IEEE802154_FCF_VERSION 0x3000
#define IEEE802154_FCF_SADDR_MASK 0xC000 /* source addressing mask */
@@ -164,7 +167,7 @@ typedef enum {
/* Macro to check for payload encryption. */
#define IEEE802154_IS_ENCRYPTED(_level_) ((_level_) & 0x4)
-/* Structure containing information regarding all necessary packet feilds. */
+/* Structure containing information regarding all necessary packet fields. */
typedef struct {
/* Frame control field. */
gint32 version;
@@ -180,15 +183,11 @@ typedef struct {
/* Addressing Info. */
guint16 dst_pan;
- union {
- guint16 addr16;
- guint64 addr64;
- } dst;
guint16 src_pan;
- union {
- guint16 addr16;
- guint64 addr64;
- } src;
+ guint16 dst16;
+ guint64 dst64;
+ guint16 src16;
+ guint64 src64;
/* Security Info. */
ieee802154_security_level security_level;
@@ -202,11 +201,49 @@ typedef struct {
/* Command ID (only if frame_type == 0x3) */
guint8 command_id;
+ GHashTable *short_table;
} ieee802154_packet;
+typedef struct {
+ guint proto;
+ GHashTable *long_table;
+ GHashTable *short_table;
+} ieee802154_addr_t;
+
+/* Key used by the short address hash table. */
+typedef struct {
+ guint16 pan;
+ guint16 addr;
+} ieee802154_short_addr;
+
+/* A mapping record for a frame, pointed to by hash table */
+typedef struct {
+ int proto; /* protocol that created this record */
+ guint start_fnum;
+ guint end_fnum;
+ guint64 addr64;
+ /*guint32 frame_counter; TODO for frame counter sequence checks. */
+} ieee802154_map_rec;
+
+#define IEEE802154_USER_MAPPING 0
+
+typedef struct {
+ guint16 src_pan;
+ guint16 src16;
+ ieee802154_map_rec *map_rec;
+} ieee802154_hints_t;
/* Some Helper Function Definitions. */
-extern gchar *print_eui64(guint64);
-extern gchar *print_eui64_oui(guint64);
+extern gchar *print_eui64(guint64);
+extern gchar *print_eui64_oui(guint64);
+extern proto_item *proto_tree_add_eui64(proto_tree *, int, tvbuff_t *, gint, gint, gint64);
+
+/* Short to Extended Address Prototypes */
+extern ieee802154_map_rec *ieee802154_addr_update(ieee802154_addr_t *, guint16, guint16, guint64, int, guint);
+extern guint ieee802154_short_addr_hash(gconstpointer);
+extern gboolean ieee802154_short_addr_equal(gconstpointer, gconstpointer);
+
+extern gboolean ieee802154_short_addr_invalidate(guint16, guint16, guint);
+extern gboolean ieee802154_long_addr_invalidate(guint64, guint);
#endif /* PACKET_IEEE802154_H */
diff --git a/epan/dissectors/packet-zbee-aps.c b/epan/dissectors/packet-zbee-aps.c
index e56dc2f94f..48771a7030 100644
--- a/epan/dissectors/packet-zbee-aps.c
+++ b/epan/dissectors/packet-zbee-aps.c
@@ -39,9 +39,9 @@
#include <epan/reassemble.h>
#include "packet-zbee.h"
+#include "packet-zbee-nwk.h"
#include "packet-zbee-security.h"
#include "packet-zbee-aps.h"
-#include "packet-zbee-nwk.h"
/*************************
* Function Declarations *
@@ -67,6 +67,10 @@ static guint dissect_zbee_aps_tunnel (tvbuff_t *tvb, packet_info *pinf
/* Helper routine. */
static guint zbee_apf_transaction_len (tvbuff_t *tvb, guint offset, guint8 type);
+static void proto_init_zbee_aps(void);
+void proto_reg_handoff_zbee_aps(void);
+void proto_register_zbee_aps(void);
+
/********************
* Global Variables *
********************
@@ -76,7 +80,7 @@ static int proto_zbee_aps = -1;
static int hf_zbee_aps_fcf_frame_type = -1;
static int hf_zbee_aps_fcf_delivery = -1;
static int hf_zbee_aps_fcf_indirect_mode = -1; /* ZigBee 2004 and earlier. */
-static int hf_zbee_aps_fcf_ack_mode = -1; /* ZigBee 2007 and later. */
+static int hf_zbee_aps_fcf_ack_format = -1; /* ZigBee 2007 and later. */
static int hf_zbee_aps_fcf_security = -1;
static int hf_zbee_aps_fcf_ack_req = -1;
static int hf_zbee_aps_fcf_ext_header = -1;
@@ -165,6 +169,7 @@ static const fragment_items zbee_aps_frag_items = {
/* Tag */
"APS Message fragments"
};
+
/********************/
/* Field Names */
/********************/
@@ -538,7 +543,7 @@ const value_string zbee_aps_cid_names[] = {
* ZigBee Application Support Sublayer dissector for wireshark.
* PARAMETERS
* tvbuff_t *tvb - pointer to buffer containing raw packet.
- * packet_into *pinfo - pointer to packet information fields
+ * packet_info *pinfo - pointer to packet information fields
* proto_tree *tree - pointer to data tree Wireshark uses to display packet.
* RETURNS
* void
@@ -556,7 +561,7 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_item *ti;
zbee_aps_packet packet;
- zbee_nwk_packet *nwk = pinfo->private_data;
+ zbee_nwk_packet *nwk = (zbee_nwk_packet *)pinfo->private_data;
guint8 fcf;
guint8 offset = 0;
@@ -577,7 +582,7 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
packet.type = zbee_get_bit_field(fcf, ZBEE_APS_FCF_FRAME_TYPE);
packet.delivery = zbee_get_bit_field(fcf, ZBEE_APS_FCF_DELIVERY_MODE);
packet.indirect_mode = zbee_get_bit_field(fcf, ZBEE_APS_FCF_INDIRECT_MODE);
- packet.ack_mode = zbee_get_bit_field(fcf, ZBEE_APS_FCF_ACK_MODE);
+ packet.ack_format = zbee_get_bit_field(fcf, ZBEE_APS_FCF_ACK_FORMAT);
packet.security = zbee_get_bit_field(fcf, ZBEE_APS_FCF_SECURITY);
packet.ack_req = zbee_get_bit_field(fcf, ZBEE_APS_FCF_ACK_REQ);
packet.ext_header = zbee_get_bit_field(fcf, ZBEE_APS_FCF_EXT_HEADER);
@@ -603,13 +608,15 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) {
/* ZigBee 2007 and later uses an ack mode flag. */
if (packet.type == ZBEE_APS_FCF_ACK) {
- proto_tree_add_boolean(field_tree, hf_zbee_aps_fcf_ack_mode, tvb, offset, 1, fcf & ZBEE_APS_FCF_ACK_MODE);
+ proto_tree_add_boolean(field_tree, hf_zbee_aps_fcf_ack_format, tvb, offset, 1,
+ fcf & ZBEE_APS_FCF_ACK_FORMAT);
}
}
else {
/* ZigBee 2004, uses indirect mode. */
if (packet.delivery == ZBEE_APS_FCF_INDIRECT) {
- proto_tree_add_boolean(field_tree, hf_zbee_aps_fcf_indirect_mode, tvb, offset, 1, fcf & ZBEE_APS_FCF_INDIRECT_MODE);
+ proto_tree_add_boolean(field_tree, hf_zbee_aps_fcf_indirect_mode, tvb, offset, 1,
+ fcf & ZBEE_APS_FCF_INDIRECT_MODE);
}
}
@@ -627,7 +634,7 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
break;
case ZBEE_APS_FCF_ACK:
- if ((pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) && (packet.ack_mode)) {
+ if ((pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) && (packet.ack_format)) {
/* Command Ack: endpoint addressing does not exist. */
goto dissect_zbee_aps_no_endpt;
}
@@ -719,7 +726,7 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset += 1;
}
- /* Get and display the profile ID if it exists. */
+ /* Get and display the profile ID. */
packet.profile = tvb_get_letohs(tvb, offset);
profile_handle = dissector_get_port_handle(zbee_aps_dissector_table, packet.profile);
if (tree) {
@@ -729,7 +736,8 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* Update the protocol root and info column later, after the source endpoint
* so that the source and destination will be back-to-back in the text.
*/
- }
+ }
+ offset += sizeof(guint16);
/* The source endpoint is present for all cases except indirect /w indirect_mode == FALSE */
if ((packet.delivery != ZBEE_APS_FCF_INDIRECT) || (!packet.indirect_mode)) {
@@ -762,7 +770,6 @@ dissect_zbee_aps_no_endpt:
offset += 1;
}
-
/* Get and display the extended header, if present. */
if (packet.ext_header) {
fcf = tvb_get_guint8(tvb, offset);
@@ -813,7 +820,7 @@ dissect_zbee_aps_no_endpt:
/* If a payload is present, and security is enabled, decrypt the payload. */
if ((offset < tvb_length(tvb)) && packet.security) {
- payload_tvb = dissect_zbee_secure(tvb, pinfo, aps_tree, offset, 0);
+ payload_tvb = dissect_zbee_secure(tvb, pinfo, aps_tree, offset);
if (payload_tvb == NULL) {
/* If Payload_tvb is NULL, then the security dissector cleaned up. */
return;
@@ -1142,9 +1149,12 @@ dissect_zbee_aps_skke_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr
static guint
dissect_zbee_aps_transport_key(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
{
- guint8 key_type;
- gchar *key = ep_alloc(ZBEE_APS_CMD_KEY_LENGTH);
- guint i;
+ guint8 key_type;
+ guint8 key[ZBEE_APS_CMD_KEY_LENGTH];
+ GSList **nwk_keyring;
+ key_record_t key_record;
+ zbee_nwk_hints_t *nwk_hints;
+ guint i;
/* Get and display the key type. */
key_type = tvb_get_guint8(tvb, offset);
@@ -1156,21 +1166,47 @@ dissect_zbee_aps_transport_key(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
/* Coincidentally, all the key descriptors start with the key. So
* get and display it.
*/
- for (i=0;i<ZBEE_APS_CMD_KEY_LENGTH; i++) {
- /* Copy the key in while swapping because the key is transmitted in little-endian
- * order, but we want to display it in big-endian.
- */
- key[(ZBEE_APS_CMD_KEY_LENGTH-1)-i] = tvb_get_guint8(tvb, offset+i);
+ for (i=0; i<ZBEE_APS_CMD_KEY_LENGTH ; i++) {
+ key[i] = tvb_get_guint8(tvb, offset+i);
} /* for */
if (tree) {
proto_tree_add_item(tree, hf_zbee_aps_cmd_key, tvb, offset, ZBEE_APS_CMD_KEY_LENGTH, ENC_BIG_ENDIAN);
}
offset += ZBEE_APS_CMD_KEY_LENGTH;
+
+ /* Update the key ring for this pan */
+ if ( !pinfo->fd->flags.visited &&
+ (nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(pinfo->fd,
+ proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK)))) {
+
+ nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan);
+ if ( !nwk_keyring ) {
+ /* Create an empty key ring for this pan. Use g_alloc() because we must free
+ * GSLists after a capture is closed and wireshark freed seasonal memory
+ * with se_free_all()
+ */
+ nwk_keyring = (GSList **)g_malloc0(sizeof(GSList**));
+ g_hash_table_insert(zbee_table_nwk_keyring,
+ g_memdup(&nwk_hints->src_pan, sizeof(nwk_hints->src_pan)), nwk_keyring);
+ }
+
+ if ( nwk_keyring ) {
+ if ( !*nwk_keyring ||
+ memcmp( ((key_record_t *)((GSList *)(*nwk_keyring))->data)->key, &key,
+ ZBEE_APS_CMD_KEY_LENGTH) ) {
+ /* Store a new or different key in the key ring */
+ key_record.frame_num = pinfo->fd->num;
+ key_record.label = NULL;
+ memcpy(&key_record.key, &key, ZBEE_APS_CMD_KEY_LENGTH);
+ *nwk_keyring = g_slist_prepend(*nwk_keyring, se_memdup(&key_record, sizeof(key_record_t)));
+ }
+ }
+ }
/* Parse the rest of the key descriptor. */
switch (key_type) {
case ZBEE_APS_CMD_KEY_STANDARD_NWK:
- case ZBEE_APS_CMD_KEY_HIGH_SEC_NWK:{
+ case ZBEE_APS_CMD_KEY_HIGH_SEC_NWK: {
/* Network Key */
guint8 seqno;
guint64 src;
@@ -1227,7 +1263,7 @@ dissect_zbee_aps_transport_key(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
guint64 partner;
guint8 initiator;
- /* get and display the parter address. */
+ /* get and display the partner address. */
partner = tvb_get_letoh64(tvb, offset);
if (tree) {
proto_tree_add_eui64(tree, hf_zbee_aps_cmd_partner, tvb, offset, sizeof(guint64), partner);
@@ -1540,7 +1576,8 @@ dissect_zbee_aps_tunnel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gui
offset += sizeof(guint64);
/* The remainder is a tunneled APS frame. */
- tunnel_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset));
+ tunnel_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset),
+ tvb_reported_length_remaining(tvb, offset));
if (tree) root = proto_tree_get_root(tree);
call_dissector(zbee_aps_handle, tunnel_tvb, pinfo, root);
offset = tvb_length(tvb);
@@ -1576,11 +1613,12 @@ static void dissect_zbee_apf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
tvbuff_t *app_tvb;
- dissector_handle_t app_dissector = (pinfo->private_data);
+ dissector_handle_t app_dissector = (dissector_handle_t)(pinfo->private_data);
/* Create the tree for the application framework. */
if (tree) {
- proto_root = proto_tree_add_protocol_format(tree, proto_zbee_apf, tvb, 0, tvb_length(tvb), "ZigBee Application Framework");
+ proto_root = proto_tree_add_protocol_format(tree, proto_zbee_apf, tvb, 0,
+ tvb_length(tvb), "ZigBee Application Framework");
apf_tree = proto_item_add_subtree(proto_root, ett_zbee_apf);
}
@@ -1714,24 +1752,6 @@ zbee_apf_transaction_len(tvbuff_t *tvb, guint offset, guint8 type)
/*FUNCTION:------------------------------------------------------
* NAME
- * proto_init_zbee_aps
- * DESCRIPTION
- * Initializes the APS dissectors prior to beginning protocol
- * dissection.
- * PARAMETERS
- * none
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
-static void proto_init_zbee_aps(void)
-{
- fragment_table_init(&zbee_aps_fragment_table);
- reassembled_table_init(&zbee_aps_reassembled_table);
-} /* proto_init_zbee_aps */
-
-/*FUNCTION:------------------------------------------------------
- * NAME
* proto_register_zbee_aps
* DESCRIPTION
* ZigBee APS protocol registration routine.
@@ -1756,8 +1776,8 @@ void proto_register_zbee_aps(void)
{ "Indirect Address Mode", "zbee.aps.indirect_mode", FT_BOOLEAN, 8, NULL, ZBEE_APS_FCF_INDIRECT_MODE,
NULL, HFILL }},
- { &hf_zbee_aps_fcf_ack_mode,
- { "Acknowledgement Mode", "zbee.aps.ack_mode", FT_BOOLEAN, 8, NULL, ZBEE_APS_FCF_ACK_MODE,
+ { &hf_zbee_aps_fcf_ack_format,
+ { "Acknowledgement Format", "zbee.aps.ack_format", FT_BOOLEAN, 8, NULL, ZBEE_APS_FCF_ACK_FORMAT,
NULL, HFILL }},
{ &hf_zbee_aps_fcf_security,
@@ -1936,24 +1956,24 @@ void proto_register_zbee_aps(void)
};
/* Register ZigBee APS protocol with Wireshark. */
- proto_zbee_aps = proto_register_protocol("ZigBee Application Support Layer", "ZigBee APS", "zbee.aps");
+ proto_zbee_aps = proto_register_protocol("ZigBee Application Support Layer", "ZigBee APS", ZBEE_PROTOABBREV_APS);
proto_register_field_array(proto_zbee_aps, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
/* Register the APS dissector and subdissector list. */
zbee_aps_dissector_table = register_dissector_table("zbee.profile", "ZigBee Profile ID", FT_UINT16, BASE_HEX);
- register_dissector("zbee.aps", dissect_zbee_aps, proto_zbee_aps);
+ register_dissector(ZBEE_PROTOABBREV_APS, dissect_zbee_aps, proto_zbee_aps);
/* Register the init routine. */
register_init_routine(proto_init_zbee_aps);
/* Register the ZigBee Application Framework protocol with Wireshark. */
- proto_zbee_apf = proto_register_protocol("ZigBee Application Framework", "ZigBee APF", "zbee.apf");
+ proto_zbee_apf = proto_register_protocol("ZigBee Application Framework", "ZigBee APF", ZBEE_PROTOABBREV_APF);
proto_register_field_array(proto_zbee_apf, hf_apf, array_length(hf_apf));
proto_register_subtree_array(ett_apf, array_length(ett_apf));
/* Register the App dissector. */
- register_dissector("zbee.apf", dissect_zbee_apf, proto_zbee_apf);
+ register_dissector(ZBEE_PROTOABBREV_APF, dissect_zbee_apf, proto_zbee_apf);
} /* proto_register_zbee_aps */
/*FUNCTION:------------------------------------------------------
@@ -1971,7 +1991,25 @@ void proto_reg_handoff_zbee_aps(void)
{
/* Find the other dissectors we need. */
data_handle = find_dissector("data");
- zbee_aps_handle = find_dissector("zbee.aps");
- zbee_apf_handle = find_dissector("zbee.apf");
+ zbee_aps_handle = find_dissector(ZBEE_PROTOABBREV_APS);
+ zbee_apf_handle = find_dissector(ZBEE_PROTOABBREV_APF);
} /* proto_reg_handoff_zbee_aps */
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_init_zbee_aps
+ * DESCRIPTION
+ * Initializes the APS dissectors prior to beginning protocol
+ * dissection.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+static void proto_init_zbee_aps(void)
+{
+ fragment_table_init(&zbee_aps_fragment_table);
+ reassembled_table_init(&zbee_aps_reassembled_table);
+} /* proto_init_zbee_aps */
+
diff --git a/epan/dissectors/packet-zbee-aps.h b/epan/dissectors/packet-zbee-aps.h
index eb106d81e2..d8aa4b1e20 100644
--- a/epan/dissectors/packet-zbee-aps.h
+++ b/epan/dissectors/packet-zbee-aps.h
@@ -27,39 +27,11 @@
#ifndef PACKET_ZBEE_APS_H
#define PACKET_ZBEE_APS_H
-/* Structure to contain the APS frame information */
-typedef struct{
- gboolean indirect_mode; /* ZigBee 2004 and Earlier */
- gboolean ack_mode; /* ZigBee 2007 and Later */
- gboolean security;
- gboolean ack_req;
- gboolean ext_header; /* ZigBee 2007 and Later */
- guint8 type;
- guint8 delivery;
-
- guint8 dst;
- guint16 group; /* ZigBee 2006 and Later */
- guint16 cluster;
- guint16 profile;
- guint8 src;
- guint8 counter;
-
- /* Fragmentation Fields. */
- guint8 fragmentation; /* ZigBee 2007 and Later */
- guint8 block_number; /* ZigBee 2007 and Later */
- guint8 ack_bitfield; /* ZigBee 2007 and Later */
-
- /* Some helpers for the upper layers. */
- gboolean profile_present;
- gboolean dst_present;
- gboolean src_present;
-} zbee_aps_packet;
-
/* ZigBee APS */
#define ZBEE_APS_FCF_FRAME_TYPE 0x03
#define ZBEE_APS_FCF_DELIVERY_MODE 0x0c
#define ZBEE_APS_FCF_INDIRECT_MODE 0x10 /* ZigBee 2004 and earlier. */
-#define ZBEE_APS_FCF_ACK_MODE 0x10 /* ZigBee 2007 and later. */
+#define ZBEE_APS_FCF_ACK_FORMAT 0x10 /* ZigBee 2007 and later. */
#define ZBEE_APS_FCF_SECURITY 0x20
#define ZBEE_APS_FCF_ACK_REQ 0x40
#define ZBEE_APS_FCF_EXT_HEADER 0x80
@@ -234,4 +206,32 @@ typedef struct{
#define ZBEE_ZCL_CID_SMART_ENERGY_TUNNELING 0x0704
#define ZBEE_ZCL_CID_PRE_PAYMENT 0x0705
+/* Structure to contain the APS frame information */
+typedef struct{
+ gboolean indirect_mode; /* ZigBee 2004 and Earlier */
+ guint8 type;
+ guint8 delivery;
+ gboolean ack_format; /* ZigBee 2007 and Later */
+ gboolean security;
+ gboolean ack_req;
+ gboolean ext_header; /* ZigBee 2007 and Later */
+
+ guint8 dst;
+ guint16 group; /* ZigBee 2006 and Later */
+ guint16 cluster;
+ guint16 profile;
+ guint8 src;
+ guint8 counter;
+
+ /* Fragmentation Fields. */
+ guint8 fragmentation; /* ZigBee 2007 and Later */
+ guint8 block_number; /* ZigBee 2007 and Later */
+ guint8 ack_bitfield; /* ZigBee 2007 and Later */
+
+ /* Some helpers for the upper layers. */
+ gboolean profile_present;
+ gboolean dst_present;
+ gboolean src_present;
+} zbee_aps_packet;
+
#endif /* PACKET_ZBEE_APS_H*/
diff --git a/epan/dissectors/packet-zbee-nwk.c b/epan/dissectors/packet-zbee-nwk.c
index 006220a53e..313cb42484 100644
--- a/epan/dissectors/packet-zbee-nwk.c
+++ b/epan/dissectors/packet-zbee-nwk.c
@@ -40,9 +40,10 @@
#include <epan/expert.h>
#include <epan/value_string.h>
+#include "packet-ieee802154.h"
#include "packet-zbee.h"
-#include "packet-zbee-security.h"
#include "packet-zbee-nwk.h"
+#include "packet-zbee-security.h"
/*************************/
/* Function Declarations */
@@ -53,17 +54,23 @@ static void dissect_zbee_nwk_cmd (tvbuff_t *tvb, packet_info *pinfo, p
static void dissect_zbee_beacon (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
/* Command Dissector Helpers */
-static guint dissect_zbee_nwk_route_req (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet * packet, guint offset);
+static guint dissect_zbee_nwk_route_req (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ zbee_nwk_packet * packet, guint offset);
static guint dissect_zbee_nwk_route_rep (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
static guint dissect_zbee_nwk_status (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
static guint dissect_zbee_nwk_leave (tvbuff_t *tvb, proto_tree *tree, guint offset);
-static guint dissect_zbee_nwk_route_rec (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet * packet, guint offset);
-static guint dissect_zbee_nwk_rejoin_req (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet * packet, guint offset);
-static guint dissect_zbee_nwk_rejoin_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet * packet, guint offset);
+static guint dissect_zbee_nwk_route_rec (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ zbee_nwk_packet * packet, guint offset);
+static guint dissect_zbee_nwk_rejoin_req (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ zbee_nwk_packet * packet, guint offset);
+static guint dissect_zbee_nwk_rejoin_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ zbee_nwk_packet * packet, guint offset);
static guint dissect_zbee_nwk_link_status(tvbuff_t *tvb, proto_tree *tree, guint offset);
static guint dissect_zbee_nwk_report (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
static guint dissect_zbee_nwk_update (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
-
+static void proto_init_zbee_nwk (void);
+void proto_register_zbee_nwk(void);
+void proto_reg_handoff_zbee_nwk(void);
/********************/
/* Global Variables */
@@ -86,6 +93,7 @@ static int hf_zbee_nwk_mcast_radius = -1;
static int hf_zbee_nwk_mcast_max_radius = -1;
static int hf_zbee_nwk_dst64 = -1;
static int hf_zbee_nwk_src64 = -1;
+static int hf_zbee_nwk_src64_origin = -1;
static int hf_zbee_nwk_relay_count = -1;
static int hf_zbee_nwk_relay_index = -1;
@@ -243,28 +251,14 @@ static const value_string zbee_nwk_stack_profiles[] = {
{ 0, NULL }
};
-/*FUNCTION:------------------------------------------------------
- * NAME
- * proto_tree_add_eui64
- * DESCRIPTION
- * Helper function to display an EUI-64 address to the tree.
- * PARAMETERS
- * proto_tree *tree
- * int hfindex
- * tvbuff_t *tvb
- * gint start
- * gint length
- * guint64 value;
- * RETURNS
- * proto_item *
- *---------------------------------------------------------------
+/* TODO: much of the following copied from ieee80154 dissector */
+/*-------------------------------------
+ * Hash Tables and Lists
+ *-------------------------------------
*/
-proto_item *
-proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, gint64 value)
-{
- header_field_info *hf = proto_registrar_get_nth(hfindex);
- return proto_tree_add_uint64_format(tree, hfindex, tvb, start, length, value, "%s: %s (%s)", hf->name, print_eui64_oui(value), print_eui64(value));
-}
+static ieee802154_addr_t zbee_nwk_addr = { 0, NULL, NULL };
+GHashTable *zbee_table_nwk_keyring = NULL;
+GHashTable *zbee_table_link_keyring = NULL;
/*FUNCTION:------------------------------------------------------
* NAME
@@ -309,7 +303,7 @@ zbee_get_bit_field(guint input, guint mask)
static gboolean
dissect_zbee_nwk_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- ieee802154_packet *packet = pinfo->private_data;
+ ieee802154_packet *packet = (ieee802154_packet *)pinfo->private_data;
/* All ZigBee frames must always have a 16-bit source address. */
if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
@@ -358,19 +352,42 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree *field_tree = NULL;
zbee_nwk_packet packet;
+ ieee802154_packet *ieee_packet = (ieee802154_packet *)pinfo->private_data;
guint offset = 0;
- gchar *src_addr = ep_alloc(32);
- gchar *dst_addr = ep_alloc(32);
+ gchar *src_addr = (gchar *)ep_alloc(32);
+ gchar *dst_addr = (gchar *)ep_alloc(32);
guint16 fcf;
+
+ ieee802154_short_addr addr16;
+ ieee802154_map_rec *map_rec;
+ ieee802154_hints_t *ieee_hints;
+
+ zbee_nwk_hints_t *nwk_hints;
+ gboolean unicast_src;
+
memset(&packet, 0, sizeof(packet));
+ /* Set up hint structures */
+ if (!pinfo->fd->flags.visited) {
+ /* Allocate frame data with hints for upper layers */
+ nwk_hints = se_alloc0(sizeof(zbee_nwk_hints_t));
+ p_add_proto_data(pinfo->fd, proto_zbee_nwk, nwk_hints);
+ } else {
+ /* Retrieve existing structure */
+ nwk_hints = p_get_proto_data(pinfo->fd, proto_zbee_nwk);
+ }
+
+ ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd,
+ proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN));
+
/* Add ourself to the protocol column, clear the info column, and create the protocol tree. */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZigBee");
col_clear(pinfo->cinfo, COL_INFO);
if (tree) {
- proto_root = proto_tree_add_protocol_format(tree, proto_zbee_nwk, tvb, offset, tvb_length(tvb), "ZigBee Network Layer");
+ proto_root = proto_tree_add_protocol_format(tree, proto_zbee_nwk, tvb, offset,
+ tvb_length(tvb), "ZigBee Network Layer");
nwk_tree = proto_item_add_subtree(proto_root, ett_zbee_nwk);
}
@@ -392,19 +409,27 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
ti = proto_tree_add_text(nwk_tree, tvb, offset, sizeof(guint16), "Frame Control Field: %s (0x%04x)",
val_to_str(packet.type, zbee_nwk_frame_types, "Unknown"), fcf);
field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_fcf);
- proto_tree_add_uint(field_tree, hf_zbee_nwk_frame_type, tvb, offset, sizeof(guint8), fcf & ZBEE_NWK_FCF_FRAME_TYPE);
+ proto_tree_add_uint(field_tree, hf_zbee_nwk_frame_type, tvb, offset, sizeof(guint8),
+ fcf & ZBEE_NWK_FCF_FRAME_TYPE);
/* Add the rest of the fcf fields to the subtree */
- proto_tree_add_uint(field_tree, hf_zbee_nwk_proto_version, tvb, offset, sizeof(guint8), fcf & ZBEE_NWK_FCF_VERSION);
- proto_tree_add_uint(field_tree, hf_zbee_nwk_discover_route, tvb, offset, sizeof(guint8), fcf & ZBEE_NWK_FCF_DISCOVER_ROUTE);
+ proto_tree_add_uint(field_tree, hf_zbee_nwk_proto_version, tvb, offset, sizeof(guint8),
+ fcf & ZBEE_NWK_FCF_VERSION);
+ proto_tree_add_uint(field_tree, hf_zbee_nwk_discover_route, tvb, offset, sizeof(guint8),
+ fcf & ZBEE_NWK_FCF_DISCOVER_ROUTE);
if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) {
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_multicast, tvb, offset+sizeof(guint8), sizeof(guint8), fcf & ZBEE_NWK_FCF_MULTICAST);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_multicast, tvb, offset+sizeof(guint8),
+ sizeof(guint8), fcf & ZBEE_NWK_FCF_MULTICAST);
}
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_security, tvb, offset+sizeof(guint8), sizeof(guint8), fcf & ZBEE_NWK_FCF_SECURITY);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_security, tvb, offset+sizeof(guint8),
+ sizeof(guint8), fcf & ZBEE_NWK_FCF_SECURITY);
if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) {
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_source_route, tvb, offset+sizeof(guint8), sizeof(guint8), fcf & ZBEE_NWK_FCF_SOURCE_ROUTE);
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_ext_dst, tvb, offset+sizeof(guint8), sizeof(guint8), fcf & ZBEE_NWK_FCF_EXT_DEST);
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_ext_src, tvb, offset+sizeof(guint8), sizeof(guint8), fcf & ZBEE_NWK_FCF_EXT_SOURCE);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_source_route, tvb, offset+sizeof(guint8),
+ sizeof(guint8), fcf & ZBEE_NWK_FCF_SOURCE_ROUTE);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_ext_dst, tvb, offset+sizeof(guint8),
+ sizeof(guint8), fcf & ZBEE_NWK_FCF_EXT_DEST);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_ext_src, tvb, offset+sizeof(guint8),
+ sizeof(guint8), fcf & ZBEE_NWK_FCF_EXT_SOURCE);
}
}
offset += sizeof(guint16);
@@ -430,9 +455,13 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|| (packet.dst == ZBEE_BCAST_ROUTERS)){
g_snprintf(dst_addr, 32, "Broadcast");
}
- else g_snprintf(dst_addr, 32, "0x%04x", packet.dst);
+ else {
+ g_snprintf(dst_addr, 32, "0x%04x", packet.dst);
+ }
+
SET_ADDRESS(&pinfo->dst, AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr);
SET_ADDRESS(&pinfo->net_dst, AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr);
+
if (tree) {
proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
}
@@ -440,9 +469,9 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
}
- /* Get the source address. */
+ /* Get the short nwk source address. */
packet.src = tvb_get_letohs(tvb, offset);
- if(tree){
+ if (tree) {
proto_tree_add_uint(nwk_tree, hf_zbee_nwk_src, tvb, offset, sizeof(guint16), packet.src);
}
offset += sizeof(guint16);
@@ -452,11 +481,17 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|| (packet.src == ZBEE_BCAST_ACTIVE)
|| (packet.src == ZBEE_BCAST_ROUTERS)){
/* Source Broadcast doesn't make much sense. */
- g_snprintf(src_addr, 32, "Broadcast");
+ g_snprintf(src_addr, 32, "Unexpected Source Broadcast");
+ unicast_src = FALSE;
}
- else g_snprintf(src_addr, 32, "0x%04x", packet.src);
+ else {
+ g_snprintf(src_addr, 32, "0x%04x", packet.src);
+ unicast_src = TRUE;
+ }
+
SET_ADDRESS(&pinfo->src, AT_STRINGZ, (int)strlen(src_addr)+1, src_addr);
SET_ADDRESS(&pinfo->net_src, AT_STRINGZ, (int)strlen(src_addr)+1, src_addr);
+
if (tree) {
proto_item_append_text(proto_root, ", Src: %s", src_addr);
}
@@ -490,9 +525,12 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
ti = proto_tree_add_text(nwk_tree, tvb, offset, sizeof(guint8), "Multicast Control Field");
field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_mcast);
/* Add the fields. */
- ti = proto_tree_add_uint(field_tree, hf_zbee_nwk_mcast_mode, tvb, offset, sizeof(guint8), mcast_control & ZBEE_NWK_MCAST_MODE);
- proto_tree_add_uint(field_tree, hf_zbee_nwk_mcast_radius, tvb, offset, sizeof(guint8), mcast_control & ZBEE_NWK_MCAST_RADIUS);
- proto_tree_add_uint(field_tree, hf_zbee_nwk_mcast_max_radius, tvb, offset, sizeof(guint8), mcast_control & ZBEE_NWK_MCAST_MAX_RADIUS);
+ ti = proto_tree_add_uint(field_tree, hf_zbee_nwk_mcast_mode, tvb, offset, sizeof(guint8),
+ mcast_control & ZBEE_NWK_MCAST_MODE);
+ proto_tree_add_uint(field_tree, hf_zbee_nwk_mcast_radius, tvb, offset, sizeof(guint8),
+ mcast_control & ZBEE_NWK_MCAST_RADIUS);
+ proto_tree_add_uint(field_tree, hf_zbee_nwk_mcast_max_radius, tvb, offset, sizeof(guint8),
+ mcast_control & ZBEE_NWK_MCAST_MAX_RADIUS);
}
offset += sizeof(guint8);
}
@@ -506,14 +544,79 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset += sizeof(guint64);
}
- /* Add the extended source address. (ZigBee 2006 and later). */
- if ((pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) && packet.ext_src) {
- packet.src64 = tvb_get_letoh64(tvb, offset);
- if (tree) {
- proto_tree_add_eui64(nwk_tree, hf_zbee_nwk_src64, tvb, offset, sizeof(guint64), packet.src64);
+ /* Display the extended source address. (ZigBee 2006 and later). */
+ if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) {
+ addr16.pan = ieee_packet->src_pan;
+
+ if (packet.ext_src) {
+ packet.src64 = tvb_get_letoh64(tvb, offset);
+ if (tree) {
+ proto_tree_add_eui64(nwk_tree, hf_zbee_nwk_src64, tvb, offset, sizeof(guint64), packet.src64);
+ }
+ offset += sizeof(guint64);
+
+ if (!pinfo->fd->flags.visited) {
+ /* Provide hints to upper layers */
+ nwk_hints->src_pan = ieee_packet->src_pan;
+
+ /* Update nwk extended address hash table */
+ if ( unicast_src ) {
+ nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_addr,
+ packet.src, addr16.pan, packet.src64, proto_zbee_nwk, pinfo->fd->num);
+ }
+ }
+ }
+ else {
+ /* See if extended source info was previously sniffed */
+ if (!pinfo->fd->flags.visited) {
+ nwk_hints->src_pan = ieee_packet->src_pan;
+ addr16.addr = packet.src;
+
+ map_rec = (ieee802154_map_rec *) g_hash_table_lookup(zbee_nwk_addr.short_table, &addr16);
+ if (map_rec) {
+ /* found a nwk mapping record */
+ nwk_hints->map_rec = map_rec;
+ }
+ else {
+ /* does ieee layer know? */
+ map_rec = (ieee802154_map_rec *) g_hash_table_lookup(ieee_packet->short_table, &addr16);
+ if (map_rec) nwk_hints->map_rec = map_rec;
+ }
+ } /* (!pinfo->fd->flags.visited) */
+ else {
+ if (tree && nwk_hints && nwk_hints->map_rec ) {
+ /* Display inferred source address info */
+ ti = proto_tree_add_eui64(nwk_tree, hf_zbee_nwk_src64, tvb, offset, 0,
+ nwk_hints->map_rec->addr64);
+ PROTO_ITEM_SET_GENERATED(ti);
+
+ if ( nwk_hints->map_rec->start_fnum ) {
+ ti = proto_tree_add_uint(nwk_tree, hf_zbee_nwk_src64_origin, tvb, 0, 0,
+ nwk_hints->map_rec->start_fnum);
+ }
+ else {
+ ti = proto_tree_add_text(nwk_tree, tvb, 0, 0, "Origin: Pre-configured");
+ }
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ }
}
- offset += sizeof(guint64);
- }
+
+ /* If ieee layer didn't know its extended source address, and nwk layer does, fill it in */
+ if (!pinfo->fd->flags.visited) {
+ if ( (ieee_packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
+ ieee_hints && !ieee_hints->map_rec ) {
+ addr16.pan = ieee_packet->src_pan;
+ addr16.addr = ieee_packet->src16;
+ map_rec = (ieee802154_map_rec *) g_hash_table_lookup(zbee_nwk_addr.short_table, &addr16);
+
+ if (map_rec) {
+ /* found a ieee mapping record */
+ ieee_hints->map_rec = map_rec;
+ }
+ }
+ } /* (!pinfo->fd->flags.visited */
+ } /* (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) */
/* Add the Source Route field. (ZigBee 2006 and later). */
if ((pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) && packet.route) {
@@ -579,7 +682,7 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
/* Payload is encrypted, attempt security operations. */
else if (packet.security) {
- payload_tvb = dissect_zbee_secure(tvb, pinfo, nwk_tree, offset, 0);
+ payload_tvb = dissect_zbee_secure(tvb, pinfo, nwk_tree, offset);
if (payload_tvb == NULL) {
/* If Payload_tvb is NULL, then the security dissector cleaned up. */
return;
@@ -609,7 +712,7 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* dissect_zbee_nwk_cmd
* DESCRIPTION
* ZigBee Network command packet dissection routine for Wireshark.
- * note: this dissector differs from others in that is shouldn't be
+ * note: this dissector differs from others in that it shouldn't be
* passed the main tree pointer, but the nwk tree instead.
* PARAMETERS
* tvbuff_t *tvb - pointer to buffer containing raw packet.
@@ -624,14 +727,15 @@ static void dissect_zbee_nwk_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
proto_tree *cmd_tree = NULL;
proto_item *cmd_root = NULL;
- zbee_nwk_packet *packet = pinfo->private_data;
+ zbee_nwk_packet *packet = (zbee_nwk_packet *)pinfo->private_data;
guint offset=0;
guint8 cmd_id = tvb_get_guint8(tvb, offset);
/* Create a subtree for this command. */
if (tree) {
- cmd_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Command Frame: %s", val_to_str(cmd_id, zbee_nwk_cmd_names, "Unknown"));
+ cmd_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Command Frame: %s",
+ val_to_str(cmd_id, zbee_nwk_cmd_names, "Unknown"));
cmd_tree = proto_item_add_subtree(cmd_root, ett_zbee_nwk_cmd);
/* Add the command ID. */
@@ -754,12 +858,16 @@ dissect_zbee_nwk_route_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) {
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_multicast, tvb, offset, sizeof(guint8), route_options & ZBEE_NWK_CMD_ROUTE_OPTION_MCAST);
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_dest_ext, tvb, offset, sizeof(guint8), route_options & ZBEE_NWK_CMD_ROUTE_OPTION_DEST_EXT);
- proto_tree_add_uint(field_tree, hf_zbee_nwk_cmd_route_opt_many_to_one, tvb, offset, sizeof(guint8), route_options & ZBEE_NWK_CMD_ROUTE_OPTION_MANY_MASK);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_multicast, tvb, offset,
+ sizeof(guint8), route_options & ZBEE_NWK_CMD_ROUTE_OPTION_MCAST);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_route_opt_dest_ext, tvb, offset,
+ sizeof(guint8), route_options & ZBEE_NWK_CMD_ROUTE_OPTION_DEST_EXT);
+ proto_tree_add_uint(field_tree, hf_zbee_nwk_cmd_route_opt_many_to_one, tvb, offset,
+ sizeof(guint8), route_options & ZBEE_NWK_CMD_ROUTE_OPTION_MANY_MASK);
}
else {
- proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_route_opt_repair, tvb, offset, sizeof(guint8), route_options & ZBEE_NWK_CMD_ROUTE_OPTION_REPAIR);
+ proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_route_opt_repair, tvb, offset, sizeof(guint8),
+ route_options & ZBEE_NWK_CMD_ROUTE_OPTION_REPAIR);
}
}
offset += sizeof(guint8);
@@ -968,9 +1076,12 @@ dissect_zbee_nwk_leave(tvbuff_t *tvb, proto_tree *tree, guint offset)
/* Get and display the leave options. */
leave_options = tvb_get_guint8(tvb, offset);
if (tree) {
- proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_rejoin, tvb, offset, sizeof(guint8), leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_REJOIN);
- proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_request, tvb, offset, sizeof(guint8), leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_REQUEST);
- proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_children, tvb, offset, sizeof(guint8), leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_CHILDREN);
+ proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_rejoin, tvb, offset, sizeof(guint8),
+ leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_REJOIN);
+ proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_request, tvb, offset, sizeof(guint8),
+ leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_REQUEST);
+ proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_leave_children, tvb, offset, sizeof(guint8),
+ leave_options & ZBEE_NWK_CMD_LEAVE_OPTION_CHILDREN);
}
offset += sizeof(guint8);
@@ -1056,12 +1167,18 @@ dissect_zbee_nwk_rejoin_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_cinfo);
/* Add the capability info flags. */
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_alt_coord, tvb, offset, sizeof(guint8), capabilities & ZBEE_CINFO_ALT_COORD);
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_type, tvb, offset, sizeof(guint8), capabilities & ZBEE_CINFO_FFD);
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_power, tvb, offset, sizeof(guint8), capabilities & ZBEE_CINFO_POWER);
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_idle_rx, tvb, offset, sizeof(guint8), capabilities & ZBEE_CINFO_IDLE_RX);
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_security, tvb, offset, sizeof(guint8), capabilities & ZBEE_CINFO_SECURITY);
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_alloc, tvb, offset, sizeof(guint8), capabilities & ZBEE_CINFO_ALLOC);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_alt_coord, tvb, offset, sizeof(guint8),
+ capabilities & ZBEE_CINFO_ALT_COORD);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_type, tvb, offset, sizeof(guint8),
+ capabilities & ZBEE_CINFO_FFD);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_power, tvb, offset, sizeof(guint8),
+ capabilities & ZBEE_CINFO_POWER);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_idle_rx, tvb, offset, sizeof(guint8),
+ capabilities & ZBEE_CINFO_IDLE_RX);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_security, tvb, offset, sizeof(guint8),
+ capabilities & ZBEE_CINFO_SECURITY);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_cmd_cinfo_alloc, tvb, offset, sizeof(guint8),
+ capabilities & ZBEE_CINFO_ALLOC);
}
offset += sizeof(guint8);
@@ -1147,8 +1264,10 @@ dissect_zbee_nwk_link_status(tvbuff_t *tvb, proto_tree *tree, guint offset)
options = tvb_get_guint8(tvb, offset);
link_count = options & ZBEE_NWK_CMD_LINK_OPTION_COUNT_MASK;
if (tree) {
- proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_link_last, tvb, offset, sizeof(guint8), options & ZBEE_NWK_CMD_LINK_OPTION_LAST_FRAME);
- proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_link_first, tvb, offset, sizeof(guint8), options & ZBEE_NWK_CMD_LINK_OPTION_FIRST_FRAME);
+ proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_link_last, tvb, offset, sizeof(guint8),
+ options & ZBEE_NWK_CMD_LINK_OPTION_LAST_FRAME);
+ proto_tree_add_boolean(tree, hf_zbee_nwk_cmd_link_first, tvb, offset, sizeof(guint8),
+ options & ZBEE_NWK_CMD_LINK_OPTION_FIRST_FRAME);
proto_tree_add_uint(tree, hf_zbee_nwk_cmd_link_count, tvb, offset, sizeof(guint8), link_count);
}
offset += sizeof(guint8);
@@ -1159,7 +1278,10 @@ dissect_zbee_nwk_link_status(tvbuff_t *tvb, proto_tree *tree, guint offset)
addr = tvb_get_letohs(tvb, offset);
options = tvb_get_guint8(tvb, offset+sizeof(guint16));
if (tree) {
- proto_tree_add_text(tree, tvb, offset, sizeof(guint16)+sizeof(guint8), "0x%04x, Incoming Cost: %d Outgoing Cost: %d", addr, options & ZBEE_NWK_CMD_LINK_INCOMMING_COST_MASK, (options & ZBEE_NWK_CMD_LINK_OUTGOING_COST_MASK)>>4);
+ proto_tree_add_text(tree, tvb, offset, sizeof(guint16)+sizeof(guint8),
+ "0x%04x, Incoming Cost: %d Outgoing Cost: %d", addr,
+ options & ZBEE_NWK_CMD_LINK_INCOMMING_COST_MASK,
+ (options & ZBEE_NWK_CMD_LINK_OUTGOING_COST_MASK)>>4);
}
offset += (sizeof(guint16)+sizeof(guint8));
} /* for */
@@ -1315,7 +1437,7 @@ dissect_zbee_nwk_update(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gui
*/
static void dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- ieee802154_packet *packet = pinfo->private_data;
+ ieee802154_packet *packet = (ieee802154_packet *)pinfo->private_data;
proto_item *beacon_root = NULL;
proto_tree *beacon_tree = NULL;
@@ -1337,7 +1459,7 @@ static void dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
/* Update the info column. */
if(check_col(pinfo->cinfo, COL_INFO)) {
col_clear(pinfo->cinfo, COL_INFO);
- col_append_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src.addr16);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src16);
}
/* Get and display the protocol id, must be 0 on all ZigBee beacons. */
@@ -1351,7 +1473,8 @@ static void dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
temp = tvb_get_guint8(tvb, offset);
pinfo->zbee_stack_vers = version = zbee_get_bit_field(temp, ZBEE_NWK_BEACON_PROTOCOL_VERSION);
if (tree) {
- proto_tree_add_uint(beacon_tree, hf_zbee_beacon_stack_profile, tvb, offset, sizeof(guint8), zbee_get_bit_field(temp, ZBEE_NWK_BEACON_STACK_PROFILE));
+ proto_tree_add_uint(beacon_tree, hf_zbee_beacon_stack_profile, tvb, offset, sizeof(guint8),
+ zbee_get_bit_field(temp, ZBEE_NWK_BEACON_STACK_PROFILE));
proto_tree_add_uint(beacon_tree, hf_zbee_beacon_version, tvb, offset, sizeof(guint8), version);
}
offset += sizeof(guint8);
@@ -1359,9 +1482,12 @@ static void dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
/* Get and display the security level and flags. */
temp = tvb_get_guint8(tvb, offset);
if (tree) {
- proto_tree_add_boolean(beacon_tree, hf_zbee_beacon_router_capacity, tvb, offset, sizeof(guint8), zbee_get_bit_field(temp, ZBEE_NWK_BEACON_ROUTER_CAPACITY));
- proto_tree_add_uint(beacon_tree, hf_zbee_beacon_depth, tvb, offset, sizeof(guint8), zbee_get_bit_field(temp, ZBEE_NWK_BEACON_NETWORK_DEPTH));
- proto_tree_add_boolean(beacon_tree, hf_zbee_beacon_end_device_capacity, tvb, offset, sizeof(guint8), zbee_get_bit_field(temp, ZBEE_NWK_BEACON_END_DEVICE_CAPACITY));
+ proto_tree_add_boolean(beacon_tree, hf_zbee_beacon_router_capacity, tvb, offset, sizeof(guint8),
+ zbee_get_bit_field(temp, ZBEE_NWK_BEACON_ROUTER_CAPACITY));
+ proto_tree_add_uint(beacon_tree, hf_zbee_beacon_depth, tvb, offset, sizeof(guint8),
+ zbee_get_bit_field(temp, ZBEE_NWK_BEACON_NETWORK_DEPTH));
+ proto_tree_add_boolean(beacon_tree, hf_zbee_beacon_end_device_capacity, tvb, offset, sizeof(guint8),
+ zbee_get_bit_field(temp, ZBEE_NWK_BEACON_END_DEVICE_CAPACITY));
}
offset += sizeof(guint8);
@@ -1369,7 +1495,8 @@ static void dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
/* In ZigBee 2006 and later, the beacon contains an extended PAN ID. */
epid = tvb_get_letoh64(tvb, offset);
if (tree) {
- proto_tree_add_uint64_format_value(beacon_tree, hf_zbee_beacon_epid, tvb, offset, sizeof(guint64), epid, "%s", print_eui64(epid));
+ proto_tree_add_uint64_format_value(beacon_tree, hf_zbee_beacon_epid, tvb, offset, sizeof(guint64),
+ epid, "%s", print_eui64(epid));
}
offset += sizeof(guint64);
@@ -1445,15 +1572,16 @@ void proto_register_zbee_nwk(void)
static hf_register_info hf[] = {
{ &hf_zbee_nwk_frame_type,
- { "Frame Type", "zbee.nwk.frame_type", FT_UINT16, BASE_HEX, VALS(zbee_nwk_frame_types), ZBEE_NWK_FCF_FRAME_TYPE,
- NULL, HFILL }},
+ { "Frame Type", "zbee.nwk.frame_type", FT_UINT16, BASE_HEX, VALS(zbee_nwk_frame_types),
+ ZBEE_NWK_FCF_FRAME_TYPE, NULL, HFILL }},
{ &hf_zbee_nwk_proto_version,
{ "Protocol Version", "zbee.nwk.proto_version", FT_UINT16, BASE_DEC, NULL, ZBEE_NWK_FCF_VERSION,
NULL, HFILL }},
{ &hf_zbee_nwk_discover_route,
- { "Discover Route", "zbee.nwk.discovery", FT_UINT16, BASE_HEX, VALS(zbee_nwk_discovery_modes), ZBEE_NWK_FCF_DISCOVER_ROUTE,
+ { "Discover Route", "zbee.nwk.discovery", FT_UINT16, BASE_HEX, VALS(zbee_nwk_discovery_modes),
+ ZBEE_NWK_FCF_DISCOVER_ROUTE,
"Determines how route discovery may be handled, if at all.", HFILL }},
{ &hf_zbee_nwk_multicast,
@@ -1469,7 +1597,7 @@ void proto_register_zbee_nwk(void)
NULL, HFILL }},
{ &hf_zbee_nwk_ext_dst,
- { "Extended Destination", "zbee.nwk.ext_dst", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_EXT_DEST,
+ { "Destination", "zbee.nwk.ext_dst", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_EXT_DEST,
NULL, HFILL }},
{ &hf_zbee_nwk_ext_src,
@@ -1494,22 +1622,27 @@ void proto_register_zbee_nwk(void)
{ &hf_zbee_nwk_mcast_mode,
{ "Multicast Mode", "zbee.nwk.multicast.mode", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_MCAST_MODE,
- "Controls whether this packet is permitted to be routed through non-members of the multicast group.", HFILL }},
+ "Controls whether this packet is permitted to be routed through non-members of the multicast group.",
+ HFILL }},
{ &hf_zbee_nwk_mcast_radius,
{ "Non-Member Radius", "zbee.nwk.multicast.radius", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_MCAST_RADIUS,
"Limits the range of multicast packets when being routed through non-members.", HFILL }},
{ &hf_zbee_nwk_mcast_max_radius,
- { "Max Non-Member Radius", "zbee.nwk.multicast.max_radius", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_MCAST_MAX_RADIUS,
- NULL, HFILL }},
+ { "Max Non-Member Radius", "zbee.nwk.multicast.max_radius", FT_UINT8, BASE_DEC, NULL,
+ ZBEE_NWK_MCAST_MAX_RADIUS, NULL, HFILL }},
{ &hf_zbee_nwk_dst64,
- { "Extended Destination", "zbee.nwk.dst64", FT_UINT64, BASE_HEX, NULL, 0x0,
+ { "Destination", "zbee.nwk.dst64", FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
{ &hf_zbee_nwk_src64,
- { "Extended Source", "zbee.nwk.scr64", FT_UINT64, BASE_HEX, NULL, 0x0,
+ { "Extended Source", "zbee.nwk.src64", FT_UINT64, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_zbee_nwk_src64_origin,
+ { "Origin", "zbee.nwk.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
{ &hf_zbee_nwk_relay_count,
@@ -1561,27 +1694,30 @@ void proto_register_zbee_nwk(void)
"A value specifying the efficiency of this route.", HFILL }},
{ &hf_zbee_nwk_cmd_route_opt_repair,
- { "Route Repair", "zbee.nwk.cmd.route.opts.repair", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_ROUTE_OPTION_REPAIR,
+ { "Route Repair", "zbee.nwk.cmd.route.opts.repair", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_ROUTE_OPTION_REPAIR,
"Flag identifying whether the route request command was to repair a failed route.", HFILL }},
{ &hf_zbee_nwk_cmd_route_opt_multicast,
- { "Multicast", "zbee.nwk.cmd.route.opts.mcast", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_ROUTE_OPTION_MCAST,
+ { "Multicast", "zbee.nwk.cmd.route.opts.mcast", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_ROUTE_OPTION_MCAST,
"Flag identifying this as a multicast route request.", HFILL }},
{ &hf_zbee_nwk_cmd_route_opt_dest_ext,
- { "Extended Destination", "zbee.nwk.cmd.route.opts.dest_ext", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_ROUTE_OPTION_DEST_EXT,
- NULL, HFILL }},
+ { "Extended Destination", "zbee.nwk.cmd.route.opts.dest_ext", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_ROUTE_OPTION_DEST_EXT, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_route_opt_resp_ext,
- { "Extended Responder", "zbee.nwk.cmd.route.opts.resp_ext", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_ROUTE_OPTION_RESP_EXT,
- NULL, HFILL }},
+ { "Extended Responder", "zbee.nwk.cmd.route.opts.resp_ext", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_ROUTE_OPTION_RESP_EXT, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_route_opt_orig_ext,
- { "Extended Originator", "zbee.nwk.cmd.route.opts.orig_ext", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_ROUTE_OPTION_ORIG_EXT,
- NULL, HFILL }},
+ { "Extended Originator", "zbee.nwk.cmd.route.opts.orig_ext", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_ROUTE_OPTION_ORIG_EXT, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_route_opt_many_to_one,
- { "Many-to-One Discovery", "zbee.nwk.cmd.route.opts.many2one", FT_UINT8, BASE_HEX, VALS(zbee_nwk_cmd_route_many_modes), ZBEE_NWK_CMD_ROUTE_OPTION_MANY_MASK,
+ { "Many-to-One Discovery", "zbee.nwk.cmd.route.opts.many2one", FT_UINT8, BASE_HEX,
+ VALS(zbee_nwk_cmd_route_many_modes), ZBEE_NWK_CMD_ROUTE_OPTION_MANY_MASK,
NULL, HFILL }},
{ &hf_zbee_nwk_cmd_nwk_status,
@@ -1589,15 +1725,17 @@ void proto_register_zbee_nwk(void)
NULL, HFILL }},
{ &hf_zbee_nwk_cmd_leave_rejoin,
- { "Rejoin", "zbee.nwk.cmd.leave.rejoin", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_LEAVE_OPTION_REJOIN,
- "Flag instructing the device to rejoin the network.", HFILL }},
+ { "Rejoin", "zbee.nwk.cmd.leave.rejoin", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_LEAVE_OPTION_REJOIN, "Flag instructing the device to rejoin the network.", HFILL }},
{ &hf_zbee_nwk_cmd_leave_request,
- { "Request", "zbee.nwk.cmd.leave.request", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_LEAVE_OPTION_REQUEST,
+ { "Request", "zbee.nwk.cmd.leave.request", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_LEAVE_OPTION_REQUEST,
"Flag identifying the direction of this command. 1=Request, 0=Indication", HFILL }},
{ &hf_zbee_nwk_cmd_leave_children,
- { "Remove Children", "zbee.nwk.cmd.leave.children", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_LEAVE_OPTION_CHILDREN,
+ { "Remove Children", "zbee.nwk.cmd.leave.children", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_LEAVE_OPTION_CHILDREN,
"Flag instructing the device to remove its children in addition to itself.", HFILL }},
{ &hf_zbee_nwk_cmd_relay_count,
@@ -1605,60 +1743,66 @@ void proto_register_zbee_nwk(void)
"Number of relays required to route to the destination.", HFILL }},
{ &hf_zbee_nwk_cmd_cinfo_alt_coord,
- { "Alternate Coordinator", "zbee.nwk.cmd.cinfo.alt_coord", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALT_PAN_COORD,
+ { "Alternate Coordinator", "zbee.nwk.cmd.cinfo.alt_coord", FT_BOOLEAN, 8, NULL,
+ IEEE802154_CMD_CINFO_ALT_PAN_COORD,
"Indicates that the device is able to operate as a PAN coordinator.", HFILL }},
{ &hf_zbee_nwk_cmd_cinfo_type,
- { "Full-Function Device", "zbee.nwk.cmd.cinfo.ffd", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_DEVICE_TYPE,
- NULL, HFILL }},
+ { "Full-Function Device", "zbee.nwk.cmd.cinfo.ffd", FT_BOOLEAN, 8, NULL,
+ IEEE802154_CMD_CINFO_DEVICE_TYPE, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_cinfo_power,
- { "AC Power", "zbee.nwk.cmd.cinfo.power", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_POWER_SRC,
- "Indicates this device is using AC/Mains power.", HFILL }},
+ { "AC Power", "zbee.nwk.cmd.cinfo.power", FT_BOOLEAN, 8, NULL,
+ IEEE802154_CMD_CINFO_POWER_SRC, "Indicates this device is using AC/Mains power.", HFILL }},
{ &hf_zbee_nwk_cmd_cinfo_idle_rx,
- { "Rx On When Idle", "zbee.nwk.cmd.cinfo.power", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
+ { "Rx On When Idle", "zbee.nwk.cmd.cinfo.power", FT_BOOLEAN, 8, NULL,
+ IEEE802154_CMD_CINFO_IDLE_RX,
"Indicates the receiver is active when the device is idle.", HFILL }},
{ &hf_zbee_nwk_cmd_cinfo_security,
- { "Security Capability", "zbee.nwk.cmd.cinfo.security", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_SEC_CAPABLE,
+ { "Security Capability", "zbee.nwk.cmd.cinfo.security", FT_BOOLEAN, 8, NULL,
+ IEEE802154_CMD_CINFO_SEC_CAPABLE,
"Indicates this device is capable of performing encryption/decryption.", HFILL }},
{ &hf_zbee_nwk_cmd_cinfo_alloc,
- { "Allocate Short Address", "zbee.nwk.cmd.cinfo.alloc", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALLOC_ADDR,
+ { "Allocate Short Address", "zbee.nwk.cmd.cinfo.alloc", FT_BOOLEAN, 8, NULL,
+ IEEE802154_CMD_CINFO_ALLOC_ADDR,
"Flag requesting the parent to allocate a short address for this device.", HFILL }},
{ &hf_zbee_nwk_cmd_rejoin_status,
- { "Status", "zbee.nwk.cmd.rejoin_status", FT_UINT8, BASE_HEX, VALS(zbee_nwk_rejoin_codes), 0x0,
- NULL, HFILL }},
+ { "Status", "zbee.nwk.cmd.rejoin_status", FT_UINT8, BASE_HEX,
+ VALS(zbee_nwk_rejoin_codes), 0x0, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_link_last,
- { "Last Frame", "zbee.nwk.cmd.link.last", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_LINK_OPTION_LAST_FRAME,
+ { "Last Frame", "zbee.nwk.cmd.link.last", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_LINK_OPTION_LAST_FRAME,
"Flag indicating the last in a series of link status commands.", HFILL }},
{ &hf_zbee_nwk_cmd_link_first,
- { "First Frame", "zbee.nwk.cmd.link.first", FT_BOOLEAN, 8, NULL, ZBEE_NWK_CMD_LINK_OPTION_FIRST_FRAME,
+ { "First Frame", "zbee.nwk.cmd.link.first", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_CMD_LINK_OPTION_FIRST_FRAME,
"Flag indicating the first in a series of link status commands.", HFILL }},
{ &hf_zbee_nwk_cmd_link_count,
- { "Link Status Count", "zbee.nwk.cmd.link.count", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_CMD_LINK_OPTION_COUNT_MASK,
- NULL, HFILL }},
+ { "Link Status Count", "zbee.nwk.cmd.link.count", FT_UINT8, BASE_DEC, NULL,
+ ZBEE_NWK_CMD_LINK_OPTION_COUNT_MASK, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_report_type,
- { "Report Type", "zbee.nwk.cmd.report.type", FT_UINT8, BASE_HEX, VALS(zbee_nwk_report_types), ZBEE_NWK_CMD_NWK_REPORT_ID_MASK,
- NULL, HFILL }},
+ { "Report Type", "zbee.nwk.cmd.report.type", FT_UINT8, BASE_HEX,
+ VALS(zbee_nwk_report_types), ZBEE_NWK_CMD_NWK_REPORT_ID_MASK, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_report_count,
- { "Report Information Count", "zbee.nwk.cmd.report.count", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_CMD_NWK_REPORT_COUNT_MASK,
- NULL, HFILL }},
+ { "Report Information Count", "zbee.nwk.cmd.report.count", FT_UINT8, BASE_DEC, NULL,
+ ZBEE_NWK_CMD_NWK_REPORT_COUNT_MASK, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_update_type,
- { "Update Type", "zbee.nwk.cmd.update.type", FT_UINT8, BASE_HEX, VALS(zbee_nwk_update_types), ZBEE_NWK_CMD_NWK_UPDATE_ID_MASK,
- NULL, HFILL }},
+ { "Update Type", "zbee.nwk.cmd.update.type", FT_UINT8, BASE_HEX,
+ VALS(zbee_nwk_update_types), ZBEE_NWK_CMD_NWK_UPDATE_ID_MASK, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_update_count,
- { "Update Information Count", "zbee.nwk.cmd.update.count", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_CMD_NWK_UPDATE_COUNT_MASK,
- NULL, HFILL }},
+ { "Update Information Count", "zbee.nwk.cmd.update.count", FT_UINT8, BASE_DEC, NULL,
+ ZBEE_NWK_CMD_NWK_UPDATE_COUNT_MASK, NULL, HFILL }},
{ &hf_zbee_nwk_cmd_update_id,
{ "Update ID", "zbee.nwk.cmd.update.id", FT_UINT8, BASE_DEC, NULL, 0x0,
@@ -1673,8 +1817,8 @@ void proto_register_zbee_nwk(void)
NULL, HFILL }},
{ &hf_zbee_beacon_stack_profile,
- { "Stack Profile", "zbee.beacon.profile", FT_UINT8, BASE_HEX, VALS(zbee_nwk_stack_profiles), 0x0,
- NULL, HFILL }},
+ { "Stack Profile", "zbee.beacon.profile", FT_UINT8, BASE_HEX,
+ VALS(zbee_nwk_stack_profiles), 0x0, NULL, HFILL }},
{ &hf_zbee_beacon_version,
{ "Protocol Version", "zbee.beacon.version", FT_UINT8, BASE_DEC, NULL, 0x0,
@@ -1717,18 +1861,20 @@ void proto_register_zbee_nwk(void)
&ett_zbee_nwk_cmd_cinfo
};
+ register_init_routine(proto_init_zbee_nwk);
+
/* Register the protocol with Wireshark. */
- proto_zbee_nwk = proto_register_protocol("ZigBee Network Layer", "ZigBee NWK", "zbee.nwk");
+ proto_zbee_nwk = proto_register_protocol("ZigBee Network Layer", "ZigBee NWK", ZBEE_PROTOABBREV_NWK);
proto_register_field_array(proto_zbee_nwk, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
/* Register the dissectors with Wireshark. */
- register_dissector("zbee.nwk", dissect_zbee_nwk, proto_zbee_nwk);
+ register_dissector(ZBEE_PROTOABBREV_NWK, dissect_zbee_nwk, proto_zbee_nwk);
register_dissector("zbee.beacon", dissect_zbee_beacon, proto_zbee_nwk);
/* Register the Security dissector. */
zbee_security_register(NULL, proto_zbee_nwk);
-} /* proto_register_zbee */
+} /* proto_register_zbee_nwk */
/*FUNCTION:------------------------------------------------------
* NAME
@@ -1748,8 +1894,43 @@ void proto_reg_handoff_zbee_nwk(void)
aps_handle = find_dissector("zbee.aps");
/* Register our dissector with IEEE 802.15.4 */
- heur_dissector_add("wpan", dissect_zbee_nwk_heur, proto_zbee_nwk);
+ heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_zbee_nwk_heur, proto_zbee_nwk);
/* Handoff the ZigBee security dissector code. */
zbee_security_handoff();
} /* proto_reg_handoff_zbee */
+
+static void free_keyring_val(gpointer a)
+{
+ GSList **slist = (GSList **)a;
+ g_slist_free(*slist);
+ return;
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_init_zbee_nwk
+ * DESCRIPTION
+ * Init routine for the nwk 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_zbee_nwk(void)
+{
+ /* Destroy the hash tables, if they exist. */
+ if (zbee_nwk_addr.short_table) g_hash_table_destroy(zbee_nwk_addr.short_table);
+ if (zbee_nwk_addr.long_table) g_hash_table_destroy(zbee_nwk_addr.long_table);
+ if (zbee_table_nwk_keyring) g_hash_table_destroy(zbee_table_nwk_keyring);
+
+ /* (Re)create the hash tables. */
+ zbee_nwk_addr.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
+ zbee_nwk_addr.long_table = g_hash_table_new(g_int64_hash, g_int64_equal);
+ zbee_table_nwk_keyring = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free_keyring_val);
+} /* proto_init_zbee_nwk */
diff --git a/epan/dissectors/packet-zbee-nwk.h b/epan/dissectors/packet-zbee-nwk.h
index b1e3da4fe4..9069e83961 100644
--- a/epan/dissectors/packet-zbee-nwk.h
+++ b/epan/dissectors/packet-zbee-nwk.h
@@ -21,7 +21,7 @@
*
* 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef PACKET_ZBEE_NWK_H
#define PACKET_ZBEE_NWK_H
@@ -122,10 +122,11 @@
#define ZBEE_NWK_STATUS_BAD_FRAME_COUNTER 0x11
#define ZBEE_NWK_STATUS_BAD_KEY_SEQNO 0x12
+#define ZBEE_SEC_CONST_KEYSIZE 16
+
typedef struct{
gboolean security;
gboolean discovery;
- gboolean is_bcast;
gboolean multicast; /* ZigBee 2006 and Later */
gboolean route; /* ZigBee 2006 and Later */
gboolean ext_dst; /* ZigBee 2006 and Later */
@@ -148,6 +149,33 @@ typedef struct{
guint8 payload_len;
} zbee_nwk_packet;
+/* Key used for link key hash table. */
+typedef struct {
+ guint64 lt_addr64; /* lesser than address */
+ guint64 gt_addr64; /* greater than address */
+} table_link_key_t;
+
+/* Values in the key rings. */
+typedef struct {
+ guint frame_num;
+ gchar *label;
+ guint8 key[ZBEE_SEC_CONST_KEYSIZE];
+} key_record_t;
+
+typedef struct {
+ gint src_pan; /* source pan */
+ gint ieee_src; /* short source address from mac */
+ ieee802154_map_rec *map_rec; /* extended src from nwk */
+ key_record_t *nwk; /* Network key found for this packet */
+ key_record_t *link; /* Link key found for this packet */
+} zbee_nwk_hints_t;
+
+extern GHashTable *zbee_table_nwk_keyring;
+extern GHashTable *zbee_table_link_keyring;
+
+/* Key Types */
+#define ZBEE_USER_KEY 0x01
+
/* Beacon Definitions. */
#define ZBEE_NWK_BEACON_PROCOL_ID 0x00
#define ZBEE_NWK_BEACON_STACK_PROFILE 0x0f
diff --git a/epan/dissectors/packet-zbee-security.c b/epan/dissectors/packet-zbee-security.c
index 16cd6079b1..768e71cbc0 100644
--- a/epan/dissectors/packet-zbee-security.c
+++ b/epan/dissectors/packet-zbee-security.c
@@ -1,6 +1,6 @@
/* packet-zbee-security.c
* Dissector helper routines for encrypted ZigBee frames.
- * By Owen Kirby <osk@exegin.com>
+ * By Owen Kirby <osk@exegin.com>; portions by Fred Fierling <fff@exegin.com>
* Copyright 2009 Exegin Technologies Limited
*
* $Id$
@@ -38,6 +38,8 @@
#include <epan/prefs.h>
#include <epan/expert.h>
+#include <epan/uat.h>
+
/* We require libgcrpyt in order to decrypt ZigBee packets. Without it the best
* we can do is parse the security header and give up.
*/
@@ -45,25 +47,34 @@
#include <gcrypt.h>
#endif /* HAVE_LIBGCRYPT */
+#include "packet-ieee802154.h"
#include "packet-zbee.h"
+#include "packet-zbee-nwk.h"
#include "packet-zbee-security.h"
/* Helper Functions */
#ifdef HAVE_LIBGCRYPT
-static gboolean zbee_sec_ccm_decrypt(const gchar *, const gchar *, const gchar *, const gchar *, gchar *, guint, guint, guint);
-static guint8 * zbee_sec_key_hash(guint8 *, guint8, packet_info *);
-static void zbee_sec_make_nonce (guint8 *, zbee_security_packet *);
+static gboolean zbee_sec_ccm_decrypt(const gchar *, const gchar *, const gchar *, const gchar *, gchar *,
+ guint, guint, guint);
+static guint8 * zbee_sec_key_hash(guint8 *, guint8, guint8 *);
+static void zbee_sec_make_nonce (zbee_security_packet *, guint8 *);
+static gboolean zbee_sec_decrypt_payload(zbee_security_packet *, const gchar *, const gchar, guint8 *,
+ guint, guint, guint8 *);
#endif
-static void zbee_security_parse_prefs(void);
+static gboolean zbee_security_parse_key(const gchar *, guint8 *, gboolean);
+static void proto_init_zbee_security(void);
/* Field pointers. */
+#if 0
static int hf_zbee_sec_level = -1;
-static int hf_zbee_sec_key = -1;
+#endif
+static int hf_zbee_sec_key_id = -1;
static int hf_zbee_sec_nonce = -1;
static int hf_zbee_sec_counter = -1;
-static int hf_zbee_sec_src = -1;
+static int hf_zbee_sec_src64 = -1;
static int hf_zbee_sec_key_seqno = -1;
static int hf_zbee_sec_mic = -1;
+static int hf_zbee_sec_key_origin = -1;
/* Subtree pointers. */
static gint ett_zbee_sec = -1;
@@ -79,6 +90,7 @@ static const value_string zbee_sec_key_names[] = {
{ 0, NULL }
};
+#if 0
/* These aren't really used anymore, as ZigBee no longer includes them in the
* security control field. If we were to display them all we would ever see is
* security level 0.
@@ -94,6 +106,7 @@ static const value_string zbee_sec_level_names[] = {
{ ZBEE_SEC_ENC_MIC128, "Encryption, 128-bit MIC" },
{ 0, NULL }
};
+#endif
/* The ZigBee security level, in enum_val_t for the security preferences. */
static enum_val_t zbee_sec_level_enums[] = {
@@ -108,22 +121,78 @@ static enum_val_t zbee_sec_level_enums[] = {
{ NULL, NULL, 0 }
};
-/* Network Key. */
-static gboolean zbee_sec_have_nwk_key = FALSE;
-static guint8 zbee_sec_nwk_key[ZBEE_SEC_CONST_KEYSIZE];
+static gint gPREF_zbee_sec_level = ZBEE_SEC_ENC_MIC32;
+static uat_t *zbee_sec_key_table_uat;
+
+static const value_string byte_order_vals[] = {
+ { 0, "Normal"},
+ { 1, "Reverse"},
+ { 0, NULL }
+};
+
+/* UAT Key Entry */
+typedef struct _uat_key_record_t {
+ gchar *string;
+ gboolean byte_order;
+ gchar *label;
+ guint8 key[ZBEE_SEC_CONST_KEYSIZE];
+} uat_key_record_t;
+
+/* */
+static uat_key_record_t *uat_key_records = NULL;
+static guint num_uat_key_records = 0;
+
+static void* uat_key_record_copy_cb(void* n, const void* o, unsigned siz _U_) {
+ uat_key_record_t* new_key = (uat_key_record_t *)n;
+ const uat_key_record_t* old_key = (uat_key_record_t *)o;
+
+ if (old_key->string) {
+ new_key->string = g_strdup(old_key->string);
+ } else {
+ new_key->string = NULL;
+ }
+
+ if (old_key->label) {
+ new_key->label = g_strdup(old_key->label);
+ } else {
+ new_key->label = NULL;
+ }
+
+ return new_key;
+}
+
+static void uat_key_record_update_cb(void* r, const char** err) {
+ uat_key_record_t* rec = (uat_key_record_t *)r;
+
+ if (rec->string == NULL) {
+ *err = ep_strdup_printf("Key can't be blank");
+ } else {
+ g_strstrip(rec->string);
+
+ if (rec->string[0] != 0) {
+ *err = NULL;
+ if ( !zbee_security_parse_key(rec->string, rec->key, rec->byte_order) ) {
+ *err = ep_strdup_printf("Expecting %d hexadecimal bytes or\n"
+ "a %d character double-quoted string", ZBEE_SEC_CONST_KEYSIZE, ZBEE_SEC_CONST_KEYSIZE);
+ }
+ } else {
+ *err = ep_strdup_printf("Key can't be blank");
+ }
+ }
+}
-/* Trust-Center Link Key. */
-static gboolean zbee_sec_have_tclink_key = FALSE;
-static guint8 zbee_sec_tclink_key[ZBEE_SEC_CONST_KEYSIZE];
+static void uat_key_record_free_cb(void*r) {
+ uat_key_record_t* key = (uat_key_record_t *)r;
-/* Trust-Center Extended Address */
-static guint64 zbee_sec_tcaddr = 0;
+ if (key->string) g_free(key->string);
+ if (key->label) g_free(key->label);
+}
-/* ZigBee Security Preferences. */
-static gint gPREF_zbee_sec_level = ZBEE_SEC_ENC_MIC32;
-static const gchar * gPREF_zbee_sec_nwk_key = NULL;
-static const gchar * gPREF_zbee_sec_tcaddr = NULL;
-static const gchar * gPREF_zbee_sec_tclink_key = NULL;
+UAT_CSTRING_CB_DEF(uat_key_records, string, uat_key_record_t)
+UAT_VS_DEF(uat_key_records, byte_order, uat_key_record_t, 0, "Normal")
+UAT_CSTRING_CB_DEF(uat_key_records, label, uat_key_record_t)
+
+static GSList *zbee_pc_keyring = NULL;
/*
* Enable this macro to use libgcrypt's CBC_MAC mode for the authentication
@@ -137,8 +206,8 @@ static const gchar * gPREF_zbee_sec_tclink_key = NULL;
* NAME
* zbee_security_register
* DESCRIPTION
- * Called to initialize the security dissectors. Roughly the
- * equivalent of proto_register_*
+ * Called by proto_register_zbee_nwk() to initialize the security
+ * dissectors.
* PARAMETERS
* module_t zbee_prefs - Prefs module to load preferences under.
* RETURNS
@@ -148,13 +217,14 @@ static const gchar * gPREF_zbee_sec_tclink_key = NULL;
void zbee_security_register(module_t *zbee_prefs, int proto)
{
static hf_register_info hf[] = {
+#if 0
{ &hf_zbee_sec_level,
{ "Level", "zbee.sec.level", FT_UINT8, BASE_HEX, VALS(zbee_sec_level_names), ZBEE_SEC_CONTROL_LEVEL,
NULL, HFILL }},
-
- { &hf_zbee_sec_key,
- { "Key", "zbee.sec.key", FT_UINT8, BASE_HEX, VALS(zbee_sec_key_names), ZBEE_SEC_CONTROL_KEY,
- NULL, HFILL }},
+#endif
+ { &hf_zbee_sec_key_id,
+ { "Key Id", "zbee.sec.key", FT_UINT8, BASE_HEX, VALS(zbee_sec_key_names),
+ ZBEE_SEC_CONTROL_KEY, NULL, HFILL }},
{ &hf_zbee_sec_nonce,
{ "Extended Nonce", "zbee.sec.ext_nonce", FT_BOOLEAN, 8, NULL, ZBEE_SEC_CONTROL_NONCE,
@@ -164,8 +234,8 @@ void zbee_security_register(module_t *zbee_prefs, int proto)
{ "Frame Counter", "zbee.sec.counter", FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL }},
- { &hf_zbee_sec_src,
- { "Source", "zbee.sec.src", FT_UINT64, BASE_HEX, NULL, 0x0,
+ { &hf_zbee_sec_src64,
+ { "Source", "zbee.sec.src64", FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
{ &hf_zbee_sec_key_seqno,
@@ -174,6 +244,10 @@ void zbee_security_register(module_t *zbee_prefs, int proto)
{ &hf_zbee_sec_mic,
{ "Message Integrity Code", "zbee.sec.mic", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_zbee_sec_key_origin,
+ { "Key Origin", "zbee.sec.key.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
NULL, HFILL }}
};
@@ -182,135 +256,136 @@ void zbee_security_register(module_t *zbee_prefs, int proto)
&ett_zbee_sec_control
};
+ static uat_field_t key_uat_fields[] = {
+ UAT_FLD_CSTRING(uat_key_records, string, "Key",
+ "A 16-byte key in hexadecimal with optional dash-,\n"
+ "colon-, or space-separator characters, or a\n"
+ "a 16-character string in double-quotes."),
+ UAT_FLD_VS(uat_key_records, byte_order, "Byte Order", byte_order_vals,
+ "Byte order of key."),
+ UAT_FLD_LSTRING(uat_key_records, label, "Label", "User label for key."),
+ UAT_END_FIELDS
+ };
+
/* If no prefs module was supplied, register our own. */
if (zbee_prefs == NULL) {
- zbee_prefs = prefs_register_protocol(proto, zbee_security_parse_prefs);
+ zbee_prefs = prefs_register_protocol(proto, NULL);
}
/* Register preferences */
prefs_register_enum_preference(zbee_prefs, "seclevel", "Security Level",
- "Specifies the security level to use in the decryption process. This value is ignored for ZigBee 2004 and unsecured networks.",
+ "Specifies the security level to use in the\n"
+ "decryption process. This value is ignored\n"
+ "for ZigBee 2004 and unsecured networks.",
&gPREF_zbee_sec_level, zbee_sec_level_enums, FALSE);
- prefs_register_string_preference(zbee_prefs, "nwkkey", "Network Key",
- "Specifies the network key to use for decryption.",
- &gPREF_zbee_sec_nwk_key);
- prefs_register_string_preference(zbee_prefs, "tcaddr", "Trust Center Address",
- "The Extended address of the trust center.",
- &gPREF_zbee_sec_tcaddr);
- prefs_register_string_preference(zbee_prefs, "tclinkkey", "Trust Center Link Key",
- "Specifies the trust center link key to use for decryption.",
- &gPREF_zbee_sec_tclink_key);
+
+ zbee_sec_key_table_uat = uat_new("Pre-configured Keys",
+ sizeof(uat_key_record_t),
+ "zigbee_pc_keys",
+ TRUE,
+ (void*) &uat_key_records,
+ &num_uat_key_records,
+ UAT_CAT_FFMT,
+ NULL, /* TODO: ptr to help manual? */
+ uat_key_record_copy_cb,
+ uat_key_record_update_cb,
+ uat_key_record_free_cb,
+ NULL, /* TODO: post_update */
+ key_uat_fields );
+
+ prefs_register_uat_preference(zbee_prefs,
+ "key_table",
+ "Pre-configured Keys",
+ "Pre-configured link or network keys.",
+ zbee_sec_key_table_uat);
proto_register_field_array(proto, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register the init routine. */
+ register_init_routine(proto_init_zbee_security);
} /* zbee_security_register */
/*FUNCTION:------------------------------------------------------
* NAME
* zbee_security_parse_key
* DESCRIPTION
- * Parses a key string into a buffer.
+ * Parses a key string from left to right into a buffer with
+ * increasing (normal byte order) or decreasing (reverse byte
+ * order) address.
* PARAMETERS
- * const gchar * key_str;
- * guint8 key_buf;
+ * const gchar *key_str - pointer to the string
+ * guint8 *key_buf - destination buffer in memory
+ * gboolean big_end - fill key_buf with incrementing address
* RETURNS
* gboolean
*---------------------------------------------------------------
*/
static gboolean
-zbee_security_parse_key(const gchar *key_str, guint8 *key_buf)
+zbee_security_parse_key(const gchar *key_str, guint8 *key_buf, gboolean byte_order)
{
- int i;
+ int i, j;
gchar temp;
+ gboolean string_mode = FALSE;
/* Clear the key. */
memset(key_buf, 0, ZBEE_SEC_CONST_KEYSIZE);
if (key_str == NULL) {
return FALSE;
}
+
/*
- * Attempt to parse the key string. The key string must represent
- * exactly 16 bytes in hexadecimal format with the following
- * separators: ':', '-', " ", or no separator at all. Start by
- * getting the first character.
+ * Attempt to parse the key string. The key string must
+ * be at least 16 pairs of hexidecimal digits with the
+ * following optional separators: ':', '-', " ", or 16
+ * alphanumeric characters after a double-quote.
*/
- temp = *(key_str++);
+ if ( (temp = *key_str++) == '"') {
+ string_mode = TRUE;
+ temp = *key_str++;
+ }
+
+ j = byte_order?ZBEE_SEC_CONST_KEYSIZE-1:0;
for (i=ZBEE_SEC_CONST_KEYSIZE-1; i>=0; i--) {
- /* If this character is a separator, skip it. */
- if ((temp == ':') || (temp == '-') || (temp == ' ')) temp = *(key_str++);
- /* Process this nibble. */
- if (('0' <= temp) && (temp <= '9')) key_buf[i] |= ((temp-'0')<<4);
- else if (('a' <= temp) && (temp <= 'f')) key_buf[i] |= ((temp-'a'+0x0a)<<4);
- else if (('A' <= temp) && (temp <= 'F')) key_buf[i] |= ((temp-'A'+0x0A)<<4);
- else return FALSE;
- /* Get the next nibble. */
- temp = *(key_str++);
- /* Process this nibble. */
- if (('0' <= temp) && (temp <= '9')) key_buf[i] |= (temp-'0');
- else if (('a' <= temp) && (temp <= 'f')) key_buf[i] |= (temp-'a'+0x0a);
- else if (('A' <= temp) && (temp <= 'F')) key_buf[i] |= (temp-'A'+0x0A);
- else return FALSE;
- /* Get the next nibble. */
- temp = *(key_str++);
- } /* for */
- /* If we get this far, then the key was good. */
- return TRUE;
-} /* zbee_security_parse_key */
+ if ( string_mode ) {
+ if ( g_ascii_isprint(temp) ) {
+ key_buf[j] = temp;
+ temp = *key_str++;
+ } else {
+ return FALSE;
+ }
+ }
+ else {
+ /* If this character is a separator, skip it. */
+ if ( (temp == ':') || (temp == '-') || (temp == ' ') ) temp = *(key_str++);
-/*FUNCTION:------------------------------------------------------
- * NAME
- * zbee_security_parse_prefs
- * DESCRIPTION
- * Parses the security preferences into the parameters needed
- * for decryption.
- * PARAMETERS
- * none
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
-static void
-zbee_security_parse_prefs(void)
-{
- int i;
- const gchar * str_ptr;
- gchar temp;
+ /* Process a nibble. */
+ if ( g_ascii_isxdigit (temp) ) key_buf[j] = g_ascii_xdigit_value(temp)<<4;
+ else return FALSE;
+
+ /* Get the next nibble. */
+ temp = *(key_str++);
+
+ /* Process another nibble. */
+ if ( g_ascii_isxdigit (temp) ) key_buf[j] |= g_ascii_xdigit_value(temp);
+ else return FALSE;
+
+ /* Get the next nibble. */
+ temp = *(key_str++);
+ }
+
+ /* Move key_buf pointer */
+ if ( byte_order ) {
+ j--;
+ } else {
+ j++;
+ }
- /* Get the network key. */
- zbee_sec_have_nwk_key = zbee_security_parse_key(gPREF_zbee_sec_nwk_key, zbee_sec_nwk_key);
- /* Get the trust-center link key. */
- zbee_sec_have_tclink_key = zbee_security_parse_key(gPREF_zbee_sec_tclink_key, zbee_sec_tclink_key);
- /* Get the trust-center address. */
- zbee_sec_tcaddr = 0;
- str_ptr = gPREF_zbee_sec_tcaddr;
- temp = *(str_ptr++);
- for (i=0;i<(int)sizeof(guint64);i++) {
- /* Except for the first octet, ensure the next character is a
- * separator and skip over it.
- */
- if ((temp == ':') || (temp == '-')) temp = *(str_ptr++);
- else if (i!=0) goto bad_tcaddr;
- /* Process this nibble. */
- if (('0' <= temp) && (temp <= '9')) zbee_sec_tcaddr |= ((guint64)(temp-'0'+0x00)<<(8*(sizeof(guint64)-i)-4));
- else if (('a' <= temp) && (temp <= 'f')) zbee_sec_tcaddr |= ((guint64)(temp-'a'+0x0a)<<(8*(sizeof(guint64)-i)-4));
- else if (('A' <= temp) && (temp <= 'F')) zbee_sec_tcaddr |= ((guint64)(temp-'A'+0x0A)<<(8*(sizeof(guint64)-i)-4));
- else goto bad_tcaddr;
- /* Get the next nibble. */
- temp = *(str_ptr++);
- /* Process this nibble. */
- if (('0' <= temp) && (temp <= '9')) zbee_sec_tcaddr |= ((guint64)(temp-'0'+0x00)<<(8*(sizeof(guint64)-i)-8));
- else if (('a' <= temp) && (temp <= 'f')) zbee_sec_tcaddr |= ((guint64)(temp-'a'+0x0a)<<(8*(sizeof(guint64)-i)-8));
- else if (('A' <= temp) && (temp <= 'F')) zbee_sec_tcaddr |= ((guint64)(temp-'A'+0x0A)<<(8*(sizeof(guint64)-i)-8));
- else goto bad_tcaddr;
- /* Get the next nibble. */
- temp = *(str_ptr++);
} /* for */
- /* Done */
- return;
-bad_tcaddr:
- zbee_sec_tcaddr = 0;
-} /* zbee_security_parse_prefs */
+ /* If we get this far, then the key was good. */
+ return TRUE;
+} /* zbee_security_parse_key */
/*FUNCTION:------------------------------------------------------
* NAME
@@ -328,8 +403,6 @@ zbee_security_handoff(void)
{
/* Lookup the data dissector. */
data_handle = find_dissector("data");
- /* Parse the security prefs. */
- zbee_security_parse_prefs();
} /* zbee_security_handoff */
/*FUNCTION:------------------------------------------------------
@@ -343,35 +416,52 @@ zbee_security_handoff(void)
* handle internally and return NULL.
* PARAMETERS
* tvbuff_t *tvb - pointer to buffer containing raw packet.
- * packet_into *pinfo - pointer to packet information fields
+ * packet_info *pinfo - pointer to packet information fields
* proto_tree *tree - pointer to data tree Wireshark uses to display packet.
* guint offset - pointer to the start of the auxilliary security header.
- * guint64 src - extended source address, or 0 if unknown.
+ * guint64 src64 - extended source address, or 0 if unknown.
* RETURNS
* tvbuff_t *
*---------------------------------------------------------------
*/
tvbuff_t *
-dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset, guint64 src)
+dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset)
{
- proto_tree * sec_tree = NULL;
- proto_item * sec_root;
- proto_tree * field_tree;
- proto_item * ti;
+ proto_tree *sec_tree = NULL;
+ proto_item *sec_root;
+ proto_tree *field_tree;
+ proto_item *ti;
zbee_security_packet packet;
guint mic_len;
guint payload_len;
- tvbuff_t * payload_tvb;
+ tvbuff_t *payload_tvb;
#ifdef HAVE_LIBGCRYPT
- const guint8 * enc_buffer;
- guint8 * dec_buffer;
- guint8 * key_buffer;
- guint8 nonce[ZBEE_SEC_CONST_NONCE_LEN];
+ guint8 *enc_buffer;
+ guint8 *dec_buffer;
+#if 0
+ guint8 buffer[ZBEE_SEC_CONST_BLOCKSIZE+1];
+ guint8 *key_buffer = buffer;
#endif
-
- /* Create a substree for the security information. */
+ gboolean decrypted;
+ GSList **nwk_keyring;
+ GSList *GSList_i;
+ key_record_t *key_rec = NULL;
+#endif
+ zbee_nwk_hints_t *nwk_hints;
+ ieee802154_hints_t *ieee_hints;
+ ieee802154_map_rec *map_rec = NULL;
+
+ /* Init */
+ memset(&packet, 0, sizeof(zbee_security_packet));
+
+ /* Get pointers to any useful frame data from lower layers */
+ nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK));
+ ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd,
+ proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN));
+
+ /* Create a subtree for the security information. */
if (tree) {
sec_root = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ZigBee Security Header");
sec_tree = proto_item_add_subtree(sec_root, ett_zbee_sec);
@@ -379,33 +469,38 @@ dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint o
/* Get and display the Security control field */
packet.control = tvb_get_guint8(tvb, offset);
+
/* Patch the security level. */
packet.control &= ~ZBEE_SEC_CONTROL_LEVEL;
packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level);
+
/*
* Eww, I think I just threw up a little... ZigBee requires this field
* to be patched before computing the MIC, but we don't have write-access
* to the tvbuff. So we need to allocate a copy of the whole thing just
- * so we can fix these 3 bits.
+ * so we can fix these 3 bits. Memory allocated by ep_tvb_memdup() is
+ * automatically freed before the next packet is processed.
*/
#ifdef HAVE_LIBGCRYPT
- enc_buffer = ep_tvb_memdup(tvb, 0, tvb_length(tvb));
+ enc_buffer = (guint8 *)ep_tvb_memdup(tvb, 0, tvb_length(tvb));
/*
* Override the const qualifiers and patch the security level field, we
* know it is safe to overide the const qualifiers because we just
* allocated this memory via ep_tvb_memdup().
*/
- ((guint8 *)(enc_buffer))[offset] = packet.control;
+ enc_buffer[offset] = packet.control;
#endif /* HAVE_LIBGCRYPT */
packet.level = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL);
- packet.key = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
+ packet.key_id = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
packet.nonce = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE);
if (tree) {
ti = proto_tree_add_text(sec_tree, tvb, offset, sizeof(guint8), "Security Control Field");
field_tree = proto_item_add_subtree(ti, ett_zbee_sec_control);
- proto_tree_add_uint(field_tree, hf_zbee_sec_key, tvb, offset, sizeof(guint8), packet.control & ZBEE_SEC_CONTROL_KEY);
- proto_tree_add_boolean(field_tree, hf_zbee_sec_nonce, tvb, offset, sizeof(guint8), packet.control & ZBEE_SEC_CONTROL_NONCE);
+ proto_tree_add_uint(field_tree, hf_zbee_sec_key_id, tvb, offset, sizeof(guint8),
+ packet.control & ZBEE_SEC_CONTROL_KEY);
+ proto_tree_add_boolean(field_tree, hf_zbee_sec_nonce, tvb, offset, sizeof(guint8),
+ packet.control & ZBEE_SEC_CONTROL_NONCE);
}
offset += sizeof(guint8);
@@ -417,21 +512,31 @@ dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint o
offset += sizeof(guint32);
if (packet.nonce) {
- /* Get and display the source address. */
- packet.src = tvb_get_letoh64(tvb, offset);
+ /* Get and display the source address of the device that secured this payload. */
+ packet.src64 = tvb_get_letoh64(tvb, offset);
if (tree) {
- proto_tree_add_eui64(sec_tree, hf_zbee_sec_src, tvb, offset, sizeof(guint64), packet.src);
+ proto_tree_add_eui64(sec_tree, hf_zbee_sec_src64, tvb, offset, sizeof(guint64), packet.src64);
}
offset += sizeof(guint64);
}
else {
- /* This field is required in the security decryption process, so
- * fill it in in case the higher layer provided it.
- */
- packet.src = src;
+ /* Look for a source address in hints */
+ switch ( packet.key_id ) {
+ case ZBEE_SEC_KEY_NWK:
+ /* use the ieee extended source address for NWK decryption */
+ if ( ieee_hints && (map_rec = ieee_hints->map_rec) ) packet.src64 = map_rec->addr64;
+ else if (tree) proto_tree_add_text(sec_tree, tvb, 0, 0, "Source: Unknown");
+ break;
+
+ default:
+ /* use the nwk extended source address for APS decryption */
+ if ( nwk_hints && (map_rec = nwk_hints->map_rec) ) packet.src64 = map_rec->addr64;
+ else if (tree) proto_tree_add_text(sec_tree, tvb, 0, 0, "Source: Unknown");
+ break;
+ }
}
- if (packet.key == ZBEE_SEC_KEY_NWK) {
+ if (packet.key_id == ZBEE_SEC_KEY_NWK) {
/* Get and display the key sequence number. */
packet.key_seqno = tvb_get_guint8(tvb, offset);
if (tree) {
@@ -441,7 +546,7 @@ dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint o
}
/* Determine the length of the MIC. */
- switch (packet.level){
+ switch (packet.level) {
case ZBEE_SEC_ENC:
case ZBEE_SEC_NONE:
default:
@@ -471,7 +576,8 @@ dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint o
if (mic_len) {
/* Display the MIC. */
if (tree) {
- ti = proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, tvb_length(tvb)-mic_len, mic_len, ENC_BIG_ENDIAN);
+ ti = proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_length(tvb)-mic_len),
+ mic_len, ENC_BIG_ENDIAN);
}
}
@@ -483,105 +589,118 @@ dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint o
(packet.level == ZBEE_SEC_MIC32) ||
(packet.level == ZBEE_SEC_MIC64) ||
(packet.level == ZBEE_SEC_MIC128)) {
+
/* Payload is only integrity protected. Just return the sub-tvbuff. */
return tvb_new_subset(tvb, offset, payload_len, payload_len);
}
#ifdef HAVE_LIBGCRYPT
- /* Ensure we have enough security material to decrypt this payload. */
- switch (packet.key) {
- /* Network Keys use the shared network key. */
- case ZBEE_SEC_KEY_NWK:
- if (!zbee_sec_have_nwk_key) {
- /* Without a key we can't decrypt (if we could what good would security be?)*/
- goto decrypt_failed;
- }
- if (packet.src == 0) {
- /* Without the extended source address, we can't create the nonce. */
- goto decrypt_failed;
- }
- /* The key, is the network key. */
- key_buffer = zbee_sec_nwk_key;
- break;
-
- /* Link Key might use the trust center link key. */
- case ZBEE_SEC_KEY_LINK:
- if (!zbee_sec_have_tclink_key) {
- /* Without a key we can't decrypt. */
- goto decrypt_failed;
- }
- if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){
- /* Without the extended source address, we can't create the nonce. */
- goto decrypt_failed;
- }
- else if (packet.src == 0) {
- packet.src = zbee_sec_tcaddr;
+ /* Allocate memory to decrypt the payload into. */
+ dec_buffer = (guint8 *)g_malloc(payload_len);
+
+ decrypted = FALSE;
+ if ( packet.src64 ) {
+ if (pinfo->fd->flags.visited) {
+ if ( nwk_hints ) {
+ /* Use previously found key */
+ switch ( packet.key_id ) {
+ case ZBEE_SEC_KEY_NWK:
+ if ( (key_rec = nwk_hints->nwk) ) {
+ decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
+ payload_len, mic_len, nwk_hints->nwk->key);
+ }
+ break;
+
+ default:
+ if ( (key_rec = nwk_hints->link) ) {
+ decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
+ payload_len, mic_len, nwk_hints->link->key);
+ }
+ break;
+ }
}
- key_buffer = zbee_sec_tclink_key;
- break;
-
- /* Key-Transport Key should use the trust center link key. */
- case ZBEE_SEC_KEY_TRANSPORT:
- if (!zbee_sec_have_tclink_key) {
- /* Without a key we can't decrypt. */
- goto decrypt_failed;
+ } /* ( !pinfo->fd->flags.visited ) */
+ else {
+ /* We only search for sniffed keys in the first pass,
+ * to save time, and because decrypting with keys
+ * transported in future packets is cheating */
+
+ /* Lookup NWK and link key in hash for this pan. */
+ /* This overkill approach is a placeholder for a hash that looks up
+ * a key ring for a link key associated with a pair of devices.
+ */
+ if ( nwk_hints ) {
+ nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan);
+
+ if ( nwk_keyring ) {
+ GSList_i = *nwk_keyring;
+ while ( GSList_i && !decrypted ) {
+ decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
+ payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);
+
+ if (decrypted) {
+ /* save pointer to the successful key record */
+ switch (packet.key_id) {
+ case ZBEE_SEC_KEY_NWK:
+ key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
+ break;
+
+ default:
+ key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
+ break;
+ }
+ } else {
+ GSList_i = g_slist_next(GSList_i);
+ }
+ }
+ }
}
- if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){
- /* Without the extended source address, we can't create the nonce. */
- goto decrypt_failed;
+
+ /* Loop through user's password table for preconfigured keys, our last resort */
+ GSList_i = zbee_pc_keyring;
+ while ( GSList_i && !decrypted ) {
+ decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
+ payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);
+
+ if (decrypted) {
+ /* save pointer to the successful key record */
+ switch (packet.key_id) {
+ case ZBEE_SEC_KEY_NWK:
+ key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
+ break;
+
+ default:
+ key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
+ break;
+ }
+ } else {
+ GSList_i = g_slist_next(GSList_i);
+ }
}
- else if (packet.src == 0) {
- packet.src = zbee_sec_tcaddr;
+ } /* ( ! pinfo->fd->flags.visited ) */
+ } /* ( packet.src64 ) */
+
+ if ( decrypted ) {
+ if ( tree && key_rec ) {
+ if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) {
+ ti = proto_tree_add_text(sec_tree, tvb, 0, 0, "Decryption Key: %s", key_rec->label);
+ } else {
+ ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0,
+ key_rec->frame_num);
}
- key_buffer = zbee_sec_key_hash(zbee_sec_tclink_key, 0x00, pinfo);
- break;
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
- /* Key-Load Key should use the trust center link key. */
- case ZBEE_SEC_KEY_LOAD:
- if (!zbee_sec_have_tclink_key) {
- /* Without a key we can't decrypt. */
- goto decrypt_failed;
- }
- if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){
- /* Without the extended source address, we can't create the nonce. */
- goto decrypt_failed;
- }
- else if (packet.src == 0) {
- packet.src = zbee_sec_tcaddr;
- }
- key_buffer = zbee_sec_key_hash(zbee_sec_tclink_key, 0x02, pinfo);
- break;
+ /* Found a key that worked, setup the new tvbuff_t and return */
+ payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len);
+ tvb_set_free_cb(payload_tvb, g_free); /* set up callback to free dec_buffer */
+ add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload");
- default:
- goto decrypt_failed;
- } /* switch */
-
- /* Create the nonce. */
- zbee_sec_make_nonce(nonce, &packet);
- /* Allocate memory to decrypt the payload into. */
- dec_buffer = g_malloc(payload_len);
- /* Perform Decryption. */
- if (!zbee_sec_ccm_decrypt(key_buffer, /* key */
- nonce, /* Nonce */
- enc_buffer, /* a, length l(a) */
- enc_buffer+offset, /* c, length l(c) = l(m) + M */
- dec_buffer, /* m, length l(m) */
- offset, /* l(a) */
- payload_len, /* l(m) */
- mic_len)) { /* M */
- /* Decryption Failed! */
- g_free(dec_buffer);
- goto decrypt_failed;
+ /* Done! */
+ return payload_tvb;
}
- /* Setup the new tvbuff_t and return */
- payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len);
- tvb_set_free_cb(payload_tvb, g_free);
- add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload");
- /* Done! */
- return payload_tvb;
-
-decrypt_failed:
+ g_free(dec_buffer);
#endif /* HAVE_LIBGCRYPT */
/* Add expert info. */
@@ -592,35 +711,97 @@ decrypt_failed:
call_dissector(data_handle, payload_tvb, pinfo, tree);
/* Couldn't decrypt, so return NULL. */
return NULL;
-
} /* dissect_zbee_secure */
#ifdef HAVE_LIBGCRYPT
/*FUNCTION:------------------------------------------------------
* NAME
+ * zbee_sec_decrypt_payload
+ * DESCRIPTION
+ * Creates a nonce and decrypts a secured payload.
+ * PARAMETERS
+ * gchar *nonce - Nonce Buffer.
+ * zbee_security_packet *packet - Security information.
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+static gboolean
+zbee_sec_decrypt_payload(zbee_security_packet *packet, const gchar *enc_buffer, const gchar offset, guint8 *dec_buffer,
+ guint payload_len, guint mic_len, guint8 *key)
+{
+ guint8 nonce[ZBEE_SEC_CONST_NONCE_LEN];
+ guint8 buffer[ZBEE_SEC_CONST_BLOCKSIZE+1];
+ guint8 *key_buffer = buffer;
+
+ switch (packet->key_id) {
+ case ZBEE_SEC_KEY_NWK:
+ /* Decrypt with the PAN's current network key */
+ case ZBEE_SEC_KEY_LINK:
+ /* Decrypt with the unhashed link key assigned by the trust center to this
+ * source/destination pair */
+ key_buffer = key;
+ break;
+
+ case ZBEE_SEC_KEY_TRANSPORT:
+ /* Decrypt with a Key-Transport key, a hashed link key that protects network
+ * keys sent from the trust center */
+ zbee_sec_key_hash(key, 0x00, buffer);
+ key_buffer = buffer;
+ break;
+
+ case ZBEE_SEC_KEY_LOAD:
+ /* Decrypt with a Key-Load key, a hashed link key that protects link keys
+ * sent from the trust center. */
+ zbee_sec_key_hash(key, 0x02, buffer);
+ key_buffer = buffer;
+ break;
+
+ default:
+ break;
+ } /* switch */
+
+ /* Perform Decryption. */
+ zbee_sec_make_nonce(packet, nonce);
+
+ if ( zbee_sec_ccm_decrypt(key_buffer, /* key */
+ nonce, /* Nonce */
+ enc_buffer, /* a, length l(a) */
+ enc_buffer+offset, /* c, length l(c) = l(m) + M */
+ dec_buffer, /* m, length l(m) */
+ offset, /* l(a) */
+ payload_len, /* l(m) */
+ mic_len) ) { /* M */
+ return TRUE;
+ }
+ else return FALSE;
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
* zbee_sec_make_nonce
* DESCRIPTION
* Fills in the ZigBee security nonce from the provided security
* packet structure.
* PARAMETERS
- * gchar *nonce - Nonce Buffer.
* zbee_security_packet *packet - Security information.
+ * gchar *nonce - Nonce Buffer.
* RETURNS
* void
*---------------------------------------------------------------
*/
static void
-zbee_sec_make_nonce(guint8 *nonce, zbee_security_packet *packet)
+zbee_sec_make_nonce(zbee_security_packet *packet, guint8 *nonce)
{
/* First 8 bytes are the extended source address (little endian). */
- *(nonce++) = (guint8)((packet->src)>>0 & 0xff);
- *(nonce++) = (guint8)((packet->src)>>8 & 0xff);
- *(nonce++) = (guint8)((packet->src)>>16 & 0xff);
- *(nonce++) = (guint8)((packet->src)>>24 & 0xff);
- *(nonce++) = (guint8)((packet->src)>>32 & 0xff);
- *(nonce++) = (guint8)((packet->src)>>40 & 0xff);
- *(nonce++) = (guint8)((packet->src)>>48 & 0xff);
- *(nonce++) = (guint8)((packet->src)>>56 & 0xff);
+ *(nonce++) = (guint8)((packet->src64)>>0 & 0xff);
+ *(nonce++) = (guint8)((packet->src64)>>8 & 0xff);
+ *(nonce++) = (guint8)((packet->src64)>>16 & 0xff);
+ *(nonce++) = (guint8)((packet->src64)>>24 & 0xff);
+ *(nonce++) = (guint8)((packet->src64)>>32 & 0xff);
+ *(nonce++) = (guint8)((packet->src64)>>40 & 0xff);
+ *(nonce++) = (guint8)((packet->src64)>>48 & 0xff);
+ *(nonce++) = (guint8)((packet->src64)>>56 & 0xff);
/* Next 4 bytes are the frame counter (little endian). */
*(nonce++) = (guint8)((packet->counter)>>0 & 0xff);
*(nonce++) = (guint8)((packet->counter)>>8 & 0xff);
@@ -806,7 +987,8 @@ zbee_sec_ccm_decrypt(const gchar *key, /* Input */
for (i=0;i<l_a;i++,j++) {
if (j>=ZBEE_SEC_CONST_BLOCKSIZE) {
/* Generate the next cipher block. */
- if (gcry_cipher_encrypt(cipher_hd, cipher_out, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, ZBEE_SEC_CONST_BLOCKSIZE)) {
+ if (gcry_cipher_encrypt(cipher_hd, cipher_out, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in,
+ ZBEE_SEC_CONST_BLOCKSIZE)) {
gcry_cipher_close(cipher_hd);
return FALSE;
}
@@ -824,7 +1006,8 @@ zbee_sec_ccm_decrypt(const gchar *key, /* Input */
for (i=0; i<l_m; i++, j++) {
if (j>=ZBEE_SEC_CONST_BLOCKSIZE) {
/* Generate the next cipher block. */
- if (gcry_cipher_encrypt(cipher_hd, cipher_out, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in, ZBEE_SEC_CONST_BLOCKSIZE)) {
+ if (gcry_cipher_encrypt(cipher_hd, cipher_out, ZBEE_SEC_CONST_BLOCKSIZE, cipher_in,
+ ZBEE_SEC_CONST_BLOCKSIZE)) {
gcry_cipher_close(cipher_hd);
return FALSE;
}
@@ -976,15 +1159,15 @@ zbee_sec_hash(guint8 *input, guint input_len, guint8 *output)
* PARAMETERS
* guint8 *key - ZigBee Security Key (must be ZBEE_SEC_CONST_KEYSIZE) in length.
* guint8 input - ZigBee CCM* Nonce (must be ZBEE_SEC_CONST_NONCE_LEN) in length.
+ * packet_info *pinfo - pointer to packet information fields
* RETURNS
* guint8*
*---------------------------------------------------------------
*/
static guint8 *
-zbee_sec_key_hash(guint8 *key, guint8 input, packet_info *pinfo _U_)
+zbee_sec_key_hash(guint8 *key, guint8 input, guint8 *hash_out)
{
guint8 hash_in[2*ZBEE_SEC_CONST_BLOCKSIZE];
- guint8 * hash_out = ep_alloc(ZBEE_SEC_CONST_BLOCKSIZE+1);
int i;
static const guint8 ipad = 0x36;
static const guint8 opad = 0x5c;
@@ -1004,3 +1187,36 @@ zbee_sec_key_hash(guint8 *key, guint8 input, packet_info *pinfo _U_)
return hash_out;
} /* zbee_sec_key_hash */
#endif /* HAVE_LIBGCRYPT */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_init_zbee_security
+ * DESCRIPTION
+ * Init routine for the
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+static void
+proto_init_zbee_security(void)
+{
+ guint i;
+ key_record_t key_record;
+
+ /* empty the key ring */
+ if (zbee_pc_keyring) {
+ g_slist_free(zbee_pc_keyring);
+ zbee_pc_keyring = NULL;
+ }
+
+ /* Load the pre-configured slist from the UAT. */
+ for (i=0; (uat_key_records) && (i<num_uat_key_records) ; i++) {
+ key_record.frame_num = ZBEE_SEC_PC_KEY; /* means it's a user PC key */
+ key_record.label = se_strdup(uat_key_records[i].label);
+ memcpy(&key_record.key, &uat_key_records[i].key, ZBEE_SEC_CONST_KEYSIZE);
+
+ zbee_pc_keyring = g_slist_prepend(zbee_pc_keyring, se_memdup(&key_record, sizeof(key_record_t)));
+ } /* for */
+} /* proto_init_zbee_security */
diff --git a/epan/dissectors/packet-zbee-security.h b/epan/dissectors/packet-zbee-security.h
index 257de8302c..6f776e7b09 100644
--- a/epan/dissectors/packet-zbee-security.h
+++ b/epan/dissectors/packet-zbee-security.h
@@ -30,13 +30,13 @@
/* Structure containing the fields stored in the Aux Header */
typedef struct{
/* The fields of the Aux Header */
- guint8 control;
- guint32 counter;
- guint64 src;
+ guint8 control; /* needed to decrypt */
+ guint32 counter; /* needed to decrypt */
+ guint64 src64; /* needed to decrypt */
guint8 key_seqno;
guint8 level;
- guint8 key;
+ guint8 key_id; /* needed to decrypt */
gboolean nonce;
} zbee_security_packet;
@@ -64,7 +64,6 @@ typedef struct{
/* ZigBee Security Constants. */
#define ZBEE_SEC_CONST_L 2
#define ZBEE_SEC_CONST_NONCE_LEN (ZBEE_SEC_CONST_BLOCKSIZE-ZBEE_SEC_CONST_L-1)
-#define ZBEE_SEC_CONST_KEYSIZE 16
#define ZBEE_SEC_CONST_BLOCKSIZE 16
/* CCM* Flags */
@@ -72,11 +71,14 @@ typedef struct{
#define ZBEE_SEC_CCM_FLAG_M(m) ((((m-2)/2) & 0x7)<<3) /* 3-bit encoding of (M-2)/2 shifted 3 bits. */
#define ZBEE_SEC_CCM_FLAG_ADATA(l_a) ((l_a>0)?0x40:0x00) /* Adata flag. */
+/* Program Constants */
+#define ZBEE_SEC_PC_KEY 0
+
/* Init routine for the Security dissectors. */
extern void zbee_security_register (module_t *module, int proto);
extern void zbee_security_handoff (void);
/* Security Dissector Routine. */
-extern tvbuff_t *dissect_zbee_secure(tvbuff_t *, packet_info *, proto_tree *, guint, guint64);
+extern tvbuff_t *dissect_zbee_secure(tvbuff_t *, packet_info *, proto_tree *, guint);
#endif /* PACKET_ZBEE_SECURITY_H */
diff --git a/epan/dissectors/packet-zbee.h b/epan/dissectors/packet-zbee.h
index 2e0f11af79..e7aded465f 100644
--- a/epan/dissectors/packet-zbee.h
+++ b/epan/dissectors/packet-zbee.h
@@ -27,7 +27,7 @@
#define PACKET_ZBEE_H
/* IEEE 802.15.4 definitions. */
-#include <epan/dissectors/packet-ieee802154.h>
+#include "packet-ieee802154.h"
/* The ZigBee Broadcast Address */
#define ZBEE_BCAST_ALL 0xffff
@@ -576,10 +576,12 @@
#define ZBEE_MFG_KAGA "Kaga Electronics"
#define ZBEE_MFG_4_NOKS "4-noks s.r.l."
+/* Protocol Abbreviations */
+#define ZBEE_PROTOABBREV_NWK "zbee.nwk"
+#define ZBEE_PROTOABBREV_APS "zbee.aps"
+#define ZBEE_PROTOABBREV_APF "zbee.apf"
+
/* Helper Functions */
-extern proto_item *proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
- gint length, gint64 value);
extern guint zbee_get_bit_field(guint input, guint mask);
#endif /* PACKET_ZBEE_H */
-