aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-lwm.c
diff options
context:
space:
mode:
authorAlexis La Goutte <alexis.lagoutte@gmail.com>2014-01-20 18:35:45 +0000
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2014-01-20 18:35:45 +0000
commitd2410336b8539d65fae563aa919032c4ce2f77b2 (patch)
treecfea27605a5aee4438c62c254017eed04b3e23e4 /epan/dissectors/packet-lwm.c
parentc80e021e6f40f498db163d1bb4e63269f1c32129 (diff)
From Lubos via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9638
New Dissector For Lightweight Mesh protocol A dissector for ATMEL Lightweight Mesh protocol (lwm). The protocol is carried on the top of 802.15.4 frame. From me: * Add Modelines info * Fix indent (use 4 spaces) * Remove trailing whitespace svn path=/trunk/; revision=54856
Diffstat (limited to 'epan/dissectors/packet-lwm.c')
-rw-r--r--epan/dissectors/packet-lwm.c977
1 files changed, 977 insertions, 0 deletions
diff --git a/epan/dissectors/packet-lwm.c b/epan/dissectors/packet-lwm.c
new file mode 100644
index 0000000000..0bd3eea8cb
--- /dev/null
+++ b/epan/dissectors/packet-lwm.c
@@ -0,0 +1,977 @@
+/* packet-lwm.c
+ * Dissector routines for the ATMEL Lightweight Mesh 1.1.1
+ * Copyright 2013 Martin Leixner <info@sewio.net>
+ *
+ * $Id: packet-lwm.c v0.1.0 2013-12-15 16:49:22 $
+ *
+ * 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 "config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/expert.h>
+
+
+/*LwMesh lengths*/
+#define LWM_HEADER_BASE_LEN 7
+#define LWM_MIC_LEN 4
+#define LWM_MULTI_HEADER_LEN 2
+
+/* Bit-masks for the FCF */
+#define LWM_FCF_ACK_REQUEST 0x01
+#define LWM_FCF_SEC_EN 0x02
+
+#define LWM_FCF_LINK_LOCAL 0x04
+#define LWM_FCF_MULTICAST 0x08
+
+#define LWM_FCF_RESERVED 0xF0
+
+#define LWM_MULTI_NON_MEM_RAD_MASK 0x000F
+#define LWM_MULTI_NON_MEM_RAD_OFFSET 0
+
+#define LWM_MULTI_MAX_NON_MEM_RAD_MASK 0x00F0
+#define LWM_MULTI_MAX_NON_MEM_RAD_OFFSET 4
+
+#define LWM_MULTI_MEM_RAD_MASK 0x0F00
+#define LWM_MULTI_MEM_RAD_OFFSET 8
+
+#define LWM_MULTI_MAX_MEM_RAD_MASK 0xF000
+#define LWM_MULTI_MAX_MEM_RAD_OFFSET 12
+
+/*Endpoints*/
+#define LWM_SRC_ENDP_MASK 0xF0
+#define LWM_SRC_ENDP_OFFSET 4
+#define LWM_DST_ENDP_MASK 0x0F
+#define LWM_DST_ENDP_OFFSET 0
+
+/*Defined addresses*/
+#define LWM_BCAST_ADDR 0xFFFF
+
+/*Command IDs*/
+#define LWM_CMD_ACK 0x00
+#define LWM_CMD_ROUTE_ERR 0x01
+#define LWM_CMD_ROUTE_REQ 0x02
+#define LWM_CMD_ROUTE_REPLY 0x03
+
+/*Lengths of command frames*/
+#define LWM_CMD_FRAME_ACK_LEN 3
+#define LWM_CMD_FRAME_ROUTE_ERR_LEN 6
+#define LWM_CMD_FRAME_ROUTE_REQ_LEN 7
+#define LWM_CMD_FRAME_ROUTE_REPLY_LEN 8
+
+/*Values for multicast field*/
+#define LWM_CMD_MULTI_ADDR_FALSE 0
+#define LWM_CMD_MULTI_ADDR_TRUE 1
+
+/*Defined strings*/
+#define LWM_CMD_LINKQ_STRING "(Sent by Originate node)"
+#define LWM_CMD_UNKNOWN_VAL_STRING "Unknown command (0x%02x)"
+
+#define LWM_MULTI_UNICAST_STRING "(Unicast)"
+#define LWM_MULTI_GROUP_STRING "(Group ID)"
+
+/* Function declarations */
+void proto_reg_handoff_lwm(void);
+
+/* Dissector handles */
+static dissector_handle_t data_handle;
+
+/* Dissection Routines. */
+static void dissect_lwm (tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_lwm_cmd_frame_ack (tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_lwm_cmd_frame_route_err (tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_lwm_cmd_frame_route_req (tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_lwm_cmd_frame_route_reply (tvbuff_t *, packet_info *, proto_tree *);
+
+/* Initialize protocol and registered fields. */
+static int proto_lwm = -1;
+
+static int hf_lwm_fcf = -1;
+static int hf_lwm_fcf_ack_req = -1;
+static int hf_lwm_fcf_security = -1;
+static int hf_lwm_fcf_linklocal = -1;
+static int hf_lwm_fcf_multicast = -1;
+static int hf_lwm_fcf_reserved = -1;
+static int hf_lwm_seq = -1;
+static int hf_lwm_src_addr = -1;
+static int hf_lwm_dst_addr = -1;
+static int hf_lwm_src_endp = -1;
+static int hf_lwm_dst_endp = -1;
+static int hf_lwm_multi_nmrad = -1;
+static int hf_lwm_multi_mnmrad = -1;
+static int hf_lwm_multi_mrad = -1;
+static int hf_lwm_multi_mmrad = -1;
+static int hf_lwm_mic = -1;
+static int hf_lwm_cmd = -1;
+static int hf_lwm_cmd_seq = -1;
+static int hf_lwm_cmd_cm = -1;
+static int hf_lwm_cmd_route_src = -1;
+static int hf_lwm_cmd_route_dst = -1;
+static int hf_lwm_cmd_route_multi = -1;
+static int hf_lwm_cmd_linkquality = -1;
+static int hf_lwm_cmd_forwlinkquality = -1;
+static int hf_lwm_cmd_revlinkquality = -1;
+
+/* Initialize protocol subtrees. */
+static gint ett_lwm = -1;
+static gint ett_lwm_fcf = -1;
+static gint ett_lwm_cmd_tree = -1;
+static gint ett_lwm_multi_tree = -1;
+
+static expert_field ei_lwm_mal_error = EI_INIT;
+static expert_field ei_lwm_n_src_broad = EI_INIT;
+static expert_field ei_lwm_missmatch_endp = EI_INIT;
+static expert_field ei_lwm_empty_payload = EI_INIT;
+
+
+static const value_string lwm_cmd_names[] = {
+ { LWM_CMD_ACK, "LwMesh ACK" },
+ { LWM_CMD_ROUTE_ERR, "Route Error" },
+ { LWM_CMD_ROUTE_REQ, "Route Request" },
+ { LWM_CMD_ROUTE_REPLY, "Route Reply" },
+ { 0, NULL }
+};
+
+static const value_string lwm_cmd_multi_names[] = {
+ { LWM_CMD_MULTI_ADDR_FALSE, "FALSE" },
+ { LWM_CMD_MULTI_ADDR_TRUE, "TRUE" },
+ { 0, NULL }
+};
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_lwm_heur
+ * DESCRIPTION
+ * Heuristic interpreter for the Lightweight Mesh.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * RETURNS
+ * Boolean value, whether it handles the packet or not.
+ *---------------------------------------------------------------
+ */
+static gboolean
+dissect_lwm_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+
+ /* 1) first byte must have bits 0000xxxx */
+ if (tvb_get_guint8(tvb, 0) & LWM_FCF_RESERVED )
+ return (FALSE);
+
+ dissect_lwm(tvb, pinfo, tree);
+ return (TRUE);
+
+} /* dissect_lwm_heur */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_lwm
+ * DESCRIPTION
+ * Lightweight Mesh 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 void dissect_lwm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gint lwm_len = 0;
+ gint lwm_header_len = 0;
+ gint lwm_payload_len = 0;
+
+ guint8 lwm_fcf;
+ guint8 lwm_fcf_security;
+ guint8 lwm_fcf_multicast;
+
+ guint16 lwm_multi_header;
+
+ guint8 lwm_seq;
+ guint16 lwm_src_addr;
+ guint16 lwm_dst_addr;
+ guint8 lwm_endp_field;
+ guint8 lwm_src_endp;
+ guint8 lwm_dst_endp;
+ guint32 lwm_mic;
+ guint8 lwm_cmd;
+
+ proto_item *proto_root, *ti;
+ proto_tree *lwm_tree = NULL;
+ proto_tree *multi_tree = NULL;
+ proto_tree *field_tree = NULL;
+
+ /*---------------------------------------------------------*/
+
+ /*Get totaly length of LWM bytes (header + payload)*/
+ lwm_len = tvb_length(tvb);
+
+ /*Set base length of LWM header*/
+ lwm_header_len = LWM_HEADER_BASE_LEN;
+ lwm_payload_len = lwm_len - lwm_header_len;
+
+
+ /*--------------------------------------------------*/
+ /* */
+ /* Load dissector bytes */
+ /* */
+ /*--------------------------------------------------*/
+
+ lwm_fcf = tvb_get_guint8(tvb, 0);
+ lwm_fcf_security = (lwm_fcf & LWM_FCF_SEC_EN);
+
+ /*Check if security MIC is present*/
+ if(lwm_fcf_security & LWM_FCF_SEC_EN){
+ lwm_mic = tvb_get_ntohl(tvb, (lwm_len - LWM_MIC_LEN));
+ lwm_payload_len -= LWM_MIC_LEN;
+ }
+
+ lwm_fcf_multicast = (lwm_fcf & LWM_FCF_MULTICAST);
+
+ lwm_seq = tvb_get_guint8(tvb, 1);
+
+ lwm_src_addr = tvb_get_letohs(tvb, 2);
+ lwm_dst_addr = tvb_get_letohs(tvb, 4);
+
+ lwm_endp_field = tvb_get_guint8(tvb, 6);
+
+ lwm_src_endp = (lwm_endp_field & LWM_SRC_ENDP_MASK) >> LWM_SRC_ENDP_OFFSET;
+ lwm_dst_endp = (lwm_endp_field & LWM_DST_ENDP_MASK) >> LWM_DST_ENDP_OFFSET;
+
+ /*If multicast field is set to one, multicast header is present*/
+ if(lwm_fcf_multicast & LWM_FCF_MULTICAST){
+
+ lwm_multi_header = tvb_get_letohs(tvb, 7);
+
+ lwm_header_len += LWM_MULTI_HEADER_LEN;
+ lwm_payload_len -= LWM_MULTI_HEADER_LEN;
+ }
+
+ /*--------------------------------------------------*/
+ /* */
+ /* Create LwMesh dissector tree */
+ /* */
+ /*--------------------------------------------------*/
+ if(tree){
+ /* Create subtree for the LwMesh*/
+ proto_root = proto_tree_add_protocol_format(tree, proto_lwm, tvb, 0, lwm_len, "Lightweight Mesh, Sequence Number: %i", lwm_seq);
+ lwm_tree = proto_item_add_subtree(proto_root, ett_lwm);
+ }
+
+ /*Check wrong values of lengths*/
+ if(lwm_payload_len < 0){
+ expert_add_info_format(pinfo, lwm_tree, &ei_lwm_mal_error,"Wrong size of LwMesh packet (missing bytes or wrong field values)");
+
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO,"Lightweight Mesh[Malformed data!]");
+
+ return;
+ }
+
+ /*Enter name of protocol to info field*/
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LwMesh");
+
+
+ /*Enter description to info field*/
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO,"Lightweight Mesh, Nwk_Dst: 0x%04x, Nwk_Src: 0x%04x",lwm_dst_addr,lwm_src_addr);
+
+
+ if(tree){
+ /*--------------------------------------------------*/
+ /* */
+ /* Display LwMesh dissector tree */
+ /* */
+ /*--------------------------------------------------*/
+
+ /*Frame control fields*/
+ ti = proto_tree_add_uint(lwm_tree, hf_lwm_fcf, tvb, 0, 1, lwm_fcf);
+
+ field_tree = proto_item_add_subtree(ti, ett_lwm_fcf);
+ proto_tree_add_boolean(field_tree, hf_lwm_fcf_ack_req, tvb, 0, 1, (lwm_fcf & LWM_FCF_ACK_REQUEST));
+
+
+ proto_tree_add_boolean(field_tree, hf_lwm_fcf_security, tvb, 0, 1, lwm_fcf_security);
+ proto_tree_add_boolean(field_tree, hf_lwm_fcf_linklocal, tvb, 0, 1, (lwm_fcf & LWM_FCF_LINK_LOCAL));
+ proto_tree_add_boolean(field_tree, hf_lwm_fcf_multicast, tvb, 0, 1, lwm_fcf_multicast);
+ proto_tree_add_item(field_tree, hf_lwm_fcf_reserved, tvb, 0, 1, ENC_NA);
+
+ /*Sequence number*/
+ proto_tree_add_uint(lwm_tree, hf_lwm_seq, tvb, 1, 1, lwm_seq);
+
+ /*Network addresses*/
+ ti=proto_tree_add_uint(lwm_tree, hf_lwm_src_addr, tvb, 2, 2, lwm_src_addr);
+
+ /*Check value of source address*/
+ if(lwm_src_addr==LWM_BCAST_ADDR){
+ expert_add_info(pinfo, lwm_tree, &ei_lwm_n_src_broad);
+ }
+
+ /*Parse Source address*/
+ if(lwm_src_addr < 0x8000){
+ proto_item_append_text(ti, " (Routing node)");
+ }else{
+ proto_item_append_text(ti, " (Non-routing node)");
+ }
+
+ /*Parse Destination address*/
+ if(lwm_dst_addr==LWM_BCAST_ADDR){
+
+ proto_tree_add_uint_format_value(lwm_tree, hf_lwm_dst_addr, tvb, 4, 2, lwm_dst_addr,
+ "Broadcast (0x%04x)",lwm_dst_addr);
+
+ }else{
+ ti=proto_tree_add_uint(lwm_tree, hf_lwm_dst_addr, tvb, 4, 2, lwm_dst_addr);
+
+ if(lwm_fcf_multicast & LWM_FCF_MULTICAST){
+ proto_item_append_text(ti, " %s",LWM_MULTI_GROUP_STRING);
+ }else{
+ proto_item_append_text(ti, " %s",LWM_MULTI_UNICAST_STRING);
+
+ if(lwm_dst_addr < 0x8000){
+ proto_item_append_text(ti, " (Routing node)");
+ }else{
+ proto_item_append_text(ti, " (Non-routing node)");
+ }
+ }
+ }
+
+ /*Endpoints*/
+ ti = proto_tree_add_uint(lwm_tree, hf_lwm_src_endp, tvb, 6, 1, lwm_src_endp);
+ if(lwm_src_endp == 0){
+ proto_item_append_text(ti, " (Stack command endpoint)");
+ }
+
+ ti = proto_tree_add_uint(lwm_tree, hf_lwm_dst_endp, tvb, 6, 1, lwm_dst_endp);
+ if(lwm_dst_endp == 0){
+ proto_item_append_text(ti, " (Stack command endpoint)");
+ }
+
+ if( (lwm_src_endp == 0) && (lwm_dst_endp == 0)){
+ /*stack command endpoints*/
+
+ }
+ else if( (lwm_src_endp == 0) || (lwm_dst_endp == 0)){
+ /*If only one endpoint is 0, alert about that*/
+
+ col_append_fstr(pinfo->cinfo, COL_INFO,"[Stack command Endpoints missmatch]");
+
+ expert_add_info(pinfo, lwm_tree,&ei_lwm_missmatch_endp);
+ }
+
+ /*Multicast header*/
+ if( (lwm_fcf_multicast & LWM_FCF_MULTICAST) ){
+
+ ti = proto_tree_add_text(lwm_tree, tvb, 7,2, "Multicast Header");
+ multi_tree = proto_item_add_subtree(ti, ett_lwm_multi_tree);
+
+ proto_tree_add_uint(multi_tree, hf_lwm_multi_nmrad, tvb, 7, 2, (lwm_multi_header & LWM_MULTI_NON_MEM_RAD_MASK) >> LWM_MULTI_NON_MEM_RAD_OFFSET);
+ proto_tree_add_uint(multi_tree, hf_lwm_multi_mnmrad, tvb, 7, 2, (lwm_multi_header & LWM_MULTI_MAX_NON_MEM_RAD_MASK) >> LWM_MULTI_MAX_NON_MEM_RAD_OFFSET);
+ proto_tree_add_uint(multi_tree, hf_lwm_multi_mrad, tvb, 7, 2, (lwm_multi_header & LWM_MULTI_MEM_RAD_MASK) >> LWM_MULTI_MEM_RAD_OFFSET);
+ proto_tree_add_uint(multi_tree, hf_lwm_multi_mmrad, tvb, 7, 2, (lwm_multi_header & LWM_MULTI_MAX_MEM_RAD_MASK) >> LWM_MULTI_MAX_MEM_RAD_OFFSET);
+ }
+
+ /*MIC field*/
+ if(lwm_fcf_security & LWM_FCF_SEC_EN){
+ proto_tree_add_uint(lwm_tree, hf_lwm_mic, tvb, (lwm_len - LWM_MIC_LEN), LWM_MIC_LEN, lwm_mic);
+ }
+
+
+ }/*END OF: If(tree)*/
+
+ /*------------------------------*/
+ /* */
+ /* Dissect payload */
+ /* */
+ /*------------------------------*/
+ if(lwm_payload_len > 0){
+
+ tvbuff_t *new_tvb;
+
+ new_tvb = tvb_new_subset(tvb, lwm_header_len, lwm_payload_len, lwm_len);
+
+ /*Encrypted data*/
+ if(lwm_fcf_security & LWM_FCF_SEC_EN){
+
+ /*Enter name info protocol field*/
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO,"Encrypted data (%i byte(s)) ",lwm_payload_len);
+
+
+ call_dissector(data_handle, new_tvb, pinfo, tree);
+ return;
+ }
+ /*stack command endpoint 0 and not secured*/
+ else if( (lwm_src_endp == 0) && (lwm_dst_endp == 0) ){
+
+ /*----------------------------------------------------------------------*/
+ /* */
+ /* Call command dissector (depends on value of first byte of payload) */
+ /* */
+ /*----------------------------------------------------------------------*/
+ lwm_cmd = tvb_get_guint8(tvb, lwm_header_len);
+
+ switch (lwm_cmd) {
+
+ case LWM_CMD_ACK:
+ dissect_lwm_cmd_frame_ack(new_tvb, pinfo, tree);
+ break;
+
+ case LWM_CMD_ROUTE_ERR:
+ dissect_lwm_cmd_frame_route_err(new_tvb, pinfo, tree);
+ break;
+
+ case LWM_CMD_ROUTE_REQ:
+ dissect_lwm_cmd_frame_route_req(new_tvb, pinfo, tree);
+ break;
+
+ case LWM_CMD_ROUTE_REPLY:
+ dissect_lwm_cmd_frame_route_reply(new_tvb, pinfo, tree);
+ break;
+
+ default:
+ /*Unknown command*/
+ col_append_fstr(pinfo->cinfo, COL_INFO,", Unknown command (0x%02x bytes)",lwm_cmd);
+
+ call_dissector(data_handle, new_tvb, pinfo, tree);
+ return;
+ break;
+
+ }
+ }
+
+ else{
+ /*unknown data*/
+ call_dissector(data_handle, new_tvb, pinfo, tree);
+ return;
+
+ }
+
+ }else{
+ /*------------------*/
+ /* */
+ /* Empty payload */
+ /* */
+ /*------------------*/
+ expert_add_info(pinfo, lwm_tree, &ei_lwm_empty_payload);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO,"[Empty LwMesh Payload]");
+
+ }
+
+} /* dissect_lwm*/
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_lwm_cmd_frame_ack
+ * DESCRIPTION
+ * LwMesh command frame - Ack.
+ *
+ * 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 void dissect_lwm_cmd_frame_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *proto_root;
+ proto_tree *lwm_cmd_tree = NULL;
+
+ guint frame_len = 0;
+ guint8 lwm_cmd;
+ guint8 lwm_seq;
+
+ /*Get length command frame*/
+ frame_len = tvb_length(tvb);
+
+ /*Get fields*/
+ lwm_cmd = tvb_get_guint8(tvb, 0);
+ lwm_seq = tvb_get_guint8(tvb, 1);
+
+
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s, Sequence number: %d", val_to_str(lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING),lwm_seq);
+
+
+ if(tree){
+ proto_root = proto_tree_add_protocol_format(tree, proto_lwm, tvb, 0, -1, "%s, Sequence number: %d",
+ val_to_str(lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING),lwm_seq);
+
+ lwm_cmd_tree = proto_item_add_subtree(proto_root, ett_lwm_cmd_tree);
+
+ }
+
+ if(frame_len ==LWM_CMD_FRAME_ACK_LEN){
+
+ /* Create subtree for the Ack frame*/
+ if(tree){
+ proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd, tvb, 0, 1, lwm_cmd);
+ proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_seq, tvb, 1, 1, lwm_seq);
+ proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_cm, tvb, 2, 1, ENC_NA);
+ }
+
+ }else{
+ expert_add_info_format(pinfo, lwm_cmd_tree, &ei_lwm_mal_error,
+ "Size is %i byte(s), instead of %i bytes",frame_len,LWM_CMD_FRAME_ACK_LEN);
+ }
+
+} /* dissect_lwm_cmd_frame_ack*/
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_lwm_cmd_frame_route_err
+ * DESCRIPTION
+ * LwMesh command frame - Route error.
+ *
+ * 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 void dissect_lwm_cmd_frame_route_err(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *proto_root, *ti;
+ proto_tree *lwm_cmd_tree = NULL;
+
+ guint frame_len = 0;
+ guint8 lwm_cmd;
+ guint8 lwm_cmd_multi;
+ guint16 lwm_src_addr;
+ guint16 lwm_dst_addr;
+
+
+ frame_len = tvb_length(tvb);
+
+
+ lwm_cmd = tvb_get_guint8(tvb, 0);
+ lwm_src_addr = tvb_get_letohs(tvb, 1);
+ lwm_dst_addr = tvb_get_letohs(tvb, 3);
+ lwm_cmd_multi = tvb_get_guint8(tvb, 5);
+
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING));
+
+
+ if(tree){
+ proto_root = proto_tree_add_protocol_format(tree, proto_lwm, tvb, 0, -1, "%s", val_to_str(lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING));
+ lwm_cmd_tree = proto_item_add_subtree(proto_root, ett_lwm_cmd_tree);
+ }
+
+
+ if(frame_len ==LWM_CMD_FRAME_ROUTE_ERR_LEN){
+
+ /* Create subtree for the Ack frame*/
+ if(tree){
+ proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd, tvb, 0, 1, lwm_cmd);
+ proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_route_src, tvb, 1, 2, lwm_src_addr);
+ ti = proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_route_dst, tvb, 3, 2, lwm_dst_addr);
+
+ if(lwm_cmd_multi == LWM_CMD_MULTI_ADDR_TRUE){
+ proto_item_append_text(ti, " %s",LWM_MULTI_GROUP_STRING);
+ }else{
+ proto_item_append_text(ti, " %s",LWM_MULTI_UNICAST_STRING);
+ }
+
+ proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_multi, tvb, 5, 1, ENC_NA);
+ }
+
+ }else{
+ expert_add_info_format(pinfo, lwm_cmd_tree, &ei_lwm_mal_error,
+ "Size is %i byte(s), instead of %i bytes",frame_len,LWM_CMD_FRAME_ROUTE_ERR_LEN);
+ }
+
+} /* dissect_lwm_cmd_frame_route_err*/
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_lwm_cmd_frame_route_req
+ * DESCRIPTION
+ * LwMesh command frame - Route Request.
+ *
+ * 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 void dissect_lwm_cmd_frame_route_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *proto_root, *ti;
+ proto_tree *lwm_cmd_tree = NULL;
+
+ guint frame_len = 0;
+ guint8 lwm_cmd;
+ guint8 lwm_cmd_multi;
+ guint16 lwm_src_addr;
+ guint16 lwm_dst_addr;
+ guint8 lwm_linkqual;
+
+ frame_len = tvb_length(tvb);
+
+
+ lwm_cmd = tvb_get_guint8(tvb, 0);
+ lwm_src_addr = tvb_get_letohs(tvb, 1);
+ lwm_dst_addr = tvb_get_letohs(tvb, 3);
+ lwm_cmd_multi = tvb_get_guint8(tvb, 5);
+ lwm_linkqual = tvb_get_guint8(tvb, 6);
+
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING));
+
+
+ if(tree){
+ proto_root = proto_tree_add_protocol_format(tree, proto_lwm, tvb, 0, -1, "%s", val_to_str(lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING));
+ lwm_cmd_tree = proto_item_add_subtree(proto_root, ett_lwm_cmd_tree);
+ }
+
+
+ if(frame_len ==LWM_CMD_FRAME_ROUTE_REQ_LEN){
+
+ /* Create subtree for the Ack frame*/
+ if(tree){
+ proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd, tvb, 0, 1, lwm_cmd);
+ proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_route_src, tvb, 1, 2, lwm_src_addr);
+ ti = proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_route_dst, tvb, 3, 2, lwm_dst_addr);
+
+ if(lwm_cmd_multi == LWM_CMD_MULTI_ADDR_TRUE){
+ proto_item_append_text(ti, " %s",LWM_MULTI_GROUP_STRING);
+ }else{
+ proto_item_append_text(ti, " %s",LWM_MULTI_UNICAST_STRING);
+ }
+
+ proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_multi, tvb, 5, 1, ENC_NA);
+ ti = proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_linkquality, tvb, 6, 1, lwm_linkqual);
+ if(lwm_linkqual == 255){
+ proto_item_append_text(ti, " %s",LWM_CMD_LINKQ_STRING);
+ }
+ }
+
+ }else{
+ expert_add_info_format(pinfo, lwm_cmd_tree, &ei_lwm_mal_error,
+ "Size is %i byte(s), instead of %i bytes",frame_len,LWM_CMD_FRAME_ROUTE_REQ_LEN);
+ }
+
+} /* dissect_lwm_cmd_frame_route_req*/
+
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_lwm_cmd_frame_route_reply
+ * DESCRIPTION
+ * LwMesh command frame - Route Reply.
+ *
+ * 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 void dissect_lwm_cmd_frame_route_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *proto_root, *ti;
+ proto_tree *lwm_cmd_tree = NULL;
+
+ guint frame_len = 0;
+ guint8 lwm_cmd;
+ guint8 lwm_cmd_multi;
+ guint16 lwm_src_addr;
+ guint16 lwm_dst_addr;
+ guint8 lwm_revlinkqual;
+
+
+ frame_len = tvb_length(tvb);
+
+ lwm_cmd = tvb_get_guint8(tvb, 0);
+ lwm_src_addr = tvb_get_letohs(tvb, 1);
+ lwm_dst_addr = tvb_get_letohs(tvb, 3);
+ lwm_cmd_multi = tvb_get_guint8(tvb, 5);
+ lwm_revlinkqual = tvb_get_guint8(tvb, 7);
+
+
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING));
+
+
+ if(tree){
+ proto_root = proto_tree_add_protocol_format(tree, proto_lwm, tvb, 0, -1, "%s", val_to_str(lwm_cmd, lwm_cmd_names, LWM_CMD_UNKNOWN_VAL_STRING));
+ lwm_cmd_tree = proto_item_add_subtree(proto_root, ett_lwm_cmd_tree);
+ }
+
+
+ if(frame_len ==LWM_CMD_FRAME_ROUTE_REPLY_LEN){
+
+ /* Create subtree for the Ack frame*/
+ if(tree){
+ proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd, tvb, 0, 1, lwm_cmd);
+ proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_route_src, tvb, 1, 2, lwm_src_addr);
+ ti = proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_route_dst, tvb, 3, 2, lwm_dst_addr);
+
+ if(lwm_cmd_multi == LWM_CMD_MULTI_ADDR_TRUE){
+ proto_item_append_text(ti, " %s",LWM_MULTI_GROUP_STRING);
+ }else{
+ proto_item_append_text(ti, " %s",LWM_MULTI_UNICAST_STRING);
+ }
+
+ proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_route_multi, tvb, 5, 1, ENC_NA);
+ proto_tree_add_item(lwm_cmd_tree, hf_lwm_cmd_forwlinkquality, tvb, 6, 1, ENC_NA);
+ ti = proto_tree_add_uint(lwm_cmd_tree, hf_lwm_cmd_revlinkquality, tvb, 7, 1, lwm_revlinkqual);
+ if(lwm_revlinkqual == 255){
+ proto_item_append_text(ti, " %s",LWM_CMD_LINKQ_STRING);
+ }
+ }
+
+ }else{
+ expert_add_info_format(pinfo, lwm_cmd_tree, &ei_lwm_mal_error,
+ "Size is %i byte(s), instead of %i bytes",frame_len,LWM_CMD_FRAME_ROUTE_REPLY_LEN);
+ }
+
+} /* dissect_lwm_cmd_frame_route_reply*/
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_register_lwm
+ * DESCRIPTION
+ * IEEE 802.15.4 protocol registration routine.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+void proto_register_lwm(void)
+{
+
+ static hf_register_info hf[] = {
+
+ /*Frame control field*/
+ { &hf_lwm_fcf,
+ { "Frame control field", "lwm.fcf", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Control information for the frame.", HFILL }},
+
+ { &hf_lwm_fcf_ack_req,
+ { "Acknowledgment Request", "lwm.ack_req", FT_BOOLEAN, 8, NULL, LWM_FCF_ACK_REQUEST,
+ "Specifies whether an acknowledgment is required from the destination node.", HFILL }},
+
+ { &hf_lwm_fcf_security,
+ { "Security Enabled", "lwm.security", FT_BOOLEAN, 8, NULL, LWM_FCF_SEC_EN,
+ "Specifies whether the frame payload is encrypted.", HFILL }},
+
+ { &hf_lwm_fcf_linklocal,
+ { "Link Local", "lwm.linklocal", FT_BOOLEAN, 8, NULL, LWM_FCF_LINK_LOCAL,
+ "It may be set to one to prevent neighboring nodes from rebroadcasting a frame.", HFILL }},
+
+ { &hf_lwm_fcf_multicast,
+ { "Multicast", "lwm.multicast", FT_BOOLEAN, 8, NULL, LWM_FCF_MULTICAST,
+ "If the Multicast subfield is set to one, Multicast Header should be present and the Destination Address is a group address.", HFILL }},
+
+ { &hf_lwm_fcf_reserved,
+ { "Reserved bits", "lwm.fcf.reserved",FT_UINT8, BASE_HEX, NULL, LWM_FCF_RESERVED,
+ "The 4 bits are reserved.", HFILL }},
+
+ /*Other fields*/
+ { &hf_lwm_seq,
+ { "Sequence Number", "lwm.seq", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Specifies the sequence identifier for the frame.", HFILL }},
+
+ { &hf_lwm_src_addr,
+ { "Network Source Address", "lwm.src_addr", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Specifies the network address of the node originating the frame.", HFILL }},
+
+ { &hf_lwm_dst_addr,
+ { "Network Destination Address", "lwm.dst_addr", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Specifies the network address of the destination node or group address for multicast messages.", HFILL }},
+
+ { &hf_lwm_src_endp,
+ { "Source Endpoint", "lwm.src_endp", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Specifies the source endpoint identifier.", HFILL }},
+
+ { &hf_lwm_dst_endp,
+ { "Destination Endpoint", "lwm.dst_endp", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Specifies the destination endpoint identifier.", HFILL }},
+
+
+ /*Multicast header*/
+ { &hf_lwm_multi_nmrad,
+ { "Non-member Radius", "lwm.multi_nmrad", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Specifies remaining radius (number of hops) for Non-members of multicast group.", HFILL }},
+
+ { &hf_lwm_multi_mnmrad,
+ { "Maximum Non-member Radius", "lwm.multi_mnmrad", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Specifies maximum radius (number of hops) for Non-members of multicast group.", HFILL }},
+
+ { &hf_lwm_multi_mrad,
+ { "Member Radius", "lwm.multi_mrad", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Specifies remaining radius (number of hops) for Members of multicast group.", HFILL }},
+
+ { &hf_lwm_multi_mmrad,
+ { "Maximum Member Radius", "lwm.multi_mmrad", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Specifies maximum radius (number of hops) for Members of multicast group.", HFILL }},
+
+
+ /*MIC, security*/
+ { &hf_lwm_mic,
+ { "Message Integrity Code", "lwm.mic", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Specifies Message Integrity Code (MIC).", HFILL }},
+
+
+ /*----------------------------------*/
+ /* */
+ /* Command Frames Specific Fields */
+ /* */
+ /*----------------------------------*/
+
+ { &hf_lwm_cmd,
+ { "Command ID", "lwm.cmd", FT_UINT8, BASE_HEX, VALS(lwm_cmd_names), 0x0,
+ "It contains Command ID value.", HFILL }},
+
+ /* Command Frame - Ack */
+ { &hf_lwm_cmd_seq,
+ { "Sequence number", "lwm.cmd.seq", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "It contains a network sequence number of a frame that is being acknowledged.", HFILL }},
+
+ { &hf_lwm_cmd_cm,
+ { "Control Message", "lwm.cmd.cm", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "It contains an arbitrary value that can be set on the sending side.", HFILL }},
+
+ /* Part of Command Frames - Route Request, Route Reply*/
+ { &hf_lwm_cmd_route_src,
+ { "Source address", "lwm.cmd.route_src", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "It contains a source network address from the frame that cannot be routed", HFILL }},
+
+ { &hf_lwm_cmd_route_dst,
+ { "Destination Address", "lwm.cmd.route_dst", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "It contains a destination network address from the frame that cannot be routed", HFILL }},
+
+ { &hf_lwm_cmd_route_multi,
+ { "Multicast", "lwm.cmd.multi", FT_UINT8, BASE_HEX, VALS(&lwm_cmd_multi_names), 0x0,
+ "If it set to 0, Destination Address field contains a network address. If it set to 1, Destination Address field contains a group ID.", HFILL }},
+
+ /* Part of Command Frame - Route Request */
+ { &hf_lwm_cmd_linkquality,
+ { "Link Quality", "lwm.cmd.linkq", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "It contains a link quality value of the potential route accumulated over all hops towards the destination.", HFILL }},
+
+ /* Part of Command Frame - Route Reply */
+ { &hf_lwm_cmd_forwlinkquality,
+ { "Forward Link Quality", "lwm.cmd.flinkq", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "It contains a value of the Link Quality field from the corresponding Route Request Command Frame.", HFILL }},
+
+ { &hf_lwm_cmd_revlinkquality,
+ { "Reverse Link Quality", "lwm.cmd.rlinkq", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "It contains a link quality value of the discovered route accumulated over all hops towards the originator.", HFILL }},
+
+
+ };
+
+ /* Subtrees */
+ static gint *ett[] = {
+ &ett_lwm,
+ &ett_lwm_fcf,
+ &ett_lwm_multi_tree,
+ &ett_lwm_cmd_tree
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_lwm_mal_error, { "lwm.malformed_error", PI_MALFORMED, PI_ERROR, "Malformed Packet", EXPFILL }},
+ { &ei_lwm_n_src_broad, { "lwm.not_src_broadcast", PI_COMMENTS_GROUP, PI_NOTE, "Source address can not be broadcast address !", EXPFILL }},
+ { &ei_lwm_missmatch_endp, { "lwm.missmatch_endp", PI_COMMENTS_GROUP, PI_WARN, "Stack command Endpoints missmatch (should be 0, both)!", EXPFILL }},
+ { &ei_lwm_empty_payload, { "lwm.empty_payload", PI_COMMENTS_GROUP, PI_WARN, "Empty LwMesh Payload!", EXPFILL }},
+
+
+
+ };
+
+ expert_module_t* expert_lwm;
+
+ /* Register protocol name and description. */
+ proto_lwm = proto_register_protocol("Lightweight Mesh (v1.1.1)", "LwMesh", "lwm");
+
+ /* Register header fields and subtrees. */
+ proto_register_field_array(proto_lwm, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_lwm = expert_register_protocol(proto_lwm);
+ expert_register_field_array(expert_lwm, ei, array_length(ei));
+
+ /* Register dissector with Wireshark. */
+ register_dissector("lwm", dissect_lwm, proto_lwm);
+
+} /* proto_register_lwm */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_reg_handoff_lwm
+ * 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_lwm(void)
+{
+ static gboolean lwm_inited = FALSE;
+
+ if ( !lwm_inited )
+ {
+ data_handle = find_dissector("data");
+
+ /* Register our dissector with IEEE 802.15.4 */
+ heur_dissector_add("wpan", dissect_lwm_heur, proto_lwm);
+
+ lwm_inited = TRUE;
+ }
+
+} /* proto_reg_handoff_lwm */
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */