diff options
author | Evan Huus <eapache@gmail.com> | 2013-05-25 01:45:16 +0000 |
---|---|---|
committer | Evan Huus <eapache@gmail.com> | 2013-05-25 01:45:16 +0000 |
commit | cf7ec9f1e9a654345be4f89f312e92ea696bb3dd (patch) | |
tree | a03b8502bed98fc06600e907d4fef208b6af8ad5 /epan/dissectors | |
parent | 035f3fc27abd0eea0a132e43d25398751950774d (diff) |
From Fabio Tarabelloni via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8387
ZigBee ZCL OnOff cluster dissection.
Also, fix decryption of APS commands.
svn path=/trunk/; revision=49571
Diffstat (limited to 'epan/dissectors')
-rw-r--r-- | epan/dissectors/Makefile.common | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-aps.c | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-aps.h | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-zcl-on-off.c | 241 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-zcl.c | 279 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee-zcl.h | 18 | ||||
-rw-r--r-- | epan/dissectors/packet-zbee.h | 17 |
7 files changed, 474 insertions, 85 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 8e0022961c..7929a7d4a6 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -1213,6 +1213,7 @@ DISSECTOR_SRC = \ packet-zbee-nwk.c \ packet-zbee-security.c \ packet-zbee-zcl.c \ + packet-zbee-zcl-on-off.c \ packet-zbee-zdp-binding.c \ packet-zbee-zdp-discovery.c \ packet-zbee-zdp-management.c \ diff --git a/epan/dissectors/packet-zbee-aps.c b/epan/dissectors/packet-zbee-aps.c index 79a1512251..c54bace73b 100644 --- a/epan/dissectors/packet-zbee-aps.c +++ b/epan/dissectors/packet-zbee-aps.c @@ -619,6 +619,7 @@ dissect_zbee_aps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_item_append_text(proto_root, " %s", val_to_str_const(packet.type, zbee_aps_frame_types, "Unknown Type")); } col_clear(pinfo->cinfo, COL_INFO); + col_append_str(pinfo->cinfo, COL_INFO, "APS: "); col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet.type, zbee_aps_frame_types, "Unknown Frame Type")); /* Display the FCF */ diff --git a/epan/dissectors/packet-zbee-aps.h b/epan/dissectors/packet-zbee-aps.h index ebd85408a5..889cc33412 100644 --- a/epan/dissectors/packet-zbee-aps.h +++ b/epan/dissectors/packet-zbee-aps.h @@ -211,7 +211,7 @@ typedef struct{ gboolean indirect_mode; /* ZigBee 2004 and Earlier */ guint8 type; guint8 delivery; - gboolean ack_format; /* ZigBee 2007 and Later */ + gboolean ack_format; /* ZigBee 2007 and Later */ gboolean security; gboolean ack_req; gboolean ext_header; /* ZigBee 2007 and Later */ diff --git a/epan/dissectors/packet-zbee-zcl-on-off.c b/epan/dissectors/packet-zbee-zcl-on-off.c new file mode 100644 index 0000000000..caa498b405 --- /dev/null +++ b/epan/dissectors/packet-zbee-zcl-on-off.c @@ -0,0 +1,241 @@ +/* packet-zbee-zcl-on-off.c + * Dissector routines for the ZigBee ZCL On Off cluster + * By Fabio Tarabelloni <fabio.tarabelloni@reloc.it> + * Copyright 2012 RELOC s.r.l. + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +/* Include Files */ +#include "config.h" + +#include <string.h> +#include <glib.h> +#include <epan/packet.h> + +#include "packet-zbee.h" +#include "packet-zbee-aps.h" +#include "packet-zbee-zcl.h" + +/*************************/ +/* Defines */ +/*************************/ + +/* Attributes */ +#define ZBEE_ZCL_ON_OFF_ATTR_ID_ONOFF 0x0000 + +/* Server Commands Received */ +#define ZBEE_ZCL_ON_OFF_CMD_OFF 0x00 /* Off */ +#define ZBEE_ZCL_ON_OFF_CMD_ON 0x01 /* On */ +#define ZBEE_ZCL_ON_OFF_CMD_TOGGLE 0x02 /* Toggle */ + +/*************************/ +/* Function Declarations */ +/*************************/ + +void proto_reg_handoff_zbee_zcl_on_off(void); + +/* Command Dissector Helpers */ + +/* Private functions prototype */ +static void dissect_zcl_on_off_attr_id (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id); +static void dissect_zcl_on_off_attr_data (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type); + +/******************** + * Global Variables * + ********************/ + +/* Initialize the protocol and registered fields */ +static int proto_zbee_zcl_on_off = -1; + +static int hf_zbee_zcl_on_off_attr_id = -1; +static int hf_zbee_zcl_on_off_attr_onoff = -1; +static int hf_zbee_zcl_on_off_srv_rx_cmd_id = -1; + +/* Initialize the subtree pointers */ +static gint ett_zbee_zcl_on_off = -1; + +/* Attributes */ +static const value_string zbee_zcl_on_off_attr_names[] = { + { ZBEE_ZCL_ON_OFF_ATTR_ID_ONOFF, "OnOff" }, + { 0, NULL } +}; + +/* Server Commands Generated */ +static const value_string zbee_zcl_on_off_srv_rx_cmd_names[] = { + { ZBEE_ZCL_ON_OFF_CMD_OFF, "Off" }, + { ZBEE_ZCL_ON_OFF_CMD_ON, "On" }, + { ZBEE_ZCL_ON_OFF_CMD_TOGGLE, "Toggle" }, + { 0, NULL } +}; + +/* OnOff Names */ +static const value_string zbee_zcl_on_off_onoff_names[] = { + { 0, "Off" }, + { 1, "On" }, + { 0, NULL } +}; + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zbee_zcl_onoff + * DESCRIPTION + * ZigBee ZCL OnOff cluster dissector for wireshark. + * PARAMETERS + * tvbuff_t *tvb - pointer to buffer containing raw packet. + * packet_info *pinfo - pointer to packet information fields + * proto_tree *tree - pointer to data tree Wireshark uses to display packet. + * RETURNS + * none + *--------------------------------------------------------------- + */ +static void +dissect_zbee_zcl_on_off(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + zbee_zcl_packet *zcl = (zbee_zcl_packet *)pinfo->private_data; + guint offset = 0; + guint8 cmd_id = zcl->cmd_id; + + /* Create a subtree for the ZCL Command frame, and add the command ID to it. */ + if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) { + if (tree) { + /* Add the command ID. */ + proto_tree_add_item(tree, hf_zbee_zcl_on_off_srv_rx_cmd_id, tvb, offset, sizeof(guint8), cmd_id); + } + offset += (int)sizeof(guint8); + + /* Append the command name to the info column. */ + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_const(cmd_id, zbee_zcl_on_off_srv_rx_cmd_names, "Unknown Command"), + zcl->tran_seqno); + } +} + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_on_off_attr_id + * DESCRIPTION + * PARAMETERS + * RETURNS + * none + *--------------------------------------------------------------- + */ +void +dissect_zcl_on_off_attr_id(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id) +{ + proto_tree_add_item(tree, hf_zbee_zcl_on_off_attr_id, tvb, *offset, sizeof(guint16), attr_id); +} /*dissect_zcl_on_off_attr_id*/ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * dissect_zcl_on_off_attr_data + * DESCRIPTION + * PARAMETERS + * RETURNS + * none + *--------------------------------------------------------------- + */ +void +dissect_zcl_on_off_attr_data(proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type) +{ + /* Dissect attribute data type and data */ + switch (attr_id) { + + case ZBEE_ZCL_ON_OFF_ATTR_ID_ONOFF: + proto_tree_add_item(tree, hf_zbee_zcl_on_off_attr_onoff, tvb, *offset, sizeof(guint8), ENC_NA); + *offset += (int)sizeof(guint8); + break; + + default: + dissect_zcl_attr_data(tvb, tree, offset, data_type); + break; + } + +} /*dissect_zcl_on_off_attr_data*/ + +/*FUNCTION:------------------------------------------------------ + * NAME + * proto_register_zbee_zcl_on_off + * DESCRIPTION + * ZigBee ZCL OnOff cluster protocol registration routine. + * PARAMETERS + * none + * RETURNS + * void + *--------------------------------------------------------------- + */ +void +proto_register_zbee_zcl_on_off(void) +{ + /* Setup list of header fields */ + static hf_register_info hf[] = { + + { &hf_zbee_zcl_on_off_attr_id, + { "Attribute", "zbee.zcl.on_off.attr.id", FT_UINT16, BASE_HEX, VALS(zbee_zcl_on_off_attr_names), + 0x00, NULL, HFILL }}, + + { &hf_zbee_zcl_on_off_attr_onoff, + { "Data Value", "zbee.zcl.on_off.attr.onoff", FT_UINT8, BASE_HEX, VALS(zbee_zcl_on_off_onoff_names), + 0x00, NULL, HFILL }}, + + { &hf_zbee_zcl_on_off_srv_rx_cmd_id, + { "Command", "zbee.zcl.on_off.srv_rx.cmd.id", FT_UINT8, BASE_HEX, VALS(zbee_zcl_on_off_srv_rx_cmd_names), + 0x00, NULL, HFILL }} + + }; + + /* Register the ZigBee ZCL OnOff cluster protocol name and description */ + proto_zbee_zcl_on_off = proto_register_protocol("ZigBee ZCL OnOff", "ZCL OnOff", ZBEE_PROTOABBREV_ZCL_ONOFF); + proto_register_field_array(proto_zbee_zcl_on_off, hf, array_length(hf)); + + /* Register the ZigBee ZCL Power Profile dissector. */ + register_dissector(ZBEE_PROTOABBREV_ZCL_ONOFF, dissect_zbee_zcl_on_off, proto_zbee_zcl_on_off); +} /* proto_register_zbee_zcl_on_off */ + +/*FUNCTION:------------------------------------------------------ + * NAME + * proto_reg_handoff_zbee_zcl_on_off + * DESCRIPTION + * Hands off the Zcl Power Profile cluster dissector. + * PARAMETERS + * none + * RETURNS + * void + *--------------------------------------------------------------- + */ +void +proto_reg_handoff_zbee_zcl_on_off(void) +{ + dissector_handle_t on_off_handle; + + /* Register our dissector with the ZigBee application dissectors. */ + on_off_handle = find_dissector(ZBEE_PROTOABBREV_ZCL_ONOFF); + + dissector_add_uint("zbee.zcl.cluster", ZBEE_ZCL_CID_ON_OFF, on_off_handle); + zbee_zcl_init_cluster( proto_zbee_zcl_on_off, + ett_zbee_zcl_on_off, + ZBEE_ZCL_CID_ON_OFF, + (zbee_zcl_fn_attr_id)dissect_zcl_on_off_attr_id, + (zbee_zcl_fn_attr_data)dissect_zcl_on_off_attr_data + ); +} /*proto_reg_handoff_zbee_zcl_on_off*/ diff --git a/epan/dissectors/packet-zbee-zcl.c b/epan/dissectors/packet-zbee-zcl.c index 7b532f0786..ab02a62fdd 100644 --- a/epan/dissectors/packet-zbee-zcl.c +++ b/epan/dissectors/packet-zbee-zcl.c @@ -34,6 +34,7 @@ #include <epan/packet.h> #include "packet-zbee.h" +#include "packet-zbee-aps.h" #include "packet-zbee-zcl.h" /************************* @@ -64,11 +65,8 @@ static void dissect_zcl_discover_attr_resp (tvbuff_t *tvb, packet_info *pinfo, p /* Helper routines */ guint zbee_apf_transaction_len (tvbuff_t *tvb, guint offset, guint8 type); -static void dissect_zcl_attr_data_type_val (tvbuff_t *tvb, proto_tree *tree, guint *offset); -#if 0 -static guint dissect_zcl_attr_data_type (tvbuff_t *tvb, proto_tree *tree, guint *offset); -#endif -static void dissect_zcl_attr_data (tvbuff_t *tvb, proto_tree *tree, guint *offset, guint data_type); +static void dissect_zcl_attr_data_general(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 attr_id, guint data_type); +static void dissect_zcl_attr_data_type_val (tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 cmd_id); static void dissect_zcl_attr_bytes (tvbuff_t *tvb, proto_tree *tree, guint *offset, guint length); static guint dissect_zcl_attr_uint8 (tvbuff_t *tvb, proto_tree *tree, guint *offset, int *length); static guint dissect_zcl_attr_uint16 (tvbuff_t *tvb, proto_tree *tree, guint *offset, int *length); @@ -146,6 +144,14 @@ static gint ett_zbee_zcl_array_elements[ZBEE_ZCL_NUM_ARRAY_ELEM_ETT]; /* Dissector Handles. */ static dissector_handle_t data_handle; +/* Dissector List. */ +static dissector_table_t zbee_zcl_dissector_table; + +/* Global variables */ +static guint16 zcl_cluster_id = -1; + +static GList *acluster_desc = NULL; + /********************/ /* Field Names */ /********************/ @@ -407,7 +413,7 @@ static const value_string zbee_mfr_code_names[] = { { 0x10ca, "Unknown" }, /**/ { 0x10cb, "Unknown" }, /**/ { ZBEE_MFG_CODE_MAINSTREAM, ZBEE_MFG_MAINSTREAM }, - { 0x10cd, "Unknown" }, /**/ + { ZBEE_MFG_CODE_INDESIT_C, ZBEE_MFG_INDESIT_C }, { 0x10ce, "Unknown" }, /**/ { 0x10cf, "Unknown" }, /**/ { 0x10d0, "Unknown" }, /**/ @@ -458,7 +464,7 @@ static const value_string zbee_mfr_code_names[] = { { 0x10fd, "Unknown" }, /**/ { 0x10fe, "Unknown" }, /**/ { 0x10ff, "Unknown" }, /**/ - + { ZBEE_MFG_CODE_RELOC, ZBEE_MFG_RELOC }, { 0, NULL } }; static value_string_ext zbee_mfr_code_names_ext = VALUE_STRING_EXT_INIT(zbee_mfr_code_names); @@ -693,6 +699,9 @@ static const value_string zbee_zcl_dis_names[] = { */ static void dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + tvbuff_t *payload_tvb = NULL; + dissector_handle_t cluster_handle = NULL; + proto_tree *zcl_tree = NULL; proto_tree *sub_tree = NULL; @@ -700,13 +709,18 @@ static void dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree proto_item *ti; zbee_zcl_packet packet; - + zbee_zcl_cluster_desc *desc; + guint8 fcf; guint offset = 0; /* Init. */ memset(&packet, 0, sizeof(zbee_zcl_packet)); - + + /* Fill the zcl cluster id */ + zcl_cluster_id = pinfo->zbee_cluster_id; + cluster_handle = dissector_get_uint_handle(zbee_zcl_dissector_table, zcl_cluster_id); + /* Create the protocol tree */ if ( tree ) { proto_root = proto_tree_add_protocol_format(tree, proto_zbee_zcl, tvb, offset, @@ -769,13 +783,18 @@ static void dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree if ( zcl_tree ) { proto_tree_add_uint(zcl_tree, hf_zbee_zcl_tran_seqno, tvb, offset, (int)sizeof(guint8), - packet.tran_seqno); + packet.tran_seqno); } offset += (int)sizeof(guint8); /* Display the command and sequence number on the proto root and info column. */ packet.cmd_id = tvb_get_guint8(tvb, offset); + desc = zbee_zcl_get_cluster_desc(zcl_cluster_id); + if (desc != NULL) { + col_append_fstr(pinfo->cinfo, COL_INFO, "%s: ", desc->name); + } + /* Add command ID to the tree. */ if ( packet.frame_type == ZBEE_ZCL_FCF_PROFILE_WIDE ) { if ( tree ) { @@ -783,37 +802,46 @@ static void dissect_zbee_zcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree val_to_str_ext_const(packet.cmd_id, &zbee_zcl_cmd_names_ext, "Unknown Command"), packet.tran_seqno); } - - if ( check_col(pinfo->cinfo, COL_INFO) ) { - col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", - val_to_str_ext_const(packet.cmd_id, &zbee_zcl_cmd_names_ext, "Unknown Command"), - packet.tran_seqno); - } - + + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", + val_to_str_ext_const(packet.cmd_id, &zbee_zcl_cmd_names_ext, "Unknown Command"), + packet.tran_seqno); + if ( zcl_tree ) { proto_tree_add_uint(zcl_tree, hf_zbee_zcl_cmd_id, tvb, offset, (int)sizeof(guint8), packet.cmd_id); } offset += (int)sizeof(guint8); - } else { - if ( tree ) { - proto_item_append_text(proto_root, ", Cluster-specific Command: 0x%02x, Seq: %u", - packet.cmd_id, packet.tran_seqno); + } + else { + /* Cluster Specific */ + payload_tvb = tvb_new_subset_remaining(tvb, offset); + + if (cluster_handle != NULL) { + /* Call the specific cluster dissector registered */ + pinfo->private_data = (void *)&packet; + call_dissector(cluster_handle, payload_tvb, pinfo, zcl_tree); } + else { + if ( tree ) { + proto_item_append_text(proto_root, ", Cluster-specific Command: 0x%02x, Seq: %u", + packet.cmd_id, packet.tran_seqno); + } - if ( check_col(pinfo->cinfo, COL_INFO) ) { - col_append_fstr(pinfo->cinfo, COL_INFO, "Command: 0x%02x, Seq: %u", - packet.cmd_id, packet.tran_seqno); - } + if ( check_col(pinfo->cinfo, COL_INFO) ) { + col_append_fstr(pinfo->cinfo, COL_INFO, "Command: 0x%02x, Seq: %u", + packet.cmd_id, packet.tran_seqno); + } - if ( zcl_tree ) { - proto_tree_add_uint(zcl_tree, hf_zbee_zcl_cs_cmd_id, tvb, offset, (int)sizeof(guint8), - packet.cmd_id); - } - offset += (int)sizeof(guint8); + if ( zcl_tree ) { + proto_tree_add_uint(zcl_tree, hf_zbee_zcl_cs_cmd_id, tvb, offset, (int)sizeof(guint8), + packet.cmd_id); + } + offset += (int)sizeof(guint8); - /* Don't decode cluster-specific commands */ - zcl_dump_data(tvb, offset, pinfo, zcl_tree); + /* Don't decode cluster-specific commands */ + zcl_dump_data(tvb, offset, pinfo, zcl_tree); + } return; } @@ -929,7 +957,8 @@ static void dissect_zcl_read_attr_resp(tvbuff_t *tvb, packet_info *pinfo _U_, pr guint tvb_len; guint i = 0; - + guint16 attr_id; + tvb_len = tvb_length(tvb); while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) { @@ -939,6 +968,7 @@ static void dissect_zcl_read_attr_resp(tvbuff_t *tvb, packet_info *pinfo _U_, pr i++; /* Dissect the attribute identifier */ + attr_id = tvb_get_letohs(tvb, *offset); dissect_zcl_attr_id(tvb, sub_tree, offset); /* Dissect the status and optionally the data type and value */ @@ -946,7 +976,7 @@ static void dissect_zcl_read_attr_resp(tvbuff_t *tvb, packet_info *pinfo _U_, pr == ZBEE_ZCL_STAT_SUCCESS ) { /* Dissect the attribute data type and data */ - dissect_zcl_attr_data_type_val(tvb, sub_tree, offset); + dissect_zcl_attr_data_type_val(tvb, sub_tree, offset, attr_id); } } @@ -974,7 +1004,8 @@ static void dissect_zcl_write_attr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_ guint tvb_len; guint i = 0; - + guint16 attr_id; + tvb_len = tvb_length(tvb); while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) { @@ -984,10 +1015,11 @@ static void dissect_zcl_write_attr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_ i++; /* Dissect the attribute identifier */ + attr_id = tvb_get_letohs(tvb, *offset); dissect_zcl_attr_id(tvb, sub_tree, offset); /* Dissect the attribute data type and data */ - dissect_zcl_attr_data_type_val(tvb, sub_tree, offset); + dissect_zcl_attr_data_type_val(tvb, sub_tree, offset, attr_id); } return; @@ -1058,6 +1090,7 @@ static void dissect_zcl_read_report_config_resp(tvbuff_t *tvb, packet_info *pinf guint data_type; guint attr_status; guint attr_dir; + guint16 attr_id; tvb_len = tvb_length(tvb); while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) { @@ -1074,6 +1107,7 @@ static void dissect_zcl_read_report_config_resp(tvbuff_t *tvb, packet_info *pinf attr_dir = dissect_zcl_attr_uint8(tvb, sub_tree, offset, &hf_zbee_zcl_attr_dir); /* Dissect the attribute id */ + attr_id = tvb_get_letohs(tvb, *offset); dissect_zcl_attr_id(tvb, sub_tree, offset); if ( attr_status == ZBEE_ZCL_STAT_SUCCESS ) { @@ -1091,7 +1125,7 @@ static void dissect_zcl_read_report_config_resp(tvbuff_t *tvb, packet_info *pinf if ( IS_ANALOG_SUBTYPE(data_type) ) { /* Dissect reportable change */ - dissect_zcl_attr_data(tvb, sub_tree, offset, data_type); + dissect_zcl_attr_data_general(tvb, sub_tree, offset, attr_id, data_type); } } else { @@ -1124,6 +1158,7 @@ static void dissect_zcl_config_report(tvbuff_t *tvb, packet_info *pinfo _U_, pro guint tvb_len; guint i = 0; guint data_type; + guint16 attr_id; tvb_len = tvb_length(tvb); while ( *offset < tvb_len && i < ZBEE_ZCL_NUM_ATTR_ETT ) { @@ -1138,6 +1173,7 @@ static void dissect_zcl_config_report(tvbuff_t *tvb, packet_info *pinfo _U_, pro == ZBEE_ZCL_DIR_REPORTED ) { /* Dissect the attribute id */ + attr_id = tvb_get_letohs(tvb, *offset); dissect_zcl_attr_id(tvb, sub_tree, offset); /* Dissect the attribute data type */ @@ -1151,7 +1187,7 @@ static void dissect_zcl_config_report(tvbuff_t *tvb, packet_info *pinfo _U_, pro if ( IS_ANALOG_SUBTYPE(data_type) ) { /* Dissect reportable change */ - dissect_zcl_attr_data(tvb, sub_tree, offset, data_type); + dissect_zcl_attr_data_general(tvb, sub_tree, offset, attr_id, data_type); } } else { @@ -1351,44 +1387,52 @@ static void dissect_zcl_discover_attr_resp(tvbuff_t *tvb, packet_info *pinfo _U_ return; } /* dissect_zcl_discover_attr_resp */ -#if 0 + /*FUNCTION:------------------------------------------------------ * NAME - * dissect_zcl_attr_data_type + * dissect_zcl_attr_id * DESCRIPTION - * Helper dissector for ZCL Attribute commands. + * Dissects Attribute ID field. This could be done with the + * dissect_zcl_attr_uint16 function, but we leave it separate + * so we can dissect the attr_id with a hash in the future. * PARAMETERS * tvbuff_t *tvb - pointer to buffer containing raw packet. * proto_tree *tree - pointer to data tree wireshark uses to display packet. * offset - offset into the tvb to begin dissection. * RETURNS - * guint - attribute data type + * void *--------------------------------------------------------------- */ -static guint dissect_zcl_attr_data_type(tvbuff_t *tvb, proto_tree *tree, guint *offset) +static void dissect_zcl_attr_id(tvbuff_t *tvb, proto_tree *tree, guint *offset) { - guint attr_data_type; - - /* Dissect attribute data type */ - attr_data_type = tvb_get_guint8(tvb, *offset); + guint16 attr_id; + zbee_zcl_cluster_desc *desc; - if ( tree ) { - proto_tree_add_uint(tree, hf_zbee_zcl_attr_data_type, tvb, *offset, (int)sizeof(guint8), - attr_data_type); + attr_id = tvb_get_letohs(tvb, *offset); + desc = zbee_zcl_get_cluster_desc(zcl_cluster_id); + if ((desc != NULL) && (desc->fn_attr_id != NULL)) { + desc->fn_attr_id(tree, tvb, offset, attr_id); } - *offset += (int)sizeof(guint8); + else { + /* Add the identifier */ + proto_tree_add_uint(tree, + hf_zbee_zcl_attr_id, + tvb, + *offset, + (int)sizeof(guint16), + attr_id); + } + + *offset += (int)sizeof(guint16); - return attr_data_type; -} /* dissect_zcl_attr_data_type */ -#endif + return; +} /* dissect_zcl_attr_id */ /*FUNCTION:------------------------------------------------------ * NAME - * dissect_zcl_attr_id + * dissect_zcl_attr_data_type_val * DESCRIPTION - * Dissects Attribute ID field. This could be done with the - * dissect_zcl_attr_uint16 function, but we leave it separate - * so we can dissect the attr_id with a hash in the future. + * Helper dissector for ZCL Attribute commands. * PARAMETERS * tvbuff_t *tvb - pointer to buffer containing raw packet. * proto_tree *tree - pointer to data tree wireshark uses to display packet. @@ -1397,40 +1441,53 @@ static guint dissect_zcl_attr_data_type(tvbuff_t *tvb, proto_tree *tree, guint * * void *--------------------------------------------------------------- */ -static void dissect_zcl_attr_id(tvbuff_t *tvb, proto_tree *tree, guint *offset) +static void dissect_zcl_attr_data_type_val(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 attr_id) { - guint16 attr_id; - - attr_id = tvb_get_letohs(tvb, *offset); + zbee_zcl_cluster_desc *desc; - /* Add the identifier */ - proto_tree_add_uint(tree, hf_zbee_zcl_attr_id, tvb, *offset, (int)sizeof(guint16), - attr_id); - *offset += (int)sizeof(guint16); + desc = zbee_zcl_get_cluster_desc(zcl_cluster_id); + if ((desc != NULL) && (desc->fn_attr_data != NULL)) { + desc->fn_attr_data(tree, tvb, offset, attr_id, + dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_data_type)); + } + else { + dissect_zcl_attr_data(tvb, tree, offset, + dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_data_type) ); + } return; -} /* dissect_zcl_attr_id */ +} /* dissect_zcl_attr_data_type_val */ + /*FUNCTION:------------------------------------------------------ * NAME - * dissect_zcl_attr_data_type_val + * dissect_zcl_attr_data_general * DESCRIPTION * Helper dissector for ZCL Attribute commands. * PARAMETERS * tvbuff_t *tvb - pointer to buffer containing raw packet. * proto_tree *tree - pointer to data tree wireshark uses to display packet. * offset - offset into the tvb to begin dissection. + * attr_id - attribute identification + * data_type - type of data * RETURNS * void *--------------------------------------------------------------- */ -static void dissect_zcl_attr_data_type_val(tvbuff_t *tvb, proto_tree *tree, guint *offset) +static void dissect_zcl_attr_data_general(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 attr_id, guint data_type) { - dissect_zcl_attr_data(tvb, tree, offset, - dissect_zcl_attr_uint8(tvb, tree, offset, &hf_zbee_zcl_attr_data_type) ); + zbee_zcl_cluster_desc *desc; + + desc = zbee_zcl_get_cluster_desc(zcl_cluster_id); + if ((desc != NULL) && (desc->fn_attr_data != NULL)) { + desc->fn_attr_data(tree, tvb, offset, attr_id, data_type); + } + else { + dissect_zcl_attr_data(tvb, tree, offset, data_type); + } return; -} /* dissect_zcl_attr_data_type_val */ +} /*dissect_zcl_attr_data_general*/ /*FUNCTION:------------------------------------------------------ * NAME @@ -1447,7 +1504,7 @@ static void dissect_zcl_attr_data_type_val(tvbuff_t *tvb, proto_tree *tree, guin * void *--------------------------------------------------------------- */ -static void dissect_zcl_attr_data(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint data_type) +void dissect_zcl_attr_data(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint data_type) { guint attr_uint; gint attr_int; @@ -2023,6 +2080,8 @@ static void zcl_dump_data(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto remainder = tvb_new_subset(tvb, offset, length, length); call_dissector(data_handle, remainder, pinfo, root); } + + return; } /* zcl_dump_data */ /*FUNCTION:------------------------------------------------------ @@ -2171,12 +2230,6 @@ void proto_register_zbee_zcl(void) { "Int64", "zbee_zcl.attr.int64", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, -#if 0 - { &hf_zbee_zcl_attr_semi, - { "Semi Float", "zbee_zcl.attr.float", FT_FLOAT, BASE_NONE, NULL, 0x0, - NULL, HFILL }}, -#endif - { &hf_zbee_zcl_attr_float, { "Float", "zbee_zcl.attr.float", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }}, @@ -2303,7 +2356,8 @@ void proto_register_zbee_zcl(void) proto_register_subtree_array(ett, array_length(ett)); /* Register the ZCL dissector and subdissector list. */ - register_dissector("zbee_zcl", dissect_zbee_zcl, proto_zbee_zcl); + zbee_zcl_dissector_table = register_dissector_table("zbee.zcl.cluster", "ZigBee ZCL Cluster ID", FT_UINT16, BASE_HEX); + register_dissector(ZBEE_PROTOABBREV_ZCL, dissect_zbee_zcl, proto_zbee_zcl); } /* proto_register_zbee_zcl */ @@ -2326,7 +2380,7 @@ void proto_reg_handoff_zbee_zcl(void) data_handle = find_dissector("data"); /* Register our dissector for the appropriate profiles. */ - zbee_zcl_handle = find_dissector("zbee_zcl"); + zbee_zcl_handle = find_dissector(ZBEE_PROTOABBREV_ZCL); dissector_add_uint("zbee.profile", ZBEE_PROFILE_IPM, zbee_zcl_handle); dissector_add_uint("zbee.profile", ZBEE_PROFILE_T1, zbee_zcl_handle); dissector_add_uint("zbee.profile", ZBEE_PROFILE_HA, zbee_zcl_handle); @@ -2338,3 +2392,66 @@ void proto_reg_handoff_zbee_zcl(void) dissector_add_uint("zbee.profile", ZBEE_PROFILE_C4_CL, zbee_zcl_handle); } /* proto_reg_handoff_zbee_zcl */ + + +/*FUNCTION:------------------------------------------------------ + * NAME + * zbee_zcl_init_cluster + * DESCRIPTION + * Register the specific cluster. + * PARAMETERS + * proto - dissector proto + * ett - ett proto (not used at the moment) + * cluster_id - cluster id + * fn_attr_id - specific cluster attribute id decode function + * fn_attr_data - specific cluster attribute data decode function + * RETURNS + * void + *--------------------------------------------------------------- + */ +void +zbee_zcl_init_cluster(int proto, gint ett, guint16 cluster_id, zbee_zcl_fn_attr_id fn_attr_id, zbee_zcl_fn_attr_data fn_attr_data) +{ + zbee_zcl_cluster_desc *cluster_desc; + cluster_desc = g_new(zbee_zcl_cluster_desc, 1); + + cluster_desc->proto = find_protocol_by_id(proto); + cluster_desc->name = proto_get_protocol_short_name(cluster_desc->proto); + cluster_desc->cluster_id = cluster_id; + cluster_desc->fn_attr_id = fn_attr_id; + cluster_desc->fn_attr_data = fn_attr_data; + acluster_desc = g_list_append(acluster_desc, cluster_desc); + + cluster_desc->proto_id = proto; + cluster_desc->ett = ett; + + return; +} + +/*FUNCTION:------------------------------------------------------ + * NAME + * zbee_zcl_get_cluster_desc + * DESCRIPTION + * Retrieves the registered specific cluster descriptor. + * PARAMETERS + * cluster_id - cluster id + * RETURNS + * zbee_zcl_cluster_desc - cluster descriptor pointer + *--------------------------------------------------------------- + */ +zbee_zcl_cluster_desc +*zbee_zcl_get_cluster_desc(guint16 cluster_id) +{ + GList *gl; + gl = acluster_desc; + + while (gl) { + zbee_zcl_cluster_desc *cluster_desc = (zbee_zcl_cluster_desc *)gl->data; + if(cluster_desc->cluster_id == cluster_id) { + return cluster_desc; + } + gl = gl->next; + } + + return NULL; +} diff --git a/epan/dissectors/packet-zbee-zcl.h b/epan/dissectors/packet-zbee-zcl.h index d8e9a181f5..6665710da5 100644 --- a/epan/dissectors/packet-zbee-zcl.h +++ b/epan/dissectors/packet-zbee-zcl.h @@ -176,4 +176,22 @@ typedef struct{ #define MONTHS_PER_YEAR 12 #define YEAR_OFFSET 1900 +typedef void (*zbee_zcl_fn_attr_id) (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id); +typedef void (*zbee_zcl_fn_attr_data) (proto_tree *tree, tvbuff_t *tvb, guint *offset, guint16 attr_id, guint data_type); + +typedef struct _zbee_zcl_cluster_desc { + int proto_id; + protocol_t *proto; + const char *name; + int ett; + guint16 cluster_id; + zbee_zcl_fn_attr_id fn_attr_id; + zbee_zcl_fn_attr_data fn_attr_data; +} zbee_zcl_cluster_desc; + + +void dissect_zcl_attr_data (tvbuff_t *tvb, proto_tree *tree, guint *offset, guint data_type); +void zbee_zcl_init_cluster(int proto, gint ett, guint16 cluster_id, zbee_zcl_fn_attr_id fn_attr_id, zbee_zcl_fn_attr_data fn_attr_data); +zbee_zcl_cluster_desc *zbee_zcl_get_cluster_desc(guint16 cluster_id); + #endif /* PACKET_ZBEE_ZCL_H*/ diff --git a/epan/dissectors/packet-zbee.h b/epan/dissectors/packet-zbee.h index 84ac504094..e8e7c15c72 100644 --- a/epan/dissectors/packet-zbee.h +++ b/epan/dissectors/packet-zbee.h @@ -398,6 +398,9 @@ #define ZBEE_ZCL_FCF_PROFILE_WIDE 0x00 #define ZBEE_ZCL_FCF_CLUSTER_SPEC 0x01 +#define ZBEE_ZCL_FCF_TO_SERVER 0x00 +#define ZBEE_ZCL_FCF_TO_CLIENT 0x01 + /* Manufacturer Codes */ /* Codes less than 0x1000 were issued for RF4CE */ #define ZBEE_MFG_CODE_SAMSUNG 0x0003 @@ -574,6 +577,7 @@ /**/ /**/ #define ZBEE_MFG_CODE_MAINSTREAM 0x10cc +#define ZBEE_MFG_CODE_INDESIT_C 0x10cd /**/ #define ZBEE_MFG_CODE_RADIOCRAFTS 0x10dd /**/ @@ -585,6 +589,8 @@ #define ZBEE_MFG_CODE_ABB 0x10eb /**/ #define ZBEE_MFG_CODE_GENUS 0x10ed +/**/ +#define ZBEE_MFG_CODE_RELOC 0x1114 /* Manufacturer Names */ #define ZBEE_MFG_CIRRONET "Cirronet" @@ -762,6 +768,7 @@ #define ZBEE_MFG_SAMSUNG "Samsung Electronics Co., Ltd." /**/ #define ZBEE_MFG_MAINSTREAM "Mainstream Engineering" +#define ZBEE_MFG_INDESIT_C "Indesit Company" /**/ #define ZBEE_MFG_RADIOCRAFTS "Radiocrafts AS" /**/ @@ -772,11 +779,15 @@ #define ZBEE_MFG_ABB "ABB" /**/ #define ZBEE_MFG_GENUS "Genus Power Infrastructures Limited" +/**/ +#define ZBEE_MFG_RELOC "RELOC" /* Protocol Abbreviations */ -#define ZBEE_PROTOABBREV_NWK "zbee_nwk" -#define ZBEE_PROTOABBREV_APS "zbee_aps" -#define ZBEE_PROTOABBREV_APF "zbee_apf" +#define ZBEE_PROTOABBREV_NWK "zbee_nwk" +#define ZBEE_PROTOABBREV_APS "zbee_aps" +#define ZBEE_PROTOABBREV_APF "zbee_apf" +#define ZBEE_PROTOABBREV_ZCL "zbee_zcl" +#define ZBEE_PROTOABBREV_ZCL_ONOFF "zbee_zcl_onoff" /* Helper Functions */ extern guint zbee_get_bit_field(guint input, guint mask); |