Back out 34627 and friends again.
svn path=/trunk/; revision=34633
This commit is contained in:
parent
2ccfd848fe
commit
b1e852cf70
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue