diff --git a/epan/dissectors/packet-zbee-aps.c b/epan/dissectors/packet-zbee-aps.c index 65c0409de1..72af736da6 100644 --- a/epan/dissectors/packet-zbee-aps.c +++ b/epan/dissectors/packet-zbee-aps.c @@ -205,6 +205,7 @@ static const value_string zbee_aps_frame_types[] = { { ZBEE_APS_FCF_DATA, "Data" }, { ZBEE_APS_FCF_CMD, "Command" }, { ZBEE_APS_FCF_ACK, "Ack" }, + { ZBEE_APS_FCF_INTERPAN, "Interpan" }, { 0, NULL } }; @@ -379,6 +380,7 @@ const range_string zbee_aps_apid_names[] = { { ZBEE_PROFILE_BM_MIN, ZBEE_PROFILE_BM_MAX, ZBEE_MFG_BM }, { ZBEE_PROFILE_AWAREPOINT_MIN, ZBEE_PROFILE_AWAREPOINT_MAX, ZBEE_MFG_AWAREPOINT }, { ZBEE_PROFILE_SAN_JUAN_1_MIN, ZBEE_PROFILE_SAN_JUAN_1_MAX, ZBEE_MFG_SAN_JUAN }, + { ZBEE_PROFILE_ZLL, ZBEE_PROFILE_ZLL, "ZLL" }, { ZBEE_PROFILE_PHILIPS_MIN, ZBEE_PROFILE_PHILIPS_MAX, ZBEE_MFG_PHILIPS }, { ZBEE_PROFILE_LUXOFT_MIN, ZBEE_PROFILE_LUXOFT_MAX, ZBEE_MFG_LUXOFT }, { ZBEE_PROFILE_KORWIN_MIN, ZBEE_PROFILE_KORWIN_MAX, ZBEE_MFG_KORWIN }, @@ -652,6 +654,7 @@ const value_string zbee_aps_cid_names[] = { {ZBEE_ZCL_CID_APPLIANCE_EVENTS_AND_ALERT, "Appliance Events And Alerts"}, {ZBEE_ZCL_CID_APPLIANCE_STATISTICS, "Appliance Statistics"}, + {ZBEE_ZCL_CID_ZLL, "ZLL Commissioning"}, { 0, NULL } }; @@ -808,57 +811,64 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data } break; + case ZBEE_APS_FCF_INTERPAN: + packet.dst_present = FALSE; + packet.src_present = FALSE; + break; + default: case ZBEE_APS_FCF_CMD: /* Endpoint addressing does not exist for these frames. */ goto dissect_zbee_aps_no_endpt; } /* switch */ - /* Determine whether the source and/or destination endpoints are present. - * We should only get here for endpoint-addressed data or ack frames. - */ - if ((packet.delivery == ZBEE_APS_FCF_UNICAST) || (packet.delivery == ZBEE_APS_FCF_BCAST)) { - /* Source and destination endpoints exist. (Although, I strongly - * disagree with the presence of the endpoint in broadcast delivery - * mode). + if (packet.type != ZBEE_APS_FCF_INTERPAN) { + /* Determine whether the source and/or destination endpoints are present. + * We should only get here for endpoint-addressed data or ack frames. */ - packet.dst_present = TRUE; - packet.src_present = TRUE; - } - else if ((packet.delivery == ZBEE_APS_FCF_INDIRECT) && (nwk->version <= ZBEE_VERSION_2004)) { - /* Indirect addressing was removed in ZigBee 2006, basically because it - * was a useless, broken feature which only complicated things. Treat - * this mode as invalid for ZigBee 2006 and later. When using indirect - * addressing, only one of the source and destination endpoints exist, - * and is controlled by the setting of indirect_mode. - */ - packet.dst_present = (!packet.indirect_mode); - packet.src_present = (packet.indirect_mode); - } - else if ((packet.delivery == ZBEE_APS_FCF_GROUP) && (nwk->version >= ZBEE_VERSION_2007)) { - /* Group addressing was added in ZigBee 2006, and contains only the - * source endpoint. (IMO, Broacast deliveries should do the same). - */ - packet.dst_present = FALSE; - packet.src_present = TRUE; - } - else { - /* Illegal Delivery Mode. */ - expert_add_info(pinfo, proto_root, &ei_zbee_aps_invalid_delivery_mode); - return tvb_captured_length(tvb); + if ((packet.delivery == ZBEE_APS_FCF_UNICAST) || (packet.delivery == ZBEE_APS_FCF_BCAST)) { + /* Source and destination endpoints exist. (Although, I strongly + * disagree with the presence of the endpoint in broadcast delivery + * mode). + */ + packet.dst_present = TRUE; + packet.src_present = TRUE; + } + else if ((packet.delivery == ZBEE_APS_FCF_INDIRECT) && (nwk->version <= ZBEE_VERSION_2004)) { + /* Indirect addressing was removed in ZigBee 2006, basically because it + * was a useless, broken feature which only complicated things. Treat + * this mode as invalid for ZigBee 2006 and later. When using indirect + * addressing, only one of the source and destination endpoints exist, + * and is controlled by the setting of indirect_mode. + */ + packet.dst_present = (!packet.indirect_mode); + packet.src_present = (packet.indirect_mode); + } + else if ((packet.delivery == ZBEE_APS_FCF_GROUP) && (nwk->version >= ZBEE_VERSION_2007)) { + /* Group addressing was added in ZigBee 2006, and contains only the + * source endpoint. (IMO, Broacast deliveries should do the same). + */ + packet.dst_present = FALSE; + packet.src_present = TRUE; + } + else { + /* Illegal Delivery Mode. */ + expert_add_info(pinfo, proto_root, &ei_zbee_aps_invalid_delivery_mode); + return tvb_captured_length(tvb); - } + } - /* If the destination endpoint is present, get and display it. */ - if (packet.dst_present) { - packet.dst = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(aps_tree, hf_zbee_aps_dst, tvb, offset, 1, packet.dst); - proto_item_append_text(proto_root, ", Dst Endpt: %d", packet.dst); - offset += 1; + /* If the destination endpoint is present, get and display it. */ + if (packet.dst_present) { + packet.dst = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(aps_tree, hf_zbee_aps_dst, tvb, offset, 1, packet.dst); + proto_item_append_text(proto_root, ", Dst Endpt: %d", packet.dst); + offset += 1; - /* Update the info column. */ - col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst Endpt: %d", packet.dst); - } + /* Update the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst Endpt: %d", packet.dst); + } + } /* if !interpan */ /* If the group address is present, display it. */ if (packet.delivery == ZBEE_APS_FCF_GROUP) { @@ -909,7 +919,8 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data offset +=2; /* The source endpoint is present for all cases except indirect /w indirect_mode == FALSE */ - if ((packet.delivery != ZBEE_APS_FCF_INDIRECT) || (!packet.indirect_mode)) { + if (packet.type != ZBEE_APS_FCF_INTERPAN && + ((packet.delivery != ZBEE_APS_FCF_INDIRECT) || (!packet.indirect_mode))) { packet.src = tvb_get_guint8(tvb, offset); proto_tree_add_uint(aps_tree, hf_zbee_aps_src, tvb, offset, 1, packet.src); proto_item_append_text(proto_root, ", Src Endpt: %d", packet.src); @@ -929,7 +940,7 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data dissect_zbee_aps_no_endpt: /* Get and display the APS counter. Only present on ZigBee 2007 and later. */ - if (nwk->version >= ZBEE_VERSION_2007) { + if (nwk->version >= ZBEE_VERSION_2007 && packet.type != ZBEE_APS_FCF_INTERPAN) { packet.counter = tvb_get_guint8(tvb, offset); proto_tree_add_uint(aps_tree, hf_zbee_aps_counter, tvb, offset, 1, packet.counter); offset += 1; @@ -1035,6 +1046,7 @@ dissect_zbee_aps_no_endpt: /* Handle the packet type. */ switch (packet.type) { case ZBEE_APS_FCF_DATA: + case ZBEE_APS_FCF_INTERPAN: if (!payload_tvb) { break; } diff --git a/epan/dissectors/packet-zbee-aps.h b/epan/dissectors/packet-zbee-aps.h index 416edc6b64..e0d196d110 100644 --- a/epan/dissectors/packet-zbee-aps.h +++ b/epan/dissectors/packet-zbee-aps.h @@ -37,6 +37,7 @@ #define ZBEE_APS_FCF_DATA 0x00 #define ZBEE_APS_FCF_CMD 0x01 #define ZBEE_APS_FCF_ACK 0x02 +#define ZBEE_APS_FCF_INTERPAN 0x03 #define ZBEE_APS_FCF_UNICAST 0x00 #define ZBEE_APS_FCF_INDIRECT 0x01 @@ -228,6 +229,8 @@ #define ZBEE_ZCL_CID_APPLIANCE_EVENTS_AND_ALERT 0x0b02 #define ZBEE_ZCL_CID_APPLIANCE_STATISTICS 0x0b03 +#define ZBEE_ZCL_CID_ZLL 0x1000 + /* ZCL Test Profile #2 Clusters */ #define ZBEE_APS_T2_CID_TCP 0x0001 #define ZBEE_APS_T2_CID_RESPC 0x0002 diff --git a/epan/dissectors/packet-zbee-nwk.c b/epan/dissectors/packet-zbee-nwk.c index accdfa50d0..5ecf368625 100644 --- a/epan/dissectors/packet-zbee-nwk.c +++ b/epan/dissectors/packet-zbee-nwk.c @@ -218,6 +218,7 @@ static dissector_handle_t zbee_gp_handle; static const value_string zbee_nwk_frame_types[] = { { ZBEE_NWK_FCF_DATA, "Data" }, { ZBEE_NWK_FCF_CMD, "Command" }, + { ZBEE_NWK_FCF_INTERPAN,"Interpan" }, { 0, NULL } }; @@ -514,192 +515,194 @@ dissect_zbee_nwk_full(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void proto_item_append_text(proto_root, " %s", val_to_str_const(packet.type, zbee_nwk_frame_types, "Unknown Type")); col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet.type, zbee_nwk_frame_types, "Reserved Frame Type")); - /* Get the destination address. */ - packet.dst = tvb_get_letohs(tvb, offset); - proto_tree_add_uint(nwk_tree, hf_zbee_nwk_dst, tvb, offset, 2, packet.dst); + if (packet.type != ZBEE_NWK_FCF_INTERPAN) { + /* Get the destination address. */ + packet.dst = tvb_get_letohs(tvb, offset); + proto_tree_add_uint(nwk_tree, hf_zbee_nwk_dst, tvb, offset, 2, packet.dst); - offset += 2; + offset += 2; - /* Display the destination address. */ - if ( (packet.dst == ZBEE_BCAST_ALL) - || (packet.dst == ZBEE_BCAST_ACTIVE) - || (packet.dst == ZBEE_BCAST_ROUTERS)){ - dst_addr = wmem_strdup(pinfo->pool, "Broadcast"); - } - else { - dst_addr = wmem_strdup_printf(pinfo->pool, "0x%04x", packet.dst); - } - - set_address(&pinfo->net_dst, AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr); - copy_address_shallow(&pinfo->dst, &pinfo->net_dst); - - proto_item_append_text(proto_root, ", Dst: %s", dst_addr); - col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr); - - - /* Get the short nwk source address and pass it to upper layers */ - packet.src = tvb_get_letohs(tvb, offset); - if (nwk_hints) - nwk_hints->src = packet.src; - proto_tree_add_uint(nwk_tree, hf_zbee_nwk_src, tvb, offset, 2, packet.src); - offset += 2; - - /* Display the source address. */ - if ( (packet.src == ZBEE_BCAST_ALL) - || (packet.src == ZBEE_BCAST_ACTIVE) - || (packet.src == ZBEE_BCAST_ROUTERS)){ - /* Source Broadcast doesn't make much sense. */ - src_addr = wmem_strdup(pinfo->pool, "Unexpected Source Broadcast"); - unicast_src = FALSE; - } - else { - src_addr = wmem_strdup_printf(pinfo->pool, "0x%04x", packet.src); - unicast_src = TRUE; - } - - set_address(&pinfo->net_src, AT_STRINGZ, (int)strlen(src_addr)+1, src_addr); - copy_address_shallow(&pinfo->src, &pinfo->net_src); - - proto_item_append_text(proto_root, ", Src: %s", src_addr); - col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr); - - /* Get and display the radius. */ - packet.radius = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(nwk_tree, hf_zbee_nwk_radius, tvb, offset, 1, packet.radius); - offset += 1; - - /* Get and display the sequence number. */ - packet.seqno = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(nwk_tree, hf_zbee_nwk_seqno, tvb, offset, 1, packet.seqno); - offset += 1; - - /* Add the extended destination address (ZigBee 2006 and later). */ - if ((packet.version >= ZBEE_VERSION_2007) && packet.ext_dst) { - packet.dst64 = tvb_get_letoh64(tvb, offset); - proto_tree_add_item(nwk_tree, hf_zbee_nwk_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN); - offset += 8; - } - - /* Display the extended source address. (ZigBee 2006 and later). */ - if (packet.version >= ZBEE_VERSION_2007) { - addr16.pan = ieee_packet->src_pan; - - if (packet.ext_src) { - packet.src64 = tvb_get_letoh64(tvb, offset); - proto_tree_add_item(nwk_tree, hf_zbee_nwk_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN); - offset += 8; - - if (!pinfo->fd->flags.visited && nwk_hints) { - /* 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_map, - packet.src, addr16.pan, packet.src64, pinfo->current_proto, pinfo->num); - } - } + /* Display the destination address. */ + if ( (packet.dst == ZBEE_BCAST_ALL) + || (packet.dst == ZBEE_BCAST_ACTIVE) + || (packet.dst == ZBEE_BCAST_ROUTERS)){ + dst_addr = wmem_strdup(pinfo->pool, "Broadcast"); } else { - /* See if extended source info was previously sniffed */ - if (!pinfo->fd->flags.visited && nwk_hints) { - nwk_hints->src_pan = ieee_packet->src_pan; - addr16.addr = packet.src; - - map_rec = (ieee802154_map_rec *) g_hash_table_lookup(zbee_nwk_map.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 (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_uint_format_value(nwk_tree, hf_zbee_nwk_src64_origin, tvb, 0, 0, 0, "Pre-configured"); - } - PROTO_ITEM_SET_GENERATED(ti); - } - } + dst_addr = wmem_strdup_printf(pinfo->pool, "0x%04x", packet.dst); } - /* 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_map.short_table, &addr16); + set_address(&pinfo->net_dst, AT_STRINGZ, (int)strlen(dst_addr)+1, dst_addr); + copy_address_shallow(&pinfo->dst, &pinfo->net_dst); - if (map_rec) { - /* found a ieee mapping record */ - ieee_hints->map_rec = map_rec; + proto_item_append_text(proto_root, ", Dst: %s", dst_addr); + col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr); + + + /* Get the short nwk source address and pass it to upper layers */ + packet.src = tvb_get_letohs(tvb, offset); + if (nwk_hints) + nwk_hints->src = packet.src; + proto_tree_add_uint(nwk_tree, hf_zbee_nwk_src, tvb, offset, 2, packet.src); + offset += 2; + + /* Display the source address. */ + if ( (packet.src == ZBEE_BCAST_ALL) + || (packet.src == ZBEE_BCAST_ACTIVE) + || (packet.src == ZBEE_BCAST_ROUTERS)){ + /* Source Broadcast doesn't make much sense. */ + src_addr = wmem_strdup(pinfo->pool, "Unexpected Source Broadcast"); + unicast_src = FALSE; + } + else { + src_addr = wmem_strdup_printf(pinfo->pool, "0x%04x", packet.src); + unicast_src = TRUE; + } + + set_address(&pinfo->net_src, AT_STRINGZ, (int)strlen(src_addr)+1, src_addr); + copy_address_shallow(&pinfo->src, &pinfo->net_src); + + proto_item_append_text(proto_root, ", Src: %s", src_addr); + col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr); + + /* Get and display the radius. */ + packet.radius = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(nwk_tree, hf_zbee_nwk_radius, tvb, offset, 1, packet.radius); + offset += 1; + + /* Get and display the sequence number. */ + packet.seqno = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(nwk_tree, hf_zbee_nwk_seqno, tvb, offset, 1, packet.seqno); + offset += 1; + + /* Add the extended destination address (ZigBee 2006 and later). */ + if ((packet.version >= ZBEE_VERSION_2007) && packet.ext_dst) { + packet.dst64 = tvb_get_letoh64(tvb, offset); + proto_tree_add_item(nwk_tree, hf_zbee_nwk_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN); + offset += 8; + } + + /* Display the extended source address. (ZigBee 2006 and later). */ + if (packet.version >= ZBEE_VERSION_2007) { + addr16.pan = ieee_packet->src_pan; + + if (packet.ext_src) { + packet.src64 = tvb_get_letoh64(tvb, offset); + proto_tree_add_item(nwk_tree, hf_zbee_nwk_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN); + offset += 8; + + if (!pinfo->fd->flags.visited && nwk_hints) { + /* 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_map, + packet.src, addr16.pan, packet.src64, pinfo->current_proto, pinfo->num); + } } } - } /* (!pinfo->fd->flags.visited */ - } /* (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) */ + else { + /* See if extended source info was previously sniffed */ + if (!pinfo->fd->flags.visited && nwk_hints) { + nwk_hints->src_pan = ieee_packet->src_pan; + addr16.addr = packet.src; - /* Add multicast control field (ZigBee 2006 and later). */ - if ((packet.version >= ZBEE_VERSION_2007) && packet.multicast) { - static const int * multicast_flags[] = { - &hf_zbee_nwk_mcast_mode, - &hf_zbee_nwk_mcast_radius, - &hf_zbee_nwk_mcast_max_radius, - NULL - }; + map_rec = (ieee802154_map_rec *) g_hash_table_lookup(zbee_nwk_map.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 (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); - guint8 mcast_control = tvb_get_guint8(tvb, offset); - packet.mcast_mode = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_MODE); - packet.mcast_radius = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_RADIUS); - packet.mcast_max_radius = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_MAX_RADIUS); + 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_uint_format_value(nwk_tree, hf_zbee_nwk_src64_origin, tvb, 0, 0, 0, "Pre-configured"); + } + PROTO_ITEM_SET_GENERATED(ti); + } + } + } - proto_tree_add_bitmask(nwk_tree, tvb, offset, hf_zbee_nwk_mcast, ett_zbee_nwk_mcast, multicast_flags, ENC_NA); - offset += 1; - } + /* 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_map.short_table, &addr16); - /* Add the Source Route field. (ZigBee 2006 and later). */ - if ((packet.version >= ZBEE_VERSION_2007) && packet.route) { - proto_tree *field_tree; - guint8 relay_count; - guint16 relay_addr; - guint i; + 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) */ - /* Create a subtree for the source route field. */ - field_tree = proto_tree_add_subtree(nwk_tree, tvb, offset, 1, ett_zbee_nwk_route, &ti, "Source Route"); + /* Add multicast control field (ZigBee 2006 and later). */ + if ((packet.version >= ZBEE_VERSION_2007) && packet.multicast) { + static const int * multicast_flags[] = { + &hf_zbee_nwk_mcast_mode, + &hf_zbee_nwk_mcast_radius, + &hf_zbee_nwk_mcast_max_radius, + NULL + }; - /* Get and display the relay count. */ - relay_count = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(field_tree, hf_zbee_nwk_relay_count, tvb, offset, 1, relay_count); - proto_item_append_text(ti, ", Length: %d", relay_count); - offset += 1; + guint8 mcast_control = tvb_get_guint8(tvb, offset); + packet.mcast_mode = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_MODE); + packet.mcast_radius = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_RADIUS); + packet.mcast_max_radius = zbee_get_bit_field(mcast_control, ZBEE_NWK_MCAST_MAX_RADIUS); - /* Correct the length of the source route fields. */ - proto_item_set_len(ti, 1 + relay_count*2); + proto_tree_add_bitmask(nwk_tree, tvb, offset, hf_zbee_nwk_mcast, ett_zbee_nwk_mcast, multicast_flags, ENC_NA); + offset += 1; + } - /* Get and display the relay index. */ - proto_tree_add_item(field_tree, hf_zbee_nwk_relay_index, tvb, offset, 1, ENC_NA); - offset += 1; + /* Add the Source Route field. (ZigBee 2006 and later). */ + if ((packet.version >= ZBEE_VERSION_2007) && packet.route) { + proto_tree *field_tree; + guint8 relay_count; + guint16 relay_addr; + guint i; - /* Get and display the relay list. */ - for (i=0; i