aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-zep.c
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2009-05-20 19:29:39 +0000
committerGerald Combs <gerald@wireshark.org>2009-05-20 19:29:39 +0000
commitf5e8e21ce2658c75f41818eb813ee4000b52ec9c (patch)
treecf014ea9608d08848508d6b9bc54bda8f10cc80c /epan/dissectors/packet-zep.c
parentbd79d12416d02871675d12427a405b8cc791122a (diff)
From Owen Kirby via bug 3431:
The attached patch file adds dissectors for the ZigBee protocol stack, which runs atop the IEEE 802.15.4 dissector. Also included is the dissector for the ZigBee Encapsulation Protocol (packet-zep.c), used by the Exegin Q51 protocol analyzer. From me: Fix a bunch of gcc (the compiler, not me) warnings. svn path=/trunk/; revision=28429
Diffstat (limited to 'epan/dissectors/packet-zep.c')
-rw-r--r--epan/dissectors/packet-zep.c395
1 files changed, 395 insertions, 0 deletions
diff --git a/epan/dissectors/packet-zep.c b/epan/dissectors/packet-zep.c
new file mode 100644
index 0000000000..7b2e0ab970
--- /dev/null
+++ b/epan/dissectors/packet-zep.c
@@ -0,0 +1,395 @@
+/* packet-zep.c
+ * Dissector routines for the ZigBee Encapsulation Protocol
+ * By Owen Kirby <osk@exegin.com>
+ * Copyright 2009 Exegin Technologies Limited
+ *
+ * $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *------------------------------------------------------------
+ *
+ * ZEP Packets must be received in the following format:
+ * |UDP Header| ZEP Header |IEEE 802.15.4 Packet|
+ * | 8 bytes | 16/32 bytes | <= 127 bytes |
+ *------------------------------------------------------------
+ *
+ * ZEP v1 Header will have the following format:
+ * |Preamble|Version|Channel ID|Device ID|CRC/LQI Mode|LQI Val|Reserved|Length|
+ * |2 bytes |1 byte | 1 byte | 2 bytes | 1 byte |1 byte |7 bytes |1 byte|
+ *
+ * ZEP v2 Header will have the following format (if type=1/Data):
+ * |Preamble|Version| Type |Channel ID|Device ID|CRC/LQI Mode|LQI Val|NTP Timestamp|Sequence#|Reserved|Length|
+ * |2 bytes |1 byte |1 byte| 1 byte | 2 bytes | 1 byte |1 byte | 8 bytes | 4 bytes |10 bytes|1 byte|
+ *
+ * ZEP v2 Header will have the following format (if type=2/Ack):
+ * |Preamble|Version| Type |Sequence#|
+ * |2 bytes |1 byte |1 byte| 4 bytes |
+ *------------------------------------------------------------
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVEHCONFIG_H */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <gmodule.h>
+
+#include "epan/packet.h"
+#include "epan/prefs.h"
+#include "epan/dissectors/packet-ntp.h"
+
+#include "packet-zep.h"
+
+/* Function declarations */
+void proto_reg_handoff_zep(void);
+void proto_register_zep(void);
+void dissect_zep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+void ntp_to_nstime(guint32, guint32, nstime_t *);
+
+/* Initialize protocol and registered fields. */
+static int proto_zep = -1;
+static int hf_zep_version = -1;
+static int hf_zep_type = -1;
+static int hf_zep_channel_id = -1;
+static int hf_zep_device_id = -1;
+static int hf_zep_lqi_mode = -1;
+static int hf_zep_lqi = -1;
+static int hf_zep_timestamp = -1;
+static int hf_zep_seqno = -1;
+static int hf_zep_ieee_length = -1;
+
+/* Initialize protocol subtrees. */
+static gint ett_zep = -1;
+
+/* Initialize preferences. */
+static guint32 gPREF_zep_udp_port = ZEP_DEFAULT_PORT;
+
+/* Dissector handles */
+static dissector_handle_t data_handle;
+static dissector_handle_t ieee802154_handle = NULL;
+static dissector_handle_t ieee802154_ccfcs_handle = NULL;
+
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * ntp_to_nstime
+ * DESCRIPTION
+ * Converts a timestamp from ntp format to nstime format.
+ * PARAMETERS
+ * guint32 ntp_secs;
+ * guint32 ntp_fraction;
+ * struct *nstime_ptr;
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+void ntp_to_nstime(guint32 ntp_secs, guint32 ntp_fraction, nstime_t *nstime_ptr)
+{
+ double temp;
+ nstime_ptr->secs = (ntp_secs >= NTP_BASETIME) ? ntp_secs - NTP_BASETIME : ntp_secs;
+ temp = (double)ntp_fraction / 4.294967296; /* 4.294967296 = (2<<32 / 10<<9) */
+ nstime_ptr->nsecs = (guint32) temp;
+} /* ntp_to_nstime */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zep
+ * DESCRIPTION
+ * IEEE 802.15.4 packet dissection routine for ethereal.
+ * 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 ethereal uses to display packet.
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+void
+dissect_zep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *next_tvb;
+ proto_item *proto_root, *pi;
+ proto_tree *zep_tree;
+ guint8 ieee_packet_len;
+ guint8 zep_header_len;
+ zep_info zep_data;
+
+ dissector_handle_t next_dissector;
+
+ /* Determine whether this is a Q51/IEEE 802.15.4 Sniffer Packet or not */
+ if(strcmp(tvb_get_string(tvb, 0, 2), ZEP_PREAMBLE)){
+ /* This is not a Q51/ZigBee sniffer packet */
+ call_dissector(data_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ memset(&zep_data, 0, sizeof(zep_data)); /* Zero all zep_data fields. */
+
+ /* Extract the protocol version from the ZEP header. */
+ zep_data.version = tvb_get_guint8(tvb, 2);
+ if (zep_data.version == 1) {
+ /* Type indicates a ZEP_v1 packet. */
+
+ zep_header_len = ZEP_V1_HEADER_LEN;
+ zep_data.type = 0;
+ zep_data.channel_id = tvb_get_guint8(tvb, 3);
+ zep_data.device_id = tvb_get_ntohs(tvb, 4);
+ zep_data.lqi_mode = tvb_get_guint8(tvb, 6)?1:0;
+ zep_data.lqi = tvb_get_guint8(tvb, 7);
+ ieee_packet_len = (tvb_get_guint8(tvb, ZEP_V1_HEADER_LEN - 1) & ZEP_LENGTH_MASK);
+ }
+ else {
+ /* At the time of writing, v2 is the latest version of ZEP, assuming
+ * anything higher than v2 has identical format. */
+
+ zep_data.type = tvb_get_guint8(tvb, 3);
+ if (zep_data.type == ZEP_V2_TYPE_ACK) {
+ /* ZEP Ack has only the seqno. */
+ zep_header_len = ZEP_V2_ACK_LEN;
+ zep_data.seqno = tvb_get_ntohl(tvb, 4);
+ ieee_packet_len = 0;
+ }
+ else {
+ /* Although, only type 1 corresponds to data, if another value is present, assume it is dissected the same. */
+ zep_header_len = ZEP_V2_HEADER_LEN;
+ zep_data.channel_id = tvb_get_guint8(tvb, 4);
+ zep_data.device_id = tvb_get_ntohs(tvb, 5);
+ zep_data.lqi_mode = tvb_get_guint8(tvb, 7)?1:0;
+ zep_data.lqi = tvb_get_guint8(tvb, 8);
+ ntp_to_nstime(tvb_get_ntohl(tvb, 9), tvb_get_ntohl(tvb, 13), &(zep_data.ntp_time));
+ zep_data.seqno = tvb_get_ntohl(tvb, 17);
+ ieee_packet_len = (tvb_get_guint8(tvb, ZEP_V2_HEADER_LEN - 1) & ZEP_LENGTH_MASK);
+ }
+ }
+
+#if 0
+//??dat
+ if (zep_data.ntp_time.secs && zep_data.ntp_time.nsecs) {
+ pinfo->fd->abs_ts = zep_data.ntp_time;
+ }
+#endif
+
+ if(ieee_packet_len < tvb_length(tvb)-zep_header_len){
+ /* Packet's length is mis-reported, abort dissection */
+ call_dissector(data_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ /* Enter name info protocol field */
+ if(check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_clear(pinfo->cinfo, COL_PROTOCOL);
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, (zep_data.version==1)?"ZEP":"ZEPv2");
+ }
+
+ /* Enter name info protocol field */
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_clear(pinfo->cinfo, COL_INFO);
+ if (!((zep_data.version>=2) && (zep_data.type==ZEP_V2_TYPE_ACK))) col_add_fstr(pinfo->cinfo, COL_INFO, "Encapsulated ZigBee Packet [Channel]=%i [Length]=%i", zep_data.channel_id, ieee_packet_len);
+ else col_add_fstr(pinfo->cinfo, COL_INFO, "Ack, Sequence Number: %i", zep_data.seqno);
+ }
+
+ if(tree){
+ /* Create subtree for the ZEP Header */
+ if (!((zep_data.version>=2) && (zep_data.type==ZEP_V2_TYPE_ACK))) {
+ proto_root = proto_tree_add_protocol_format(tree, proto_zep, tvb, 0, zep_header_len, "ZigBee Encapsulation Protocol, Channel: %i, Length: %i", zep_data.channel_id, ieee_packet_len);
+ }
+ else {
+ proto_root = proto_tree_add_protocol_format(tree, proto_zep, tvb, 0, zep_header_len, "ZigBee Encapsulation Protocol, Ack");
+ }
+ zep_tree = proto_item_add_subtree(proto_root, ett_zep);
+
+ /* Display the information in the subtree */
+ proto_tree_add_text(zep_tree, tvb, 0, 2, "Protocol ID String: EX");
+ if (zep_data.version==1) {
+ proto_tree_add_uint(zep_tree, hf_zep_version, tvb, 2, 1, zep_data.version);
+ proto_tree_add_uint(zep_tree, hf_zep_channel_id, tvb, 3, 1, zep_data.channel_id);
+ proto_tree_add_uint(zep_tree, hf_zep_device_id, tvb, 4, 2, zep_data.device_id);
+ proto_tree_add_boolean_format(zep_tree, hf_zep_lqi_mode, tvb, 6, 1, zep_data.lqi_mode, "LQI/CRC Mode: %s", zep_data.lqi_mode?"CRC":"LQI");
+ if(!(zep_data.lqi_mode)){
+ proto_tree_add_uint(zep_tree, hf_zep_lqi, tvb, 7, 1, zep_data.lqi);
+ }
+ proto_tree_add_text(zep_tree, tvb, 7+((zep_data.lqi_mode)?0:1), 7+((zep_data.lqi_mode)?1:0), "Reserved Fields");
+ }
+ else {
+ proto_tree_add_uint(zep_tree, hf_zep_version, tvb, 2, 1, zep_data.version);
+ if (zep_data.type == ZEP_V2_TYPE_ACK) {
+ proto_tree_add_uint_format(zep_tree, hf_zep_version, tvb, 3, 1, zep_data.type, "Type: %i (Ack)", ZEP_V2_TYPE_ACK);
+ proto_tree_add_uint(zep_tree, hf_zep_seqno, tvb, 4, 4, zep_data.seqno);
+ }
+ else {
+ proto_tree_add_uint_format(zep_tree, hf_zep_version, tvb, 3, 1, zep_data.type, "Type: %i (%s)", zep_data.type, (zep_data.type==ZEP_V2_TYPE_DATA)?"Data":"Reserved");
+ proto_tree_add_uint(zep_tree, hf_zep_channel_id, tvb, 4, 1, zep_data.channel_id);
+ proto_tree_add_uint(zep_tree, hf_zep_device_id, tvb, 5, 2, zep_data.device_id);
+ proto_tree_add_boolean_format(zep_tree, hf_zep_lqi_mode, tvb, 7, 1, zep_data.lqi_mode, "LQI/CRC Mode: %s", zep_data.lqi_mode?"CRC":"LQI");
+ if(!(zep_data.lqi_mode)){
+ proto_tree_add_uint(zep_tree, hf_zep_lqi, tvb, 8, 1, zep_data.lqi);
+ }
+ pi = proto_tree_add_time(zep_tree, hf_zep_timestamp, tvb, 9, 8, &(zep_data.ntp_time));
+ proto_item_append_text(pi, " (%lu.%09lus)", (unsigned long)zep_data.ntp_time.secs, (unsigned long)zep_data.ntp_time.nsecs);
+ proto_tree_add_uint(zep_tree, hf_zep_seqno, tvb, 17, 4, zep_data.seqno);
+ }
+ }
+ if (!((zep_data.version==2) && (zep_data.type==ZEP_V2_TYPE_ACK))) proto_tree_add_uint_format(zep_tree, hf_zep_ieee_length, tvb, zep_header_len - 1, 1, ieee_packet_len, "Length: %i %s", ieee_packet_len, (ieee_packet_len==1)?"Byte":"Bytes");
+ }
+
+ /* Determine which dissector to call next. */
+ if (zep_data.lqi_mode) {
+ /* CRC present, use standard IEEE dissector. */
+ next_dissector = ieee802154_handle;
+ }
+ else {
+ /* ChipCon compliant FCS present. */
+ next_dissector = ieee802154_ccfcs_handle;
+ }
+ if (!next_dissector) {
+ /* IEEE 802.15.4 dissectors couldn't be found. */
+ next_dissector = data_handle;
+ }
+
+ /* Call the IEEE 802.15.4 dissector */
+ if (!((zep_data.version>=2) && (zep_data.type==ZEP_V2_TYPE_ACK))) {
+ next_tvb = tvb_new_subset(tvb, zep_header_len, ieee_packet_len, ieee_packet_len);
+ call_dissector(next_dissector, next_tvb, pinfo, tree);
+ }
+} /* dissect_ieee802_15_4 */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_register_zep
+ * DESCRIPTION
+ * IEEE 802.15.4 protocol registration routine.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+void proto_register_zep(void)
+{
+ module_t *zep_module;
+
+ static hf_register_info hf[] = {
+ { &hf_zep_version,
+ { "Protocol Version", "zep.version", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The version of the sniffer.", HFILL }},
+
+ { &hf_zep_type,
+ { "Type", "zep.type", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zep_channel_id,
+ { "Channel ID", "zep.channel_id", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The logical channel on which this packet was detected.", HFILL }},
+
+ { &hf_zep_device_id,
+ { "Device ID", "zep.device_id", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The ID of the device that detected this packet.", HFILL }},
+
+ { &hf_zep_lqi_mode,
+ { "LQI/CRC Mode", "zep.lqi_mode", FT_BOOLEAN, 8, NULL, 0x0,
+ "Determines what format the last two bytes of the MAC frame use.", HFILL }},
+
+ { &hf_zep_lqi,
+ { "Link Quality Indication", "zep.lqi", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zep_timestamp,
+ { "Timestamp", "zep.time", FT_ABSOLUTE_TIME, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zep_seqno,
+ { "Sequence Number", "zep.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zep_ieee_length,
+ { "Length", "zep.length", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The length (in bytes) of the encapsulated IEEE 802.15.4 MAC frame.", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_zep
+ };
+
+ /* Register protocol name and description. */
+ proto_zep = proto_register_protocol("ZigBee Encapsulation Protocol", "ZEP", "zep");
+
+ /* Register header fields and subtrees. */
+ proto_register_field_array(proto_zep, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register preferences module */
+ zep_module = prefs_register_protocol(proto_zep, proto_reg_handoff_zep);
+
+ /* Register preferences */
+ prefs_register_uint_preference(zep_module, "udp.port", "ZEP UDP port",
+ "Set the port for ZEP Protocol\n"
+ "Default port is 17754",
+ 10, &gPREF_zep_udp_port);
+
+ /* Register dissector with Ethereal. */
+ register_dissector("zep", dissect_zep, proto_zep);
+} /* proto_register_zep */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_reg_handoff_zep
+ * DESCRIPTION
+ * Registers the zigbee dissector with Ethereal.
+ * Will be called every time 'apply' is pressed in the preferences menu.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+void proto_reg_handoff_zep(void)
+{
+ static gboolean inited = FALSE;
+ static int lastPort;
+ dissector_handle_t h;
+ dissector_handle_t zep_handle;
+
+ /* Get dissector handles. */
+ if ( !(h = find_dissector("wpan")) ) { /* Try use built-in 802.15.4 disector */
+ h = find_dissector("ieee802154"); /* otherwise use older 802.15.4 plugin disector */
+ }
+ ieee802154_handle = h;
+ if ( !(h = find_dissector("wpan_cc24xx")) ) { /* Try use built-in 802.15.4 (Chipcon) disector */
+ h = find_dissector("ieee802154_ccfcs"); /* otherwise use older 802.15.4 (Chipcon) plugin disector */
+ }
+ ieee802154_ccfcs_handle = h;
+ zep_handle = find_dissector("zep");
+ data_handle = find_dissector("data");
+
+ if (inited){
+ /* If we were already registered, de-register our dissector
+ * to free the port. */
+ dissector_delete("udp.port", lastPort, zep_handle);
+ }
+
+ /* Register our dissector. */
+ dissector_add("udp.port", gPREF_zep_udp_port, zep_handle);
+ lastPort = gPREF_zep_udp_port;
+ inited = TRUE;
+} /* proto_reg_handoff_zep */
+