diff options
-rw-r--r-- | epan/dissectors/packet-6lowpan.c | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee802154.c | 594 | ||||
-rw-r--r-- | epan/dissectors/packet-ieee802154.h | 61 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-aps.c | 145 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-aps.h | 58 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-nwk.c | 427 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-nwk.h | 32 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-security.c | 715 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-security.h | 12 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee.h | 10 |
10 files changed, 689 insertions, 1373 deletions
diff --git a/epan/dissectors/packet-6lowpan.c b/epan/dissectors/packet-6lowpan.c index 7cd4054bdb..f2525b0e3b 100644 --- a/epan/dissectors/packet-6lowpan.c +++ b/epan/dissectors/packet-6lowpan.c @@ -516,14 +516,14 @@ lowpan_dlsrc_to_ifcid(packet_info *pinfo, guint8 *ifcid) /* Derive the IID from the IEEE 802.15.4 packet structure. */ if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) { guint64 addr; - addr = pntoh64(&packet->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; } diff --git a/epan/dissectors/packet-ieee802154.c b/epan/dissectors/packet-ieee802154.c index 8a1d4f87e8..9d230807bd 100644 --- a/epan/dissectors/packet-ieee802154.c +++ b/epan/dissectors/packet-ieee802154.c @@ -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; - - 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; + tvbuff_t *volatile payload_tvb; + proto_tree *volatile ieee802154_tree = NULL; + proto_item *volatile proto_root = NULL; + proto_item *ti; + void *pd_save; + + guint offset = 0; + volatile gboolean fcs_ok = TRUE; + const char *saved_proto; + ieee802154_packet *packet = ep_alloc(sizeof(ieee802154_packet)); + ws_decrypt_status status; /* 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; - } - else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) { - /* Use the hint */ - srcAddr = ieee_hints->map_rec->addr64; + srcAddr = packet->src.addr64; + } + else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) { + ieee802154_short_addr addr16; + ieee802154_long_addr * addr64; + + /* Try to lookup the EUI-64 from the address table. */ + addr16.addr = packet->src.addr16; + addr16.pan = packet->src_pan; + addr64 = (ieee802154_long_addr *)g_hash_table_lookup(ieee802154_addr_table, &addr16); + if (!addr64) { + /* Lookup failed. */ + *status = DECRYPT_PACKET_NO_EXT_SRC_ADDR; + return NULL; + } + /* Lookup successful. */ + srcAddr = addr64->addr; } else { - /* 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, - NULL, HFILL }}, - - { &hf_ieee802154_src64, - { "Extended Source", "wpan.src64", FT_UINT64, BASE_HEX, NULL, 0x0, + { &hf_ieee802154_src_addr16, + { "Source", "wpan.src_addr16", FT_UINT16, 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 */ + diff --git a/epan/dissectors/packet-ieee802154.h b/epan/dissectors/packet-ieee802154.h index c106be5f38..428f573359 100644 --- a/epan/dissectors/packet-ieee802154.h +++ b/epan/dissectors/packet-ieee802154.h @@ -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 */ diff --git a/epan/dissectors/packet-zbee-aps.c b/epan/dissectors/packet-zbee-aps.c index 9e468b3c23..48cc7b84e6 100644 --- a/epan/dissectors/packet-zbee-aps.c +++ b/epan/dissectors/packet-zbee-aps.c @@ -39,9 +39,9 @@ #include <epan/reassemble.h> #include "packet-zbee.h" -#include "packet-zbee-nwk.h" #include "packet-zbee-security.h" #include "packet-zbee-aps.h" +#include "packet-zbee-nwk.h" /************************* * Function Declarations * @@ -67,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); } @@ -1746,6 +1719,24 @@ zbee_apf_transaction_len(tvbuff_t *tvb, guint offset, guint8 type) /*FUNCTION:------------------------------------------------------ * NAME + * proto_init_zbee_aps + * DESCRIPTION + * Initializes the APS dissectors prior to beginning protocol + * dissection. + * PARAMETERS + * none + * RETURNS + * void + *--------------------------------------------------------------- + */ +static void proto_init_zbee_aps(void) +{ + fragment_table_init(&zbee_aps_fragment_table); + reassembled_table_init(&zbee_aps_reassembled_table); +} /* proto_init_zbee_aps */ + +/*FUNCTION:------------------------------------------------------ + * NAME * proto_register_zbee_aps * DESCRIPTION * ZigBee APS protocol registration routine. @@ -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 */ - diff --git a/epan/dissectors/packet-zbee-aps.h b/epan/dissectors/packet-zbee-aps.h index d8aa4b1e20..eb106d81e2 100644 --- a/epan/dissectors/packet-zbee-aps.h +++ b/epan/dissectors/packet-zbee-aps.h @@ -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*/ diff --git a/epan/dissectors/packet-zbee-nwk.c b/epan/dissectors/packet-zbee-nwk.c index 341ea94f78..006220a53e 100644 --- a/epan/dissectors/packet-zbee-nwk.c +++ b/epan/dissectors/packet-zbee-nwk.c @@ -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; - } - else { - g_snprintf(src_addr, 32, "0x%04x", packet.src); - unicast_src = TRUE; + g_snprintf(src_addr, 32, "Broadcast"); } - + 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); - } - } - } - 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); - } - } + /* 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); } - - /* 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 */ diff --git a/epan/dissectors/packet-zbee-nwk.h b/epan/dissectors/packet-zbee-nwk.h index 9069e83961..b1e3da4fe4 100644 --- a/epan/dissectors/packet-zbee-nwk.h +++ b/epan/dissectors/packet-zbee-nwk.h @@ -21,7 +21,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PACKET_ZBEE_NWK_H #define PACKET_ZBEE_NWK_H @@ -122,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 diff --git a/epan/dissectors/packet-zbee-security.c b/epan/dissectors/packet-zbee-security.c index 246dfcf445..2bde0c9b81 100644 --- a/epan/dissectors/packet-zbee-security.c +++ b/epan/dissectors/packet-zbee-security.c @@ -1,6 +1,6 @@ /* packet-zbee-security.c * Dissector helper routines for encrypted ZigBee frames. - * By Owen Kirby <osk@exegin.com>; 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; - -static const value_string byte_order_vals[] = { - { 0, "Normal"}, - { 1, "Reverse"}, - { 0, NULL } -}; - -/* 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; - -/* */ -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"); - } - } -} +/* Network Key. */ +static gboolean zbee_sec_have_nwk_key = FALSE; +static guint8 zbee_sec_nwk_key[ZBEE_SEC_CONST_KEYSIZE]; -static void uat_key_record_free_cb(void*r) { - uat_key_record_t* key = r; +/* Trust-Center Link Key. */ +static gboolean zbee_sec_have_tclink_key = FALSE; +static guint8 zbee_sec_tclink_key[ZBEE_SEC_CONST_KEYSIZE]; - if (key->string) g_free(key->string); - if (key->label) g_free(key->label); -} +/* Trust-Center Extended Address */ +static guint64 zbee_sec_tcaddr = 0; -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,139 +182,138 @@ 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 * DESCRIPTION * Hands off the security dissector. @@ -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 - /* Allocate memory to decrypt the payload into. */ - dec_buffer = g_malloc(payload_len); + /* 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; - 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; - } + /* 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; } - } /* ( !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); - } - } - } + if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){ + /* Without the extended source address, we can't create the nonce. */ + goto decrypt_failed; } - - /* Loop through user's password table for preconfigured keys, our last resort */ - GSList_i = zbee_pc_keyring; - while ( GSList_i && !decrypted ) { - decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, - payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key); - - if (decrypted) { - /* save pointer to the successful key record */ - switch (packet.key_id) { - case ZBEE_SEC_KEY_NWK: - key_rec = nwk_hints->nwk = GSList_i->data; - break; - - default: - key_rec = nwk_hints->link = GSList_i->data; - break; - } - } else { - GSList_i = g_slist_next(GSList_i); - } + else if (packet.src == 0) { + packet.src = zbee_sec_tcaddr; } - } /* ( ! pinfo->fd->flags.visited ) */ - } /* ( packet.src64 ) */ - - if ( decrypted ) { - if ( tree && key_rec ) { - if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) { - ti = proto_tree_add_text(sec_tree, tvb, 0, 0, "Decryption Key: %s", key_rec->label); - } else { - ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0, - key_rec->frame_num); + key_buffer = zbee_sec_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; } - PROTO_ITEM_SET_GENERATED(ti); - } + 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; - /* 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"); + /* 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; - /* Done! */ - return payload_tvb; + default: + goto decrypt_failed; + } /* switch */ + + /* Create the nonce. */ + zbee_sec_make_nonce(nonce, &packet); + /* Allocate memory to decrypt the payload into. */ + dec_buffer = g_malloc(payload_len); + /* Perform Decryption. */ + if (!zbee_sec_ccm_decrypt(key_buffer, /* key */ + nonce, /* Nonce */ + enc_buffer, /* a, length l(a) */ + enc_buffer+offset, /* c, length l(c) = l(m) + M */ + dec_buffer, /* m, length l(m) */ + offset, /* l(a) */ + payload_len, /* l(m) */ + mic_len)) { /* M */ + /* Decryption Failed! */ + g_free(dec_buffer); + goto decrypt_failed; } - 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,97 +592,35 @@ 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 * DESCRIPTION * 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 */ diff --git a/epan/dissectors/packet-zbee-security.h b/epan/dissectors/packet-zbee-security.h index 56aee490e9..257de8302c 100644 --- a/epan/dissectors/packet-zbee-security.h +++ b/epan/dissectors/packet-zbee-security.h @@ -30,13 +30,13 @@ /* Structure containing the fields stored in the Aux Header */ typedef struct{ /* The fields of the Aux Header */ - guint8 control; /* 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); diff --git a/epan/dissectors/packet-zbee.h b/epan/dissectors/packet-zbee.h index e7aded465f..2e0f11af79 100644 --- a/epan/dissectors/packet-zbee.h +++ b/epan/dissectors/packet-zbee.h @@ -27,7 +27,7 @@ #define PACKET_ZBEE_H /* IEEE 802.15.4 definitions. */ -#include "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 */ + |