forked from osmocom/wireshark
![Michael Mann](/assets/img/avatar_default.png)
Similar to the "tcp.port" changes in I99604f95d426ad345f4b494598d94178b886eb67, convert dissectors that use "udp.port". More cleanup done on dissectors that use both TCP and UDP dissector tables, so that less preference callbacks exist. Change-Id: If07be9b9e850c244336a7069599cd554ce312dd3 Reviewed-on: https://code.wireshark.org/review/18120 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
354 lines
14 KiB
C
354 lines
14 KiB
C
/* packet-zep.c
|
|
* Dissector routines for the ZigBee Encapsulation Protocol
|
|
* By Owen Kirby <osk@exegin.com>
|
|
* Copyright 2009 Exegin Technologies Limited
|
|
*
|
|
* 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.
|
|
*------------------------------------------------------------
|
|
*
|
|
* 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 |
|
|
*------------------------------------------------------------
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
|
|
#include <epan/packet.h>
|
|
#include "packet-ntp.h"
|
|
|
|
#include "packet-zep.h"
|
|
|
|
/* Function declarations */
|
|
void proto_reg_handoff_zep(void);
|
|
void proto_register_zep(void);
|
|
|
|
/* 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;
|
|
static int hf_zep_protocol_id = -1;
|
|
static int hf_zep_reserved_field = -1;
|
|
|
|
/* Initialize protocol subtrees. */
|
|
static gint ett_zep = -1;
|
|
|
|
/* Dissector handle */
|
|
static dissector_handle_t zep_handle;
|
|
|
|
/* Subdissector handles */
|
|
static dissector_handle_t data_handle;
|
|
static dissector_handle_t ieee802154_handle;
|
|
static dissector_handle_t ieee802154_ccfcs_handle;
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
* NAME
|
|
* dissect_zep
|
|
* DESCRIPTION
|
|
* IEEE 802.15.4 packet dissection routine 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
|
|
* void
|
|
*---------------------------------------------------------------
|
|
*/
|
|
static int dissect_zep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
|
{
|
|
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_enc(wmem_packet_scope(), tvb, 0, 2, ENC_ASCII), ZEP_PREAMBLE)){
|
|
/* This is not a Q51/ZigBee sniffer packet */
|
|
return 0;
|
|
}
|
|
|
|
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, 9, &(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->abs_ts = zep_data.ntp_time;
|
|
}
|
|
#endif
|
|
|
|
if(ieee_packet_len < tvb_reported_length(tvb)-zep_header_len){
|
|
/* Packet's length is mis-reported, abort dissection */
|
|
return 0;
|
|
}
|
|
|
|
/* Enter name info protocol field */
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, (zep_data.version==1)?"ZEP":"ZEPv2");
|
|
|
|
/* Enter name info protocol field */
|
|
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_item(zep_tree, hf_zep_protocol_id, tvb, 0, 2, ENC_NA|ENC_ASCII);
|
|
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_item(zep_tree, hf_zep_reserved_field, tvb, 7+((zep_data.lqi_mode)?0:1), 7+((zep_data.lqi_mode)?1:0), ENC_NA);
|
|
}
|
|
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_value(zep_tree, hf_zep_type, tvb, 3, 1, zep_data.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_value(zep_tree, hf_zep_type, tvb, 3, 1, zep_data.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, " (%ld.%09ds)", (long)zep_data.ntp_time.secs, 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_value(zep_tree, hf_zep_ieee_length, tvb, zep_header_len - 1, 1, ieee_packet_len, "%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_length(tvb, zep_header_len, ieee_packet_len);
|
|
call_dissector(next_dissector, next_tvb, pinfo, tree);
|
|
}
|
|
return tvb_captured_length(tvb);
|
|
} /* 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)
|
|
{
|
|
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,
|
|
NULL, 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, BASE_NONE, 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,
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_zep_timestamp,
|
|
{ "Timestamp", "zep.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_zep_seqno,
|
|
{ "Sequence Number", "zep.seqno", FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
NULL, 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 }},
|
|
|
|
{ &hf_zep_protocol_id,
|
|
{ "Protocol ID String", "zep.protocol_id", FT_STRING, BASE_NONE, NULL, 0x0,
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_zep_reserved_field,
|
|
{ "Reserved Fields", "zep.reserved_field", FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
NULL, 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 dissector with Wireshark. */
|
|
zep_handle = register_dissector("zep", dissect_zep, proto_zep);
|
|
} /* proto_register_zep */
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
* NAME
|
|
* proto_reg_handoff_zep
|
|
* DESCRIPTION
|
|
* Registers the zigbee dissector with Wireshark.
|
|
* Will be called every time 'apply' is pressed in the preferences menu.
|
|
* PARAMETERS
|
|
* none
|
|
* RETURNS
|
|
* void
|
|
*---------------------------------------------------------------
|
|
*/
|
|
void proto_reg_handoff_zep(void)
|
|
{
|
|
dissector_handle_t h;
|
|
|
|
/* Get dissector handles. */
|
|
if ( !(h = find_dissector("wpan")) ) { /* Try use built-in 802.15.4 dissector */
|
|
h = find_dissector("ieee802154"); /* otherwise use older 802.15.4 plugin dissector */
|
|
}
|
|
ieee802154_handle = h;
|
|
if ( !(h = find_dissector("wpan_cc24xx")) ) { /* Try use built-in 802.15.4 (Chipcon) dissector */
|
|
h = find_dissector("ieee802154_ccfcs"); /* otherwise use older 802.15.4 (Chipcon) plugin dissector */
|
|
}
|
|
ieee802154_ccfcs_handle = h;
|
|
|
|
data_handle = find_dissector("data");
|
|
dissector_add_uint("udp.port", ZEP_DEFAULT_PORT, zep_handle);
|
|
} /* proto_reg_handoff_zep */
|
|
|
|
/*
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local variables:
|
|
* c-basic-offset: 4
|
|
* tab-width: 8
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
*/
|