diff options
author | Chris Brandson <chris.brandson@gmail.com> | 2016-04-12 17:31:33 -0700 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2016-04-15 08:55:33 +0000 |
commit | 84d369528a242d5dfe4edec4b28c27b9b6741754 (patch) | |
tree | 615bcd0d99215347be94030cc6a52df07cfa4980 /epan/dissectors/packet-zbee-nwk.c | |
parent | 43a783d1b6352fe94ffd5d3ffaa44178ca114963 (diff) |
802.15.4 fixed support for new ZigBee IEs
This is an update to change 14547. The processing of the ZigBee IEs
have been removed from the IEEE dissector and a new dissector added
to the ZigBee NWK module. In addition dissection has been simplified
and enhanced.
Change-Id: I1a2ee2d125b49443b90633163171e2712a8fdcdd
Reviewed-on: https://code.wireshark.org/review/14898
Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-zbee-nwk.c')
-rw-r--r-- | epan/dissectors/packet-zbee-nwk.c | 271 |
1 files changed, 215 insertions, 56 deletions
diff --git a/epan/dissectors/packet-zbee-nwk.c b/epan/dissectors/packet-zbee-nwk.c index 20cd4a753a..1c1c47a18c 100644 --- a/epan/dissectors/packet-zbee-nwk.c +++ b/epan/dissectors/packet-zbee-nwk.c @@ -32,6 +32,7 @@ #include <epan/addr_resolv.h> #include <epan/expert.h> #include <epan/proto_data.h> +#include "packet-ieee802154.h" #include "packet-zbee.h" #include "packet-zbee-nwk.h" #include "packet-zbee-security.h" @@ -44,6 +45,10 @@ static int dissect_zbee_nwk (tvbuff_t *tvb, packet_info *pinfo, p static void dissect_zbee_nwk_cmd (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zbee_nwk_packet* packet); static int dissect_zbee_beacon (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); static int dissect_zbip_beacon (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); +static int dissect_zbee_ie (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); +static void dissect_ieee802154_zigbee_rejoin(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset); +static void dissect_ieee802154_zigbee_txpower(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset); + /* Command Dissector Helpers */ static guint dissect_zbee_nwk_route_req (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, @@ -74,6 +79,7 @@ void proto_reg_handoff_zbee_nwk(void); static int proto_zbee_nwk = -1; static int proto_zbee_beacon = -1; static int proto_zbip_beacon = -1; +static int proto_zbee_ie = -1; static int hf_zbee_nwk_fcf = -1; static int hf_zbee_nwk_frame_type = -1; static int hf_zbee_nwk_proto_version = -1; @@ -171,8 +177,18 @@ static int hf_zbip_beacon_host_capacity = -1; static int hf_zbip_beacon_unsecure = -1; static int hf_zbip_beacon_network_id = -1; +/* IEEE 802.15.4 IEs (Information Elements) */ +static int hf_ieee802154_zigbee_ie = -1; +static int hf_ieee802154_zigbee_ie_id = -1; +static int hf_ieee802154_zigbee_ie_length = -1; +static int hf_ieee802154_zigbee_ie_tx_power = -1; +static int hf_ieee802154_zigbee_ie_source_addr = -1; + +static int hf_ieee802154_zigbee_rejoin_epid = -1; +static int hf_ieee802154_zigbee_rejoin_source_addr = -1; + static gint ett_zbee_nwk = -1; -static gint ett_zbee_beacon = -1; +static gint ett_zbee_nwk_beacon = -1; static gint ett_zbee_nwk_fcf = -1; static gint ett_zbee_nwk_fcf_ext = -1; static gint ett_zbee_nwk_mcast = -1; @@ -183,6 +199,11 @@ static gint ett_zbee_nwk_cmd_cinfo = -1; static gint ett_zbee_nwk_cmd_link = -1; static gint ett_zbee_nwk_cmd_ed_to_rsp_prnt_info = -1; static gint ett_zbee_nwk_cmd_link_pwr_struct = -1; +static gint ett_zbee_nwk_zigbee_ie_fields = -1; +static gint ett_zbee_nwk_ie_rejoin = -1; +static gint ett_zbee_nwk_header = -1; +static gint ett_zbee_nwk_header_ie = -1; +static gint ett_zbee_nwk_beacon_bitfield = -1; static expert_field ei_zbee_nwk_missing_payload = EI_INIT; @@ -314,6 +335,14 @@ static const value_string zbee_nwk_end_device_timeout_resp_status[] = { { 0, NULL } }; +/* Names of IEEE 802.15.4 IEs (Information Elements) for ZigBee */ +static const value_string ieee802154_zigbee_ie_names[] = { + { ZBEE_ZIGBEE_IE_REJOIN, "ReJoin" }, + { ZBEE_ZIGBEE_IE_TX_POWER, "Tx Power" }, + { ZBEE_ZIGBEE_IE_BEACON_PAYLOAD, "Extended Beacon Payload" }, + { 0, NULL } +}; + /* Stack Profile Values. */ static const value_string zbee_nwk_link_power_delta_types[] = { { 0x00, "Notification" }, @@ -1410,62 +1439,58 @@ dissect_zbee_beacon_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo } /* dissect_zbee_beacon_heur */ /** - *Dissector for ZigBee network beacons. + *Dissector for Legacy ZigBee Beacon Payloads (prior to the Enhanced Beacon) * *@param tvb pointer to buffer containing raw packet. *@param pinfo pointer to packet information fields *@param tree pointer to data tree Wireshark uses to display packet. */ -static int dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +static int dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { - ieee802154_packet *packet; proto_item *beacon_root; proto_tree *beacon_tree; - guint offset = 0; - - guint8 version; - guint64 epid; - - /* Reject the packet if data is NULL */ - if (data == NULL) - return 0; - packet = (ieee802154_packet *)data; + guint offset = 0; + guint8 version; + guint32 profile; + + static const int * beacon_fields[] = { + &hf_zbee_beacon_stack_profile, + &hf_zbee_beacon_version, + &hf_zbee_beacon_router_capacity, + &hf_zbee_beacon_depth, + &hf_zbee_beacon_end_device_capacity, + NULL + }; /* Add ourself to the protocol column. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZigBee"); /* Create the tree for this beacon. */ beacon_root = proto_tree_add_item(tree, proto_zbee_beacon, tvb, 0, -1, ENC_NA); - beacon_tree = proto_item_add_subtree(beacon_root, ett_zbee_beacon); - - /* Update the info column. */ - col_add_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src16); + beacon_tree = proto_item_add_subtree(beacon_root, ett_zbee_nwk_beacon); /* Get and display the protocol id, must be 0 on all ZigBee beacons. */ proto_tree_add_item(beacon_tree, hf_zbee_beacon_protocol, tvb, offset, 1, ENC_NA); offset += 1; - /* Get and display the stack profile and protocol version. */ - version = zbee_get_bit_field(tvb_get_guint8(tvb, offset), ZBEE_NWK_BEACON_PROTOCOL_VERSION); - proto_tree_add_item(beacon_tree, hf_zbee_beacon_stack_profile, tvb, offset, 1, ENC_NA); - proto_tree_add_item(beacon_tree, hf_zbee_beacon_version, tvb, offset, 1, ENC_NA); - offset += 1; + proto_tree_add_bitmask_text(beacon_tree, tvb, offset, 2, "Beacon: ", NULL , ett_zbee_nwk_beacon_bitfield, beacon_fields, + ENC_LITTLE_ENDIAN, BMT_NO_INT|BMT_NO_TFS); - /* Get and display the security level and flags. */ - proto_tree_add_item(beacon_tree, hf_zbee_beacon_router_capacity, tvb, offset, 1, ENC_NA); - proto_tree_add_item(beacon_tree, hf_zbee_beacon_depth, tvb, offset, 1, ENC_NA); - proto_tree_add_item(beacon_tree, hf_zbee_beacon_end_device_capacity, tvb, offset, 1, ENC_NA); - offset += 1; + /* Get and display the stack profile and protocol version. */ + version = (guint8)((tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN) & ZBEE_NWK_BEACON_PROTOCOL_VERSION) >> 4); + profile = (guint32)(tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN) & ZBEE_NWK_BEACON_STACK_PROFILE); + proto_item_append_text(beacon_root, ", %s", val_to_str_const(profile, zbee_nwk_stack_profiles, "Unknown Profile")); + offset += 2; if (version >= ZBEE_VERSION_2007) { /* In ZigBee 2006 and later, the beacon contains an extended PAN ID. */ - epid = tvb_get_letoh64(tvb, offset); proto_tree_add_item(beacon_tree, hf_zbee_beacon_epid, tvb, offset, 8, ENC_LITTLE_ENDIAN); + col_append_fstr(pinfo->cinfo, COL_INFO, ", EPID: %s", eui64_to_display(wmem_packet_scope(), + tvb_get_guint64(tvb, offset, ENC_LITTLE_ENDIAN))); + proto_item_append_text(beacon_root, ", EPID: %s", eui64_to_display(wmem_packet_scope(), + tvb_get_guint64(tvb, offset, ENC_LITTLE_ENDIAN))); offset += 8; - /* Update the Info Column with the EPID. */ - col_append_fstr(pinfo->cinfo, COL_INFO, ", EPID: %s", eui64_to_display(wmem_packet_scope(), epid)); - /* * In ZigBee 2006 the Tx-Offset is optional, while in the 2007 and * later versions, the Tx-Offset is a required value. Since both 2006 and @@ -1488,25 +1513,9 @@ static int dissect_zbee_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr proto_tree_add_item(beacon_tree, hf_zbee_beacon_tx_offset, tvb, offset, 3, ENC_LITTLE_ENDIAN); offset += 3; - /* Update the info column with the PAN ID. */ - col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->src_pan); } - /* Check for leftover bytes. */ - if (offset < tvb_captured_length(tvb)) { - /* Bytes leftover! */ - tvbuff_t *leftover_tvb = tvb_new_subset_remaining(tvb, offset); - proto_tree *root; - - /* Correct the length of the beacon tree. */ - root = proto_tree_get_root(tree); - proto_item_set_len(beacon_root, offset); - - /* Dump the leftover to the data dissector. */ - call_data_dissector(leftover_tvb, pinfo, root); - } - - return tvb_captured_length(tvb); + return offset; } /* dissect_zbee_beacon */ /** @@ -1556,7 +1565,7 @@ static int dissect_zbip_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZigBee IP"); /* Create the tree for this beacon. */ beacon_root = proto_tree_add_item(tree, proto_zbip_beacon, tvb, 0, -1, ENC_NA); - beacon_tree = proto_item_add_subtree(beacon_root, ett_zbee_beacon); + beacon_tree = proto_item_add_subtree(beacon_root, ett_zbee_nwk_beacon); /* Update the info column. */ col_clear(pinfo->cinfo, COL_INFO); @@ -1599,6 +1608,123 @@ static int dissect_zbip_beacon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr } /* dissect_zbip_beacon */ /** + *Subdissector command for ZigBee Specific IEs (Information Elements) + * + *@param tvb pointer to buffer containing raw packet. + *@param pinfo pointer to packet information fields (unused). + *@param tree pointer to command subtree. + *@param data pointer to the length of the payload IE. +*/ +static int +dissect_zbee_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + proto_tree *subtree; + tvbuff_t *ie_tvb; + guint16 zigbee_ie; + guint16 id; + guint16 length; + guint pie_length; + guint offset = 0; + + static const int * fields[] = { + &hf_ieee802154_zigbee_ie_id, + &hf_ieee802154_zigbee_ie_length, + NULL + }; + + pie_length = *(gint *)data; + + do { + zigbee_ie = tvb_get_letohs(tvb, offset); + id = (zigbee_ie & ZBEE_ZIGBEE_IE_ID_MASK) >> 6; + length = zigbee_ie & ZBEE_ZIGBEE_IE_LENGTH_MASK; + + /* Create a subtree for this command frame. */ + subtree = proto_tree_add_subtree(tree, tvb, offset, 2+length, ett_zbee_nwk_header, NULL, "ZigBee IE"); + proto_item_append_text(subtree, ", %s, Length: %d", val_to_str_const(id, ieee802154_zigbee_ie_names, "Unknown"), length); + + proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_zigbee_ie, + ett_zbee_nwk_zigbee_ie_fields, fields, ENC_LITTLE_ENDIAN); + offset += 2; + + switch (id) { + case ZBEE_ZIGBEE_IE_REJOIN: + dissect_ieee802154_zigbee_rejoin(tvb, pinfo, subtree, &offset); + break; + + case ZBEE_ZIGBEE_IE_TX_POWER: + dissect_ieee802154_zigbee_txpower(tvb, pinfo, subtree, &offset); + break; + + case ZBEE_ZIGBEE_IE_BEACON_PAYLOAD: + ie_tvb = tvb_new_subset_length(tvb, offset, ZBEE_NWK_BEACON_LENGTH); + offset += dissect_zbee_beacon(ie_tvb, pinfo, subtree, NULL); /* Legacy ZigBee Beacon */ + dissect_ieee802154_superframe(tvb, pinfo, subtree, &offset); + proto_tree_add_item(subtree, hf_ieee802154_zigbee_ie_source_addr, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + default: + if (length > 0) { /* just use the data dissector */ + call_data_dissector(tvb, pinfo, tree); + offset += length; + } + break; + } + } while (offset < pie_length); + + return tvb_captured_length(tvb); +} + +/** + *Subdissector for the ZigBee specific TX Power IE (information element) + * + *@param tvb pointer to buffer containing raw packet. + *@param pinfo pointer to packet information fields (unused). + *@param tree pointer to command subtree. + *@param offset offset into the tvbuff to begin dissection. +*/ +static void +dissect_ieee802154_zigbee_txpower(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset) +{ + gint32 txpower; + + txpower = (char)tvb_get_guint8(tvb, *offset); /* tx power is a signed byte */ + + proto_tree_add_item_ret_int(tree, hf_ieee802154_zigbee_ie_tx_power, tvb, *offset, 1, ENC_NA, &txpower); + proto_item_append_text(tree, ", TX Power %d dBm", txpower); + + *offset += 1; +} + +/** + *Subdissector for the ZigBee specific Rejoin IE (information element) + * + *@param tvb pointer to buffer containing raw packet. + *@param pinfo pointer to packet information fields (unused). + *@param tree pointer to command subtree. + *@param offset offset into the tvbuff to begin dissection. +*/ +static void +dissect_ieee802154_zigbee_rejoin(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset) +{ + proto_tree *subtree; + + subtree = proto_tree_add_subtree(tree, tvb, *offset, 10, ett_zbee_nwk_ie_rejoin, NULL, "ZigBee Rejoin"); + + proto_tree_add_item(subtree, hf_ieee802154_zigbee_rejoin_epid, tvb, *offset, 8, ENC_LITTLE_ENDIAN); + proto_item_append_text(tree, ", EPID %s", eui64_to_display(wmem_packet_scope(), + tvb_get_guint64(tvb, *offset, ENC_LITTLE_ENDIAN))); + *offset += 8; + + proto_tree_add_item(subtree, hf_ieee802154_zigbee_rejoin_source_addr, tvb, *offset, 2, ENC_NA); + proto_item_append_text(tree, ", Src: 0x%04x", + tvb_get_guint16(tvb, *offset, ENC_LITTLE_ENDIAN)); + *offset += 2; + +} /* dissect_ieee802154_zigbee_rejoin */ + +/** *ZigBee protocol registration routine. * */ @@ -1922,7 +2048,7 @@ void proto_register_zbee_nwk(void) VALS(zbee_nwk_link_power_delta_types), ZBEE_NWK_CMD_NWK_LINK_PWR_DELTA_TYPE_MASK, NULL, HFILL }}, { &hf_zbee_nwk_cmd_link_pwr_list_count, - { "Count", "zbee_nwk.cmd.link_pwr_delta.list_count", FT_UINT8, BASE_HEX, NULL, 0x0, + { "Structure Count", "zbee_nwk.cmd.link_pwr_delta.list_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_zbee_nwk_cmd_link_pwr_device_address, @@ -1938,23 +2064,23 @@ void proto_register_zbee_nwk(void) NULL, HFILL }}, { &hf_zbee_beacon_stack_profile, - { "Stack Profile", "zbee_beacon.profile", FT_UINT8, BASE_HEX, + { "Stack Profile", "zbee_beacon.profile", FT_UINT16, BASE_HEX, VALS(zbee_nwk_stack_profiles), ZBEE_NWK_BEACON_STACK_PROFILE, NULL, HFILL }}, { &hf_zbee_beacon_version, - { "Protocol Version", "zbee_beacon.version", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_BEACON_PROTOCOL_VERSION, + { "Protocol Version", "zbee_beacon.version", FT_UINT16, BASE_DEC, NULL, ZBEE_NWK_BEACON_PROTOCOL_VERSION, NULL, HFILL }}, { &hf_zbee_beacon_router_capacity, - { "Router Capacity", "zbee_beacon.router", FT_BOOLEAN, 8, NULL, ZBEE_NWK_BEACON_ROUTER_CAPACITY, + { "Router Capacity", "zbee_beacon.router", FT_BOOLEAN, 16, NULL, ZBEE_NWK_BEACON_ROUTER_CAPACITY, "Whether the device can accept join requests from routing capable devices.", HFILL }}, { &hf_zbee_beacon_depth, - { "Device Depth", "zbee_beacon.depth", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_BEACON_NETWORK_DEPTH, + { "Device Depth", "zbee_beacon.depth", FT_UINT16, BASE_DEC, NULL, ZBEE_NWK_BEACON_NETWORK_DEPTH, "The tree depth of the device, 0 indicates the network coordinator.", HFILL }}, { &hf_zbee_beacon_end_device_capacity, - { "End Device Capacity", "zbee_beacon.end_dev", FT_BOOLEAN, 8, NULL, ZBEE_NWK_BEACON_END_DEVICE_CAPACITY, + { "End Device Capacity", "zbee_beacon.end_dev", FT_BOOLEAN, 16, NULL, ZBEE_NWK_BEACON_END_DEVICE_CAPACITY, "Whether the device can accept join requests from ZigBee end devices.", HFILL }}, { &hf_zbee_beacon_epid, @@ -1989,12 +2115,38 @@ void proto_register_zbee_nwk(void) { "Network ID", "zbip_beacon.network_id", FT_STRING, BASE_NONE, NULL, 0x0, "A string that uniquely identifies this network.", HFILL }}, + { &hf_ieee802154_zigbee_ie, + { "IE header", "zbee_nwk.zigbee_ie", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + + { &hf_ieee802154_zigbee_ie_id, + { "Id", "zbee_nwk.zigbee_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_zigbee_ie_names), + ZBEE_ZIGBEE_IE_ID_MASK, NULL, HFILL }}, + + { &hf_ieee802154_zigbee_ie_length, + { "Length", "zbee_nwk.zigbee_ie.length", FT_UINT16, BASE_DEC, NULL, + ZBEE_ZIGBEE_IE_LENGTH_MASK, NULL, HFILL }}, + + { &hf_ieee802154_zigbee_ie_tx_power, + { "Tx Power (dBm)", "zbee_nwk.zigbee_ie.tx_power", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + + { &hf_ieee802154_zigbee_ie_source_addr, + { "Source Address", "zbee_nwk.zigbee_ie.source_address", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + + + { &hf_ieee802154_zigbee_rejoin_epid, + { "Extended PAN ID", "zbee_nwk.zigbee_rejoin.ext_panid", FT_EUI64, BASE_NONE, NULL, 0x0, + "Extended PAN identifier", HFILL }}, + + { &hf_ieee802154_zigbee_rejoin_source_addr, + { "Source Address", "zbee_nwk.zigbee_rejoin.source_address", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + + }; /* NWK Layer subtrees */ static gint *ett[] = { &ett_zbee_nwk, - &ett_zbee_beacon, + &ett_zbee_nwk_beacon, &ett_zbee_nwk_fcf, &ett_zbee_nwk_fcf_ext, &ett_zbee_nwk_mcast, @@ -2005,6 +2157,11 @@ void proto_register_zbee_nwk(void) &ett_zbee_nwk_cmd_link, &ett_zbee_nwk_cmd_ed_to_rsp_prnt_info, &ett_zbee_nwk_cmd_link_pwr_struct, + &ett_zbee_nwk_zigbee_ie_fields, + &ett_zbee_nwk_ie_rejoin, + &ett_zbee_nwk_header, + &ett_zbee_nwk_header_ie, + &ett_zbee_nwk_beacon_bitfield, }; static ei_register_info ei[] = { @@ -2023,6 +2180,7 @@ void proto_register_zbee_nwk(void) proto_zbee_nwk = proto_register_protocol("ZigBee Network Layer", "ZigBee", ZBEE_PROTOABBREV_NWK); proto_zbee_beacon = proto_register_protocol("ZigBee Beacon", "ZigBee Beacon", "zbee_beacon"); proto_zbip_beacon = proto_register_protocol("ZigBee IP Beacon", "ZigBee IP Beacon", "zbip_beacon"); + proto_zbee_ie = proto_register_protocol("ZigBee IE", "ZigBee IE", "zbee_ie"); proto_register_field_array(proto_zbee_nwk, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); @@ -2030,6 +2188,7 @@ void proto_register_zbee_nwk(void) register_dissector(ZBEE_PROTOABBREV_NWK, dissect_zbee_nwk, proto_zbee_nwk); register_dissector("zbee_beacon", dissect_zbee_beacon, proto_zbee_beacon); register_dissector("zbip_beacon", dissect_zbip_beacon, proto_zbip_beacon); + register_dissector("zbee_ie", dissect_zbee_ie, proto_zbee_ie); /* Register the Security dissector. */ zbee_security_register(NULL, proto_zbee_nwk); |