ZigBee ZCL OnOff cluster dissection.

Also, fix decryption of APS commands.

svn path=/trunk/; revision=49571
This commit is contained in:
Evan Huus 2013-05-25 01:45:16 +00:00
parent 035f3fc27a
commit cf7ec9f1e9
9 changed files with 480 additions and 89 deletions

View File

@ -3736,6 +3736,7 @@ Hauke Mehrtens <hauke[AT]hauke-m.de>
Peter Van Eynde <pevaneyn[AT]cisco.com>
Marko Hrastovec <marko.hrastovec[AT]sloveniacontrol.si>
Mike Garratt <mg.wireshark[AT]evn.co.nz>
Fabio Tarabelloni <fabio.tarabelloni[AT]reloc.it>
Dan Lasley <dlasley[AT]promus.com> gave permission for his
dumpit() hex-dump routine to be used.

View File

@ -1291,6 +1291,7 @@ set(DISSECTOR_SRC
dissectors/packet-zbee-nwk.c
dissectors/packet-zbee-security.c
dissectors/packet-zbee-zcl.c
dissectors/packet-zbee-zcl-on-off.c
dissectors/packet-zbee-zdp-binding.c
dissectors/packet-zbee-zdp-discovery.c
dissectors/packet-zbee-zdp-management.c

View File

@ -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 \

View File

@ -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 */

View File

@ -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 */

View File

@ -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*/

View File

@ -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);
/* Don't decode cluster-specific commands */
zcl_dump_data(tvb, offset, pinfo, zcl_tree);
}
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);
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,36 +1387,6 @@ 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
* 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.
* RETURNS
* guint - attribute data type
*---------------------------------------------------------------
*/
static guint dissect_zcl_attr_data_type(tvbuff_t *tvb, proto_tree *tree, guint *offset)
{
guint attr_data_type;
/* Dissect attribute data type */
attr_data_type = tvb_get_guint8(tvb, *offset);
if ( tree ) {
proto_tree_add_uint(tree, hf_zbee_zcl_attr_data_type, tvb, *offset, (int)sizeof(guint8),
attr_data_type);
}
*offset += (int)sizeof(guint8);
return attr_data_type;
} /* dissect_zcl_attr_data_type */
#endif
/*FUNCTION:------------------------------------------------------
* NAME
@ -1399,13 +1405,24 @@ static guint dissect_zcl_attr_data_type(tvbuff_t *tvb, proto_tree *tree, guint *
*/
static void dissect_zcl_attr_id(tvbuff_t *tvb, proto_tree *tree, guint *offset)
{
guint16 attr_id;
guint16 attr_id;
zbee_zcl_cluster_desc *desc;
attr_id = tvb_get_letohs(tvb, *offset);
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);
}
else {
/* Add the identifier */
proto_tree_add_uint(tree,
hf_zbee_zcl_attr_id,
tvb,
*offset,
(int)sizeof(guint16),
attr_id);
}
/* 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;
@ -1424,14 +1441,54 @@ static void dissect_zcl_attr_id(tvbuff_t *tvb, proto_tree *tree, guint *offset)
* void
*---------------------------------------------------------------
*/
static void dissect_zcl_attr_data_type_val(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)
{
dissect_zcl_attr_data(tvb, tree, offset,
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,
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_data_type_val */
/*FUNCTION:------------------------------------------------------
* NAME
* 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_general(tvbuff_t *tvb, proto_tree *tree, guint *offset, guint16 attr_id, guint 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_general*/
/*FUNCTION:------------------------------------------------------
* NAME
* dissect_zcl_attr_data
@ -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;
}

View File

@ -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*/

View File

@ -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);