Back out 34627 and friends again.

svn path=/trunk/; revision=34633
This commit is contained in:
Anders Broman 2010-10-24 15:22:44 +00:00
parent 2ccfd848fe
commit b1e852cf70
10 changed files with 691 additions and 1375 deletions

View File

@ -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->src64);
addr = pntoh64(&packet->src.addr64);
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->src16, ifcid);
lowpan_addr16_to_ifcid(packet->src.addr16, 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->dst64);
addr = pntoh64(&packet->dst.addr64);
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->dst16, ifcid);
lowpan_addr16_to_ifcid(packet->dst.addr16, ifcid);
return TRUE;
}

View File

@ -90,11 +90,6 @@
#include "packet-ieee802154.h"
#include "packet-frame.h" /* For Exception Handling */
/* Forward declarations */
static gboolean ieee802154_short_addr_invalidate(guint16, guint16, guint);
static gboolean ieee802154_long_addr_invalidate(guint64, guint);
/* Dissection Options for dissect_ieee802154_common */
#define DISSECT_IEEE802154_OPTION_CC24xx 0x00000001 /* FCS field contains a TI CC24xx style FCS. */
#define DISSECT_IEEE802154_OPTION_LINUX 0x00000002 /* Addressing fields are padded DLT_IEEE802_15_4_LINUX, not implemented. */
@ -105,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 ok before payload is dissected */
/* boolean value set if the FCS must be oke before data is dissected */
static gboolean ieee802154_fcs_ok = TRUE;
/* User string with the decryption key. */
@ -114,10 +109,56 @@ static gboolean ieee802154_key_valid;
static guint8 ieee802154_key[IEEE802154_CIPHER_SIZE];
/*-------------------------------------
* Address Hash Tables
* Address Hash Table
*-------------------------------------
*/
static ieee802154_addr_t ieee802154_addr = { 0, NULL, NULL };
static GHashTable * ieee802154_addr_table = NULL;
/* Value used for the hash table. */
typedef struct {
guint64 addr;
/*guint32 frame_counter; TODO for frame counter sequence checks. Any other security state to save across packets? */
} ieee802154_long_addr;
/* Keys used for the hash table. */
typedef struct {
guint16 addr;
guint16 pan;
} ieee802154_short_addr;
/* Key hash function. */
static guint
ieee802154_addr_hash(gconstpointer key)
{
return (((ieee802154_short_addr *)key)->addr) | (((ieee802154_short_addr *)key)->pan << 16);
}
/* Key equals function. */
static gboolean
ieee802154_addr_equals(gconstpointer a, gconstpointer b)
{
return (((ieee802154_short_addr *)a)->addr == ((ieee802154_short_addr *)b)->addr) &&
(((ieee802154_short_addr *)a)->pan == ((ieee802154_short_addr *)b)->pan);
}
/* Function to update the address table. */
/* TODO: Make this a public function, in case other layers expose short-to-extended address pairs. */
static void ieee802154_addr_update(guint16 short_addr, guint16 pan, guint64 long_addr)
{
ieee802154_short_addr addr16;
ieee802154_long_addr * addr64;
addr16.addr = short_addr;
addr16.pan = pan;
addr64 = g_hash_table_lookup(ieee802154_addr_table, &addr16);
if (addr64) {
addr64->addr = long_addr;
}
else {
addr64 = se_alloc(sizeof(ieee802154_long_addr));
addr64->addr = long_addr;
g_hash_table_insert(ieee802154_addr_table, se_memdup(&addr16, sizeof(addr16)), addr64);
}
} /* ieee802154_addr_update */
/*-------------------------------------
* Static Address Mapping UAT
@ -151,7 +192,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 length";
*err = "Invalid EUI-64";
}
} /* ieee802154_addr_uat_update_cb */
@ -202,11 +243,10 @@ 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 *, 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 *);
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);
/* Initialize Protocol and Registered fields */
static int proto_ieee802154_nonask_phy = -1;
@ -228,9 +268,8 @@ 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_src16 = -1;
static int hf_ieee802154_src64 = -1;
static int hf_ieee802154_src64_origin = -1;
static int hf_ieee802154_src_addr16 = -1;
static int hf_ieee802154_src_addr64 = -1;
static int hf_ieee802154_fcs = -1;
static int hf_ieee802154_rssi = -1;
static int hf_ieee802154_fcs_ok = -1;
@ -470,9 +509,8 @@ dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee
packet->src_addr_mode = (fcf & IEEE802154_FCF_SADDR_MASK) >> 14;
/* Display the frame type. */
if (tree)
proto_item_append_text(tree, " %s", val_to_str(packet->frame_type, ieee802154_frame_types, "Reserved"));
col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
if (tree) proto_item_append_text(tree, " %s", val_to_str(packet->frame_type, ieee802154_frame_types, "Reserved"));
if (check_col(pinfo->cinfo, COL_INFO)) col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
/* Add the FCF to the protocol tree. */
if (tree) {
@ -530,9 +568,11 @@ dissect_ieee802154_nonask_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre
/* Add the protocol name. */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 non-ASK PHY");
/* Add the packet length. */
col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
if(check_col(pinfo->cinfo, COL_PACKET_LENGTH)){
col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
}
preamble=tvb_get_letohl(tvb,offset);
sfd=tvb_get_guint8(tvb,offset+4);
phr=tvb_get_guint8(tvb,offset+4+1);
@ -664,36 +704,23 @@ 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;
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;
guint offset = 0;
volatile gboolean fcs_ok = TRUE;
const char *saved_proto;
ieee802154_packet *packet = ep_alloc(sizeof(ieee802154_packet));
ws_decrypt_status status;
/* 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");
@ -702,8 +729,10 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
/* Add the protocol name. */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4");
/* Add the packet length. */
col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
if(check_col(pinfo->cinfo, COL_PACKET_LENGTH)){
col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
}
/*=====================================================
* FRAME CONTROL FIELD
@ -753,25 +782,20 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
gchar *dst_addr = ep_alloc(32);
/* Get the address. */
packet->dst16 = tvb_get_letohs(tvb, offset);
packet->dst.addr16 = tvb_get_letohs(tvb, offset);
/* Display the destination address. */
if ( packet->dst16 == IEEE802154_BCAST_ADDR ) {
g_snprintf(dst_addr, 32, "Broadcast");
}
else {
g_snprintf(dst_addr, 32, "0x%04x", packet->dst16);
}
if(packet->dst.addr16==IEEE802154_BCAST_ADDR) g_snprintf(dst_addr, 32, "Broadcast");
else g_snprintf(dst_addr, 32, "0x%04x", packet->dst.addr16);
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->dst16);
proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_addr16, tvb, offset, 2, packet->dst.addr16);
proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
}
col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
}
offset += 2;
}
else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
@ -780,14 +804,14 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
gchar *dst, *dst_oui;
/* Get the address */
packet->dst64 = tvb_get_letoh64(tvb, offset);
packet->dst.addr64 = tvb_get_letoh64(tvb, offset);
/* print the address strings. */
dst = print_eui64(packet->dst64);
dst_oui = print_eui64_oui(packet->dst64);
dst = print_eui64(packet->dst.addr64);
dst_oui = print_eui64_oui(packet->dst.addr64);
/* Copy and convert the address to network byte order. */
*(guint64 *)(addr) = pntoh64(&(packet->dst64));
*(guint64 *)(addr) = pntoh64(&(packet->dst.addr64));
/* Display the destination address. */
/* NOTE: OUI resolution doesn't happen when displaying EUI64 addresses
@ -797,12 +821,12 @@ 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->dst64, "%s (%s)", dst_oui, dst);
proto_tree_add_uint64_format_value(ieee802154_tree, hf_ieee802154_dst_addr64, tvb, offset, 8, packet->dst.addr64, "%s (%s)", dst_oui, dst);
proto_item_append_text(proto_root, ", Dst: %s", dst_oui);
}
col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_oui);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_oui);
}
offset += 8;
}
else if (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) {
@ -819,8 +843,7 @@ 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. */
ieee_hints->src_pan = packet->src_pan = tvb_get_letohs(tvb, offset);
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);
}
@ -828,64 +851,31 @@ 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. */
ieee_hints->src_pan = packet->src_pan = packet->dst_pan;
packet->src_pan = packet->dst_pan;
}
/* Get short source address if present. */
/* Get 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->src16 = tvb_get_letohs(tvb, offset);
packet->src.addr16 = tvb_get_letohs(tvb, offset);
/* Update the Address fields. */
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);
}
}
}
if(packet->src.addr16==IEEE802154_BCAST_ADDR) g_snprintf(src_addr, 32, "Broadcast");
else g_snprintf(src_addr, 32, "0x%04x", packet->src.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_src16, tvb, offset, 2, packet->src16);
proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_addr16, tvb, offset, 2, packet->src.addr16);
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);
}
}
col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
}
offset += 2;
}
else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
@ -894,14 +884,14 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
gchar *src, *src_oui;
/* Get the address. */
packet->src64 = tvb_get_letoh64(tvb, offset);
packet->src.addr64 = tvb_get_letoh64(tvb, offset);
/* Print the address strings. */
src = print_eui64(packet->src64);
src_oui = print_eui64_oui(packet->src64);
src = print_eui64(packet->src.addr64);
src_oui = print_eui64_oui(packet->src.addr64);
/* Copy and convert the address to network byte order. */
*(guint64 *)(addr) = pntoh64(&(packet->src64));
*(guint64 *)(addr) = pntoh64(&(packet->src.addr64));
/* Display the source address. */
/* NOTE: OUI resolution doesn't happen when displaying EUI64 addresses
@ -911,12 +901,12 @@ 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_src64, tvb, offset,
8, packet->src64, "%s (%s)", src_oui, src);
proto_tree_add_uint64_format_value(ieee802154_tree, hf_ieee802154_src_addr64, tvb, offset, 8, packet->src.addr64, "%s (%s)", src_oui, src);
proto_item_append_text(proto_root, ", Src: %s", src_oui);
}
col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_oui);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_oui);
}
offset += 8;
}
else if (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) {
@ -955,14 +945,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 auxiliary header. */
guint aux_length = 5; /* Minimum length of the auxilliary 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 auxiliary header and create a subtree. */
/* Compute the length of the auxilliar 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;
@ -1029,7 +1019,9 @@ dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, g
offset++;
/* Display the command identifier in the info column. */
col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
if(check_col(pinfo->cinfo, COL_INFO)) {
col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
}
}
/* No other frame types have nonpayload fields. */
@ -1169,7 +1161,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->dst16 == IEEE802154_BCAST_ADDR) &&
(packet->dst.addr16 == IEEE802154_BCAST_ADDR) &&
(packet->src_pan == IEEE802154_BCAST_PAN) &&
(packet->dst_pan == IEEE802154_BCAST_PAN));
/* No payload expected. */
@ -1179,7 +1171,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->dst16 == IEEE802154_BCAST_ADDR) &&
(packet->dst.addr16 == IEEE802154_BCAST_ADDR) &&
(packet->dst_pan == IEEE802154_BCAST_PAN));
/* No payload expected. */
break;
@ -1191,7 +1183,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->dst16 == IEEE802154_BCAST_ADDR);
IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id, packet->dst.addr16 == IEEE802154_BCAST_ADDR);
}
dissect_ieee802154_realign(payload_tvb, pinfo, ieee802154_tree, packet);
break;
@ -1201,8 +1193,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->src16 != IEEE802154_BCAST_ADDR) &&
(packet->src16 != IEEE802154_NO_ADDR16));
(packet->src.addr16 != IEEE802154_BCAST_ADDR) &&
(packet->src.addr16 != IEEE802154_NO_ADDR16));
dissect_ieee802154_gtsreq(payload_tvb, pinfo, ieee802154_tree, packet);
break;
@ -1545,8 +1537,7 @@ 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);
}
@ -1569,24 +1560,25 @@ dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
offset += 1;
/* Update the info column. */
if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
/* Association was successful. */
if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->dst_pan);
if (check_col(pinfo->cinfo, COL_INFO)) {
if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
/* Association was successful. */
if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->dst_pan);
}
if (short_addr != IEEE802154_NO_ADDR16) {
col_append_fstr(pinfo->cinfo, COL_INFO, " Addr: 0x%04x", short_addr);
}
}
if (short_addr != IEEE802154_NO_ADDR16) {
col_append_fstr(pinfo->cinfo, COL_INFO, " Addr: 0x%04x", short_addr);
else {
/* Association was unsuccessful. */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Unsuccessful");
}
}
else {
/* Association was unsuccessful. */
col_append_fstr(pinfo->cinfo, COL_INFO, ", Unsuccessful");
}
/* Update the address table. */
if ((status == IEEE802154_CMD_ASRSP_AS_SUCCESS) && (short_addr != IEEE802154_NO_ADDR16)) {
ieee802154_addr_update(&ieee802154_addr, short_addr, packet->dst_pan, packet->dst64,
proto_ieee802154, pinfo->fd->num);
ieee802154_addr_update(short_addr, packet->dst_pan, packet->dst.addr64);
}
/* Call the data dissector for any leftover bytes. */
@ -1622,7 +1614,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 disassociation reason. */
/* Get and display the dissasociation reason. */
reason = tvb_get_guint8(tvb, 0);
if (tree) {
ti = proto_tree_add_uint(subtree, hf_ieee802154_disassoc_reason, tvb, 0, 1, reason);
@ -1641,15 +1633,6 @@ 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);
@ -1690,45 +1673,40 @@ dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* Get and display the command PAN ID. */
pan_id = tvb_get_letohs(tvb, offset);
if (tree)
proto_tree_add_uint(subtree, hf_ieee802154_realign_pan, tvb, offset, 2, pan_id);
col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", pan_id);
if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_pan, tvb, offset, 2, pan_id);
if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", pan_id);
offset += 2;
/* Get and display the coordinator address. */
coord_addr = tvb_get_letohs(tvb, offset);
if (tree)
proto_tree_add_uint(subtree, hf_ieee802154_realign_caddr, tvb, offset, 2, coord_addr);
col_append_fstr(pinfo->cinfo, COL_INFO, ", Coordinator: 0x%04x", coord_addr);
if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_caddr, tvb, offset, 2, coord_addr);
if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, ", Coordinator: 0x%04x", coord_addr);
offset += 2;
/* Get and display the channel. */
channel = tvb_get_guint8(tvb, offset);
if (tree)
proto_tree_add_uint(subtree, hf_ieee802154_realign_channel, tvb, offset, 1, channel);
col_append_fstr(pinfo->cinfo, COL_INFO, ", Channel: %u", channel);
if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_channel, tvb, offset, 1, channel);
if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, ", Channel: %u", channel);
offset += 1;
/* Get and display the short address. */
short_addr = tvb_get_letohs(tvb, offset);
if (tree)
proto_tree_add_uint(subtree, hf_ieee802154_realign_addr, tvb, offset, 2, short_addr);
if ( (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_addr, tvb, offset, 2, short_addr);
if ( (check_col(pinfo->cinfo, COL_INFO))
&& (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
&& (short_addr != IEEE802154_NO_ADDR16)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Addr: 0x%04x", short_addr);
}
offset += 2;
/* Update the address table. */
if ((short_addr != IEEE802154_NO_ADDR16) && (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) {
ieee802154_addr_update(&ieee802154_addr, short_addr, packet->dst_pan, packet->dst64,
proto_ieee802154, pinfo->fd->num);
ieee802154_addr_update(short_addr, packet->dst_pan, packet->dst.addr64);
}
/* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
if (tvb_bytes_exist(tvb, offset, 1)) {
guint8 channel_page = tvb_get_guint8(tvb, offset);
if (tree)
proto_tree_add_uint(subtree, hf_ieee802154_realign_channel_page, tvb, offset, 1, channel_page);
if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_channel_page, tvb, offset, 1, channel_page);
offset += 1;
}
@ -1774,8 +1752,7 @@ 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);
}
@ -1835,9 +1812,6 @@ 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;
@ -1881,14 +1855,26 @@ 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->src64;
srcAddr = packet->src.addr64;
}
else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
/* Use the hint */
srcAddr = ieee_hints->map_rec->addr64;
else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
ieee802154_short_addr addr16;
ieee802154_long_addr * addr64;
/* Try to lookup the EUI-64 from the address table. */
addr16.addr = packet->src.addr16;
addr16.pan = packet->src_pan;
addr64 = (ieee802154_long_addr *)g_hash_table_lookup(ieee802154_addr_table, &addr16);
if (!addr64) {
/* Lookup failed. */
*status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
return NULL;
}
/* Lookup successful. */
srcAddr = addr64->addr;
}
else {
/* Lookup failed. */
/* No addressing is present in the headers. We're screwed. */
*status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
return NULL;
}
@ -2208,177 +2194,6 @@ 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
*---------------------------------------------------------------
*/
static 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
*---------------------------------------------------------------
*/
static 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
@ -2405,14 +2220,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,
@ -2435,12 +2250,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,
@ -2462,16 +2277,12 @@ void proto_register_ieee802154(void)
{ "Source PAN", "wpan.src_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
{ &hf_ieee802154_src16,
{ "Source", "wpan.src16", FT_UINT16, BASE_HEX, NULL, 0x0,
{ &hf_ieee802154_src_addr16,
{ "Source", "wpan.src_addr16", 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_src64_origin,
{ "Origin", "wpan.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
{ &hf_ieee802154_src_addr64,
{ "Source", "wpan.src_addr64", FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
{ &hf_ieee802154_fcs,
@ -2575,8 +2386,7 @@ 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,
@ -2618,12 +2428,11 @@ 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,
@ -2678,10 +2487,8 @@ 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",
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");
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");
/* Register header fields and subtrees. */
proto_register_field_array(proto_ieee802154, hf, array_length(hf));
@ -2691,7 +2498,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.",
@ -2701,8 +2508,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 only good FCS",
"Dissect payload only if FCS is valid.",
"Dissect data only if FCS is ok",
"Dissect data only if FCS is ok.",
&ieee802154_fcs_ok);
/* Create a UAT for static address mappings. */
@ -2730,10 +2537,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(IEEE802154_PROTOABBREV_WPAN, &ieee802154_heur_subdissector_list);
register_heur_dissector_list("wpan", &ieee802154_heur_subdissector_list);
/* Register dissectors with Wireshark. */
register_dissector(IEEE802154_PROTOABBREV_WPAN, dissect_ieee802154, proto_ieee802154);
register_dissector("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);
@ -2764,7 +2571,7 @@ void proto_reg_handoff_ieee802154(void)
if (!prefs_initialized){
/* Get the dissector handles. */
ieee802154_handle = find_dissector(IEEE802154_PROTOABBREV_WPAN);
ieee802154_handle = find_dissector("wpan");
ieee802154_nonask_phy_handle = find_dissector("wpan-nonask-phy");
ieee802154_nofcs_handle = find_dissector("wpan_nofcs");
data_handle = find_dissector("data");
@ -2797,9 +2604,9 @@ void proto_reg_handoff_ieee802154(void)
* NAME
* proto_init_ieee802154
* DESCRIPTION
* 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
* Init routine for the IEEE 802.15.4 dissector. Creates a
* hash table for mapping 16-bit to 64-bit addresses and
* populates it with static address pairs from a UAT
* preference table.
* PARAMETERS
* none
@ -2812,17 +2619,16 @@ proto_init_ieee802154(void)
{
guint i;
/* 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);
/* Destroy the hash table, if it exists. */
if (ieee802154_addr_table)
g_hash_table_destroy(ieee802154_addr_table);
/* 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)create the hash table. */
ieee802154_addr_table = g_hash_table_new(ieee802154_addr_hash, ieee802154_addr_equals);
/* Re-load the hash table from the static address UAT. */
for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
ieee802154_addr_update(&ieee802154_addr,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
pntoh64(static_addrs[i].eui64), proto_ieee802154, IEEE802154_USER_MAPPING);
ieee802154_addr_update((guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan, pntoh64(static_addrs[i].eui64));
} /* for */
} /* proto_init_ieee802154 */

View File

@ -27,9 +27,6 @@
#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
@ -51,7 +48,7 @@
#define IEEE802154_CMD_ASRSP_PAN_FULL 0x01
#define IEEE802154_CMD_ASRSP_PAN_DENIED 0x02
/* Bit Masks for Capability Information Field
/* Bit Masks for Capability Information Feild
Included in Association Req. command */
#define IEEE802154_CMD_CINFO_ALT_PAN_COORD 0x01
#define IEEE802154_CMD_CINFO_DEVICE_TYPE 0x02
@ -102,7 +99,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 /* known as PAN ID Compression in IEEE 802.15.4-2006 */
#define IEEE802154_FCF_INTRA_PAN 0x0040
#define IEEE802154_FCF_DADDR_MASK 0x0C00 /* destination addressing mask */
#define IEEE802154_FCF_VERSION 0x3000
#define IEEE802154_FCF_SADDR_MASK 0xC000 /* source addressing mask */
@ -167,7 +164,7 @@ typedef enum {
/* Macro to check for payload encryption. */
#define IEEE802154_IS_ENCRYPTED(_level_) ((_level_) & 0x4)
/* Structure containing information regarding all necessary packet fields. */
/* Structure containing information regarding all necessary packet feilds. */
typedef struct {
/* Frame control field. */
gint32 version;
@ -183,11 +180,15 @@ typedef struct {
/* Addressing Info. */
guint16 dst_pan;
union {
guint16 addr16;
guint64 addr64;
} dst;
guint16 src_pan;
guint16 dst16;
guint64 dst64;
guint16 src16;
guint64 src64;
union {
guint16 addr16;
guint64 addr64;
} src;
/* Security Info. */
ieee802154_security_level security_level;
@ -201,47 +202,11 @@ 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 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 gchar *print_eui64(guint64);
extern gchar *print_eui64_oui(guint64);
#endif /* PACKET_IEEE802154_H */

View File

@ -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,8 +67,6 @@ 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);
/********************
* Global Variables *
********************
@ -78,7 +76,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_format = -1; /* ZigBee 2007 and later. */
static int hf_zbee_aps_fcf_ack_mode = -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;
@ -167,7 +165,6 @@ static const fragment_items zbee_aps_frag_items = {
/* Tag */
"APS Message fragments"
};
/********************/
/* Field Names */
/********************/
@ -541,7 +538,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_info *pinfo - pointer to packet information fields
* packet_into *pinfo - pointer to packet information fields
* proto_tree *tree - pointer to data tree Wireshark uses to display packet.
* RETURNS
* void
@ -580,7 +577,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_format = zbee_get_bit_field(fcf, ZBEE_APS_FCF_ACK_FORMAT);
packet.ack_mode = zbee_get_bit_field(fcf, ZBEE_APS_FCF_ACK_MODE);
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);
@ -606,7 +603,7 @@ 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_format, tvb, offset, sizeof(guint8), fcf & ZBEE_APS_FCF_ACK_FORMAT);
proto_tree_add_boolean(field_tree, hf_zbee_aps_fcf_ack_mode, tvb, offset, sizeof(guint8), fcf & ZBEE_APS_FCF_ACK_MODE);
}
}
else {
@ -630,7 +627,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_format)) {
if ((pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) && (packet.ack_mode)) {
/* Command Ack: endpoint addressing does not exist. */
goto dissect_zbee_aps_no_endpt;
}
@ -722,17 +719,17 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset += sizeof(guint8);
}
/* Get and display the profile ID. */
/* Get and display the profile ID if it exists. */
packet.profile = tvb_get_letohs(tvb, offset);
profile_handle = dissector_get_port_handle(zbee_aps_dissector_table, packet.profile);
if (tree) {
ti = proto_tree_add_uint(aps_tree, hf_zbee_aps_profile, tvb, offset, sizeof(guint16),
packet.profile);
offset += sizeof(guint16);
/* 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)) {
@ -765,6 +762,7 @@ dissect_zbee_aps_no_endpt:
offset += sizeof(guint8);
}
/* Get and display the extended header, if present. */
if (packet.ext_header) {
fcf = tvb_get_guint8(tvb, offset);
@ -1073,8 +1071,9 @@ dissect_zbee_aps_skke_challenge(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre
offset += sizeof(guint64);
/* Get and display the SKKE data. */
tvb_ensure_bytes_exist(tvb, offset, ZBEE_APS_CMD_SKKE_DATA_LENGTH);
if (tree) {
proto_tree_add_item(tree, hf_zbee_aps_cmd_challenge, tvb, offset, ZBEE_APS_CMD_SKKE_DATA_LENGTH, ENC_BIG_ENDIAN);
proto_tree_add_bytes(tree, hf_zbee_aps_cmd_challenge, tvb, offset, ZBEE_APS_CMD_SKKE_DATA_LENGTH, ep_tvb_memdup(tvb, offset, ZBEE_APS_CMD_SKKE_DATA_LENGTH));
}
offset += ZBEE_APS_CMD_SKKE_DATA_LENGTH;
@ -1118,8 +1117,9 @@ dissect_zbee_aps_skke_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr
offset += sizeof(guint64);
/* Get and display the SKKE data. */
tvb_ensure_bytes_exist(tvb, offset, ZBEE_APS_CMD_SKKE_DATA_LENGTH);
if (tree) {
proto_tree_add_item(tree, hf_zbee_aps_cmd_mac, tvb, offset, ZBEE_APS_CMD_SKKE_DATA_LENGTH, ENC_BIG_ENDIAN);
proto_tree_add_bytes(tree, hf_zbee_aps_cmd_mac, tvb, offset, ZBEE_APS_CMD_SKKE_DATA_LENGTH, ep_tvb_memdup(tvb, offset, ZBEE_APS_CMD_SKKE_DATA_LENGTH));
}
offset += ZBEE_APS_CMD_SKKE_DATA_LENGTH;
@ -1144,12 +1144,9 @@ 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;
guint8 key[ZBEE_APS_CMD_KEY_LENGTH];
GSList **nwk_keyring;
key_record_t key_record;
zbee_nwk_hints_t *nwk_hints;
guint i;
guint8 key_type;
gchar *key = ep_alloc(ZBEE_APS_CMD_KEY_LENGTH);
guint i;
/* Get and display the key type. */
key_type = tvb_get_guint8(tvb, offset);
@ -1161,46 +1158,21 @@ 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++) {
key[i] = tvb_get_guint8(tvb, offset+i);
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 */
if (tree) {
proto_tree_add_item(tree, hf_zbee_aps_cmd_key, tvb, offset, ZBEE_APS_CMD_KEY_LENGTH, ENC_BIG_ENDIAN);
proto_tree_add_bytes(tree, hf_zbee_aps_cmd_key, tvb, offset, ZBEE_APS_CMD_KEY_LENGTH, key);
}
offset += ZBEE_APS_CMD_KEY_LENGTH;
/* Update the key ring for this pan */
if ( !pinfo->fd->flags.visited &&
(nwk_hints = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK)))) {
nwk_keyring = 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 = 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;
@ -1257,7 +1229,7 @@ dissect_zbee_aps_transport_key(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
guint64 partner;
guint8 initiator;
/* get and display the partner address. */
/* get and display the parter address. */
partner = tvb_get_letoh64(tvb, offset);
if (tree) {
proto_tree_add_eui64(tree, hf_zbee_aps_cmd_partner, tvb, offset, sizeof(guint64), partner);
@ -1483,8 +1455,9 @@ dissect_zbee_aps_auth_challenge(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre
offset += sizeof(guint64);
/* Get and display the challenge. */
tvb_ensure_bytes_exist(tvb, offset, ZBEE_APS_CMD_EA_CHALLENGE_LENGTH);
if (tree) {
proto_tree_add_item(tree, hf_zbee_aps_cmd_challenge, tvb, offset, ZBEE_APS_CMD_EA_CHALLENGE_LENGTH, ENC_BIG_ENDIAN);
proto_tree_add_bytes(tree, hf_zbee_aps_cmd_challenge, tvb, offset, ZBEE_APS_CMD_EA_CHALLENGE_LENGTH, ep_tvb_memdup(tvb, offset, ZBEE_APS_CMD_EA_CHALLENGE_LENGTH));
}
offset += ZBEE_APS_CMD_EA_CHALLENGE_LENGTH;
@ -1513,8 +1486,9 @@ dissect_zbee_aps_auth_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr
guint8 data_type;
/* Get and display the MAC. */
tvb_ensure_bytes_exist(tvb, offset, ZBEE_APS_CMD_EA_MAC_LENGTH);
if (tree) {
proto_tree_add_item(tree, hf_zbee_aps_cmd_mac, tvb, offset, ZBEE_APS_CMD_EA_MAC_LENGTH, ENC_BIG_ENDIAN);
proto_tree_add_bytes(tree, hf_zbee_aps_cmd_mac, tvb, offset, ZBEE_APS_CMD_EA_MAC_LENGTH, ep_tvb_memdup(tvb, offset, ZBEE_APS_CMD_EA_MAC_LENGTH));
}
offset += ZBEE_APS_CMD_EA_MAC_LENGTH;
@ -1532,8 +1506,9 @@ dissect_zbee_aps_auth_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tr
offset += sizeof(guint8);
/* Get and display the data field. */
tvb_ensure_bytes_exist(tvb, offset, ZBEE_APS_CMD_EA_DATA_LENGTH);
if (tree) {
proto_tree_add_item(tree, hf_zbee_aps_cmd_ea_data, tvb, offset, ZBEE_APS_CMD_EA_DATA_LENGTH, ENC_BIG_ENDIAN);
proto_tree_add_bytes(tree, hf_zbee_aps_cmd_ea_data, tvb, offset, ZBEE_APS_CMD_EA_DATA_LENGTH, ep_tvb_memdup(tvb, offset, ZBEE_APS_CMD_EA_DATA_LENGTH));
}
offset += ZBEE_APS_CMD_EA_DATA_LENGTH;
@ -1570,8 +1545,7 @@ 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);
@ -1611,8 +1585,7 @@ static void dissect_zbee_apf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
/* 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);
}
@ -1744,6 +1717,24 @@ zbee_apf_transaction_len(tvbuff_t *tvb, guint offset, guint8 type)
}
} /* zbee_apf_transaction_len */
/*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
@ -1770,8 +1761,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_format,
{ "Acknowledgement Format", "zbee.aps.ack_format", FT_BOOLEAN, 8, NULL, ZBEE_APS_FCF_ACK_FORMAT,
{ &hf_zbee_aps_fcf_ack_mode,
{ "Acknowledgement Mode", "zbee.aps.ack_mode", FT_BOOLEAN, 8, NULL, ZBEE_APS_FCF_ACK_MODE,
NULL, HFILL }},
{ &hf_zbee_aps_fcf_security,
@ -1950,24 +1941,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_PROTOABBREV_APS);
proto_zbee_aps = proto_register_protocol("ZigBee Application Support Layer", "ZigBee APS", "zbee.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_PROTOABBREV_APS, dissect_zbee_aps, proto_zbee_aps);
register_dissector("zbee.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_PROTOABBREV_APF);
proto_zbee_apf = proto_register_protocol("ZigBee Application Framework", "ZigBee APF", "zbee.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_PROTOABBREV_APF, dissect_zbee_apf, proto_zbee_apf);
register_dissector("zbee.apf", dissect_zbee_apf, proto_zbee_apf);
} /* proto_register_zbee_aps */
/*FUNCTION:------------------------------------------------------
@ -1985,25 +1976,7 @@ void proto_reg_handoff_zbee_aps(void)
{
/* Find the other dissectors we need. */
data_handle = find_dissector("data");
zbee_aps_handle = find_dissector(ZBEE_PROTOABBREV_APS);
zbee_apf_handle = find_dissector(ZBEE_PROTOABBREV_APF);
zbee_aps_handle = find_dissector("zbee.aps");
zbee_apf_handle = find_dissector("zbee.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 */

View File

@ -27,11 +27,39 @@
#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_FORMAT 0x10 /* ZigBee 2007 and later. */
#define ZBEE_APS_FCF_ACK_MODE 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
@ -206,32 +234,4 @@
#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*/

View File

@ -40,10 +40,9 @@
#include <epan/expert.h>
#include <epan/value_string.h>
#include "packet-ieee802154.h"
#include "packet-zbee.h"
#include "packet-zbee-nwk.h"
#include "packet-zbee-security.h"
#include "packet-zbee-nwk.h"
/*************************/
/* Function Declarations */
@ -54,21 +53,16 @@ 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);
/********************/
@ -92,7 +86,6 @@ 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;
@ -250,14 +243,28 @@ static const value_string zbee_nwk_stack_profiles[] = {
{ 0, NULL }
};
/* TODO: much of the following copied from ieee80154 dissector */
/*-------------------------------------
* Hash Tables and Lists
*-------------------------------------
/*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 *
*---------------------------------------------------------------
*/
static ieee802154_addr_t zbee_nwk_addr = { 0, NULL, NULL };
GHashTable *zbee_table_nwk_keyring = NULL;
GHashTable *zbee_table_link_keyring = NULL;
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
@ -351,41 +358,19 @@ 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 = pinfo->private_data;
guint offset = 0;
gchar *src_addr = ep_alloc(32);
gchar *dst_addr = 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 = 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);
}
@ -407,27 +392,19 @@ 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);
@ -453,13 +430,9 @@ 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);
}
@ -467,9 +440,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 short nwk source address. */
/* Get the 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);
@ -479,17 +452,11 @@ 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, "Unexpected Source Broadcast");
unicast_src = FALSE;
g_snprintf(src_addr, 32, "Broadcast");
}
else {
g_snprintf(src_addr, 32, "0x%04x", packet.src);
unicast_src = TRUE;
}
else g_snprintf(src_addr, 32, "0x%04x", packet.src);
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);
}
@ -523,12 +490,9 @@ 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);
}
@ -542,79 +506,14 @@ dissect_zbee_nwk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset += sizeof(guint64);
}
/* 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);
}
}
/* 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);
}
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);
}
}
}
/* 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) */
offset += sizeof(guint64);
}
/* Add the Source Route field. (ZigBee 2006 and later). */
if ((pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) && packet.route) {
@ -710,7 +609,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 it shouldn't be
* note: this dissector differs from others in that is shouldn't be
* passed the main tree pointer, but the nwk tree instead.
* PARAMETERS
* tvbuff_t *tvb - pointer to buffer containing raw packet.
@ -732,8 +631,7 @@ static void dissect_zbee_nwk_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
/* 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. */
@ -856,16 +754,12 @@ 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);
@ -1074,12 +968,9 @@ 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);
@ -1165,18 +1056,12 @@ 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);
@ -1262,10 +1147,8 @@ 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);
@ -1276,10 +1159,7 @@ 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 */
@ -1457,7 +1337,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->src16);
col_append_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src.addr16);
}
/* Get and display the protocol id, must be 0 on all ZigBee beacons. */
@ -1471,8 +1351,7 @@ 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);
@ -1480,12 +1359,9 @@ 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);
@ -1493,8 +1369,7 @@ 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);
@ -1570,16 +1445,15 @@ 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,
@ -1595,7 +1469,7 @@ void proto_register_zbee_nwk(void)
NULL, HFILL }},
{ &hf_zbee_nwk_ext_dst,
{ "Destination", "zbee.nwk.ext_dst", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_EXT_DEST,
{ "Extended Destination", "zbee.nwk.ext_dst", FT_BOOLEAN, 16, NULL, ZBEE_NWK_FCF_EXT_DEST,
NULL, HFILL }},
{ &hf_zbee_nwk_ext_src,
@ -1620,27 +1494,22 @@ 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,
{ "Destination", "zbee.nwk.dst64", FT_UINT64, BASE_HEX, NULL, 0x0,
{ "Extended Destination", "zbee.nwk.dst64", FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
{ &hf_zbee_nwk_src64,
{ "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,
{ "Extended Source", "zbee.nwk.scr64", FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
{ &hf_zbee_nwk_relay_count,
@ -1692,30 +1561,27 @@ 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,
@ -1723,17 +1589,15 @@ 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,
@ -1741,66 +1605,60 @@ 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,
@ -1815,8 +1673,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,
@ -1859,20 +1717,18 @@ 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_PROTOABBREV_NWK);
proto_zbee_nwk = proto_register_protocol("ZigBee Network Layer", "ZigBee NWK", "zbee.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_PROTOABBREV_NWK, dissect_zbee_nwk, proto_zbee_nwk);
register_dissector("zbee.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_nwk */
} /* proto_register_zbee */
/*FUNCTION:------------------------------------------------------
* NAME
@ -1892,43 +1748,8 @@ void proto_reg_handoff_zbee_nwk(void)
aps_handle = find_dissector("zbee.aps");
/* Register our dissector with IEEE 802.15.4 */
heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_zbee_nwk_heur, proto_zbee_nwk);
heur_dissector_add("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 = 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 */

View File

@ -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,11 +122,10 @@
#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 */
@ -149,33 +148,6 @@ 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

View File

@ -1,6 +1,6 @@
/* packet-zbee-security.c
* Dissector helper routines for encrypted ZigBee frames.
* By Owen Kirby <osk@exegin.com>; portions by Fred Fierling <fff@exegin.com>
* By Owen Kirby <osk@exegin.com>
* Copyright 2009 Exegin Technologies Limited
*
* $Id$
@ -38,8 +38,6 @@
#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.
*/
@ -47,36 +45,25 @@
#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, 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 *);
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 *);
#endif
static gboolean zbee_security_parse_key(const gchar *, guint8 *, gboolean);
static void proto_init_zbee_security(void);
static void zbee_security_parse_prefs(void);
/* Field pointers. */
#if 0
static int hf_zbee_sec_level = -1;
#endif
static int hf_zbee_sec_key_id = -1;
static int hf_zbee_sec_key = -1;
static int hf_zbee_sec_nonce = -1;
static int hf_zbee_sec_counter = -1;
static int hf_zbee_sec_src64 = -1;
static int hf_zbee_sec_isrc64 = -1;
static int hf_zbee_sec_src = -1;
static int hf_zbee_sec_key_seqno = -1;
static int hf_zbee_sec_mic = -1;
static int hf_zbee_sec_key_origin = -1;
static int hf_zbee_sec_src64_origin = -1;
/* Subtree pointers. */
static gint ett_zbee_sec = -1;
@ -92,7 +79,6 @@ 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.
@ -108,7 +94,6 @@ 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[] = {
@ -123,78 +108,22 @@ static enum_val_t zbee_sec_level_enums[] = {
{ NULL, NULL, 0 }
};
static gint gPREF_zbee_sec_level = ZBEE_SEC_ENC_MIC32;
static uat_t *zbee_sec_key_table_uat;
/* Network Key. */
static gboolean zbee_sec_have_nwk_key = FALSE;
static guint8 zbee_sec_nwk_key[ZBEE_SEC_CONST_KEYSIZE];
static const value_string byte_order_vals[] = {
{ 0, "Normal"},
{ 1, "Reverse"},
{ 0, NULL }
};
/* Trust-Center Link Key. */
static gboolean zbee_sec_have_tclink_key = FALSE;
static guint8 zbee_sec_tclink_key[ZBEE_SEC_CONST_KEYSIZE];
/* UAT Key Entry */
typedef struct _uat_key_record_t {
gchar *string;
gint byte_order;
gchar *label;
guint8 key[ZBEE_SEC_CONST_KEYSIZE];
} uat_key_record_t;
/* Trust-Center Extended Address */
static guint64 zbee_sec_tcaddr = 0;
/* */
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 = n;
const uat_key_record_t* old_key = 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 = 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");
}
}
}
static void uat_key_record_free_cb(void*r) {
uat_key_record_t* key = r;
if (key->string) g_free(key->string);
if (key->label) g_free(key->label);
}
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;
/* 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;
/*
* Enable this macro to use libgcrypt's CBC_MAC mode for the authentication
@ -208,8 +137,8 @@ static GSList *zbee_pc_keyring = NULL;
* NAME
* zbee_security_register
* DESCRIPTION
* Called by proto_register_zbee_nwk() to initialize the security
* dissectors.
* Called to initialize the security dissectors. Roughly the
* equivalent of proto_register_*
* PARAMETERS
* module_t zbee_prefs - Prefs module to load preferences under.
* RETURNS
@ -219,13 +148,12 @@ static GSList *zbee_pc_keyring = 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 }},
#endif
{ &hf_zbee_sec_key_id,
{ "Key Id", "zbee.sec.key", FT_UINT8, BASE_HEX, VALS(zbee_sec_key_names), ZBEE_SEC_CONTROL_KEY,
{ &hf_zbee_sec_key,
{ "Key", "zbee.sec.key", FT_UINT8, BASE_HEX, VALS(zbee_sec_key_names), ZBEE_SEC_CONTROL_KEY,
NULL, HFILL }},
{ &hf_zbee_sec_nonce,
@ -236,8 +164,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_src64,
{ "Source", "zbee.sec.src64", FT_UINT64, BASE_HEX, NULL, 0x0,
{ &hf_zbee_sec_src,
{ "Source", "zbee.sec.src", FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
{ &hf_zbee_sec_key_seqno,
@ -246,11 +174,6 @@ 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 }}
};
@ -259,137 +182,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, NULL);
zbee_prefs = prefs_register_protocol(proto, zbee_security_parse_prefs);
}
/* Register preferences */
prefs_register_enum_preference(zbee_prefs, "seclevel", "Security Level",
"Specifies the security level to use in the\n"
"decryption process. This value is ignored\n"
"for ZigBee 2004 and unsecured networks.",
"Specifies the security level to use in the decryption process. This value is ignored for ZigBee 2004 and unsecured networks.",
&gPREF_zbee_sec_level, zbee_sec_level_enums, FALSE);
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);
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);
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 from left to right into a buffer with
* increasing (normal byte order) or decreasing (reverse byte
* order) address.
* Parses a key string into a buffer.
* PARAMETERS
* const gchar *key_str - pointer to the string
* guint8 *key_buf - destination buffer in memory
* gboolean big_end - fill key_buf with incrementing address
* const gchar * key_str;
* guint8 key_buf;
* RETURNS
* gboolean
*---------------------------------------------------------------
*/
static gboolean
zbee_security_parse_key(const gchar *key_str, guint8 *key_buf, gboolean byte_order)
zbee_security_parse_key(const gchar *key_str, guint8 *key_buf)
{
int i, j;
int i;
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
* be at least 16 pairs of hexidecimal digits with the
* following optional separators: ':', '-', " ", or 16
* alphanumeric characters after a double-quote.
* 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.
*/
if ( (temp = *key_str++) == '"') {
string_mode = TRUE;
temp = *key_str++;
}
j = byte_order?ZBEE_SEC_CONST_KEYSIZE-1:0;
temp = *(key_str++);
for (i=ZBEE_SEC_CONST_KEYSIZE-1; i>=0; i--) {
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++);
/* 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++;
}
/* 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 */
/*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;
/* 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 */
/*FUNCTION:------------------------------------------------------
* NAME
* zbee_security_handoff
@ -406,6 +328,8 @@ 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:------------------------------------------------------
@ -419,49 +343,35 @@ zbee_security_handoff(void)
* handle internally and return NULL.
* PARAMETERS
* tvbuff_t *tvb - pointer to buffer containing raw packet.
* packet_info *pinfo - pointer to packet information fields
* packet_into *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 src64 - extended source address, or 0 if unknown.
* guint64 src - 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 src64)
dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset, guint64 src)
{
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 buffer[ZBEE_SEC_CONST_BLOCKSIZE+1];
guint8 *key_buffer = buffer;
gboolean decrypted;
GSList **nwk_keyring;
GSList *GSList_i;
key_record_t *key_rec = NULL;
const guint8 * enc_buffer;
guint8 * dec_buffer;
guint8 * key_buffer;
guint8 nonce[ZBEE_SEC_CONST_NONCE_LEN];
#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 = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK));
ieee_hints = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN));
/* Create a subtree for the security information. */
/* Create a substree 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);
@ -469,17 +379,14 @@ 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. Memory allocated by ep_tvb_memdup() is
* automatically freed before the next packet is processed.
* so we can fix these 3 bits.
*/
#ifdef HAVE_LIBGCRYPT
enc_buffer = ep_tvb_memdup(tvb, 0, tvb_length(tvb));
@ -491,16 +398,14 @@ dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint o
((guint8 *)(enc_buffer))[offset] = packet.control;
#endif /* HAVE_LIBGCRYPT */
packet.level = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL);
packet.key_id = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
packet.key = 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_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);
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);
}
offset += sizeof(guint8);
@ -512,32 +417,21 @@ 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 of the device that secured this payload. */
packet.src64 = tvb_get_letoh64(tvb, offset);
/* Get and display the source address. */
packet.src = tvb_get_letoh64(tvb, offset);
if (tree) {
proto_tree_add_eui64(sec_tree, hf_zbee_sec_src64, tvb, offset, sizeof(guint64), packet.src64);
proto_tree_add_eui64(sec_tree, hf_zbee_sec_src, tvb, offset, sizeof(guint64), packet.src);
}
offset += sizeof(guint64);
}
else {
/* 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;
}
/* This field is required in the security decryption process, so
* fill it in in case the higher layer provided it.
*/
packet.src = src;
}
if (packet.key_id == ZBEE_SEC_KEY_NWK) {
if (packet.key == ZBEE_SEC_KEY_NWK) {
/* Get and display the key sequence number. */
packet.key_seqno = tvb_get_guint8(tvb, offset);
if (tree) {
@ -547,7 +441,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:
@ -577,8 +471,7 @@ 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_bytes(sec_tree, hf_zbee_sec_mic, tvb, tvb_length(tvb)-mic_len,
mic_len, ep_tvb_memdup(tvb, tvb_length(tvb)-mic_len, mic_len));
ti = proto_tree_add_bytes(sec_tree, hf_zbee_sec_mic, tvb, tvb_length(tvb)-mic_len, mic_len, ep_tvb_memdup(tvb, tvb_length(tvb)-mic_len, mic_len));
}
}
@ -590,118 +483,105 @@ 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;
}
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;
}
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, 0x00, pinfo);
break;
/* 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;
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);
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;
}
}
} /* ( !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 = 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 = GSList_i->data;
break;
default:
key_rec = nwk_hints->link = GSList_i->data;
break;
}
} else {
GSList_i = g_slist_next(GSList_i);
}
}
}
}
/* 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 = GSList_i->data;
break;
default:
key_rec = nwk_hints->link = GSList_i->data;
break;
}
} else {
GSList_i = g_slist_next(GSList_i);
}
}
} /* ( ! 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);
}
PROTO_ITEM_SET_GENERATED(ti);
}
/* 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");
/* Done! */
return payload_tvb;
/* 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;
}
g_free(dec_buffer);
/* 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:
#endif /* HAVE_LIBGCRYPT */
/* Add expert info. */
@ -712,72 +592,10 @@ dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint o
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
@ -785,24 +603,24 @@ zbee_sec_decrypt_payload(zbee_security_packet *packet, const gchar *enc_buffer,
* Fills in the ZigBee security nonce from the provided security
* packet structure.
* PARAMETERS
* zbee_security_packet *packet - Security information.
* gchar *nonce - Nonce Buffer.
* zbee_security_packet *packet - Security information.
* RETURNS
* void
*---------------------------------------------------------------
*/
static void
zbee_sec_make_nonce(zbee_security_packet *packet, guint8 *nonce)
zbee_sec_make_nonce(guint8 *nonce, zbee_security_packet *packet)
{
/* First 8 bytes are the extended source address (little endian). */
*(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);
*(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);
/* Next 4 bytes are the frame counter (little endian). */
*(nonce++) = (guint8)((packet->counter)>>0 & 0xff);
*(nonce++) = (guint8)((packet->counter)>>8 & 0xff);
@ -988,8 +806,7 @@ 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;
}
@ -1007,8 +824,7 @@ 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;
}
@ -1160,15 +976,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, guint8 *hash_out)
zbee_sec_key_hash(guint8 *key, guint8 input, packet_info *pinfo _U_)
{
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;
@ -1188,36 +1004,3 @@ zbee_sec_key_hash(guint8 *key, guint8 input, guint8 *hash_out)
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 */

View File

@ -30,13 +30,13 @@
/* Structure containing the fields stored in the Aux Header */
typedef struct{
/* The fields of the Aux Header */
guint8 control; /* needed to decrypt */
guint32 counter; /* needed to decrypt */
guint64 src64; /* needed to decrypt */
guint8 control;
guint32 counter;
guint64 src;
guint8 key_seqno;
guint8 level;
guint8 key_id; /* needed to decrypt */
guint8 key;
gboolean nonce;
} zbee_security_packet;
@ -64,6 +64,7 @@ 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 */
@ -71,9 +72,6 @@ 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);

View File

@ -27,7 +27,7 @@
#define PACKET_ZBEE_H
/* IEEE 802.15.4 definitions. */
#include "packet-ieee802154.h"
#include <epan/dissectors/packet-ieee802154.h>
/* The ZigBee Broadcast Address */
#define ZBEE_BCAST_ALL 0xffff
@ -576,12 +576,10 @@
#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 */