2009-10-03 10:06:19 +00:00
|
|
|
/* packet-6lowpan.c
|
|
|
|
* Routines for 6LoWPAN packet disassembly
|
|
|
|
* By Owen Kirby <osk@exegin.com>
|
|
|
|
* Copyright 2009 Owen Kirby
|
|
|
|
*
|
|
|
|
* 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
|
2012-06-28 22:56:06 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2009-10-03 10:06:19 +00:00
|
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <epan/packet.h>
|
2010-09-30 19:23:31 +00:00
|
|
|
#include <epan/prefs.h>
|
2009-10-03 10:06:19 +00:00
|
|
|
#include <epan/expert.h>
|
|
|
|
#include <epan/reassemble.h>
|
|
|
|
#include <epan/ipproto.h>
|
|
|
|
#include <epan/in_cksum.h>
|
2013-12-21 17:23:17 +00:00
|
|
|
#include <epan/addr_resolv.h>
|
2012-12-18 03:15:23 +00:00
|
|
|
#include <epan/wmem/wmem.h>
|
2011-02-23 13:51:49 +00:00
|
|
|
#include "packet-ipv6.h"
|
|
|
|
#include "packet-ieee802154.h"
|
2012-09-01 11:54:16 +00:00
|
|
|
#include "packet-6lowpan.h"
|
2013-12-15 23:44:12 +00:00
|
|
|
void proto_register_6lowpan(void);
|
|
|
|
void proto_reg_handoff_6lowpan(void);
|
2013-12-28 12:26:37 +00:00
|
|
|
#include "packet-zbee.h"
|
2013-12-15 23:44:12 +00:00
|
|
|
|
2009-10-04 17:50:39 +00:00
|
|
|
/* Definitions for 6lowpan packet disassembly structures and routines */
|
|
|
|
|
|
|
|
/* 6LoWPAN Patterns */
|
|
|
|
#define LOWPAN_PATTERN_NALP 0x00
|
|
|
|
#define LOWPAN_PATTERN_NALP_BITS 2
|
|
|
|
#define LOWPAN_PATTERN_IPV6 0x41
|
|
|
|
#define LOWPAN_PATTERN_IPV6_BITS 8
|
|
|
|
#define LOWPAN_PATTERN_HC1 0x42 /* Deprecated - replaced with IPHC. */
|
|
|
|
#define LOWPAN_PATTERN_HC1_BITS 8
|
|
|
|
#define LOWPAN_PATTERN_BC0 0x50
|
|
|
|
#define LOWPAN_PATTERN_BC0_BITS 8
|
2011-07-29 14:26:41 +00:00
|
|
|
#define LOWPAN_PATTERN_IPHC 0x03 /* See draft-ietf-6lowpan-hc-15.txt */
|
2009-10-04 17:50:39 +00:00
|
|
|
#define LOWPAN_PATTERN_IPHC_BITS 3
|
|
|
|
#define LOWPAN_PATTERN_ESC 0x7f
|
|
|
|
#define LOWPAN_PATTERN_ESC_BITS 8
|
|
|
|
#define LOWPAN_PATTERN_MESH 0x02
|
|
|
|
#define LOWPAN_PATTERN_MESH_BITS 2
|
|
|
|
#define LOWPAN_PATTERN_FRAG1 0x18
|
|
|
|
#define LOWPAN_PATTERN_FRAGN 0x1c
|
|
|
|
#define LOWPAN_PATTERN_FRAG_BITS 5
|
|
|
|
|
|
|
|
/* 6LoWPAN HC1 Header */
|
|
|
|
#define LOWPAN_HC1_SOURCE_PREFIX 0x80
|
|
|
|
#define LOWPAN_HC1_SOURCE_IFC 0x40
|
|
|
|
#define LOWPAN_HC1_DEST_PREFIX 0x20
|
|
|
|
#define LOWPAN_HC1_DEST_IFC 0x10
|
|
|
|
#define LOWPAN_HC1_TRAFFIC_CLASS 0x08
|
|
|
|
#define LOWPAN_HC1_NEXT 0x06
|
|
|
|
#define LOWPAN_HC1_MORE 0x01
|
|
|
|
|
|
|
|
/* IPv6 header field lengths (in bits) */
|
|
|
|
#define LOWPAN_IPV6_TRAFFIC_CLASS_BITS 8
|
|
|
|
#define LOWPAN_IPV6_FLOW_LABEL_BITS 20
|
|
|
|
#define LOWPAN_IPV6_NEXT_HEADER_BITS 8
|
|
|
|
#define LOWPAN_IPV6_HOP_LIMIT_BITS 8
|
|
|
|
#define LOWPAN_IPV6_PREFIX_BITS 64
|
|
|
|
#define LOWPAN_IPV6_INTERFACE_BITS 64
|
|
|
|
|
|
|
|
/* HC_UDP header field lengths (in bits). */
|
|
|
|
#define LOWPAN_UDP_PORT_BITS 16
|
|
|
|
#define LOWPAN_UDP_PORT_COMPRESSED_BITS 4
|
|
|
|
#define LOWPAN_UDP_LENGTH_BITS 16
|
|
|
|
#define LOWPAN_UDP_CHECKSUM_BITS 16
|
|
|
|
|
|
|
|
/* HC1 Next Header compression modes. */
|
|
|
|
#define LOWPAN_HC1_NEXT_NONE 0x00
|
|
|
|
#define LOWPAN_HC1_NEXT_UDP 0x01
|
|
|
|
#define LOWPAN_HC1_NEXT_ICMP 0x02
|
|
|
|
#define LOWPAN_HC1_NEXT_TCP 0x03
|
|
|
|
|
|
|
|
/* HC_UDP Header */
|
|
|
|
#define LOWPAN_HC2_UDP_SRCPORT 0x80
|
|
|
|
#define LOWPAN_HC2_UDP_DSTPORT 0x40
|
|
|
|
#define LOWPAN_HC2_UDP_LENGTH 0x20
|
|
|
|
#define LOWPAN_HC2_UDP_RESERVED 0x1f
|
|
|
|
|
|
|
|
/* IPHC Base flags */
|
|
|
|
#define LOWPAN_IPHC_FLAG_FLOW 0x1800
|
|
|
|
#define LOWPAN_IPHC_FLAG_NHDR 0x0400
|
|
|
|
#define LOWPAN_IPHC_FLAG_HLIM 0x0300
|
|
|
|
#define LOWPAN_IPHC_FLAG_CONTEXT_ID 0x0080
|
|
|
|
#define LOWPAN_IPHC_FLAG_SRC_COMP 0x0040
|
|
|
|
#define LOWPAN_IPHC_FLAG_SRC_MODE 0x0030
|
|
|
|
#define LOWPAN_IPHC_FLAG_MCAST_COMP 0x0008
|
|
|
|
#define LOWPAN_IPHC_FLAG_DST_COMP 0x0004
|
|
|
|
#define LOWPAN_IPHC_FLAG_DST_MODE 0x0003
|
|
|
|
#define LOWPAN_IPHC_FLAG_SCI 0xf0
|
|
|
|
#define LOWPAN_IPHC_FLAG_DCI 0x0f
|
|
|
|
/* Offsets for extracting integer fields. */
|
|
|
|
#define LOWPAN_IPHC_FLAG_OFFSET_FLOW 11
|
|
|
|
#define LOWPAN_IPHC_FLAG_OFFSET_HLIM 8
|
|
|
|
#define LOWPAN_IPHC_FLAG_OFFSET_SRC_MODE 4
|
|
|
|
#define LOWPAN_IPHC_FLAG_OFFSET_DST_MODE 0
|
2010-09-30 19:23:31 +00:00
|
|
|
#define LOWPAN_IPHC_FLAG_OFFSET_SCI 4
|
|
|
|
#define LOWPAN_IPHC_FLAG_OFFSET_DCI 0
|
2009-10-04 17:50:39 +00:00
|
|
|
|
|
|
|
/* IPHC Flow encoding values. */
|
|
|
|
#define LOWPAN_IPHC_FLOW_CLASS_LABEL 0x0
|
|
|
|
#define LOWPAN_IPHC_FLOW_ECN_LABEL 0x1
|
|
|
|
#define LOWPAN_IPHC_FLOW_CLASS 0x2
|
|
|
|
#define LOWPAN_IPHC_FLOW_COMPRESSED 0x3
|
|
|
|
|
|
|
|
/* IPHC Hop limit encoding. */
|
|
|
|
#define LOWPAN_IPHC_HLIM_INLINE 0x0
|
|
|
|
#define LOWPAN_IPHC_HLIM_1 0x1
|
|
|
|
#define LOWPAN_IPHC_HLIM_64 0x2
|
|
|
|
#define LOWPAN_IPHC_HLIM_255 0x3
|
|
|
|
|
|
|
|
/* IPHC address modes. */
|
2010-03-10 19:21:17 +00:00
|
|
|
#define LOWPAN_IPHC_ADDR_SRC_UNSPEC 0x0
|
2009-10-04 17:50:39 +00:00
|
|
|
#define LOWPAN_IPHC_ADDR_FULL_INLINE 0x0
|
|
|
|
#define LOWPAN_IPHC_ADDR_64BIT_INLINE 0x1
|
|
|
|
#define LOWPAN_IPHC_ADDR_16BIT_INLINE 0x2
|
|
|
|
#define LOWPAN_IPHC_ADDR_COMPRESSED 0x3
|
|
|
|
|
2010-02-12 22:10:53 +00:00
|
|
|
/* IPHC multicast address modes. */
|
2014-08-29 11:19:13 +00:00
|
|
|
#define LOWPAN_IPHC_MCAST_FULL 0x0
|
2010-02-12 22:10:53 +00:00
|
|
|
#define LOWPAN_IPHC_MCAST_48BIT 0x1
|
|
|
|
#define LOWPAN_IPHC_MCAST_32BIT 0x2
|
|
|
|
#define LOWPAN_IPHC_MCAST_8BIT 0x3
|
|
|
|
|
2014-08-29 11:19:13 +00:00
|
|
|
#define LOWPAN_IPHC_MCAST_STATEFUL_48BIT 0x0
|
2010-03-10 19:21:17 +00:00
|
|
|
|
2009-10-04 17:50:39 +00:00
|
|
|
/* IPHC Traffic class and flow label field sizes (in bits) */
|
|
|
|
#define LOWPAN_IPHC_ECN_BITS 2
|
|
|
|
#define LOWPAN_IPHC_DSCP_BITS 6
|
|
|
|
#define LOWPAN_IPHC_LABEL_BITS 20
|
|
|
|
/* Bitmasks for the reconstructed traffic class field. */
|
|
|
|
#define LOWPAN_IPHC_TRAFFIC_ECN 0x03
|
|
|
|
#define LOWPAN_IPHC_TRAFFIC_DSCP 0xfc
|
|
|
|
|
|
|
|
/* NHC Patterns. */
|
|
|
|
#define LOWPAN_NHC_PATTERN_EXT 0x0e
|
|
|
|
#define LOWPAN_NHC_PATTERN_EXT_BITS 4
|
|
|
|
#define LOWPAN_NHC_PATTERN_UDP 0x1e
|
|
|
|
#define LOWPAN_NHC_PATTERN_UDP_BITS 5
|
2011-07-29 14:26:41 +00:00
|
|
|
/* IP-in-IP tunneling is handled as a separate NHC pattern. */
|
|
|
|
#define LOWPAN_NHC_PATTERN_EXT_IPV6 ((LOWPAN_NHC_PATTERN_EXT << LOWPAN_NHC_EXT_EID_BITS) | LOWPAN_NHC_EID_IPV6)
|
|
|
|
#define LOWPAN_NHC_PATTERN_EXT_IPV6_BITS (LOWPAN_NHC_PATTERN_EXT_BITS + LOWPAN_NHC_EXT_EID_BITS)
|
2009-10-04 17:50:39 +00:00
|
|
|
|
|
|
|
/* NHC Extension header fields. */
|
|
|
|
#define LOWPAN_NHC_EXT_EID 0x0e
|
|
|
|
#define LOWPAN_NHC_EXT_EID_OFFSET 1
|
2011-07-29 14:26:41 +00:00
|
|
|
#define LOWPAN_NHC_EXT_EID_BITS 3
|
2009-10-04 17:50:39 +00:00
|
|
|
#define LOWPAN_NHC_EXT_NHDR 0x01
|
|
|
|
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Extension header ID codes. */
|
2009-10-04 17:50:39 +00:00
|
|
|
#define LOWPAN_NHC_EID_HOP_BY_HOP 0x00
|
|
|
|
#define LOWPAN_NHC_EID_ROUTING 0x01
|
|
|
|
#define LOWPAN_NHC_EID_FRAGMENT 0x02
|
|
|
|
#define LOWPAN_NHC_EID_DEST_OPTIONS 0x03
|
|
|
|
#define LOWPAN_NHC_EID_MOBILITY 0x04
|
|
|
|
#define LOWPAN_NHC_EID_IPV6 0x07
|
|
|
|
|
|
|
|
/* NHC UDP fields. */
|
|
|
|
#define LOWPAN_NHC_UDP_CHECKSUM 0x04
|
|
|
|
#define LOWPAN_NHC_UDP_SRCPORT 0x02
|
|
|
|
#define LOWPAN_NHC_UDP_DSTPORT 0x01
|
|
|
|
|
|
|
|
/* 6LoWPAN Mesh Header */
|
|
|
|
#define LOWPAN_MESH_HEADER_V 0x20
|
|
|
|
#define LOWPAN_MESH_HEADER_F 0x10
|
|
|
|
#define LOWPAN_MESH_HEADER_HOPS 0x0f
|
|
|
|
|
|
|
|
/* 6LoWPAN First Fragment Header */
|
|
|
|
#define LOWPAN_FRAG_DGRAM_SIZE_BITS 11
|
|
|
|
|
|
|
|
/* Compressed port number offset. */
|
|
|
|
#define LOWPAN_PORT_8BIT_OFFSET 0xf000
|
|
|
|
#define LOWPAN_PORT_12BIT_OFFSET (LOWPAN_PORT_8BIT_OFFSET | 0xb0)
|
|
|
|
|
|
|
|
/* 6LoWPAN interface identifier length. */
|
|
|
|
#define LOWPAN_IFC_ID_LEN 8
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Protocol fields handles. */
|
|
|
|
static int proto_6lowpan = -1;
|
|
|
|
static int hf_6lowpan_pattern = -1;
|
|
|
|
static int hf_6lowpan_nhc_pattern = -1;
|
|
|
|
|
|
|
|
/* Header compression fields. */
|
|
|
|
static int hf_6lowpan_hc1_source_prefix = -1;
|
|
|
|
static int hf_6lowpan_hc1_source_ifc = -1;
|
|
|
|
static int hf_6lowpan_hc1_dest_prefix = -1;
|
|
|
|
static int hf_6lowpan_hc1_dest_ifc = -1;
|
|
|
|
static int hf_6lowpan_hc1_class = -1;
|
|
|
|
static int hf_6lowpan_hc1_next = -1;
|
|
|
|
static int hf_6lowpan_hc1_more = -1;
|
|
|
|
static int hf_6lowpan_hc2_udp_src = -1;
|
|
|
|
static int hf_6lowpan_hc2_udp_dst = -1;
|
|
|
|
static int hf_6lowpan_hc2_udp_len = -1;
|
|
|
|
|
|
|
|
/* IPHC header field. */
|
|
|
|
static int hf_6lowpan_iphc_flag_tf = -1;
|
|
|
|
static int hf_6lowpan_iphc_flag_nhdr = -1;
|
|
|
|
static int hf_6lowpan_iphc_flag_hlim = -1;
|
|
|
|
static int hf_6lowpan_iphc_flag_cid = -1;
|
|
|
|
static int hf_6lowpan_iphc_flag_sac = -1;
|
|
|
|
static int hf_6lowpan_iphc_flag_sam = -1;
|
|
|
|
static int hf_6lowpan_iphc_flag_mcast = -1;
|
|
|
|
static int hf_6lowpan_iphc_flag_dac = -1;
|
|
|
|
static int hf_6lowpan_iphc_flag_dam = -1;
|
|
|
|
static int hf_6lowpan_iphc_sci = -1;
|
|
|
|
static int hf_6lowpan_iphc_dci = -1;
|
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
static int hf_6lowpan_iphc_sctx_prefix = -1;
|
|
|
|
static int hf_6lowpan_iphc_sctx_origin = -1;
|
|
|
|
static int hf_6lowpan_iphc_dctx_prefix = -1;
|
|
|
|
static int hf_6lowpan_iphc_dctx_origin = -1;
|
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/* NHC IPv6 extension header fields. */
|
|
|
|
static int hf_6lowpan_nhc_ext_eid = -1;
|
|
|
|
static int hf_6lowpan_nhc_ext_nh = -1;
|
|
|
|
static int hf_6lowpan_nhc_ext_next = -1;
|
|
|
|
static int hf_6lowpan_nhc_ext_length = -1;
|
|
|
|
|
|
|
|
/* NHC UDP compression header fields. */
|
|
|
|
static int hf_6lowpan_nhc_udp_checksum = -1;
|
|
|
|
static int hf_6lowpan_nhc_udp_src = -1;
|
|
|
|
static int hf_6lowpan_nhc_udp_dst = -1;
|
|
|
|
|
|
|
|
/* Inline IPv6 header fields. */
|
|
|
|
static int hf_6lowpan_traffic_class = -1;
|
|
|
|
static int hf_6lowpan_flow_label = -1;
|
|
|
|
static int hf_6lowpan_ecn = -1;
|
|
|
|
static int hf_6lowpan_dscp = -1;
|
|
|
|
static int hf_6lowpan_next_header = -1;
|
|
|
|
static int hf_6lowpan_hop_limit = -1;
|
|
|
|
static int hf_6lowpan_source = -1;
|
|
|
|
static int hf_6lowpan_dest = -1;
|
|
|
|
|
|
|
|
/* Inline UDP header fields. */
|
|
|
|
static int hf_6lowpan_udp_src = -1;
|
|
|
|
static int hf_6lowpan_udp_dst = -1;
|
|
|
|
static int hf_6lowpan_udp_len = -1;
|
|
|
|
static int hf_6lowpan_udp_checksum = -1;
|
|
|
|
|
|
|
|
/* Broadcast header fields. */
|
|
|
|
static int hf_6lowpan_bcast_seqnum = -1;
|
|
|
|
|
|
|
|
/* Mesh header fields. */
|
|
|
|
static int hf_6lowpan_mesh_v = -1;
|
|
|
|
static int hf_6lowpan_mesh_f = -1;
|
|
|
|
static int hf_6lowpan_mesh_hops = -1;
|
2010-07-23 20:19:05 +00:00
|
|
|
static int hf_6lowpan_mesh_hops8 = -1;
|
2009-10-03 10:06:19 +00:00
|
|
|
static int hf_6lowpan_mesh_orig16 = -1;
|
|
|
|
static int hf_6lowpan_mesh_orig64 = -1;
|
|
|
|
static int hf_6lowpan_mesh_dest16 = -1;
|
|
|
|
static int hf_6lowpan_mesh_dest64 = -1;
|
|
|
|
|
|
|
|
/* Fragmentation header fields. */
|
|
|
|
static int hf_6lowpan_frag_dgram_size = -1;
|
|
|
|
static int hf_6lowpan_frag_dgram_tag = -1;
|
|
|
|
static int hf_6lowpan_frag_dgram_offset = -1;
|
|
|
|
|
|
|
|
/* Protocol tree handles. */
|
|
|
|
static gint ett_6lowpan = -1;
|
|
|
|
static gint ett_6lowpan_hc1 = -1;
|
|
|
|
static gint ett_6lowpan_hc2_udp = -1;
|
|
|
|
static gint ett_6lowpan_iphc = -1;
|
|
|
|
static gint ett_6lowpan_nhc_ext = -1;
|
|
|
|
static gint ett_6lowpan_nhc_udp = -1;
|
|
|
|
static gint ett_6lowpan_bcast = -1;
|
|
|
|
static gint ett_6lowpan_mesh = -1;
|
|
|
|
static gint ett_6lowpan_mesh_flags = -1;
|
|
|
|
static gint ett_6lowpan_frag = -1;
|
|
|
|
static gint ett_6lopwan_traffic_class = -1;
|
|
|
|
|
2013-06-09 03:28:05 +00:00
|
|
|
static expert_field ei_6lowpan_hc1_more_bits = EI_INIT;
|
|
|
|
static expert_field ei_6lowpan_illegal_dest_addr_mode = EI_INIT;
|
|
|
|
static expert_field ei_6lowpan_bad_ipv6_header_length = EI_INIT;
|
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Subdissector handles. */
|
|
|
|
static dissector_handle_t data_handle;
|
|
|
|
static dissector_handle_t ipv6_handle;
|
|
|
|
|
|
|
|
/* Value Strings */
|
|
|
|
static const value_string lowpan_patterns [] = {
|
|
|
|
{ LOWPAN_PATTERN_NALP, "Not a LoWPAN frame" },
|
|
|
|
{ LOWPAN_PATTERN_IPV6, "Uncompressed IPv6" },
|
|
|
|
{ LOWPAN_PATTERN_HC1, "Header compression" },
|
|
|
|
{ LOWPAN_PATTERN_BC0, "Broadcast" },
|
|
|
|
{ LOWPAN_PATTERN_IPHC, "IP header compression" },
|
|
|
|
{ LOWPAN_PATTERN_ESC, "Escape" },
|
|
|
|
{ LOWPAN_PATTERN_MESH, "Mesh" },
|
|
|
|
{ LOWPAN_PATTERN_FRAG1, "First fragment" },
|
|
|
|
{ LOWPAN_PATTERN_FRAGN, "Fragment" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
static const true_false_string lowpan_compression = {
|
|
|
|
"Compressed",
|
|
|
|
"Inline"
|
|
|
|
};
|
|
|
|
static const value_string lowpan_hc1_next [] = {
|
|
|
|
{ LOWPAN_HC1_NEXT_NONE, "Inline" },
|
|
|
|
{ LOWPAN_HC1_NEXT_UDP, "UDP" },
|
|
|
|
{ LOWPAN_HC1_NEXT_ICMP, "ICMP" },
|
|
|
|
{ LOWPAN_HC1_NEXT_TCP, "TCP" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
static const value_string lowpan_iphc_traffic [] = {
|
|
|
|
{ LOWPAN_IPHC_FLOW_CLASS_LABEL, "Traffic class and flow label inline" },
|
|
|
|
{ LOWPAN_IPHC_FLOW_ECN_LABEL, "ECN and flow label inline" },
|
|
|
|
{ LOWPAN_IPHC_FLOW_CLASS, "Traffic class inline" },
|
|
|
|
{ LOWPAN_IPHC_FLOW_COMPRESSED, "Version, traffic class, and flow label compressed" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
static const value_string lowpan_iphc_hop_limit [] = {
|
|
|
|
{ LOWPAN_IPHC_HLIM_INLINE, "Inline" },
|
|
|
|
{ LOWPAN_IPHC_HLIM_1, "1" },
|
|
|
|
{ LOWPAN_IPHC_HLIM_64, "64" },
|
|
|
|
{ LOWPAN_IPHC_HLIM_255, "255" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
static const true_false_string lowpan_iphc_addr_compression = {
|
|
|
|
"Stateful",
|
|
|
|
"Stateless"
|
|
|
|
};
|
|
|
|
static const value_string lowpan_iphc_addr_modes [] = {
|
|
|
|
{ LOWPAN_IPHC_ADDR_FULL_INLINE, "Inline" },
|
|
|
|
{ LOWPAN_IPHC_ADDR_64BIT_INLINE,"64-bits inline" },
|
|
|
|
{ LOWPAN_IPHC_ADDR_16BIT_INLINE,"16-bits inline" },
|
|
|
|
{ LOWPAN_IPHC_ADDR_COMPRESSED, "Compressed" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
2014-08-29 11:19:13 +00:00
|
|
|
static const value_string lowpan_iphc_saddr_stateful_modes [] = {
|
|
|
|
{ LOWPAN_IPHC_ADDR_FULL_INLINE, "Unspecified address (::)" },
|
|
|
|
{ LOWPAN_IPHC_ADDR_64BIT_INLINE,"64-bits inline" },
|
|
|
|
{ LOWPAN_IPHC_ADDR_16BIT_INLINE,"16-bits inline" },
|
|
|
|
{ LOWPAN_IPHC_ADDR_COMPRESSED, "Compressed" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
static const value_string lowpan_iphc_daddr_stateful_modes [] = {
|
|
|
|
{ LOWPAN_IPHC_ADDR_64BIT_INLINE,"64-bits inline" },
|
|
|
|
{ LOWPAN_IPHC_ADDR_16BIT_INLINE,"16-bits inline" },
|
|
|
|
{ LOWPAN_IPHC_ADDR_COMPRESSED, "Compressed" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
2010-02-12 22:10:53 +00:00
|
|
|
static const value_string lowpan_iphc_mcast_modes [] = {
|
2014-08-29 11:19:13 +00:00
|
|
|
{ LOWPAN_IPHC_MCAST_FULL, "Inline" },
|
2010-02-12 22:10:53 +00:00
|
|
|
{ LOWPAN_IPHC_MCAST_48BIT, "48-bits inline" },
|
|
|
|
{ LOWPAN_IPHC_MCAST_32BIT, "32-bits inline" },
|
|
|
|
{ LOWPAN_IPHC_MCAST_8BIT, "8-bits inline" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
2014-08-29 11:19:13 +00:00
|
|
|
static const value_string lowpan_iphc_mcast_stateful_modes [] = {
|
|
|
|
{ LOWPAN_IPHC_MCAST_STATEFUL_48BIT, "48-bits inline" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
2009-10-03 10:06:19 +00:00
|
|
|
static const value_string lowpan_nhc_patterns [] = {
|
|
|
|
{ LOWPAN_NHC_PATTERN_EXT, "IPv6 extension header" },
|
|
|
|
{ LOWPAN_NHC_PATTERN_UDP, "UDP compression header" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
static const value_string lowpan_nhc_eid [] = {
|
|
|
|
{ LOWPAN_NHC_EID_HOP_BY_HOP, "IPv6 hop-by-hop options" },
|
|
|
|
{ LOWPAN_NHC_EID_ROUTING, "IPv6 routing" },
|
|
|
|
{ LOWPAN_NHC_EID_FRAGMENT, "IPv6 fragment" },
|
|
|
|
{ LOWPAN_NHC_EID_DEST_OPTIONS, "IPv6 destination options" },
|
|
|
|
{ LOWPAN_NHC_EID_MOBILITY, "IPv6 mobility header" },
|
|
|
|
{ LOWPAN_NHC_EID_IPV6, "IPv6 header" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
/* Reassembly Data */
|
|
|
|
static int hf_6lowpan_fragments = -1;
|
|
|
|
static int hf_6lowpan_fragment = -1;
|
|
|
|
static int hf_6lowpan_fragment_overlap = -1;
|
|
|
|
static int hf_6lowpan_fragment_overlap_conflicts = -1;
|
|
|
|
static int hf_6lowpan_fragment_multiple_tails = -1;
|
|
|
|
static int hf_6lowpan_fragment_too_long_fragment = -1;
|
|
|
|
static int hf_6lowpan_fragment_error = -1;
|
2011-01-30 21:01:07 +00:00
|
|
|
static int hf_6lowpan_fragment_count = -1;
|
2009-10-03 10:06:19 +00:00
|
|
|
static int hf_6lowpan_reassembled_in = -1;
|
2010-02-02 16:01:52 +00:00
|
|
|
static int hf_6lowpan_reassembled_length = -1;
|
2009-10-03 10:06:19 +00:00
|
|
|
static gint ett_6lowpan_fragment = -1;
|
|
|
|
static gint ett_6lowpan_fragments = -1;
|
|
|
|
|
|
|
|
static const fragment_items lowpan_frag_items = {
|
|
|
|
/* Fragment subtrees */
|
|
|
|
&ett_6lowpan_fragment,
|
|
|
|
&ett_6lowpan_fragments,
|
|
|
|
/* Fragment fields */
|
|
|
|
&hf_6lowpan_fragments,
|
|
|
|
&hf_6lowpan_fragment,
|
|
|
|
&hf_6lowpan_fragment_overlap,
|
|
|
|
&hf_6lowpan_fragment_overlap_conflicts,
|
|
|
|
&hf_6lowpan_fragment_multiple_tails,
|
|
|
|
&hf_6lowpan_fragment_too_long_fragment,
|
|
|
|
&hf_6lowpan_fragment_error,
|
2011-01-30 21:01:07 +00:00
|
|
|
&hf_6lowpan_fragment_count,
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Reassembled in field */
|
|
|
|
&hf_6lowpan_reassembled_in,
|
2010-02-02 16:01:52 +00:00
|
|
|
/* Reassembled length field */
|
|
|
|
&hf_6lowpan_reassembled_length,
|
2012-09-07 02:09:59 +00:00
|
|
|
/* Reassembled data field */
|
|
|
|
NULL,
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Tag */
|
|
|
|
"6LoWPAN fragments"
|
|
|
|
};
|
|
|
|
|
2013-03-22 23:59:54 +00:00
|
|
|
static reassembly_table lowpan_reassembly_table;
|
2012-09-01 11:54:16 +00:00
|
|
|
static GHashTable *lowpan_context_table = NULL;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Link-Local prefix used by 6LoWPAN (FF80::/10) */
|
2009-10-03 10:06:19 +00:00
|
|
|
static const guint8 lowpan_llprefix[8] = {
|
|
|
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
|
|
};
|
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Context hash table map key. */
|
|
|
|
typedef struct {
|
|
|
|
guint16 pan; /* PAN Identifier */
|
|
|
|
guint8 cid; /* Context Identifier */
|
|
|
|
} lowpan_context_key;
|
|
|
|
|
|
|
|
/* Context hash table map data. */
|
|
|
|
typedef struct {
|
|
|
|
guint frame; /* Frame where the context was discovered. */
|
|
|
|
guint8 plen; /* Prefix length. */
|
|
|
|
struct e_in6_addr prefix; /* Compression context. */
|
|
|
|
} lowpan_context_data;
|
|
|
|
|
|
|
|
/* 6LoWPAN contexts. */
|
|
|
|
#define LOWPAN_CONTEXT_MAX 16
|
|
|
|
#define LOWPAN_CONTEXT_DEFAULT 0
|
|
|
|
#define LOWPAN_CONTEXT_LINK_LOCAL LOWPAN_CONTEXT_MAX
|
|
|
|
#define LOWPAN_CONTEXT_LINK_LOCAL_BITS 10
|
|
|
|
static lowpan_context_data lowpan_context_local;
|
|
|
|
static lowpan_context_data lowpan_context_default;
|
|
|
|
static const gchar * lowpan_context_prefs[LOWPAN_CONTEXT_MAX];
|
2010-09-30 19:23:31 +00:00
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Helper macro to convert a bit offset/length into a byte count. */
|
|
|
|
#define BITS_TO_BYTE_LEN(bitoff, bitlen) ((bitlen)?(((bitlen) + ((bitoff)&0x07) + 7) >> 3):(0))
|
|
|
|
|
|
|
|
/* Structure for rebuilding UDP datagrams. */
|
|
|
|
struct udp_hdr {
|
|
|
|
guint16 src_port;
|
|
|
|
guint16 dst_port;
|
|
|
|
guint16 length;
|
|
|
|
guint16 checksum;
|
|
|
|
};
|
|
|
|
|
2009-10-04 17:50:39 +00:00
|
|
|
/* Structure used to store decompressed header chains until reassembly. */
|
2009-10-03 10:06:19 +00:00
|
|
|
struct lowpan_nhdr {
|
|
|
|
/* List Linking */
|
|
|
|
struct lowpan_nhdr *next;
|
|
|
|
/* Next Header */
|
|
|
|
guint8 proto;
|
|
|
|
guint length;
|
|
|
|
guint reported;
|
|
|
|
};
|
2010-09-30 19:23:31 +00:00
|
|
|
#define LOWPAN_NHDR_DATA(nhdr) ((guint8 *)(nhdr) + sizeof (struct lowpan_nhdr))
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2009-10-04 17:50:39 +00:00
|
|
|
/* Dissector prototypes */
|
2010-03-09 23:22:03 +00:00
|
|
|
static void proto_init_6lowpan (void);
|
2010-09-30 19:23:31 +00:00
|
|
|
static void prefs_6lowpan_apply (void);
|
2014-04-18 03:33:42 +00:00
|
|
|
static int dissect_6lowpan (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
|
2010-03-09 23:22:03 +00:00
|
|
|
static tvbuff_t * dissect_6lowpan_ipv6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
|
2014-09-18 05:20:01 +00:00
|
|
|
static tvbuff_t * dissect_6lowpan_hc1 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint dgram_size, const guint8 *siid, const guint8 *diid);
|
2010-03-09 23:22:03 +00:00
|
|
|
static tvbuff_t * dissect_6lowpan_bc0 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
|
2014-09-18 05:20:01 +00:00
|
|
|
static tvbuff_t * dissect_6lowpan_iphc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint dgram_size, const guint8 *siid, const guint8 *diid);
|
2012-03-06 02:28:04 +00:00
|
|
|
static struct lowpan_nhdr *
|
2014-09-18 05:20:01 +00:00
|
|
|
dissect_6lowpan_iphc_nhc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint dgram_size, const guint8 *siid, const guint8 *diid);
|
|
|
|
static tvbuff_t * dissect_6lowpan_mesh (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 *siid, guint8 *diid);
|
|
|
|
static tvbuff_t * dissect_6lowpan_frag_first (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const guint8 *siid, const guint8 *diid);
|
2010-03-09 23:22:03 +00:00
|
|
|
static tvbuff_t * dissect_6lowpan_frag_middle (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
|
|
|
|
static void dissect_6lowpan_unknown (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
|
2009-10-04 17:50:39 +00:00
|
|
|
|
|
|
|
/* Helper functions. */
|
|
|
|
static gboolean lowpan_dlsrc_to_ifcid (packet_info *pinfo, guint8 *ifcid);
|
|
|
|
static gboolean lowpan_dldst_to_ifcid (packet_info *pinfo, guint8 *ifcid);
|
2010-09-30 19:23:31 +00:00
|
|
|
static void lowpan_addr16_to_ifcid (guint16 addr, guint8 *ifcid);
|
2010-01-13 07:42:42 +00:00
|
|
|
static tvbuff_t * lowpan_reassemble_ipv6 (tvbuff_t *tvb, struct ip6_hdr * ipv6, struct lowpan_nhdr * nhdr_list);
|
2009-10-04 17:50:39 +00:00
|
|
|
static guint8 lowpan_parse_nhc_proto (tvbuff_t *tvb, gint offset);
|
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Context table helpers */
|
|
|
|
static guint lowpan_context_hash (gconstpointer key);
|
|
|
|
static gboolean lowpan_context_equal (gconstpointer a, gconstpointer b);
|
|
|
|
static lowpan_context_data *lowpan_context_find(guint8 cid, guint16 pan);
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_pfxcpy
|
|
|
|
* DESCRIPTION
|
2012-09-07 02:09:59 +00:00
|
|
|
* A version of memcpy that takes a length in bits. If the
|
2012-09-01 11:54:16 +00:00
|
|
|
* length is not byte-aligned, the final byte will be
|
|
|
|
* manipulated so that only the desired number of bits are
|
|
|
|
* copied.
|
|
|
|
* PARAMETERS
|
|
|
|
* dst ; Destination.
|
|
|
|
* src ; Source.
|
|
|
|
* bits ; Number of bits to copy.
|
|
|
|
* RETURNS
|
|
|
|
* void ;
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
lowpan_pfxcpy(void *dst, const void *src, size_t bits)
|
|
|
|
{
|
|
|
|
memcpy(dst, src, bits>>3);
|
|
|
|
if (bits & 0x7) {
|
|
|
|
guint8 mask = ((0xff00) >> (bits & 0x7));
|
2013-12-08 23:16:06 +00:00
|
|
|
guint8 last = ((const guint8 *)src)[bits>>3] & mask;
|
2012-09-01 11:54:16 +00:00
|
|
|
((guint8 *)dst)[bits>>3] &= ~mask;
|
|
|
|
((guint8 *)dst)[bits>>3] |= last;
|
|
|
|
}
|
|
|
|
} /* lowpan_pfxcpy */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_context_hash
|
|
|
|
* DESCRIPTION
|
|
|
|
* Context table hash function.
|
|
|
|
* PARAMETERS
|
|
|
|
* key ; Pointer to a lowpan_context_key type.
|
|
|
|
* RETURNS
|
|
|
|
* guint ; The hashed key value.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static guint
|
|
|
|
lowpan_context_hash(gconstpointer key)
|
|
|
|
{
|
2013-12-08 23:16:06 +00:00
|
|
|
return (((const lowpan_context_key *)key)->cid) | (((const lowpan_context_key *)key)->pan << 8);
|
2012-09-01 11:54:16 +00:00
|
|
|
} /* lowpan_context_hash */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_context_equal
|
|
|
|
* DESCRIPTION
|
|
|
|
* Context table equals function.
|
|
|
|
* PARAMETERS
|
|
|
|
* key ; Pointer to a lowpan_context_key type.
|
|
|
|
* RETURNS
|
2012-09-07 02:09:59 +00:00
|
|
|
* gboolean ;
|
2012-09-01 11:54:16 +00:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
lowpan_context_equal(gconstpointer a, gconstpointer b)
|
|
|
|
{
|
2013-12-08 23:16:06 +00:00
|
|
|
return (((const lowpan_context_key *)a)->pan == ((const lowpan_context_key *)b)->pan) &&
|
|
|
|
(((const lowpan_context_key *)a)->cid == ((const lowpan_context_key *)b)->cid);
|
2012-09-01 11:54:16 +00:00
|
|
|
} /* lowpan_context_equal */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_context_find
|
|
|
|
* DESCRIPTION
|
|
|
|
* Context table lookup function.
|
|
|
|
* PARAMETERS
|
|
|
|
* cid ; Context identifier.
|
|
|
|
* pan ; PAN identifier.
|
|
|
|
* RETURNS
|
2012-09-07 02:09:59 +00:00
|
|
|
* lowpan_context_data *;
|
2012-09-01 11:54:16 +00:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static lowpan_context_data *
|
|
|
|
lowpan_context_find(guint8 cid, guint16 pan)
|
|
|
|
{
|
|
|
|
lowpan_context_key key;
|
|
|
|
lowpan_context_data *data;
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Check for the internal link-local context. */
|
|
|
|
if (cid == LOWPAN_CONTEXT_LINK_LOCAL) return &lowpan_context_local;
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Lookup the context from the table. */
|
|
|
|
key.pan = pan;
|
|
|
|
key.cid = cid;
|
2013-03-19 20:00:52 +00:00
|
|
|
data = (lowpan_context_data *)g_hash_table_lookup(lowpan_context_table, &key);
|
2012-09-01 11:54:16 +00:00
|
|
|
if (data) return data;
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* If we didn't find a match, try again with the broadcast PAN. */
|
|
|
|
if (pan != IEEE802154_BCAST_PAN) {
|
|
|
|
key.pan = IEEE802154_BCAST_PAN;
|
2013-03-19 20:00:52 +00:00
|
|
|
data = (lowpan_context_data *)g_hash_table_lookup(lowpan_context_table, &key);
|
2012-09-01 11:54:16 +00:00
|
|
|
if (data) return data;
|
|
|
|
}
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* If the lookup failed, return the default context (::/0) */
|
|
|
|
return &lowpan_context_default;
|
|
|
|
} /* lowpan_context_find */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_context_insert
|
|
|
|
* DESCRIPTION
|
|
|
|
* Context table insert function.
|
|
|
|
* PARAMETERS
|
|
|
|
* cid ; Context identifier.
|
|
|
|
* pan ; PAN identifier.
|
|
|
|
* plen ; Prefix length.
|
|
|
|
* prefix ; Compression prefix.
|
|
|
|
* frame ; Frame number.
|
|
|
|
* RETURNS
|
2012-09-07 02:09:59 +00:00
|
|
|
* void ;
|
2012-09-01 11:54:16 +00:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
lowpan_context_insert(guint8 cid, guint16 pan, guint8 plen, struct e_in6_addr *prefix, guint frame)
|
|
|
|
{
|
|
|
|
lowpan_context_key key;
|
|
|
|
lowpan_context_data *data;
|
|
|
|
gpointer pkey;
|
|
|
|
gpointer pdata;
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Sanity! */
|
|
|
|
if (plen > 128) return;
|
|
|
|
if (!prefix) return;
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Search the context table for an existing entry. */
|
|
|
|
key.pan = pan;
|
|
|
|
key.cid = cid;
|
|
|
|
if (g_hash_table_lookup_extended(lowpan_context_table, &key, &pkey, &pdata)) {
|
|
|
|
/* Context already exists. */
|
2013-03-19 20:00:52 +00:00
|
|
|
data = (lowpan_context_data *)pdata;
|
2012-09-01 11:54:16 +00:00
|
|
|
if ( (data->plen == plen) && (memcmp(&data->prefix, prefix, (plen+7)/8) == 0) ) {
|
|
|
|
/* Context already exists with no change. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2013-09-12 20:37:30 +00:00
|
|
|
pkey = wmem_memdup(wmem_file_scope(), &key, sizeof(key));
|
2012-09-01 11:54:16 +00:00
|
|
|
}
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Create a new context */
|
2013-09-12 20:37:30 +00:00
|
|
|
data = wmem_new(wmem_file_scope(), lowpan_context_data);
|
2012-09-01 11:54:16 +00:00
|
|
|
data->frame = frame;
|
|
|
|
data->plen = plen;
|
|
|
|
memset(&data->prefix, 0, sizeof(struct e_in6_addr)); /* Ensure zero paddeding */
|
|
|
|
lowpan_pfxcpy(&data->prefix, prefix, plen);
|
|
|
|
g_hash_table_insert(lowpan_context_table, pkey, data);
|
|
|
|
} /* lowpan_context_insert */
|
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_addr16_to_ifcid
|
|
|
|
* DESCRIPTION
|
|
|
|
* Converts a short address to in interface identifier as
|
|
|
|
* per rfc 4944 section 6.
|
|
|
|
* PARAMETERS
|
|
|
|
* addr ; 16-bit short address.
|
|
|
|
* ifcid ; interface identifier (output).
|
|
|
|
* RETURNS
|
|
|
|
* void ;
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
2010-09-30 19:23:31 +00:00
|
|
|
lowpan_addr16_to_ifcid(guint16 addr, guint8 *ifcid)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
2010-09-30 19:23:31 +00:00
|
|
|
/* Note: The PANID is no longer used in building the IID. */
|
|
|
|
ifcid[0] = 0x00; /* the U/L bit must be cleared. */
|
|
|
|
ifcid[1] = 0x00;
|
2009-10-03 10:06:19 +00:00
|
|
|
ifcid[2] = 0x00;
|
|
|
|
ifcid[3] = 0xff;
|
|
|
|
ifcid[4] = 0xfe;
|
|
|
|
ifcid[5] = 0x00;
|
|
|
|
ifcid[6] = (addr >> 8) & 0xff;
|
|
|
|
ifcid[7] = (addr >> 0) & 0xff;
|
|
|
|
} /* lowpan_addr16_to_ifcid */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_dlsrc_to_ifcid
|
|
|
|
* DESCRIPTION
|
|
|
|
* Finds an interface identifier from the data-link source
|
|
|
|
* addressing.
|
|
|
|
* PARAMETERS
|
|
|
|
* pinfo ; packet information.
|
|
|
|
* ifcid ; interface identifier (output).
|
|
|
|
* RETURNS
|
|
|
|
* gboolean ; TRUE if an interface identifier could
|
|
|
|
* be found.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
lowpan_dlsrc_to_ifcid(packet_info *pinfo, guint8 *ifcid)
|
|
|
|
{
|
2012-09-01 11:54:16 +00:00
|
|
|
ieee802154_hints_t *hints;
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Check the link-layer address field. */
|
|
|
|
if (pinfo->dl_src.type == AT_EUI64) {
|
|
|
|
memcpy(ifcid, pinfo->dl_src.data, LOWPAN_IFC_ID_LEN);
|
2010-02-09 08:40:40 +00:00
|
|
|
/* RFC2464: Invert the U/L bit when using an EUI64 address. */
|
|
|
|
ifcid[0] ^= 0x02;
|
2009-10-03 10:06:19 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Lookup the IEEE 802.15.4 addressing hints. */
|
2013-11-23 02:20:13 +00:00
|
|
|
hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
|
2013-05-12 18:11:02 +00:00
|
|
|
proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
|
2012-09-01 11:54:16 +00:00
|
|
|
if (hints) {
|
|
|
|
lowpan_addr16_to_ifcid(hints->src16, ifcid);
|
2009-10-03 10:06:19 +00:00
|
|
|
return TRUE;
|
2012-09-01 11:54:16 +00:00
|
|
|
} else {
|
|
|
|
/* Failed to find a link-layer source address. */
|
|
|
|
return FALSE;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
} /* lowpan_dlsrc_to_ifcid */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_dldst_to_ifcid
|
|
|
|
* DESCRIPTION
|
|
|
|
* Finds an interface identifier from the data-link destination
|
|
|
|
* addressing.
|
|
|
|
* PARAMETERS
|
|
|
|
* pinfo ; packet information.
|
|
|
|
* ifcid ; interface identifier (output).
|
|
|
|
* RETURNS
|
|
|
|
* gboolean ; TRUE if an interface identifier could
|
|
|
|
* be found.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
lowpan_dldst_to_ifcid(packet_info *pinfo, guint8 *ifcid)
|
|
|
|
{
|
2012-09-01 11:54:16 +00:00
|
|
|
ieee802154_hints_t *hints;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Check the link-layer address field. */
|
|
|
|
if (pinfo->dl_dst.type == AT_EUI64) {
|
|
|
|
memcpy(ifcid, pinfo->dl_dst.data, LOWPAN_IFC_ID_LEN);
|
2010-02-09 08:40:40 +00:00
|
|
|
/* RFC2464: Invert the U/L bit when using an EUI64 address. */
|
|
|
|
ifcid[0] ^= 0x02;
|
2009-10-03 10:06:19 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Lookup the IEEE 802.15.4 addressing hints. */
|
2013-11-23 02:20:13 +00:00
|
|
|
hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
|
2013-05-12 18:11:02 +00:00
|
|
|
proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
|
2012-09-01 11:54:16 +00:00
|
|
|
if (hints) {
|
|
|
|
lowpan_addr16_to_ifcid(hints->dst16, ifcid);
|
2009-10-03 10:06:19 +00:00
|
|
|
return TRUE;
|
2012-09-01 11:54:16 +00:00
|
|
|
} else {
|
|
|
|
/* Failed to find a link-layer destination address. */
|
|
|
|
return FALSE;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
} /* lowpan_dldst_to_ifcid */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_reassemble_ipv6
|
|
|
|
* DESCRIPTION
|
|
|
|
* Helper function to rebuild an IPv6 packet from the IPv6
|
|
|
|
* header structure, and a list of next header structures.
|
|
|
|
* PARAMETERS
|
|
|
|
* ipv6 ; IPv6 Header.
|
|
|
|
* nhdr_list ; Next header list.
|
|
|
|
* RETURNS
|
|
|
|
* tvbuff_t * ; Reassembled IPv6 packet.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static tvbuff_t *
|
2010-01-13 07:42:42 +00:00
|
|
|
lowpan_reassemble_ipv6(tvbuff_t *tvb, struct ip6_hdr *ipv6, struct lowpan_nhdr *nhdr_list)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
|
|
|
gint length = 0;
|
|
|
|
gint reported = 0;
|
|
|
|
guint8 * buffer;
|
|
|
|
guint8 * cursor;
|
|
|
|
struct lowpan_nhdr *nhdr;
|
2010-01-13 07:42:42 +00:00
|
|
|
tvbuff_t *ret;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Compute the real and reported lengths. */
|
|
|
|
for (nhdr = nhdr_list; nhdr; nhdr = nhdr->next) {
|
|
|
|
length += nhdr->length;
|
|
|
|
reported += nhdr->reported;
|
|
|
|
}
|
|
|
|
ipv6->ip6_plen = g_ntohs(reported);
|
|
|
|
|
|
|
|
/* Allocate a buffer for the packet and copy in the IPv6 header. */
|
2010-04-07 00:34:20 +00:00
|
|
|
buffer = (guint8 *)g_malloc(length + sizeof(struct ip6_hdr));
|
2009-10-03 10:06:19 +00:00
|
|
|
memcpy(buffer, ipv6, sizeof(struct ip6_hdr));
|
|
|
|
cursor = buffer + sizeof(struct ip6_hdr);
|
|
|
|
|
|
|
|
/* Add the next headers into the buffer. */
|
|
|
|
for (nhdr = nhdr_list; nhdr; nhdr = nhdr->next) {
|
2010-04-07 00:34:20 +00:00
|
|
|
memcpy(cursor, LOWPAN_NHDR_DATA(nhdr), nhdr->length);
|
2009-10-03 10:06:19 +00:00
|
|
|
cursor += nhdr->length;
|
|
|
|
};
|
|
|
|
|
2014-09-18 05:20:01 +00:00
|
|
|
/* Return the reassembled packet. */
|
2012-12-26 05:57:06 +00:00
|
|
|
ret = tvb_new_child_real_data(tvb, buffer, length + (int)sizeof(struct ip6_hdr), reported + (int)sizeof(struct ip6_hdr));
|
2010-01-13 07:42:42 +00:00
|
|
|
tvb_set_free_cb(ret, g_free);
|
|
|
|
return ret;
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* lowpan_reassemble_ipv6 */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* lowpan_parse_nhc_proto
|
|
|
|
* DESCRIPTION
|
|
|
|
* Parses the start of an 6LoWPAN NHC header to determine the
|
|
|
|
* next header protocol identifier. Will return IP_PROTO_NONE
|
|
|
|
* if no valid protocol could be determined.
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* offset ; offset of the NHC.
|
|
|
|
* RETURNS
|
|
|
|
* guint8 ; IP_PROTO_* of the next header's protocol.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static guint8
|
|
|
|
lowpan_parse_nhc_proto(tvbuff_t *tvb, gint offset)
|
|
|
|
{
|
|
|
|
/* Ensure that at least one byte exists. */
|
2014-05-22 21:53:30 +00:00
|
|
|
if (!tvb_bytes_exist(tvb, offset, 1)) return IP_PROTO_NONE;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Check for IPv6 extension headers. */
|
|
|
|
if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_BITS) == LOWPAN_NHC_PATTERN_EXT) {
|
|
|
|
guint8 eid = (tvb_get_guint8(tvb, offset) & LOWPAN_NHC_EXT_EID) >> LOWPAN_NHC_EXT_EID_OFFSET;
|
|
|
|
switch (eid) {
|
|
|
|
case LOWPAN_NHC_EID_HOP_BY_HOP:
|
|
|
|
return IP_PROTO_HOPOPTS;
|
|
|
|
case LOWPAN_NHC_EID_ROUTING:
|
|
|
|
return IP_PROTO_ROUTING;
|
|
|
|
case LOWPAN_NHC_EID_FRAGMENT:
|
|
|
|
return IP_PROTO_FRAGMENT;
|
|
|
|
case LOWPAN_NHC_EID_DEST_OPTIONS:
|
|
|
|
return IP_PROTO_DSTOPTS;
|
|
|
|
case LOWPAN_NHC_EID_MOBILITY:
|
|
|
|
return IP_PROTO_MIPV6;
|
|
|
|
case LOWPAN_NHC_EID_IPV6:
|
2011-07-29 14:26:41 +00:00
|
|
|
return IP_PROTO_IPV6;
|
2009-10-03 10:06:19 +00:00
|
|
|
default:
|
|
|
|
/* Unknown protocol type. */
|
|
|
|
return IP_PROTO_NONE;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
/* Check for compressed UDP headers. */
|
|
|
|
if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_UDP_BITS) == LOWPAN_NHC_PATTERN_UDP) {
|
|
|
|
return IP_PROTO_UDP;
|
|
|
|
}
|
|
|
|
/* Unknown header type. */
|
|
|
|
return IP_PROTO_NONE;
|
|
|
|
} /* lowpan_parse_nhc_proto */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_heur
|
|
|
|
* DESCRIPTION
|
|
|
|
* Heuristic dissector for 6LoWPAN. Checks if the pattern is
|
|
|
|
* a valid 6LoWPAN type, and not NALP.
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; protocol display tree.
|
2014-03-09 20:11:43 +00:00
|
|
|
* data : ieee802154_packet,
|
2009-10-03 10:06:19 +00:00
|
|
|
* RETURNS
|
|
|
|
* boolean ; TRUE if the tvbuff was dissected as a
|
|
|
|
* 6LoWPAN packet. If this returns FALSE,
|
|
|
|
* then no dissection will be attempted.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static gboolean
|
2014-03-09 20:11:43 +00:00
|
|
|
dissect_6lowpan_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
2014-04-18 03:33:42 +00:00
|
|
|
guint offset = 0;
|
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Check for valid patterns. */
|
2014-04-18 03:33:42 +00:00
|
|
|
for (;;) {
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Parse patterns until we find a match. */
|
2014-04-18 03:33:42 +00:00
|
|
|
if (!tvb_reported_length_remaining(tvb, offset)) return FALSE;
|
|
|
|
if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_IPV6_BITS) == LOWPAN_PATTERN_IPV6) break;
|
|
|
|
if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_HC1_BITS) == LOWPAN_PATTERN_HC1) break;
|
|
|
|
if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_BC0_BITS) == LOWPAN_PATTERN_BC0) {
|
|
|
|
/* Broadcast headers must be followed by another valid header. */
|
|
|
|
offset += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) break;
|
|
|
|
if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_MESH_BITS) == LOWPAN_PATTERN_MESH) {
|
|
|
|
/* Mesh headers must be followed by another valid header. */
|
|
|
|
guint8 mesh = tvb_get_guint8(tvb, offset++);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += (mesh & LOWPAN_MESH_HEADER_V) ? 2 : 8;
|
|
|
|
offset += (mesh & LOWPAN_MESH_HEADER_F) ? 2 : 8;
|
2014-04-18 03:33:42 +00:00
|
|
|
if ((mesh & LOWPAN_MESH_HEADER_HOPS) == LOWPAN_MESH_HEADER_HOPS) offset++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_FRAG_BITS) == LOWPAN_PATTERN_FRAG1) {
|
|
|
|
/* First fragment headers must be followed by another valid header. */
|
|
|
|
offset += 4;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_FRAG_BITS) == LOWPAN_PATTERN_FRAGN) break;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* If we get here, then we couldn't match to any pattern. */
|
|
|
|
return FALSE;
|
2014-04-18 03:33:42 +00:00
|
|
|
} /* for */
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* If we get here, then we found a matching pattern. */
|
2014-04-18 03:33:42 +00:00
|
|
|
dissect_6lowpan(tvb, pinfo, tree, data);
|
2009-10-03 10:06:19 +00:00
|
|
|
return TRUE;
|
|
|
|
} /* dissect_6lowpan_heur */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for 6LoWPAN packets.
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; protocol display tree.
|
2014-04-18 03:33:42 +00:00
|
|
|
* data ; Packet data (ieee 802.15.4).
|
2009-10-03 10:06:19 +00:00
|
|
|
* RETURNS
|
2014-04-18 03:33:42 +00:00
|
|
|
* int ; Length of data processed, or 0 if not 6LoWPAN.
|
2009-10-03 10:06:19 +00:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
2014-04-18 03:33:42 +00:00
|
|
|
static int
|
|
|
|
dissect_6lowpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
|
|
|
proto_tree *volatile lowpan_tree = NULL;
|
|
|
|
proto_item *volatile lowpan_root = NULL;
|
|
|
|
tvbuff_t * next = tvb;
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Interface identifier of the encapsulating layer. */
|
|
|
|
guint8 src_iid[LOWPAN_IFC_ID_LEN];
|
|
|
|
guint8 dst_iid[LOWPAN_IFC_ID_LEN];
|
2012-03-06 02:28:04 +00:00
|
|
|
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Get the interface identifiers from the encapsulating layer. */
|
|
|
|
lowpan_dlsrc_to_ifcid(pinfo, src_iid);
|
|
|
|
lowpan_dldst_to_ifcid(pinfo, dst_iid);
|
2012-03-06 02:28:04 +00:00
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Create the protocol tree. */
|
|
|
|
if (tree) {
|
2014-03-09 20:11:43 +00:00
|
|
|
lowpan_root = proto_tree_add_protocol_format(tree, proto_6lowpan, tvb, 0, -1, "6LoWPAN");
|
2009-10-03 10:06:19 +00:00
|
|
|
lowpan_tree = proto_item_add_subtree(lowpan_root, ett_6lowpan);
|
|
|
|
}
|
|
|
|
/* Add the protocol name. */
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "6LoWPAN");
|
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
/* Mesh and Broadcast headers always come first in a 6LoWPAN frame. */
|
|
|
|
if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_MESH_BITS) == LOWPAN_PATTERN_MESH) {
|
2014-09-18 05:20:01 +00:00
|
|
|
next = dissect_6lowpan_mesh(next, pinfo, lowpan_tree, src_iid, dst_iid);
|
2014-04-18 03:33:42 +00:00
|
|
|
if (!next) return tvb_captured_length(tvb);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_BC0_BITS) == LOWPAN_PATTERN_BC0) {
|
|
|
|
next = dissect_6lowpan_bc0(next, pinfo, lowpan_tree);
|
2014-04-18 03:33:42 +00:00
|
|
|
if (!next) return tvb_captured_length(tvb);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 14:26:41 +00:00
|
|
|
/* After the mesh and broadcast headers, process dispatch codes recursively. */
|
|
|
|
/* Fragmentation headers.*/
|
2010-03-09 23:22:03 +00:00
|
|
|
if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_FRAG_BITS) == LOWPAN_PATTERN_FRAG1) {
|
2011-07-29 14:26:41 +00:00
|
|
|
next = dissect_6lowpan_frag_first(next, pinfo, lowpan_tree, src_iid, dst_iid);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_FRAG_BITS) == LOWPAN_PATTERN_FRAGN) {
|
|
|
|
next = dissect_6lowpan_frag_middle(next, pinfo, lowpan_tree);
|
|
|
|
}
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Uncompressed IPv6 packets. */
|
2010-03-09 23:22:03 +00:00
|
|
|
else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_IPV6_BITS) == LOWPAN_PATTERN_IPV6) {
|
|
|
|
next = dissect_6lowpan_ipv6(next, pinfo, lowpan_tree);
|
|
|
|
}
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Compressed IPv6 packets. */
|
2010-03-09 23:22:03 +00:00
|
|
|
else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_HC1_BITS) == LOWPAN_PATTERN_HC1) {
|
2011-07-29 14:26:41 +00:00
|
|
|
next = dissect_6lowpan_hc1(next, pinfo, lowpan_tree, -1, src_iid, dst_iid);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) {
|
2011-07-29 14:26:41 +00:00
|
|
|
next = dissect_6lowpan_iphc(next, pinfo, lowpan_tree, -1, src_iid, dst_iid);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
/* Unknown 6LoWPAN dispatch type */
|
|
|
|
else {
|
|
|
|
dissect_6lowpan_unknown(next, pinfo, lowpan_tree);
|
2014-04-18 03:33:42 +00:00
|
|
|
return tvb_captured_length(tvb);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
2012-03-06 02:28:04 +00:00
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
/* The last step should have returned an uncompressed IPv6 datagram. */
|
|
|
|
if (next) {
|
|
|
|
call_dissector(ipv6_handle, next, pinfo, tree);
|
|
|
|
}
|
2014-04-18 03:33:42 +00:00
|
|
|
return tvb_captured_length(tvb);
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* dissect_6lowpan */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_ipv6
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for an uncompressed IPv6 header type.
|
2010-03-09 23:22:03 +00:00
|
|
|
*
|
|
|
|
* This is one of the final encapsulation types, and will
|
|
|
|
* returned an uncompressed IPv6 datagram (or fragment
|
|
|
|
* thereof).
|
2009-10-03 10:06:19 +00:00
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
|
|
|
* offset ; offset to the start of the header.
|
|
|
|
* RETURNS
|
|
|
|
* tvbuff_t * ; The remaining payload to be parsed.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static tvbuff_t *
|
2010-03-09 23:22:03 +00:00
|
|
|
dissect_6lowpan_ipv6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
|
|
|
/* Get and display the pattern. */
|
|
|
|
if (tree) {
|
2011-10-24 19:57:53 +00:00
|
|
|
proto_tree_add_bits_item(tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_IPV6_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a tvbuff subset for the ipv6 datagram. */
|
2014-05-22 21:53:30 +00:00
|
|
|
return tvb_new_subset_remaining(tvb, 1);
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* dissect_6lowpan_ipv6 */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_hc1
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for a 6LoWPAN HC1 header.
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
2010-03-09 23:22:03 +00:00
|
|
|
* dgram_size ; Datagram size (or <0 if not fragmented).
|
2011-07-29 14:26:41 +00:00
|
|
|
* siid ; Source Interface ID.
|
|
|
|
* diid ; Destination Interface ID.
|
2009-10-03 10:06:19 +00:00
|
|
|
* RETURNS
|
|
|
|
* tvbuff_t * ; The remaining payload to be parsed.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static tvbuff_t *
|
2014-09-18 05:20:01 +00:00
|
|
|
dissect_6lowpan_hc1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint dgram_size, const guint8 *siid, const guint8 *diid)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
|
|
|
gint offset = 0;
|
|
|
|
gint bit_offset;
|
|
|
|
int i;
|
|
|
|
guint8 hc1_encoding;
|
|
|
|
guint8 hc_udp_encoding = 0;
|
|
|
|
guint8 next_header;
|
2014-06-20 21:34:10 +00:00
|
|
|
proto_tree * hc_tree;
|
|
|
|
proto_item * hc_item;
|
2009-10-03 10:06:19 +00:00
|
|
|
tvbuff_t * ipv6_tvb;
|
|
|
|
/* IPv6 header. */
|
|
|
|
guint8 ipv6_class;
|
|
|
|
struct ip6_hdr ipv6;
|
|
|
|
struct lowpan_nhdr *nhdr_list;
|
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Parse HC Encoding Flags
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
/* Create a tree for the HC1 Header. */
|
2014-06-20 21:34:10 +00:00
|
|
|
hc_tree = proto_tree_add_subtree(tree, tvb, 0, 2, ett_6lowpan_hc1, &hc_item, "HC1 Encoding");
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2014-06-20 21:34:10 +00:00
|
|
|
/* Get and display the pattern. */
|
|
|
|
proto_tree_add_bits_item(hc_tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_HC1_BITS, ENC_BIG_ENDIAN);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the HC1 encoding bits. */
|
|
|
|
hc1_encoding = tvb_get_guint8(tvb, offset);
|
|
|
|
next_header = ((hc1_encoding & LOWPAN_HC1_NEXT) >> 1);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc1_source_prefix, tvb, offset, 1, hc1_encoding & LOWPAN_HC1_SOURCE_PREFIX);
|
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc1_source_ifc, tvb, offset, 1, hc1_encoding & LOWPAN_HC1_SOURCE_IFC);
|
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc1_dest_prefix, tvb, offset, 1, hc1_encoding & LOWPAN_HC1_DEST_PREFIX);
|
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc1_dest_ifc, tvb, offset, 1, hc1_encoding & LOWPAN_HC1_DEST_IFC);
|
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc1_class, tvb, offset, 1, hc1_encoding & LOWPAN_HC1_TRAFFIC_CLASS);
|
|
|
|
proto_tree_add_uint(hc_tree, hf_6lowpan_hc1_next, tvb, offset, 1, hc1_encoding & LOWPAN_HC1_NEXT);
|
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc1_more, tvb, offset, 1, hc1_encoding & LOWPAN_HC1_MORE);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the HC2 encoding bits, if present. */
|
|
|
|
if (hc1_encoding & LOWPAN_HC1_MORE) {
|
|
|
|
if (next_header == LOWPAN_HC1_NEXT_UDP) {
|
|
|
|
hc_udp_encoding = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
2014-06-20 21:34:10 +00:00
|
|
|
hc_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_6lowpan_hc2_udp, NULL, "HC_UDP Encoding");
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc2_udp_src, tvb, offset, 1, hc_udp_encoding & LOWPAN_HC2_UDP_SRCPORT);
|
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc2_udp_dst, tvb, offset, 1, hc_udp_encoding & LOWPAN_HC2_UDP_DSTPORT);
|
|
|
|
proto_tree_add_boolean(hc_tree, hf_6lowpan_hc2_udp_len, tvb, offset, 1, hc_udp_encoding & LOWPAN_HC2_UDP_LENGTH);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* HC1 states there are more bits, but an illegal next header was defined. */
|
2014-06-20 21:34:10 +00:00
|
|
|
expert_add_info(pinfo, hc_item, &ei_6lowpan_hc1_more_bits);
|
2009-10-03 10:06:19 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Parse Uncompressed IPv6 Header Fields
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* And now all hell breaks loose. After the header encoding fields, we are
|
|
|
|
* left with an assortment of optional fields from the IPv6 header,
|
|
|
|
* depending on which fields are present or not, the headers may not be
|
|
|
|
* aligned to an octet boundary.
|
|
|
|
*
|
|
|
|
* From now on we have to parse the uncompressed fields relative to a bit
|
|
|
|
* offset.
|
|
|
|
*/
|
|
|
|
bit_offset = offset << 3;
|
|
|
|
|
2010-07-23 20:19:05 +00:00
|
|
|
/* Parse hop limit */
|
2009-10-03 10:06:19 +00:00
|
|
|
ipv6.ip6_hops = tvb_get_bits8(tvb, bit_offset, LOWPAN_IPV6_HOP_LIMIT_BITS);
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_hop_limit, tvb, bit_offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(bit_offset, LOWPAN_IPV6_HOP_LIMIT_BITS), ipv6.ip6_hops);
|
|
|
|
}
|
|
|
|
bit_offset += LOWPAN_IPV6_HOP_LIMIT_BITS;
|
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Parse/Decompress IPv6 Source Address
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
offset = bit_offset;
|
|
|
|
if (!(hc1_encoding & LOWPAN_HC1_SOURCE_PREFIX)) {
|
|
|
|
for (i=0; i<8; i++, bit_offset += 8) {
|
|
|
|
ipv6.ip6_src.bytes[i] = tvb_get_bits8(tvb, bit_offset, 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
memcpy(ipv6.ip6_src.bytes, lowpan_llprefix, sizeof(lowpan_llprefix));
|
|
|
|
}
|
|
|
|
if (!(hc1_encoding & LOWPAN_HC1_SOURCE_IFC)) {
|
|
|
|
for (i=8; i<16; i++, bit_offset += 8) {
|
|
|
|
ipv6.ip6_src.bytes[i] = tvb_get_bits8(tvb, bit_offset, 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2011-07-29 14:26:41 +00:00
|
|
|
memcpy(&ipv6.ip6_src.bytes[sizeof(ipv6.ip6_src) - LOWPAN_IFC_ID_LEN], siid, LOWPAN_IFC_ID_LEN);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
/* Display the source address. */
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_ipv6(tree, hf_6lowpan_source, tvb, offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(offset, (bit_offset-offset)), (guint8 *)&ipv6.ip6_src);
|
|
|
|
}
|
2010-03-09 23:22:03 +00:00
|
|
|
/*
|
|
|
|
* Do not set the address columns until after defragmentation, since we have
|
|
|
|
* to do decompression before reassembly, and changing the address will cause
|
|
|
|
* wireshark to think that the middle fragments came from another device.
|
|
|
|
*/
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Parse/Decompress IPv6 Destination Address
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
offset = bit_offset;
|
|
|
|
if (!(hc1_encoding & LOWPAN_HC1_DEST_PREFIX)) {
|
|
|
|
for (i=0; i<8; i++, bit_offset += 8) {
|
|
|
|
ipv6.ip6_dst.bytes[i] = tvb_get_bits8(tvb, bit_offset, 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
memcpy(ipv6.ip6_dst.bytes, lowpan_llprefix, sizeof(lowpan_llprefix));
|
|
|
|
}
|
|
|
|
if (!(hc1_encoding & LOWPAN_HC1_DEST_IFC)) {
|
|
|
|
for (i=8; i<16; i++, bit_offset += 8) {
|
|
|
|
ipv6.ip6_dst.bytes[i] = tvb_get_bits8(tvb, bit_offset, 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2011-07-29 14:26:41 +00:00
|
|
|
memcpy(&ipv6.ip6_dst.bytes[sizeof(ipv6.ip6_dst) - LOWPAN_IFC_ID_LEN], diid, LOWPAN_IFC_ID_LEN);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
/* Display the destination address. */
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_ipv6(tree, hf_6lowpan_dest, tvb, offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(offset, (bit_offset-offset)), (guint8 *)&ipv6.ip6_dst);
|
|
|
|
}
|
2010-03-09 23:22:03 +00:00
|
|
|
/*
|
|
|
|
* Do not set the address columns until after defragmentation, since we have
|
|
|
|
* to do decompression before reassembly, and changing the address will cause
|
|
|
|
* wireshark to think that the middle fragments came from another device.
|
|
|
|
*/
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2010-07-23 20:19:05 +00:00
|
|
|
/* Parse the traffic class and flow label. */
|
|
|
|
ipv6_class = 0;
|
|
|
|
ipv6.ip6_flow = 0;
|
|
|
|
if (!(hc1_encoding & LOWPAN_HC1_TRAFFIC_CLASS)) {
|
|
|
|
/* Parse the traffic class. */
|
|
|
|
ipv6_class = tvb_get_bits8(tvb, bit_offset, LOWPAN_IPV6_TRAFFIC_CLASS_BITS);
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_traffic_class, tvb, bit_offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(bit_offset, LOWPAN_IPV6_TRAFFIC_CLASS_BITS), ipv6_class);
|
|
|
|
}
|
|
|
|
bit_offset += LOWPAN_IPV6_TRAFFIC_CLASS_BITS;
|
|
|
|
|
|
|
|
/* Parse the flow label. */
|
2011-10-24 19:57:53 +00:00
|
|
|
ipv6.ip6_flow = tvb_get_bits32(tvb, bit_offset, LOWPAN_IPV6_FLOW_LABEL_BITS, ENC_BIG_ENDIAN);
|
2010-07-23 20:19:05 +00:00
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_flow_label, tvb, bit_offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(bit_offset, LOWPAN_IPV6_FLOW_LABEL_BITS), ipv6.ip6_flow);
|
|
|
|
}
|
|
|
|
bit_offset += LOWPAN_IPV6_FLOW_LABEL_BITS;
|
|
|
|
}
|
|
|
|
ipv6.ip6_flow = g_ntohl(ipv6.ip6_flow | (ipv6_class << LOWPAN_IPV6_FLOW_LABEL_BITS));
|
|
|
|
ipv6.ip6_vfc = ((0x6 << 4) | (ipv6_class >> 4));
|
|
|
|
|
|
|
|
/* Parse the IPv6 next header field. */
|
|
|
|
if (next_header == LOWPAN_HC1_NEXT_UDP) {
|
|
|
|
ipv6.ip6_nxt = IP_PROTO_UDP;
|
|
|
|
}
|
|
|
|
else if (next_header == LOWPAN_HC1_NEXT_ICMP) {
|
|
|
|
ipv6.ip6_nxt = IP_PROTO_ICMPV6;
|
|
|
|
}
|
|
|
|
else if (next_header == LOWPAN_HC1_NEXT_TCP) {
|
|
|
|
ipv6.ip6_nxt = IP_PROTO_TCP;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Parse the next header field. */
|
|
|
|
ipv6.ip6_nxt = tvb_get_bits8(tvb, bit_offset, LOWPAN_IPV6_NEXT_HEADER_BITS);
|
|
|
|
if (tree) {
|
2013-09-15 01:48:30 +00:00
|
|
|
proto_tree_add_uint_format_value(tree, hf_6lowpan_next_header, tvb, bit_offset>>3,
|
2010-07-23 20:19:05 +00:00
|
|
|
BITS_TO_BYTE_LEN(bit_offset, LOWPAN_IPV6_NEXT_HEADER_BITS), ipv6.ip6_nxt,
|
2013-09-15 01:48:30 +00:00
|
|
|
"%s (0x%02x)", ipprotostr(ipv6.ip6_nxt), ipv6.ip6_nxt);
|
2010-07-23 20:19:05 +00:00
|
|
|
}
|
|
|
|
bit_offset += LOWPAN_IPV6_NEXT_HEADER_BITS;
|
|
|
|
}
|
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/*=====================================================
|
|
|
|
* Parse and Reconstruct the UDP Header
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
if ((hc1_encoding & LOWPAN_HC1_MORE) && (next_header == LOWPAN_HC1_NEXT_UDP)) {
|
|
|
|
struct udp_hdr udp;
|
|
|
|
gint length;
|
|
|
|
|
|
|
|
/* Parse the source port. */
|
|
|
|
offset = bit_offset;
|
|
|
|
if (hc_udp_encoding & LOWPAN_HC2_UDP_SRCPORT) {
|
|
|
|
udp.src_port = tvb_get_bits8(tvb, bit_offset, LOWPAN_UDP_PORT_COMPRESSED_BITS) + LOWPAN_PORT_12BIT_OFFSET;
|
|
|
|
bit_offset += LOWPAN_UDP_PORT_COMPRESSED_BITS;
|
|
|
|
}
|
|
|
|
else {
|
2011-10-24 19:57:53 +00:00
|
|
|
udp.src_port = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_PORT_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
bit_offset += LOWPAN_UDP_PORT_BITS;
|
|
|
|
}
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_udp_src, tvb, offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(offset, (bit_offset-offset)), udp.src_port);
|
|
|
|
}
|
|
|
|
udp.src_port = g_ntohs(udp.src_port);
|
|
|
|
|
|
|
|
/* Parse the destination port. */
|
|
|
|
offset = bit_offset;
|
|
|
|
if (hc_udp_encoding & LOWPAN_HC2_UDP_DSTPORT) {
|
|
|
|
udp.dst_port = tvb_get_bits8(tvb, bit_offset, LOWPAN_UDP_PORT_COMPRESSED_BITS) + LOWPAN_PORT_12BIT_OFFSET;
|
|
|
|
bit_offset += LOWPAN_UDP_PORT_COMPRESSED_BITS;
|
|
|
|
}
|
|
|
|
else {
|
2011-10-24 19:57:53 +00:00
|
|
|
udp.dst_port = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_PORT_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
bit_offset += LOWPAN_UDP_PORT_BITS;
|
|
|
|
}
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_udp_dst, tvb, offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(offset, (bit_offset-offset)), udp.dst_port);
|
|
|
|
}
|
|
|
|
udp.dst_port = g_ntohs(udp.dst_port);
|
|
|
|
|
|
|
|
/* Parse the length, if present. */
|
2009-11-25 19:46:08 +00:00
|
|
|
if (!(hc_udp_encoding & LOWPAN_HC2_UDP_LENGTH)) {
|
2011-10-24 19:57:53 +00:00
|
|
|
udp.length = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_LENGTH_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_udp_len, tvb, bit_offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(bit_offset, LOWPAN_UDP_LENGTH_BITS), udp.length);
|
|
|
|
|
|
|
|
}
|
|
|
|
bit_offset += LOWPAN_UDP_LENGTH_BITS;
|
|
|
|
}
|
2010-03-09 23:22:03 +00:00
|
|
|
/* Compute the length from the fragmentation headers. */
|
|
|
|
else if (dgram_size >= 0) {
|
2010-03-10 10:23:19 +00:00
|
|
|
if (dgram_size < (gint)sizeof(struct ip6_hdr)) {
|
|
|
|
/* Datagram size is too small */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
udp.length = dgram_size - (gint)sizeof(struct ip6_hdr);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Compute the length from the tvbuff size. */
|
|
|
|
else {
|
|
|
|
udp.length = tvb_reported_length(tvb);
|
|
|
|
udp.length -= BITS_TO_BYTE_LEN(0, bit_offset + LOWPAN_UDP_CHECKSUM_BITS);
|
2012-12-26 05:57:06 +00:00
|
|
|
udp.length += (int)sizeof(struct udp_hdr);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
udp.length = g_ntohs(udp.length);
|
|
|
|
|
|
|
|
/* Parse the checksum. */
|
2011-10-24 19:57:53 +00:00
|
|
|
udp.checksum = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_CHECKSUM_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_udp_checksum, tvb, bit_offset>>3,
|
|
|
|
BITS_TO_BYTE_LEN(bit_offset, LOWPAN_UDP_CHECKSUM_BITS), udp.checksum);
|
|
|
|
}
|
|
|
|
bit_offset += LOWPAN_UDP_CHECKSUM_BITS;
|
|
|
|
udp.checksum = g_ntohs(udp.checksum);
|
|
|
|
|
|
|
|
/* Construct the next header for the UDP datagram. */
|
|
|
|
offset = BITS_TO_BYTE_LEN(0, bit_offset);
|
2014-06-19 17:17:16 +00:00
|
|
|
length = (gint)tvb_ensure_length_remaining(tvb, offset);
|
2013-09-12 20:37:30 +00:00
|
|
|
nhdr_list = (struct lowpan_nhdr *)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr) + sizeof(struct udp_hdr) + length);
|
2009-10-03 10:06:19 +00:00
|
|
|
nhdr_list->next = NULL;
|
|
|
|
nhdr_list->proto = IP_PROTO_UDP;
|
2012-12-26 05:57:06 +00:00
|
|
|
nhdr_list->length = length + (int)sizeof(struct udp_hdr);
|
2009-10-03 10:06:19 +00:00
|
|
|
nhdr_list->reported = g_ntohs(udp.length);
|
|
|
|
|
|
|
|
/* Copy the UDP header into the buffer. */
|
2010-04-07 00:34:20 +00:00
|
|
|
memcpy(LOWPAN_NHDR_DATA(nhdr_list), &udp, sizeof(struct udp_hdr));
|
|
|
|
tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr_list) + sizeof(struct udp_hdr), offset, length);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
/*=====================================================
|
|
|
|
* Reconstruct the IPv6 Packet
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
else {
|
2011-02-23 22:49:59 +00:00
|
|
|
gint length;
|
2009-10-03 10:06:19 +00:00
|
|
|
offset = BITS_TO_BYTE_LEN(0, bit_offset);
|
2014-06-19 17:17:16 +00:00
|
|
|
length = (gint)tvb_ensure_length_remaining(tvb, offset);
|
2013-09-12 20:37:30 +00:00
|
|
|
nhdr_list = (struct lowpan_nhdr *)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr) + length);
|
2009-10-03 10:06:19 +00:00
|
|
|
nhdr_list->next = NULL;
|
|
|
|
nhdr_list->proto = ipv6.ip6_nxt;
|
2011-02-23 22:49:59 +00:00
|
|
|
nhdr_list->length = length;
|
2010-03-09 23:22:03 +00:00
|
|
|
if (dgram_size < 0) {
|
|
|
|
nhdr_list->reported = tvb_reported_length_remaining(tvb, offset);
|
|
|
|
}
|
|
|
|
else {
|
2012-12-26 05:57:06 +00:00
|
|
|
nhdr_list->reported = dgram_size - (int)sizeof(struct ip6_hdr);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
2010-04-07 00:34:20 +00:00
|
|
|
tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr_list), offset, nhdr_list->length);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Link the reassembled tvbuff together. */
|
2010-01-13 07:42:42 +00:00
|
|
|
ipv6_tvb = lowpan_reassemble_ipv6(tvb, &ipv6, nhdr_list);
|
2012-10-14 02:33:26 +00:00
|
|
|
|
|
|
|
/* Add a new data source for it. */
|
2012-10-14 02:54:25 +00:00
|
|
|
add_new_data_source(pinfo, ipv6_tvb, "Decompressed 6LoWPAN HC1");
|
2012-10-14 02:33:26 +00:00
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
return ipv6_tvb;
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* dissect_6lowpan_hc1 */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_iphc
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for a 6LoWPAN IPHC header.
|
|
|
|
*
|
|
|
|
* This header is still in the draft phase, but is expected
|
|
|
|
* to replace HC1.
|
|
|
|
*
|
2011-07-29 14:26:41 +00:00
|
|
|
* See draft-ietf-6lowpan-hc-15.txt
|
2009-10-03 10:06:19 +00:00
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
2010-03-09 23:22:03 +00:00
|
|
|
* dgram_size ; Datagram size (or <0 if not fragmented).
|
2011-07-29 14:26:41 +00:00
|
|
|
* siid ; Source Interface ID.
|
|
|
|
* diid ; Destination Interface ID.
|
2009-10-03 10:06:19 +00:00
|
|
|
* RETURNS
|
|
|
|
* tvbuff_t * ; The remaining payload to be parsed.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static tvbuff_t *
|
2014-09-18 05:20:01 +00:00
|
|
|
dissect_6lowpan_iphc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint dgram_size, const guint8 *siid, const guint8 *diid)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
2012-09-01 11:54:16 +00:00
|
|
|
ieee802154_hints_t *hints;
|
|
|
|
guint16 hint_panid;
|
2009-10-03 10:06:19 +00:00
|
|
|
gint offset = 0;
|
2010-09-30 19:41:44 +00:00
|
|
|
gint length = 0;
|
2009-10-03 10:52:15 +00:00
|
|
|
proto_tree * iphc_tree = NULL;
|
2009-10-03 10:06:19 +00:00
|
|
|
proto_item * ti = NULL;
|
|
|
|
proto_item * ti_dam = NULL;
|
|
|
|
/* IPHC header fields. */
|
|
|
|
guint16 iphc_flags;
|
|
|
|
guint8 iphc_traffic;
|
|
|
|
guint8 iphc_hop_limit;
|
|
|
|
guint8 iphc_src_mode;
|
|
|
|
guint8 iphc_dst_mode;
|
|
|
|
guint8 iphc_ctx = 0;
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Contexts to use for address decompression. */
|
2010-09-30 19:23:31 +00:00
|
|
|
gint iphc_sci = LOWPAN_CONTEXT_DEFAULT;
|
|
|
|
gint iphc_dci = LOWPAN_CONTEXT_DEFAULT;
|
2012-09-01 11:54:16 +00:00
|
|
|
lowpan_context_data *sctx;
|
|
|
|
lowpan_context_data *dctx;
|
2009-10-03 10:06:19 +00:00
|
|
|
/* IPv6 header */
|
|
|
|
guint8 ipv6_class = 0;
|
|
|
|
struct ip6_hdr ipv6;
|
|
|
|
tvbuff_t * ipv6_tvb;
|
|
|
|
/* Next header chain */
|
2012-09-01 11:54:16 +00:00
|
|
|
struct lowpan_nhdr *nhdr_list;
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Lookup the IEEE 802.15.4 addressing hints. */
|
2013-11-23 02:20:13 +00:00
|
|
|
hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
|
2013-05-12 18:11:02 +00:00
|
|
|
proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
|
2012-09-01 11:54:16 +00:00
|
|
|
hint_panid = (hints) ? (hints->src_pan) : (IEEE802154_BCAST_PAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Create a tree for the IPHC header. */
|
2014-06-20 21:34:10 +00:00
|
|
|
iphc_tree = proto_tree_add_subtree(tree, tvb, 0, 2, ett_6lowpan_iphc, NULL, "IPHC Header");
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2014-06-20 21:34:10 +00:00
|
|
|
/* Display the pattern. */
|
|
|
|
proto_tree_add_bits_item(iphc_tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_IPHC_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Parse IPHC Header flags.
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
iphc_flags = tvb_get_ntohs(tvb, offset);
|
|
|
|
iphc_traffic = (iphc_flags & LOWPAN_IPHC_FLAG_FLOW) >> LOWPAN_IPHC_FLAG_OFFSET_FLOW;
|
|
|
|
iphc_hop_limit = (iphc_flags & LOWPAN_IPHC_FLAG_HLIM) >> LOWPAN_IPHC_FLAG_OFFSET_HLIM;
|
|
|
|
iphc_src_mode = (iphc_flags & LOWPAN_IPHC_FLAG_SRC_MODE) >> LOWPAN_IPHC_FLAG_OFFSET_SRC_MODE;
|
|
|
|
iphc_dst_mode = (iphc_flags & LOWPAN_IPHC_FLAG_DST_MODE) >> LOWPAN_IPHC_FLAG_OFFSET_DST_MODE;
|
|
|
|
if (tree) {
|
2014-08-29 11:19:13 +00:00
|
|
|
const value_string *am_vs;
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint (iphc_tree, hf_6lowpan_iphc_flag_tf, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_FLOW);
|
|
|
|
proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_nhdr, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_NHDR);
|
|
|
|
proto_tree_add_uint (iphc_tree, hf_6lowpan_iphc_flag_hlim, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_HLIM);
|
|
|
|
proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_cid, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_CONTEXT_ID);
|
|
|
|
proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_sac, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP);
|
2014-08-29 11:19:13 +00:00
|
|
|
am_vs = iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP ? lowpan_iphc_saddr_stateful_modes : lowpan_iphc_addr_modes;
|
|
|
|
proto_tree_add_uint_format_value(iphc_tree, hf_6lowpan_iphc_flag_sam, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_SRC_MODE,
|
|
|
|
"%s (0x%04x)", val_to_str_const(iphc_src_mode, am_vs, "Reserved"), iphc_src_mode);
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_mcast, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_MCAST_COMP);
|
|
|
|
proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_dac, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP);
|
2010-02-12 22:10:53 +00:00
|
|
|
/* Destination address mode changes meanings depending on multicast compression. */
|
2014-08-29 11:19:13 +00:00
|
|
|
if (iphc_flags & LOWPAN_IPHC_FLAG_MCAST_COMP) {
|
|
|
|
if (iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP) {
|
|
|
|
am_vs = lowpan_iphc_mcast_stateful_modes;
|
|
|
|
} else {
|
|
|
|
am_vs = lowpan_iphc_mcast_modes;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP) {
|
|
|
|
am_vs = lowpan_iphc_daddr_stateful_modes;
|
|
|
|
} else {
|
|
|
|
am_vs = lowpan_iphc_addr_modes;
|
|
|
|
}
|
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
ti_dam = proto_tree_add_uint_format_value(iphc_tree, hf_6lowpan_iphc_flag_dam, tvb, offset, 2,
|
2014-08-29 11:19:13 +00:00
|
|
|
iphc_flags & LOWPAN_IPHC_FLAG_DST_MODE, "%s (0x%04x)", val_to_str_const(iphc_dst_mode, am_vs, "Reserved"), iphc_dst_mode);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 2;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Display the context identifier extension, if present. */
|
|
|
|
if (iphc_flags & LOWPAN_IPHC_FLAG_CONTEXT_ID) {
|
|
|
|
iphc_ctx = tvb_get_guint8(tvb, offset);
|
2010-09-30 19:23:31 +00:00
|
|
|
iphc_sci = (iphc_ctx & LOWPAN_IPHC_FLAG_SCI) >> LOWPAN_IPHC_FLAG_OFFSET_SCI;
|
|
|
|
iphc_dci = (iphc_ctx & LOWPAN_IPHC_FLAG_DCI) >> LOWPAN_IPHC_FLAG_OFFSET_DCI;
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(iphc_tree, hf_6lowpan_iphc_sci, tvb, offset, 1, iphc_ctx & LOWPAN_IPHC_FLAG_SCI);
|
|
|
|
proto_tree_add_uint(iphc_tree, hf_6lowpan_iphc_dci, tvb, offset, 1, iphc_ctx & LOWPAN_IPHC_FLAG_DCI);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2010-09-30 19:23:31 +00:00
|
|
|
/* Use link-local contexts if stateless. */
|
|
|
|
if (!(iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP)) {
|
|
|
|
iphc_sci = LOWPAN_CONTEXT_LINK_LOCAL;
|
|
|
|
}
|
|
|
|
if (!(iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP)) {
|
|
|
|
iphc_dci = LOWPAN_CONTEXT_LINK_LOCAL;
|
|
|
|
}
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Lookup the contexts. */
|
|
|
|
/*
|
|
|
|
* Don't display their origin until after we decompress the address in case
|
2012-09-07 02:09:59 +00:00
|
|
|
* the address modes indicate that we should use a different context.
|
2012-09-01 11:54:16 +00:00
|
|
|
*/
|
|
|
|
sctx = lowpan_context_find(iphc_sci, hint_panid);
|
|
|
|
dctx = lowpan_context_find(iphc_dci, hint_panid);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Parse Traffic Class and Flow Label
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
offset <<= 3;
|
|
|
|
/* Parse the ECN field. */
|
|
|
|
if (iphc_traffic != LOWPAN_IPHC_FLOW_COMPRESSED) {
|
|
|
|
ipv6_class |= tvb_get_bits8(tvb, offset, LOWPAN_IPHC_ECN_BITS);
|
|
|
|
offset += LOWPAN_IPHC_ECN_BITS;
|
|
|
|
}
|
|
|
|
/* Parse the DSCP field. */
|
|
|
|
if ((iphc_traffic == LOWPAN_IPHC_FLOW_CLASS_LABEL) || (iphc_traffic == LOWPAN_IPHC_FLOW_CLASS)) {
|
|
|
|
ipv6_class |= (tvb_get_bits8(tvb, offset, LOWPAN_IPHC_DSCP_BITS) << LOWPAN_IPHC_ECN_BITS);
|
|
|
|
offset += LOWPAN_IPHC_DSCP_BITS;
|
|
|
|
}
|
2010-02-12 22:10:53 +00:00
|
|
|
/* Display the traffic class field only if included inline. */
|
|
|
|
if ((tree) && (iphc_traffic != LOWPAN_IPHC_FLOW_COMPRESSED)) {
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Create a tree for the traffic class. */
|
|
|
|
proto_tree * tf_tree;
|
2014-05-22 21:53:30 +00:00
|
|
|
ti = proto_tree_add_uint(tree, hf_6lowpan_traffic_class, tvb, offset>>3, 1, ipv6_class);
|
2009-10-03 10:06:19 +00:00
|
|
|
tf_tree = proto_item_add_subtree(ti, ett_6lopwan_traffic_class);
|
|
|
|
|
|
|
|
/* Add the ECN and DSCP fields. */
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(tf_tree, hf_6lowpan_ecn, tvb, offset>>3, 1, ipv6_class & LOWPAN_IPHC_TRAFFIC_ECN);
|
|
|
|
proto_tree_add_uint(tf_tree, hf_6lowpan_dscp, tvb, offset>>3, 1, ipv6_class & LOWPAN_IPHC_TRAFFIC_DSCP);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse and display the traffic label. */
|
|
|
|
if ((iphc_traffic == LOWPAN_IPHC_FLOW_CLASS_LABEL) || (iphc_traffic == LOWPAN_IPHC_FLOW_ECN_LABEL)) {
|
|
|
|
/* Pad to 4-bits past the start of the byte. */
|
|
|
|
offset += ((4 - offset) & 0x7);
|
2011-10-24 19:57:53 +00:00
|
|
|
ipv6.ip6_flow = tvb_get_bits32(tvb, offset, LOWPAN_IPHC_LABEL_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
2011-10-24 19:57:53 +00:00
|
|
|
proto_tree_add_bits_item(tree, hf_6lowpan_flow_label, tvb, offset, LOWPAN_IPHC_LABEL_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
offset += LOWPAN_IPHC_LABEL_BITS;
|
|
|
|
}
|
|
|
|
else ipv6.ip6_flow = 0;
|
|
|
|
|
|
|
|
/* Rebuild the IPv6 flow label and traffic class fields. */
|
|
|
|
ipv6.ip6_flow = g_ntohl(ipv6.ip6_flow) | (ipv6_class << LOWPAN_IPV6_FLOW_LABEL_BITS);
|
|
|
|
ipv6.ip6_vfc = (0x6 << 4) | (ipv6_class >> 4);
|
|
|
|
|
|
|
|
/* Convert back to byte offsets. */
|
|
|
|
offset >>= 3;
|
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Parse Next Header and Hop Limit
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
/* Get the next header field, if present. */
|
|
|
|
if (!(iphc_flags & LOWPAN_IPHC_FLAG_NHDR)) {
|
|
|
|
ipv6.ip6_nxt = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint_format_value(tree, hf_6lowpan_next_header, tvb, offset, 1, ipv6.ip6_nxt,
|
2013-09-15 01:48:30 +00:00
|
|
|
"%s (0x%02x)", ipprotostr(ipv6.ip6_nxt), ipv6.ip6_nxt);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the hop limit field, if present. */
|
|
|
|
if (iphc_hop_limit == LOWPAN_IPHC_HLIM_1) {
|
|
|
|
ipv6.ip6_hlim = 1;
|
|
|
|
}
|
|
|
|
else if (iphc_hop_limit == LOWPAN_IPHC_HLIM_64) {
|
|
|
|
ipv6.ip6_hlim = 64;
|
|
|
|
}
|
|
|
|
else if (iphc_hop_limit == LOWPAN_IPHC_HLIM_255) {
|
|
|
|
ipv6.ip6_hlim = 255;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ipv6.ip6_hlim = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_hop_limit, tvb, offset, 1, ipv6.ip6_hlim);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Parse and decompress the source address.
|
|
|
|
*=====================================================
|
|
|
|
*/
|
2012-09-01 11:54:16 +00:00
|
|
|
length = 0;
|
|
|
|
memset(&ipv6.ip6_src, 0, sizeof(ipv6.ip6_src));
|
2010-09-30 19:23:31 +00:00
|
|
|
/* (SAC=1 && SAM=00) -> the unspecified address (::). */
|
|
|
|
if ((iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP) && (iphc_src_mode == LOWPAN_IPHC_ADDR_SRC_UNSPEC)) {
|
2012-09-01 11:54:16 +00:00
|
|
|
sctx = &lowpan_context_default;
|
2010-09-30 19:23:31 +00:00
|
|
|
}
|
2011-07-29 14:26:41 +00:00
|
|
|
/* The IID is derived from the encapsulating layer. */
|
2010-09-30 19:23:31 +00:00
|
|
|
else if (iphc_src_mode == LOWPAN_IPHC_ADDR_COMPRESSED) {
|
2011-07-29 14:26:41 +00:00
|
|
|
memcpy(&ipv6.ip6_src.bytes[sizeof(ipv6.ip6_src) - LOWPAN_IFC_ID_LEN], siid, LOWPAN_IFC_ID_LEN);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2010-09-30 19:23:31 +00:00
|
|
|
/* Full Address inline. */
|
|
|
|
else if (iphc_src_mode == LOWPAN_IPHC_ADDR_FULL_INLINE) {
|
2012-09-01 11:54:16 +00:00
|
|
|
if (!(iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP)) sctx = &lowpan_context_default;
|
2012-12-26 05:57:06 +00:00
|
|
|
length = (int)sizeof(ipv6.ip6_src);
|
2012-09-01 11:54:16 +00:00
|
|
|
tvb_memcpy(tvb, &ipv6.ip6_src, offset, length);
|
2010-09-30 19:23:31 +00:00
|
|
|
}
|
|
|
|
/* 64-bits inline. */
|
|
|
|
else if (iphc_src_mode == LOWPAN_IPHC_ADDR_64BIT_INLINE) {
|
2014-05-22 21:53:30 +00:00
|
|
|
length = 8;
|
2012-09-01 11:54:16 +00:00
|
|
|
tvb_memcpy(tvb, &ipv6.ip6_src.bytes[sizeof(ipv6.ip6_src) - length], offset, length);
|
2010-09-30 19:23:31 +00:00
|
|
|
}
|
|
|
|
/* 16-bits inline. */
|
|
|
|
else if (iphc_src_mode == LOWPAN_IPHC_ADDR_16BIT_INLINE) {
|
2014-05-22 21:53:30 +00:00
|
|
|
length = 2;
|
2010-09-30 19:23:31 +00:00
|
|
|
/* Format becomes ff:fe00:xxxx */
|
|
|
|
ipv6.ip6_src.bytes[11] = 0xff;
|
|
|
|
ipv6.ip6_src.bytes[12] = 0xfe;
|
|
|
|
tvb_memcpy(tvb, &ipv6.ip6_src.bytes[sizeof(ipv6.ip6_src) - length], offset, length);
|
2012-09-01 11:54:16 +00:00
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Copy the context bits. */
|
|
|
|
lowpan_pfxcpy(&ipv6.ip6_src, &sctx->prefix, sctx->plen);
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Update the IID of the encapsulating layer. */
|
|
|
|
siid = &ipv6.ip6_src.bytes[sizeof(ipv6.ip6_src) - LOWPAN_IFC_ID_LEN];
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Display the source IPv6 address. */
|
|
|
|
if (tree) {
|
2011-04-04 15:38:19 +00:00
|
|
|
proto_tree_add_ipv6(tree, hf_6lowpan_source, tvb, offset, length, (guint8 *)&ipv6.ip6_src);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Add information about where the context came from. */
|
|
|
|
/* TODO: We should display the prefix length too. */
|
|
|
|
if (tree && sctx->plen) {
|
|
|
|
ti = proto_tree_add_ipv6(iphc_tree, hf_6lowpan_iphc_sctx_prefix, tvb, 0, 0, (guint8 *)&sctx->prefix);
|
|
|
|
PROTO_ITEM_SET_GENERATED(ti);
|
|
|
|
if ( sctx->frame ) {
|
|
|
|
ti = proto_tree_add_uint(iphc_tree, hf_6lowpan_iphc_sctx_origin, tvb, 0, 0, sctx->frame);
|
|
|
|
PROTO_ITEM_SET_GENERATED(ti);
|
|
|
|
}
|
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
offset += length;
|
2010-03-09 23:22:03 +00:00
|
|
|
/*
|
|
|
|
* Do not set the address columns until after defragmentation, since we have
|
|
|
|
* to do decompression before reassembly, and changing the address will cause
|
|
|
|
* wireshark to think that the middle fragments came from another device.
|
|
|
|
*/
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/*=====================================================
|
2010-09-30 19:23:31 +00:00
|
|
|
* Parse and decompress a multicast address.
|
2009-10-03 10:06:19 +00:00
|
|
|
*=====================================================
|
|
|
|
*/
|
2012-09-01 11:54:16 +00:00
|
|
|
length = 0;
|
|
|
|
memset(&ipv6.ip6_dst, 0, sizeof(ipv6.ip6_dst));
|
2010-09-30 19:23:31 +00:00
|
|
|
/* Stateless multicast compression. */
|
|
|
|
if ((iphc_flags & LOWPAN_IPHC_FLAG_MCAST_COMP) && !(iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP)) {
|
2009-10-03 10:06:19 +00:00
|
|
|
if (iphc_dst_mode == LOWPAN_IPHC_ADDR_FULL_INLINE) {
|
2012-12-26 05:57:06 +00:00
|
|
|
length = (int)sizeof(ipv6.ip6_dst);
|
2009-10-03 10:06:19 +00:00
|
|
|
tvb_memcpy(tvb, &ipv6.ip6_dst.bytes[sizeof(ipv6.ip6_dst) - length], offset, length);
|
|
|
|
}
|
2010-09-30 19:23:31 +00:00
|
|
|
else if (iphc_dst_mode == LOWPAN_IPHC_MCAST_48BIT) {
|
2009-10-03 10:06:19 +00:00
|
|
|
ipv6.ip6_dst.bytes[0] = 0xff;
|
|
|
|
ipv6.ip6_dst.bytes[1] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[11] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[12] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[13] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[14] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[15] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
}
|
2010-02-12 22:10:53 +00:00
|
|
|
else if (iphc_dst_mode == LOWPAN_IPHC_MCAST_32BIT) {
|
2009-10-03 10:06:19 +00:00
|
|
|
ipv6.ip6_dst.bytes[0] = 0xff;
|
|
|
|
ipv6.ip6_dst.bytes[1] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[13] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[14] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[15] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
}
|
2010-02-12 22:10:53 +00:00
|
|
|
else if (iphc_dst_mode == LOWPAN_IPHC_MCAST_8BIT) {
|
2009-10-03 10:06:19 +00:00
|
|
|
ipv6.ip6_dst.bytes[0] = 0xff;
|
|
|
|
ipv6.ip6_dst.bytes[1] = 0x02;
|
|
|
|
ipv6.ip6_dst.bytes[15] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
}
|
2010-02-12 22:10:53 +00:00
|
|
|
else {
|
|
|
|
/* Illegal destination address compression mode. */
|
2013-06-09 03:28:05 +00:00
|
|
|
expert_add_info(pinfo, ti_dam, &ei_6lowpan_illegal_dest_addr_mode);
|
2010-02-12 22:10:53 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2010-09-30 19:23:31 +00:00
|
|
|
/* Stateful multicast compression. */
|
|
|
|
else if ((iphc_flags & LOWPAN_IPHC_FLAG_MCAST_COMP) && (iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP)) {
|
2010-03-10 19:21:17 +00:00
|
|
|
if (iphc_dst_mode == LOWPAN_IPHC_MCAST_STATEFUL_48BIT) {
|
2012-09-01 11:54:16 +00:00
|
|
|
/* RFC 3306 unicast-prefix based multicast address of the form:
|
|
|
|
* ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
|
|
|
|
* XX = inline byte.
|
|
|
|
* LL = prefix/context length (up to 64-bits).
|
|
|
|
* PP = prefix/context byte.
|
|
|
|
*/
|
2009-10-03 10:06:19 +00:00
|
|
|
ipv6.ip6_dst.bytes[0] = 0xff;
|
|
|
|
ipv6.ip6_dst.bytes[1] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[2] = tvb_get_guint8(tvb, offset + (length++));
|
2012-09-01 11:54:16 +00:00
|
|
|
ipv6.ip6_dst.bytes[3] = (dctx->plen > 64) ? (64) : (dctx->plen);
|
|
|
|
memcpy(&ipv6.ip6_dst.bytes[4], &dctx->prefix, 8);
|
2009-10-03 10:06:19 +00:00
|
|
|
ipv6.ip6_dst.bytes[12] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[13] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[14] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
ipv6.ip6_dst.bytes[15] = tvb_get_guint8(tvb, offset + (length++));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Illegal destination address compression mode. */
|
2013-06-09 03:28:05 +00:00
|
|
|
expert_add_info(pinfo, ti_dam, &ei_6lowpan_illegal_dest_addr_mode);
|
2009-10-03 10:06:19 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2010-09-30 19:23:31 +00:00
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2010-09-30 19:23:31 +00:00
|
|
|
/*=====================================================
|
|
|
|
* Parse and decompress a unicast destination address.
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
else {
|
|
|
|
/* (DAC=1 && DAM=00) -> reserved value. */
|
2012-09-01 11:54:16 +00:00
|
|
|
if ((iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP) && (iphc_dst_mode == LOWPAN_IPHC_ADDR_FULL_INLINE)) {
|
2010-09-30 19:23:31 +00:00
|
|
|
/* Illegal destination address compression mode. */
|
2013-06-09 03:28:05 +00:00
|
|
|
expert_add_info(pinfo, ti_dam, &ei_6lowpan_illegal_dest_addr_mode);
|
2010-09-30 19:23:31 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/* The IID is derived from the link-layer source. */
|
|
|
|
else if (iphc_dst_mode == LOWPAN_IPHC_ADDR_COMPRESSED) {
|
2011-07-29 14:26:41 +00:00
|
|
|
memcpy(&ipv6.ip6_dst.bytes[sizeof(ipv6.ip6_dst) - LOWPAN_IFC_ID_LEN], diid, LOWPAN_IFC_ID_LEN);
|
2010-09-30 19:23:31 +00:00
|
|
|
}
|
|
|
|
/* Full Address inline. */
|
|
|
|
else if (iphc_dst_mode == LOWPAN_IPHC_ADDR_FULL_INLINE) {
|
2012-09-01 11:54:16 +00:00
|
|
|
dctx = &lowpan_context_default;
|
2012-12-26 05:57:06 +00:00
|
|
|
length = (int)sizeof(ipv6.ip6_dst);
|
2012-09-01 11:54:16 +00:00
|
|
|
tvb_memcpy(tvb, &ipv6.ip6_dst, offset, length);
|
2010-09-30 19:23:31 +00:00
|
|
|
}
|
|
|
|
/* 64-bits inline. */
|
|
|
|
else if (iphc_dst_mode == LOWPAN_IPHC_ADDR_64BIT_INLINE) {
|
2014-05-22 21:53:30 +00:00
|
|
|
length = 8;
|
2012-09-01 11:54:16 +00:00
|
|
|
tvb_memcpy(tvb, &ipv6.ip6_dst.bytes[sizeof(ipv6.ip6_dst) - length], offset, length);
|
2010-09-30 19:23:31 +00:00
|
|
|
}
|
|
|
|
/* 16-bits inline. */
|
|
|
|
else if (iphc_dst_mode == LOWPAN_IPHC_ADDR_16BIT_INLINE) {
|
2014-05-22 21:53:30 +00:00
|
|
|
length = 2;
|
2010-09-30 19:23:31 +00:00
|
|
|
/* Format becomes ff:fe00:xxxx */
|
|
|
|
ipv6.ip6_dst.bytes[11] = 0xff;
|
|
|
|
ipv6.ip6_dst.bytes[12] = 0xfe;
|
|
|
|
tvb_memcpy(tvb, &ipv6.ip6_dst.bytes[sizeof(ipv6.ip6_dst) - length], offset, length);
|
|
|
|
}
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Copy the context bits. */
|
|
|
|
lowpan_pfxcpy(&ipv6.ip6_dst, &dctx->prefix, dctx->plen);
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Update the interface id of the encapsulating layer. */
|
|
|
|
diid = &ipv6.ip6_dst.bytes[sizeof(ipv6.ip6_dst) - LOWPAN_IFC_ID_LEN];
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Display the destination IPv6 address. */
|
|
|
|
if (tree) {
|
2011-04-04 15:38:19 +00:00
|
|
|
proto_tree_add_ipv6(tree, hf_6lowpan_dest, tvb, offset, length, (guint8 *)&ipv6.ip6_dst);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Add information about where the context came from. */
|
|
|
|
/* TODO: We should display the prefix length too. */
|
|
|
|
if (tree && dctx->plen) {
|
|
|
|
ti = proto_tree_add_ipv6(iphc_tree, hf_6lowpan_iphc_dctx_prefix, tvb, 0, 0, (guint8 *)&dctx->prefix);
|
|
|
|
PROTO_ITEM_SET_GENERATED(ti);
|
|
|
|
if ( dctx->frame ) {
|
|
|
|
ti = proto_tree_add_uint(iphc_tree, hf_6lowpan_iphc_dctx_origin, tvb, 0, 0, dctx->frame);
|
|
|
|
PROTO_ITEM_SET_GENERATED(ti);
|
|
|
|
}
|
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
offset += length;
|
2010-03-09 23:22:03 +00:00
|
|
|
/*
|
|
|
|
* Do not set the address columns until after defragmentation, since we have
|
|
|
|
* to do decompression before reassembly, and changing the address will cause
|
|
|
|
* wireshark to think that the middle fragments came from another device.
|
|
|
|
*/
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Decompress extension headers.
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
/* Parse the list of extension headers. */
|
|
|
|
if (iphc_flags & LOWPAN_IPHC_FLAG_NHDR) {
|
2010-02-12 22:10:53 +00:00
|
|
|
/* Parse the next header protocol identifier. */
|
2009-10-03 10:06:19 +00:00
|
|
|
ipv6.ip6_nxt = lowpan_parse_nhc_proto(tvb, offset);
|
|
|
|
|
|
|
|
/* Parse the 6LoWPAN NHC fields. */
|
2012-12-26 05:57:06 +00:00
|
|
|
nhdr_list = dissect_6lowpan_iphc_nhc(tvb, pinfo, tree, offset, dgram_size - (int)sizeof(struct ip6_hdr), siid, diid);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
/* Create an extension header for the remaining payload. */
|
|
|
|
else {
|
2014-06-19 17:17:16 +00:00
|
|
|
length = (gint)tvb_ensure_length_remaining(tvb, offset);
|
2013-09-12 20:37:30 +00:00
|
|
|
nhdr_list = (struct lowpan_nhdr *)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr) + length);
|
2009-10-03 10:06:19 +00:00
|
|
|
nhdr_list->next = NULL;
|
|
|
|
nhdr_list->proto = ipv6.ip6_nxt;
|
2011-02-23 22:49:59 +00:00
|
|
|
nhdr_list->length = length;
|
2010-03-09 23:22:03 +00:00
|
|
|
if (dgram_size < 0) {
|
|
|
|
nhdr_list->reported = tvb_reported_length_remaining(tvb, offset);
|
|
|
|
}
|
|
|
|
else {
|
2012-12-26 05:57:06 +00:00
|
|
|
nhdr_list->reported = dgram_size - (int)sizeof(struct ip6_hdr);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
2010-04-07 00:34:20 +00:00
|
|
|
tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr_list), offset, nhdr_list->length);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*=====================================================
|
|
|
|
* Rebuild the IPv6 packet.
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
/* Reassemble the IPv6 packet. */
|
2010-01-13 07:42:42 +00:00
|
|
|
ipv6_tvb = lowpan_reassemble_ipv6(tvb, &ipv6, nhdr_list);
|
2012-10-14 02:33:26 +00:00
|
|
|
|
|
|
|
/* Add a new data source for it. */
|
2012-10-14 02:54:25 +00:00
|
|
|
add_new_data_source(pinfo, ipv6_tvb, "Decompressed 6LoWPAN IPHC");
|
2012-10-14 02:33:26 +00:00
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
return ipv6_tvb;
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* dissect_6lowpan_iphc */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_iphc_nhc
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for a 6LoWPAN IPHC next header structure(s).
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
|
|
|
* offset ; packet buffer offset.
|
2010-03-09 23:22:03 +00:00
|
|
|
* dgram_size ; Remaining datagram size (or <0 if unknown).
|
2011-07-29 14:26:41 +00:00
|
|
|
* siid ; Source Interface ID.
|
|
|
|
* diid ; Destination Interface ID.
|
2009-10-03 10:06:19 +00:00
|
|
|
* RETURNS
|
2013-09-12 20:37:30 +00:00
|
|
|
* lowpan_nhdr * ; List of wmem_alloc'd next header structures.
|
2009-10-03 10:06:19 +00:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static struct lowpan_nhdr *
|
2014-09-18 05:20:01 +00:00
|
|
|
dissect_6lowpan_iphc_nhc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint dgram_size, const guint8 *siid, const guint8 *diid)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
|
|
|
gint length;
|
|
|
|
proto_item * ti = NULL;
|
|
|
|
proto_tree * nhc_tree = NULL;
|
|
|
|
struct lowpan_nhdr *nhdr;
|
|
|
|
|
2011-07-29 14:26:41 +00:00
|
|
|
/*=====================================================
|
|
|
|
* IP-in-IP Tunneling
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_IPV6_BITS) == LOWPAN_NHC_PATTERN_EXT_IPV6) {
|
|
|
|
guint8 ext_flags;
|
|
|
|
tvbuff_t *iphc_tvb;
|
2012-03-06 02:28:04 +00:00
|
|
|
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Create a tree for the IPv6 extension header. */
|
|
|
|
if (tree) {
|
2014-06-20 21:34:10 +00:00
|
|
|
nhc_tree = proto_tree_add_subtree(tree, tvb, offset, 2, ett_6lowpan_nhc_ext, NULL, "IPv6 extension header");
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Display the NHC-UDP pattern. */
|
2011-10-24 19:57:53 +00:00
|
|
|
proto_tree_add_bits_item(nhc_tree, hf_6lowpan_nhc_pattern, tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_BITS, ENC_BIG_ENDIAN);
|
2011-07-29 14:26:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get and display the extension header compression flags. */
|
|
|
|
ext_flags = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(nhc_tree, hf_6lowpan_nhc_ext_eid, tvb, offset, 1, ext_flags & LOWPAN_NHC_EXT_EID);
|
|
|
|
proto_tree_add_boolean(nhc_tree, hf_6lowpan_nhc_ext_nh, tvb, offset, 1, ext_flags & LOWPAN_NHC_EXT_NHDR);
|
2011-07-29 14:26:41 +00:00
|
|
|
if (ext_flags & LOWPAN_NHC_EXT_NHDR) {
|
|
|
|
/* TODO: Flag a warning, the NH bit MUST be 0 when EID==0x7 (IP-in-IP). */
|
|
|
|
}
|
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2012-03-06 02:28:04 +00:00
|
|
|
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Decode the remainder of the packet using IPHC encoding. */
|
2012-03-06 02:28:04 +00:00
|
|
|
iphc_tvb = dissect_6lowpan_iphc(tvb_new_subset_remaining(tvb, offset), pinfo, tree, dgram_size, siid, diid);
|
2011-07-29 14:26:41 +00:00
|
|
|
if (!iphc_tvb) return NULL;
|
2012-03-06 02:28:04 +00:00
|
|
|
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Create the next header structure for the tunneled IPv6 header. */
|
2014-09-07 19:01:10 +00:00
|
|
|
nhdr = (struct lowpan_nhdr *)wmem_alloc0(wmem_packet_scope(), sizeof(struct lowpan_nhdr) + tvb_captured_length(iphc_tvb));
|
2011-07-29 14:26:41 +00:00
|
|
|
nhdr->next = NULL;
|
|
|
|
nhdr->proto = IP_PROTO_IPV6;
|
2014-09-07 19:01:10 +00:00
|
|
|
nhdr->length = tvb_captured_length(iphc_tvb);
|
2011-07-29 14:26:41 +00:00
|
|
|
nhdr->reported = tvb_reported_length(iphc_tvb);
|
|
|
|
tvb_memcpy(iphc_tvb, LOWPAN_NHDR_DATA(nhdr), 0, nhdr->length);
|
|
|
|
return nhdr;
|
|
|
|
}
|
|
|
|
/*=====================================================
|
|
|
|
* IPv6 Extension Header
|
|
|
|
*=====================================================
|
|
|
|
*/
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_BITS) == LOWPAN_NHC_PATTERN_EXT) {
|
|
|
|
struct ip6_ext ipv6_ext;
|
|
|
|
guint8 ext_flags;
|
|
|
|
guint8 ext_len;
|
|
|
|
guint8 ext_proto;
|
|
|
|
|
|
|
|
/* Parse the IPv6 extension header protocol. */
|
|
|
|
ext_proto = lowpan_parse_nhc_proto(tvb, offset);
|
|
|
|
|
2009-10-04 17:50:39 +00:00
|
|
|
/* Create a tree for the IPv6 extension header. */
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
2014-06-20 21:34:10 +00:00
|
|
|
nhc_tree = proto_tree_add_subtree(tree, tvb, offset, 2, ett_6lowpan_nhc_ext, NULL, "IPv6 extension header");
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Display the NHC-UDP pattern. */
|
2011-10-24 19:57:53 +00:00
|
|
|
proto_tree_add_bits_item(nhc_tree, hf_6lowpan_nhc_pattern, tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get and display the extension header compression flags. */
|
|
|
|
ext_flags = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(nhc_tree, hf_6lowpan_nhc_ext_eid, tvb, offset, 1, ext_flags & LOWPAN_NHC_EXT_EID);
|
|
|
|
proto_tree_add_boolean(nhc_tree, hf_6lowpan_nhc_ext_nh, tvb, offset, 1, ext_flags & LOWPAN_NHC_EXT_NHDR);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the next header field, if present. */
|
|
|
|
if (!(ext_flags & LOWPAN_NHC_EXT_NHDR)) {
|
|
|
|
ipv6_ext.ip6e_nxt = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint_format_value(nhc_tree, hf_6lowpan_nhc_ext_next, tvb, offset, 1, ipv6_ext.ip6e_nxt,
|
2013-09-15 01:48:30 +00:00
|
|
|
"%s (0x%02x)", ipprotostr(ipv6_ext.ip6e_nxt), ipv6_ext.ip6e_nxt);
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_item_set_end(ti, tvb, offset+1);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get and display the extension header length. */
|
|
|
|
ext_len = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(nhc_tree, hf_6lowpan_nhc_ext_length, tvb, offset, 1, ext_len);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Compute the length of the extension header padded to an 8-byte alignment. */
|
2012-12-26 05:57:06 +00:00
|
|
|
length = (int)sizeof(struct ip6_ext) + ext_len;
|
2009-10-08 16:13:53 +00:00
|
|
|
length = (length + 7) & ~0x7;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Create the next header structure for the IPv6 extension header. */
|
2013-09-12 20:37:30 +00:00
|
|
|
nhdr = (struct lowpan_nhdr *)wmem_alloc0(wmem_packet_scope(), sizeof(struct lowpan_nhdr) + length);
|
2009-10-03 10:06:19 +00:00
|
|
|
nhdr->next = NULL;
|
|
|
|
nhdr->proto = ext_proto;
|
2010-03-10 07:15:07 +00:00
|
|
|
nhdr->length = length;
|
|
|
|
nhdr->reported = length;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Add the IPv6 extension header to the buffer. */
|
|
|
|
if (ext_flags & LOWPAN_NHC_EXT_NHDR) {
|
|
|
|
ipv6_ext.ip6e_nxt = lowpan_parse_nhc_proto(tvb, offset+ext_len);
|
|
|
|
}
|
|
|
|
ipv6_ext.ip6e_len = nhdr->reported>>3; /* Convert to units of 8 bytes. */
|
2010-02-12 22:10:53 +00:00
|
|
|
ipv6_ext.ip6e_len -= 1; /* Don't include the first 8 bytes. */
|
2010-04-07 00:34:20 +00:00
|
|
|
memcpy(LOWPAN_NHDR_DATA(nhdr), &ipv6_ext, sizeof(struct ip6_ext));
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the extension header was truncated, display the remainder using
|
|
|
|
* the data dissector, and end NHC dissection here.
|
|
|
|
*/
|
|
|
|
if (!tvb_bytes_exist(tvb, offset, ext_len)) {
|
|
|
|
/* Call the data dissector for the remainder. */
|
2012-03-06 02:28:04 +00:00
|
|
|
call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, nhc_tree);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Copy the remainder, and truncate the real buffer length. */
|
2014-09-07 19:01:10 +00:00
|
|
|
nhdr->length = tvb_captured_length_remaining(tvb, offset) + (int)sizeof(struct ip6_ext);
|
|
|
|
tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr) + sizeof(struct ip6_ext), offset, tvb_captured_length_remaining(tvb, offset));
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* There is nothing more we can do. */
|
|
|
|
return nhdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Display the extension header using the data dissector. */
|
2014-06-06 14:35:50 +00:00
|
|
|
call_dissector(data_handle, tvb_new_subset_length(tvb, offset, ext_len), pinfo, nhc_tree);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Copy the extension header into the struct. */
|
2010-04-07 00:34:20 +00:00
|
|
|
tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr) + sizeof(struct ip6_ext), offset, ext_len);
|
2009-10-03 10:06:19 +00:00
|
|
|
offset += ext_len;
|
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
if (ext_flags & LOWPAN_NHC_EXT_NHDR) {
|
|
|
|
/*
|
|
|
|
* There are more LOWPAN_NHC structures to parse. Call ourself again
|
|
|
|
* recursively to parse them and build the linked list.
|
|
|
|
*/
|
2012-12-26 05:57:06 +00:00
|
|
|
nhdr->next = dissect_6lowpan_iphc_nhc(tvb, pinfo, tree, offset, dgram_size - ext_len - (int)sizeof(struct ip6_ext), siid, diid);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Create another next header structure for the remaining payload. */
|
2014-06-19 17:17:16 +00:00
|
|
|
length = (gint)tvb_ensure_length_remaining(tvb, offset);
|
2013-09-12 20:37:30 +00:00
|
|
|
nhdr->next = (struct lowpan_nhdr *)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr) + length);
|
2009-10-03 10:06:19 +00:00
|
|
|
nhdr->next->next = NULL;
|
|
|
|
nhdr->next->proto = ipv6_ext.ip6e_nxt;
|
2011-02-23 22:49:59 +00:00
|
|
|
nhdr->next->length = length;
|
2010-03-09 23:22:03 +00:00
|
|
|
if (dgram_size < 0) {
|
|
|
|
nhdr->next->reported = tvb_reported_length_remaining(tvb, offset);
|
|
|
|
}
|
|
|
|
else {
|
2012-12-26 05:57:06 +00:00
|
|
|
nhdr->next->reported = dgram_size - ext_len - (int)sizeof(struct ip6_ext);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
2010-04-07 00:34:20 +00:00
|
|
|
tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr->next), offset, nhdr->next->length);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Done. */
|
|
|
|
return nhdr;
|
|
|
|
}
|
|
|
|
/*=====================================================
|
|
|
|
* UDP Header
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_UDP_BITS) == LOWPAN_NHC_PATTERN_UDP) {
|
|
|
|
struct udp_hdr udp;
|
|
|
|
gint src_bitlen;
|
|
|
|
gint dst_bitlen;
|
|
|
|
guint8 udp_flags;
|
|
|
|
|
|
|
|
/* Create a tree for the UDP header. */
|
|
|
|
if (tree) {
|
2014-06-20 21:34:10 +00:00
|
|
|
nhc_tree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_6lowpan_nhc_udp, NULL, "UDP header compression");
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Display the NHC-UDP pattern. */
|
2011-10-24 19:57:53 +00:00
|
|
|
proto_tree_add_bits_item(nhc_tree, hf_6lowpan_nhc_pattern, tvb, offset<<3, LOWPAN_NHC_PATTERN_UDP_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get and display the UDP header compression options */
|
|
|
|
udp_flags = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_boolean(nhc_tree, hf_6lowpan_nhc_udp_checksum, tvb, offset, 1, udp_flags & LOWPAN_NHC_UDP_CHECKSUM);
|
|
|
|
proto_tree_add_boolean(nhc_tree, hf_6lowpan_nhc_udp_src, tvb, offset, 1, udp_flags & LOWPAN_NHC_UDP_SRCPORT);
|
|
|
|
proto_tree_add_boolean(nhc_tree, hf_6lowpan_nhc_udp_dst, tvb, offset, 1, udp_flags & LOWPAN_NHC_UDP_DSTPORT);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the ports. */
|
|
|
|
switch (udp_flags & (LOWPAN_NHC_UDP_SRCPORT | LOWPAN_NHC_UDP_DSTPORT)) {
|
|
|
|
case (LOWPAN_NHC_UDP_SRCPORT | LOWPAN_NHC_UDP_DSTPORT):
|
2009-11-05 22:39:00 +00:00
|
|
|
udp.src_port = LOWPAN_PORT_12BIT_OFFSET + (tvb_get_guint8(tvb, offset) >> 4);
|
2009-11-06 07:08:40 +00:00
|
|
|
udp.dst_port = LOWPAN_PORT_12BIT_OFFSET + (tvb_get_guint8(tvb, offset) & 0x0f);
|
2009-10-03 10:06:19 +00:00
|
|
|
src_bitlen = 4;
|
|
|
|
dst_bitlen = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOWPAN_NHC_UDP_SRCPORT:
|
2009-11-05 22:39:00 +00:00
|
|
|
udp.src_port = LOWPAN_PORT_8BIT_OFFSET + tvb_get_guint8(tvb, offset);
|
|
|
|
udp.dst_port = tvb_get_ntohs(tvb, offset + 1);
|
2009-10-03 10:06:19 +00:00
|
|
|
src_bitlen = 8;
|
|
|
|
dst_bitlen = 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LOWPAN_NHC_UDP_DSTPORT:
|
2009-11-05 22:39:00 +00:00
|
|
|
udp.src_port = tvb_get_ntohs(tvb, offset);
|
|
|
|
udp.dst_port = LOWPAN_PORT_8BIT_OFFSET + tvb_get_guint8(tvb, offset + 2);
|
2009-10-03 10:06:19 +00:00
|
|
|
src_bitlen = 16;
|
|
|
|
dst_bitlen = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-11-05 22:39:00 +00:00
|
|
|
udp.src_port = tvb_get_ntohs(tvb, offset);
|
|
|
|
udp.dst_port = tvb_get_ntohs(tvb, offset+2);
|
2009-10-03 10:06:19 +00:00
|
|
|
src_bitlen = 16;
|
|
|
|
dst_bitlen = 16;
|
|
|
|
break;
|
|
|
|
} /* switch */
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_udp_src, tvb, offset, BITS_TO_BYTE_LEN(offset<<3, src_bitlen), udp.src_port);
|
2009-11-05 22:39:00 +00:00
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_udp_dst, tvb, offset+(src_bitlen>>3), BITS_TO_BYTE_LEN((offset<<3)+src_bitlen, dst_bitlen), udp.dst_port);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
offset += ((src_bitlen + dst_bitlen)>>3);
|
|
|
|
udp.src_port = g_ntohs(udp.src_port);
|
|
|
|
udp.dst_port = g_ntohs(udp.dst_port);
|
|
|
|
|
|
|
|
/* Get and display the checksum. */
|
|
|
|
if (!(udp_flags & LOWPAN_NHC_UDP_CHECKSUM)) {
|
|
|
|
/* Parse the checksum. */
|
|
|
|
udp.checksum = tvb_get_ntohs(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(tree, hf_6lowpan_udp_checksum, tvb, offset, 2, udp.checksum);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 2;
|
2009-10-03 10:06:19 +00:00
|
|
|
udp.checksum = g_ntohs(udp.checksum);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
udp.checksum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute the datagram length. */
|
2010-03-09 23:22:03 +00:00
|
|
|
if (dgram_size < 0) {
|
|
|
|
length = tvb_reported_length_remaining(tvb, offset);
|
2012-12-26 05:57:06 +00:00
|
|
|
udp.length = g_htons(length + (int)sizeof(struct udp_hdr));
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
udp.length = g_htons(dgram_size);
|
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Although rfc768 (udp) allows a packet to be sent with a checksum of
|
|
|
|
* 0 to mean that no checksum was computed, apparently IPv6 specifically
|
|
|
|
* disallows sending UDP datagrams without checksums. Likewise, 6LoWPAN
|
|
|
|
* requires that we recompute the checksum.
|
|
|
|
*
|
2009-11-05 22:39:00 +00:00
|
|
|
* If the datagram is incomplete, then leave the checsum at 0.
|
2009-10-03 10:06:19 +00:00
|
|
|
*/
|
2010-03-09 23:22:03 +00:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* This has been disabled, since we might only be dissecting a fragment
|
|
|
|
* of the packet, and thus we might not have the entire UDP payload at
|
|
|
|
* this time.
|
|
|
|
*
|
|
|
|
* If we want to display the checksums, they will have to be recomputed
|
2010-09-30 19:23:31 +00:00
|
|
|
* after packet reassembly. Lots of work for not much gain, since we can
|
|
|
|
* just set the UDP checksum to 0 and Wireshark doesn't care.
|
2010-03-09 23:22:03 +00:00
|
|
|
*/
|
2009-10-03 10:06:19 +00:00
|
|
|
if ((udp_flags & LOWPAN_NHC_UDP_CHECKSUM) && tvb_bytes_exist(tvb, offset, length)) {
|
|
|
|
vec_t cksum_vec[3];
|
|
|
|
struct {
|
|
|
|
struct e_in6_addr src;
|
|
|
|
struct e_in6_addr dst;
|
2009-11-05 22:39:00 +00:00
|
|
|
guint32 length;
|
|
|
|
guint8 zero[3];
|
2009-10-03 10:06:19 +00:00
|
|
|
guint8 proto;
|
|
|
|
} cksum_phdr;
|
|
|
|
|
|
|
|
/* Fill in the pseudo-header. */
|
|
|
|
memcpy(&cksum_phdr.src, pinfo->src.data, sizeof(struct e_in6_addr));
|
|
|
|
memcpy(&cksum_phdr.dst, pinfo->dst.data, sizeof(struct e_in6_addr));
|
2012-12-26 05:57:06 +00:00
|
|
|
cksum_phdr.length = g_htonl(length + (int)sizeof(struct udp_hdr));
|
2009-11-05 22:39:00 +00:00
|
|
|
memset(cksum_phdr.zero, 0, sizeof(cksum_phdr.zero));
|
2009-10-03 10:06:19 +00:00
|
|
|
cksum_phdr.proto = IP_PROTO_UDP;
|
|
|
|
|
|
|
|
/* Compute the checksum. */
|
Clean up Internet checksum handling.
Add macros to set entries of a vec_t, one for use when you have a
pointer to private data, and one for use when you have data in a tvbuff.
The latter wraps the use of tvb_get_ptr(), so that you're not directly
calling it in a dissector.
Move ip_checksum() to epan/in_cksum.c, and add an ip_checksum_tvb() that
wraps the use of tvb_get_ptr().
In the CARP dissector, give the length variable an unsigned type -
there's no benefit to it being signed, and that requires some casts to
be thrown around.
In the DCCP dissector, check only against the coverage length to see if
we have enough data, combine the "should we check the checksum?" check
with the "*can* we check the checksum?" check in a single if, and throw
a dissector assertion if the source network address type isn't IPv4 or
IPv6.
Get rid of inclues of <epan/in_cksum.h> in dissectors that don't use any
of the Internet checksum routines.
In the HIP dissector, make sure we have the data to calculate the
checksum before doing so.
Change-Id: I2f9674775dbb54c533d33082632809f7d32ec8ae
Reviewed-on: https://code.wireshark.org/review/3517
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-08-09 01:09:00 +00:00
|
|
|
SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)&cksum_phdr, sizeof(cksum_phdr));
|
|
|
|
SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)&udp, sizeof(struct udp_hdr));
|
|
|
|
SET_CKSUM_VEC_TVB(cksum_vec[2], tvb, offset, length);
|
2009-11-05 22:39:00 +00:00
|
|
|
udp.checksum = in_cksum(cksum_vec, 3);
|
|
|
|
if (udp.checksum == 0) udp.checksum = 0xffff;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2010-03-09 23:22:03 +00:00
|
|
|
#endif
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Create the next header structure for the UDP datagram. */
|
2014-06-19 17:17:16 +00:00
|
|
|
length = (gint)tvb_ensure_length_remaining(tvb, offset);
|
2013-09-12 20:37:30 +00:00
|
|
|
nhdr = (struct lowpan_nhdr *)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr) + sizeof(struct udp_hdr) + length);
|
2009-10-03 10:06:19 +00:00
|
|
|
nhdr->next = NULL;
|
|
|
|
nhdr->proto = IP_PROTO_UDP;
|
2012-12-26 05:57:06 +00:00
|
|
|
nhdr->length = length + (int)sizeof(struct udp_hdr);
|
2009-10-03 10:06:19 +00:00
|
|
|
nhdr->reported = g_ntohs(udp.length);
|
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
/* Copy the UDP header and payload into the buffer. */
|
2010-04-07 00:34:20 +00:00
|
|
|
memcpy(LOWPAN_NHDR_DATA(nhdr), &udp, sizeof(struct udp_hdr));
|
2014-09-07 19:01:10 +00:00
|
|
|
tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr) + sizeof(struct udp_hdr), offset, tvb_captured_length_remaining(tvb, offset));
|
2009-10-03 10:06:19 +00:00
|
|
|
return nhdr;
|
|
|
|
}
|
|
|
|
/*=====================================================
|
|
|
|
* Unknown Next Header Type
|
|
|
|
*=====================================================
|
|
|
|
*/
|
|
|
|
return NULL;
|
|
|
|
} /* dissect_6lowpan_iphc_nhc */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_bc0
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for a 6LoWPAN broadcast header.
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
|
|
|
* RETURNS
|
|
|
|
* tvbuff_t * ; The remaining payload to be parsed.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static tvbuff_t *
|
|
|
|
dissect_6lowpan_bc0(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
|
|
|
|
{
|
|
|
|
guint8 seqnum;
|
|
|
|
proto_tree * bcast_tree;
|
|
|
|
|
|
|
|
/* Create a tree for the broadcast header. */
|
|
|
|
if (tree) {
|
2014-06-20 21:34:10 +00:00
|
|
|
bcast_tree = proto_tree_add_subtree(tree, tvb, 0, 2, ett_6lowpan_bcast, NULL, "Broadcast Header");
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2009-11-05 22:39:00 +00:00
|
|
|
/* Get and display the pattern. */
|
2011-10-24 19:57:53 +00:00
|
|
|
proto_tree_add_bits_item(bcast_tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_BC0_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2009-11-05 22:39:00 +00:00
|
|
|
/* Get and display the sequence number. */
|
2014-05-22 21:53:30 +00:00
|
|
|
seqnum = tvb_get_guint8(tvb, 1);
|
|
|
|
proto_tree_add_uint(bcast_tree, hf_6lowpan_bcast_seqnum, tvb, 1, 1, seqnum);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the remaining buffer. */
|
2014-05-22 21:53:30 +00:00
|
|
|
return tvb_new_subset_remaining(tvb, 2);
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* dissect_6lowpan_bc0 */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_mesh
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for a 6LoWPAN mesh header.
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
|
|
|
* offset ; offset to the start of the header.
|
2014-09-18 05:20:01 +00:00
|
|
|
* siid ; Source Interface ID.
|
|
|
|
* diid ; Destination Interface ID.
|
2009-10-03 10:06:19 +00:00
|
|
|
* RETURNS
|
|
|
|
* tvbuff_t * ; The remaining payload to be parsed.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static tvbuff_t *
|
2014-09-18 05:20:01 +00:00
|
|
|
dissect_6lowpan_mesh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 *siid, guint8 *diid)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
|
|
|
gint offset = 0;
|
|
|
|
guint8 mesh_header;
|
|
|
|
proto_tree * mesh_tree = NULL;
|
|
|
|
proto_item * ti = NULL;
|
|
|
|
const guint8 * src_ifcid;
|
|
|
|
const guint8 * dst_ifcid;
|
|
|
|
|
|
|
|
/* Create a tree for the mesh header. */
|
2014-06-20 21:34:10 +00:00
|
|
|
mesh_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_6lowpan_mesh, NULL, "Mesh Header");
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the mesh flags. */
|
|
|
|
mesh_header = tvb_get_guint8(tvb, offset);
|
|
|
|
if (tree) {
|
|
|
|
proto_tree * flag_tree;
|
|
|
|
|
|
|
|
/* Create the mesh header subtree. */
|
2014-06-20 21:34:10 +00:00
|
|
|
flag_tree = proto_tree_add_subtree(mesh_tree, tvb, offset, 1, ett_6lowpan_mesh, NULL, "Flags");
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Add the mesh header fields. */
|
2011-10-24 19:57:53 +00:00
|
|
|
proto_tree_add_bits_item(flag_tree, hf_6lowpan_pattern, tvb, offset * 8, LOWPAN_PATTERN_MESH_BITS, ENC_BIG_ENDIAN);
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_boolean(flag_tree, hf_6lowpan_mesh_v, tvb, offset, 1, mesh_header & LOWPAN_MESH_HEADER_V);
|
|
|
|
proto_tree_add_boolean(flag_tree, hf_6lowpan_mesh_f, tvb, offset, 1, mesh_header & LOWPAN_MESH_HEADER_F);
|
2014-04-18 03:33:42 +00:00
|
|
|
proto_tree_add_uint(flag_tree, hf_6lowpan_mesh_hops, tvb, offset, 1, mesh_header & LOWPAN_MESH_HEADER_HOPS);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2014-04-18 03:33:42 +00:00
|
|
|
if ((mesh_header & LOWPAN_MESH_HEADER_HOPS) == LOWPAN_MESH_HEADER_HOPS) {
|
|
|
|
if (tree) proto_tree_add_item(mesh_tree, hf_6lowpan_mesh_hops8, tvb, offset, 1, ENC_NA);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2014-04-18 03:33:42 +00:00
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the originator address. */
|
2010-07-23 19:40:32 +00:00
|
|
|
if (!(mesh_header & LOWPAN_MESH_HEADER_V)) {
|
2009-10-03 10:06:19 +00:00
|
|
|
guint64 addr64 = tvb_get_ntoh64(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint64(mesh_tree, hf_6lowpan_mesh_orig64, tvb, offset, 8, addr64);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
src_ifcid = tvb_get_ptr(tvb, offset, 8);
|
2014-09-18 05:20:01 +00:00
|
|
|
memcpy(siid, src_ifcid, 8);
|
|
|
|
siid[0] ^= 0x02; /* swap U/L bit */
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 8;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
guint16 addr16 = tvb_get_ntohs(tvb, offset);
|
2010-04-07 00:34:20 +00:00
|
|
|
guint8 * ifcid;
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(mesh_tree, hf_6lowpan_mesh_orig16, tvb, offset, 2, addr16);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
ifcid = (guint8 *)wmem_alloc(pinfo->pool, 8);
|
2010-09-30 19:23:31 +00:00
|
|
|
lowpan_addr16_to_ifcid(addr16, ifcid);
|
2010-04-07 00:34:20 +00:00
|
|
|
src_ifcid = ifcid;
|
2014-09-18 05:20:01 +00:00
|
|
|
memcpy(siid, src_ifcid, 8);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 2;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
SET_ADDRESS(&pinfo->src, AT_EUI64, 8, src_ifcid);
|
|
|
|
SET_ADDRESS(&pinfo->net_src, AT_EUI64, 8, src_ifcid);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the destination address. */
|
2010-07-23 19:40:32 +00:00
|
|
|
if (!(mesh_header & LOWPAN_MESH_HEADER_F)) {
|
2009-10-03 10:06:19 +00:00
|
|
|
guint64 addr64 = tvb_get_ntoh64(tvb, offset);
|
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint64(mesh_tree, hf_6lowpan_mesh_dest64, tvb, offset, 8, addr64);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
dst_ifcid = tvb_get_ptr(tvb, offset, 8);
|
2014-09-18 05:20:01 +00:00
|
|
|
memcpy(diid, dst_ifcid, 8);
|
|
|
|
diid[0] ^= 0x02; /* swap U/L bit */
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 8;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
guint16 addr16 = tvb_get_ntohs(tvb, offset);
|
2010-04-07 00:34:20 +00:00
|
|
|
guint8 * ifcid;
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(mesh_tree, hf_6lowpan_mesh_dest16, tvb, offset, 2, addr16);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
ifcid = (guint8 *)wmem_alloc(pinfo->pool, 8);
|
2010-09-30 19:23:31 +00:00
|
|
|
lowpan_addr16_to_ifcid(addr16, ifcid);
|
2010-04-07 00:34:20 +00:00
|
|
|
dst_ifcid = ifcid;
|
2014-09-18 05:20:01 +00:00
|
|
|
memcpy(diid, dst_ifcid, 8);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 2;
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
SET_ADDRESS(&pinfo->dst, AT_EUI64, 8, dst_ifcid);
|
|
|
|
SET_ADDRESS(&pinfo->net_dst, AT_EUI64, 8, dst_ifcid);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Adjust the mesh header length. */
|
|
|
|
if (tree) {
|
|
|
|
proto_item_set_end(ti, tvb, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the remaining buffer. */
|
2012-03-06 02:28:04 +00:00
|
|
|
return tvb_new_subset_remaining(tvb, offset);
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* dissect_6lowpan_mesh */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
2010-03-09 23:22:03 +00:00
|
|
|
* dissect_6lowpan_frag_first
|
2009-10-03 10:06:19 +00:00
|
|
|
* DESCRIPTION
|
2010-03-09 23:22:03 +00:00
|
|
|
* Dissector routine for a 6LoWPAN FRAG1 headers.
|
|
|
|
*
|
|
|
|
* If reassembly could be completed, this should return an
|
|
|
|
* uncompressed IPv6 packet. If reassembly had to be delayed
|
|
|
|
* for more packets, this will return NULL.
|
2009-10-03 10:06:19 +00:00
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
2011-07-29 14:26:41 +00:00
|
|
|
* siid ; Source Interface ID.
|
|
|
|
* diid ; Destination Interface ID.
|
2009-10-03 10:06:19 +00:00
|
|
|
* RETURNS
|
2010-03-09 23:22:03 +00:00
|
|
|
* tvbuff_t * ; reassembled IPv6 packet.
|
2009-10-03 10:06:19 +00:00
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static tvbuff_t *
|
2014-09-18 05:20:01 +00:00
|
|
|
dissect_6lowpan_frag_first(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const guint8 *siid, const guint8 *diid)
|
2010-03-09 23:22:03 +00:00
|
|
|
{
|
|
|
|
gint offset = 0;
|
|
|
|
gint frag_size;
|
|
|
|
guint16 dgram_size;
|
|
|
|
guint16 dgram_tag;
|
2014-06-20 21:34:10 +00:00
|
|
|
proto_tree * frag_tree;
|
|
|
|
proto_item * ti;
|
|
|
|
proto_item * length_item;
|
2010-03-09 23:22:03 +00:00
|
|
|
/* Reassembly parameters. */
|
2014-03-09 20:11:43 +00:00
|
|
|
tvbuff_t * new_tvb;
|
|
|
|
tvbuff_t * frag_tvb;
|
|
|
|
fragment_head * frag_data;
|
2010-03-09 23:22:03 +00:00
|
|
|
gboolean save_fragmented;
|
|
|
|
|
|
|
|
/* Create a tree for the fragmentation header. */
|
2014-06-20 21:34:10 +00:00
|
|
|
frag_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_6lowpan_frag, &ti, "Fragmentation Header");
|
2010-03-09 23:22:03 +00:00
|
|
|
|
|
|
|
/* Get and display the pattern and datagram size. */
|
2011-10-24 19:57:53 +00:00
|
|
|
dgram_size = tvb_get_bits16(tvb, (offset * 8) + LOWPAN_PATTERN_FRAG_BITS, LOWPAN_FRAG_DGRAM_SIZE_BITS, ENC_BIG_ENDIAN);
|
2014-06-20 21:34:10 +00:00
|
|
|
proto_tree_add_bits_item(frag_tree, hf_6lowpan_pattern, tvb, offset * 8, LOWPAN_PATTERN_FRAG_BITS, ENC_BIG_ENDIAN);
|
|
|
|
length_item = proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_size, tvb, offset, 2, dgram_size);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 2;
|
2010-03-09 23:22:03 +00:00
|
|
|
|
|
|
|
/* Get and display the datagram tag. */
|
|
|
|
dgram_tag = tvb_get_ntohs(tvb, offset);
|
2014-06-20 21:34:10 +00:00
|
|
|
proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_tag, tvb, offset, 2, dgram_tag);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 2;
|
2010-03-09 23:22:03 +00:00
|
|
|
|
|
|
|
/* Adjust the fragmentation header length. */
|
2014-06-20 21:34:10 +00:00
|
|
|
proto_item_set_end(ti, tvb, offset);
|
2010-03-09 23:22:03 +00:00
|
|
|
|
2011-07-29 14:26:41 +00:00
|
|
|
/* The first fragment can contain an uncompressed IPv6, HC1 or IPHC fragment. */
|
2012-03-06 02:28:04 +00:00
|
|
|
frag_tvb = tvb_new_subset_remaining(tvb, offset);
|
2010-03-09 23:22:03 +00:00
|
|
|
if (tvb_get_bits8(frag_tvb, 0, LOWPAN_PATTERN_IPV6_BITS) == LOWPAN_PATTERN_IPV6) {
|
|
|
|
frag_tvb = dissect_6lowpan_ipv6(frag_tvb, pinfo, tree);
|
|
|
|
}
|
|
|
|
else if (tvb_get_bits8(frag_tvb, 0, LOWPAN_PATTERN_HC1_BITS) == LOWPAN_PATTERN_HC1) {
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Check if the datagram size is sane. */
|
|
|
|
if (dgram_size < (gint)sizeof(struct ip6_hdr)) {
|
2013-09-09 00:44:09 +00:00
|
|
|
expert_add_info_format(pinfo, length_item, &ei_6lowpan_bad_ipv6_header_length,
|
2013-06-09 03:28:05 +00:00
|
|
|
"Length is less than IPv6 header length %u", (guint)sizeof(struct ip6_hdr));
|
2011-07-29 14:26:41 +00:00
|
|
|
}
|
|
|
|
frag_tvb = dissect_6lowpan_hc1(frag_tvb, pinfo, tree, dgram_size, siid, diid);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
else if (tvb_get_bits8(frag_tvb, 0, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) {
|
2011-07-29 14:26:41 +00:00
|
|
|
/* Check if the datagram size is sane. */
|
|
|
|
if (dgram_size < (gint)sizeof(struct ip6_hdr)) {
|
2013-09-09 00:44:09 +00:00
|
|
|
expert_add_info_format(pinfo, length_item, &ei_6lowpan_bad_ipv6_header_length,
|
2013-06-09 03:28:05 +00:00
|
|
|
"Length is less than IPv6 header length %u", (guint)sizeof(struct ip6_hdr));
|
2011-07-29 14:26:41 +00:00
|
|
|
}
|
|
|
|
frag_tvb = dissect_6lowpan_iphc(frag_tvb, pinfo, tree, dgram_size, siid, diid);
|
2010-03-09 23:22:03 +00:00
|
|
|
}
|
|
|
|
/* Unknown 6LoWPAN dispatch type */
|
|
|
|
else {
|
|
|
|
dissect_6lowpan_unknown(frag_tvb, pinfo, tree);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-05-27 07:02:26 +00:00
|
|
|
/* Check call to dissect_6lowpan_xxx was successful */
|
|
|
|
if (frag_tvb == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
/* Add this datagram to the fragment table. */
|
2014-09-07 19:01:10 +00:00
|
|
|
frag_size = tvb_captured_length(frag_tvb);
|
2010-03-09 23:22:03 +00:00
|
|
|
tvb_set_reported_length(frag_tvb, frag_size);
|
|
|
|
save_fragmented = pinfo->fragmented;
|
|
|
|
pinfo->fragmented = TRUE;
|
2013-03-22 23:59:54 +00:00
|
|
|
frag_data = fragment_add_check(&lowpan_reassembly_table,
|
|
|
|
frag_tvb, 0, pinfo, dgram_tag, NULL,
|
2010-03-09 23:22:03 +00:00
|
|
|
0, frag_size, (frag_size < dgram_size));
|
|
|
|
|
|
|
|
/* Attempt reassembly. */
|
|
|
|
new_tvb = process_reassembled_data(frag_tvb, 0, pinfo,
|
2012-10-14 02:54:25 +00:00
|
|
|
"Reassembled 6LoWPAN", frag_data, &lowpan_frag_items,
|
2010-03-09 23:22:03 +00:00
|
|
|
NULL, tree);
|
|
|
|
|
2011-07-31 23:41:20 +00:00
|
|
|
pinfo->fragmented = save_fragmented;
|
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
if (new_tvb) {
|
2012-10-14 02:33:26 +00:00
|
|
|
/* Reassembly was successful; return the completed datagram. */
|
2010-03-09 23:22:03 +00:00
|
|
|
return new_tvb;
|
2012-10-14 02:33:26 +00:00
|
|
|
} else {
|
|
|
|
/* Reassembly was unsuccessful; show this fragment. This may
|
|
|
|
just mean that we don't yet have all the fragments, so
|
|
|
|
we should not just continue dissecting. */
|
2010-03-09 23:22:03 +00:00
|
|
|
call_dissector(data_handle, frag_tvb, pinfo, proto_tree_get_root(tree));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} /* dissect_6lowpan_frag_first */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_frag_middle
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for a 6LoWPAN FRAGN headers.
|
|
|
|
*
|
|
|
|
* If reassembly could be completed, this should return an
|
|
|
|
* uncompressed IPv6 packet. If reassembly had to be delayed
|
|
|
|
* for more packets, this will return NULL.
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
|
|
|
* RETURNS
|
|
|
|
* tvbuff_t * ; reassembled IPv6 packet.
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static tvbuff_t *
|
|
|
|
dissect_6lowpan_frag_middle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
2009-10-03 10:06:19 +00:00
|
|
|
{
|
|
|
|
gint offset = 0;
|
|
|
|
gint frag_size;
|
|
|
|
guint16 dgram_size;
|
|
|
|
guint16 dgram_tag;
|
2009-11-05 22:39:00 +00:00
|
|
|
guint16 dgram_offset = 0;
|
2009-10-03 10:06:19 +00:00
|
|
|
proto_tree * frag_tree = NULL;
|
2014-06-20 21:34:10 +00:00
|
|
|
proto_item * ti;
|
2009-10-03 10:06:19 +00:00
|
|
|
/* Reassembly parameters. */
|
2014-03-09 20:11:43 +00:00
|
|
|
tvbuff_t * new_tvb;
|
|
|
|
fragment_head * frag_data;
|
2009-10-03 10:06:19 +00:00
|
|
|
gboolean save_fragmented;
|
|
|
|
|
|
|
|
/* Create a tree for the fragmentation header. */
|
2014-06-20 21:34:10 +00:00
|
|
|
frag_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_6lowpan_frag, &ti, "Fragmentation Header");
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the pattern and datagram size. */
|
2011-10-24 19:57:53 +00:00
|
|
|
dgram_size = tvb_get_bits16(tvb, (offset * 8) + LOWPAN_PATTERN_FRAG_BITS, LOWPAN_FRAG_DGRAM_SIZE_BITS, ENC_BIG_ENDIAN);
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
2011-10-24 19:57:53 +00:00
|
|
|
proto_tree_add_bits_item(frag_tree, hf_6lowpan_pattern, tvb, offset * 8, LOWPAN_PATTERN_FRAG_BITS, ENC_BIG_ENDIAN);
|
2014-05-22 21:53:30 +00:00
|
|
|
proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_size, tvb, offset, 2, dgram_size);
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 2;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Get and display the datagram tag. */
|
|
|
|
dgram_tag = tvb_get_ntohs(tvb, offset);
|
2014-06-20 21:34:10 +00:00
|
|
|
proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_tag, tvb, offset, 2, dgram_tag);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 2;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2010-03-09 23:22:03 +00:00
|
|
|
/* Get and display the datagram offset. */
|
|
|
|
dgram_offset = tvb_get_guint8(tvb, offset) * 8;
|
2014-06-20 21:34:10 +00:00
|
|
|
proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_offset, tvb, offset, 1, dgram_offset);
|
2014-05-22 21:53:30 +00:00
|
|
|
offset += 1;
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Adjust the fragmentation header length. */
|
2009-11-05 22:39:00 +00:00
|
|
|
frag_size = tvb_reported_length_remaining(tvb, offset);
|
2009-10-03 10:06:19 +00:00
|
|
|
if (tree) {
|
|
|
|
proto_item_set_end(ti, tvb, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add this datagram to the fragment table. */
|
|
|
|
save_fragmented = pinfo->fragmented;
|
|
|
|
pinfo->fragmented = TRUE;
|
2013-03-22 23:59:54 +00:00
|
|
|
frag_data = fragment_add_check(&lowpan_reassembly_table,
|
|
|
|
tvb, offset, pinfo, dgram_tag, NULL,
|
2009-10-03 10:06:19 +00:00
|
|
|
dgram_offset, frag_size, ((dgram_offset + frag_size) < dgram_size));
|
|
|
|
|
|
|
|
/* Attempt reassembly. */
|
|
|
|
new_tvb = process_reassembled_data(tvb, offset, pinfo,
|
2012-10-14 02:54:25 +00:00
|
|
|
"Reassembled 6LoWPAN", frag_data, &lowpan_frag_items,
|
2009-10-03 10:06:19 +00:00
|
|
|
NULL, tree);
|
|
|
|
|
2011-07-31 23:41:20 +00:00
|
|
|
pinfo->fragmented = save_fragmented;
|
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/* If reassembly was successful, then return the completed datagram. */
|
|
|
|
if (new_tvb) {
|
|
|
|
return new_tvb;
|
|
|
|
}
|
2010-03-09 23:22:03 +00:00
|
|
|
/* If reassembly failed, display the payload fragment using the data dissector. */
|
2009-10-03 10:06:19 +00:00
|
|
|
else {
|
2012-03-06 02:28:04 +00:00
|
|
|
new_tvb = tvb_new_subset_remaining(tvb, offset);
|
2010-03-09 23:22:03 +00:00
|
|
|
call_dissector(data_handle, new_tvb, pinfo, proto_tree_get_root(tree));
|
2009-10-03 10:06:19 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2010-03-09 23:22:03 +00:00
|
|
|
} /* dissect_6lowpan_frag_middle */
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* dissect_6lowpan_unknown
|
|
|
|
* DESCRIPTION
|
|
|
|
* Dissector routine for 6LoWPAN packets after encountering
|
|
|
|
* an unknown header.
|
|
|
|
* PARAMETERS
|
|
|
|
* tvb ; packet buffer.
|
|
|
|
* pinfo ; packet info.
|
|
|
|
* tree ; 6LoWPAN display tree.
|
|
|
|
* RETURNS
|
|
|
|
* void ;
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
2010-03-09 23:22:03 +00:00
|
|
|
void
|
2009-10-03 10:06:19 +00:00
|
|
|
dissect_6lowpan_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
tvbuff_t * data_tvb;
|
|
|
|
|
|
|
|
/* Get and display the pattern. */
|
|
|
|
if (tree) {
|
2014-04-18 03:33:42 +00:00
|
|
|
/* Give a special case for NALP. */
|
|
|
|
if (tvb_get_bits8(tvb, 0, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) {
|
|
|
|
proto_tree_add_bits_item(tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_IPHC_BITS, ENC_BIG_ENDIAN);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
guint8 pattern = tvb_get_guint8(tvb, 0);
|
|
|
|
proto_tree_add_uint_bits_format_value(tree, hf_6lowpan_pattern, tvb, 0, 8, pattern, "Unknown (0x%02x)", pattern);
|
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a tvbuff subset for the remaining data. */
|
2014-05-22 21:53:30 +00:00
|
|
|
data_tvb = tvb_new_subset_remaining(tvb, 1);
|
2009-10-03 10:06:19 +00:00
|
|
|
call_dissector(data_handle, data_tvb, pinfo, proto_tree_get_root(tree));
|
|
|
|
} /* dissect_6lowpan_unknown */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* proto_register_6lowpan
|
|
|
|
* DESCRIPTION
|
|
|
|
* Protocol registration routine for 6LoWPAN. Called during
|
|
|
|
* Wireshark initialization.
|
|
|
|
* PARAMETERS
|
|
|
|
* none ;
|
|
|
|
* RETURNS
|
|
|
|
* void ;
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
proto_register_6lowpan(void)
|
|
|
|
{
|
|
|
|
static hf_register_info hf[] = {
|
|
|
|
/* Common 6LoWPAN fields. */
|
|
|
|
{ &hf_6lowpan_pattern,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Pattern", "6lowpan.pattern",
|
|
|
|
FT_UINT8, BASE_HEX, VALS(lowpan_patterns), 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_nhc_pattern,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Pattern", "6lowpan.nhc.pattern",
|
|
|
|
FT_UINT8, BASE_HEX, VALS(lowpan_nhc_patterns), 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* HC1 header fields. */
|
|
|
|
{ &hf_6lowpan_hc1_source_prefix,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source prefix", "6lowpan.hc1.src_prefix",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_SOURCE_PREFIX, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hc1_source_ifc,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source interface", "6lowpan.hc1.src_ifc",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_SOURCE_IFC, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hc1_dest_prefix,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination prefix", "6lowpan.hc1.dst_prefix",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_DEST_PREFIX, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hc1_dest_ifc,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination interface", "6lowpan.hc1.dst_ifc",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_DEST_IFC, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hc1_class,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Traffic class and flow label", "6lowpan.hc1.class",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_TRAFFIC_CLASS, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hc1_next,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Next header", "6lowpan.hc1.next",
|
|
|
|
FT_UINT8, BASE_HEX, VALS(lowpan_hc1_next), LOWPAN_HC1_NEXT, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hc1_more,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "More HC bits", "6lowpan.hc1.more",
|
|
|
|
FT_BOOLEAN, 8, NULL, LOWPAN_HC1_MORE, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* HC_UDP header fields. */
|
|
|
|
{ &hf_6lowpan_hc2_udp_src,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source port", "6lowpan.hc2.udp.src",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC2_UDP_SRCPORT, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hc2_udp_dst,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination port", "6lowpan.hc2.udp.dst",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC2_UDP_DSTPORT, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hc2_udp_len,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Length", "6lowpan.hc2.udp.length",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC2_UDP_LENGTH, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* IPHC header fields. */
|
|
|
|
{ &hf_6lowpan_iphc_flag_tf,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Traffic class and flow label", "6lowpan.iphc.tf",
|
|
|
|
FT_UINT16, BASE_HEX, VALS(lowpan_iphc_traffic), LOWPAN_IPHC_FLAG_FLOW, "traffic class and flow control encoding", HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_flag_nhdr,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Next header", "6lowpan.iphc.nh",
|
|
|
|
FT_BOOLEAN, 16, TFS(&lowpan_compression), LOWPAN_IPHC_FLAG_NHDR, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_flag_hlim,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Hop limit", "6lowpan.iphc.hlim",
|
|
|
|
FT_UINT16, BASE_HEX, VALS(lowpan_iphc_hop_limit), LOWPAN_IPHC_FLAG_HLIM, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_flag_cid,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Context identifier extension", "6lowpan.iphc.cid",
|
|
|
|
FT_BOOLEAN, 16, NULL, LOWPAN_IPHC_FLAG_CONTEXT_ID, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_flag_sac,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source address compression", "6lowpan.iphc.sac",
|
|
|
|
FT_BOOLEAN, 16, TFS(&lowpan_iphc_addr_compression), LOWPAN_IPHC_FLAG_SRC_COMP, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_flag_sam,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source address mode", "6lowpan.iphc.sam",
|
|
|
|
FT_UINT16, BASE_HEX, VALS(lowpan_iphc_addr_modes), LOWPAN_IPHC_FLAG_SRC_MODE, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_flag_mcast,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Multicast address compression", "6lowpan.iphc.m",
|
|
|
|
FT_BOOLEAN, 16, NULL, LOWPAN_IPHC_FLAG_MCAST_COMP, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_flag_dac,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination address compression","6lowpan.iphc.dac",
|
|
|
|
FT_BOOLEAN, 16, TFS(&lowpan_iphc_addr_compression), LOWPAN_IPHC_FLAG_DST_COMP, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_flag_dam,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination address mode", "6lowpan.iphc.dam",
|
|
|
|
FT_UINT16, BASE_HEX, VALS(lowpan_iphc_addr_modes), LOWPAN_IPHC_FLAG_DST_MODE, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_sci,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source context identifier", "6lowpan.iphc.sci",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, LOWPAN_IPHC_FLAG_SCI, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_iphc_dci,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination context identifier", "6lowpan.iphc.dci",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, LOWPAN_IPHC_FLAG_DCI, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Context information fields. */
|
|
|
|
{ &hf_6lowpan_iphc_sctx_prefix,
|
|
|
|
{ "Source context", "6lowpan.iphc.sctx.prefix", FT_IPv6, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_6lowpan_iphc_sctx_origin,
|
|
|
|
{ "Origin", "6lowpan.iphc.sctx.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_6lowpan_iphc_dctx_prefix,
|
|
|
|
{ "Destination context", "6lowpan.iphc.dctx.prefix", FT_IPv6, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{ &hf_6lowpan_iphc_dctx_origin,
|
|
|
|
{ "Origin", "6lowpan.iphc.dctx.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
|
2010-02-12 22:10:53 +00:00
|
|
|
/* NHC IPv6 extension header fields. */
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_nhc_ext_eid,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Header ID", "6lowpan.nhc.ext.eid",
|
|
|
|
FT_UINT8, BASE_HEX, VALS(lowpan_nhc_eid), LOWPAN_NHC_EXT_EID, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_nhc_ext_nh,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Next header", "6lowpan.nhc.ext.nh",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_NHC_EXT_NHDR, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_nhc_ext_next,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Next header", "6lowpan.nhc.ext.next",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_nhc_ext_length,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Header length", "6lowpan.nhc.ext.length",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* NHC UDP header fields. */
|
|
|
|
{ &hf_6lowpan_nhc_udp_checksum,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Checksum", "6lowpan.nhc.udp.checksum",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_NHC_UDP_CHECKSUM, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_nhc_udp_src,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source port", "6lowpan.nhc.udp.src",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_NHC_UDP_SRCPORT, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_nhc_udp_dst,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination port", "6lowpan.nhc.udp.dst",
|
|
|
|
FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_NHC_UDP_DSTPORT, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Uncompressed IPv6 fields. */
|
|
|
|
{ &hf_6lowpan_traffic_class,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Traffic class", "6lowpan.class",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_flow_label,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Flow label", "6lowpan.flow",
|
|
|
|
FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_ecn,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "ECN", "6lowpan.ecn",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, LOWPAN_IPHC_TRAFFIC_ECN, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_dscp,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "DSCP", "6lowpan.dscp",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, LOWPAN_IPHC_TRAFFIC_DSCP, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_next_header,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Next header", "6lowpan.next",
|
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_hop_limit,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Hop limit", "6lowpan.hops",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_source,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source", "6lowpan.src",
|
|
|
|
FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 address", HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_dest,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination", "6lowpan.dst",
|
|
|
|
FT_IPv6, BASE_NONE, NULL, 0x0, "Destination IPv6 address", HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Uncompressed UDP fields. */
|
|
|
|
{ &hf_6lowpan_udp_src,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Source port", "6lowpan.udp.src",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_udp_dst,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination port", "6lowpan.udp.dst",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_udp_len,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "UDP length", "6lowpan.udp.length",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_udp_checksum,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "UDP checksum", "6lowpan.udp.checksum",
|
|
|
|
FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Broadcast header fields. */
|
|
|
|
{ &hf_6lowpan_bcast_seqnum,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Sequence number", "6lowpan.bcast.seqnum",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Mesh header fields. */
|
|
|
|
{ &hf_6lowpan_mesh_v,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "V", "6lowpan.mesh.v",
|
|
|
|
FT_BOOLEAN, 8, NULL, LOWPAN_MESH_HEADER_V, "short originator address present", HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_mesh_f,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "D", "6lowpan.mesh.f",
|
|
|
|
FT_BOOLEAN, 8, NULL, LOWPAN_MESH_HEADER_F, "short destination address present", HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_mesh_hops,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Hops left", "6lowpan.mesh.hops",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, LOWPAN_MESH_HEADER_HOPS, NULL, HFILL }},
|
2010-07-26 13:04:10 +00:00
|
|
|
{ &hf_6lowpan_mesh_hops8,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Deep Hops left (Flags.Hops left == 15)", "6lowpan.mesh.hops8",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_mesh_orig16,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Originator", "6lowpan.mesh.orig16",
|
|
|
|
FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_mesh_orig64,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Originator", "6lowpan.mesh.orig64",
|
|
|
|
FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_mesh_dest16,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination", "6lowpan.mesh.dest16",
|
|
|
|
FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_mesh_dest64,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Destination", "6lowpan.mesh.dest64",
|
|
|
|
FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Fragmentation header fields. */
|
|
|
|
{ &hf_6lowpan_frag_dgram_size,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Datagram size", "6lowpan.frag.size",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_frag_dgram_tag,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Datagram tag", "6lowpan.frag.tag",
|
|
|
|
FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_frag_dgram_offset,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Datagram offset", "6lowpan.frag.offset",
|
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Reassembly fields. */
|
|
|
|
{ &hf_6lowpan_fragments,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Message fragments", "6lowpan.fragments",
|
|
|
|
FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_fragment,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Message fragment", "6lowpan.fragment",
|
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_fragment_overlap,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Message fragment overlap", "6lowpan.fragment.overlap",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_fragment_overlap_conflicts,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Message fragment overlapping with conflicting data", "6lowpan.fragment.overlap.conflicts",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_fragment_multiple_tails,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Message has multiple tail fragments", "6lowpan.fragment.multiple_tails",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_fragment_too_long_fragment,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Message fragment too long", "6lowpan.fragment.too_long_fragment",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_fragment_error,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Message defragmentation error", "6lowpan.fragment.error",
|
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
2011-01-30 21:01:07 +00:00
|
|
|
{ &hf_6lowpan_fragment_count,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Message fragment count", "6lowpan.fragment.count",
|
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
2009-10-03 10:06:19 +00:00
|
|
|
{ &hf_6lowpan_reassembled_in,
|
2012-03-06 02:28:04 +00:00
|
|
|
{ "Reassembled in", "6lowpan.reassembled.in",
|
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
2010-02-02 16:01:52 +00:00
|
|
|
{ &hf_6lowpan_reassembled_length,
|
2012-10-14 02:54:25 +00:00
|
|
|
{ "Reassembled 6LoWPAN length", "6lowpan.reassembled.length",
|
2012-03-06 02:28:04 +00:00
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}
|
2009-10-03 10:06:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_6lowpan,
|
|
|
|
&ett_6lowpan_hc1,
|
|
|
|
&ett_6lowpan_hc2_udp,
|
|
|
|
&ett_6lowpan_iphc,
|
|
|
|
&ett_6lowpan_nhc_ext,
|
|
|
|
&ett_6lowpan_nhc_udp,
|
|
|
|
&ett_6lowpan_bcast,
|
|
|
|
&ett_6lowpan_mesh,
|
|
|
|
&ett_6lowpan_mesh_flags,
|
|
|
|
&ett_6lowpan_frag,
|
|
|
|
&ett_6lopwan_traffic_class,
|
|
|
|
/* Reassembly subtrees. */
|
|
|
|
&ett_6lowpan_fragment,
|
|
|
|
&ett_6lowpan_fragments
|
|
|
|
};
|
|
|
|
|
2013-06-09 03:28:05 +00:00
|
|
|
static ei_register_info ei[] = {
|
|
|
|
{ &ei_6lowpan_hc1_more_bits, { "6lowpan.hc1_more_bits", PI_MALFORMED, PI_ERROR, "HC1 more bits expected for illegal next header type.", EXPFILL }},
|
|
|
|
{ &ei_6lowpan_illegal_dest_addr_mode, { "6lowpan.illegal_dest_addr_mode", PI_MALFORMED, PI_ERROR, "Illegal destination address mode", EXPFILL }},
|
|
|
|
{ &ei_6lowpan_bad_ipv6_header_length, { "6lowpan.bad_ipv6_header_length", PI_MALFORMED, PI_ERROR, "Length is less than IPv6 header length", EXPFILL }},
|
|
|
|
};
|
|
|
|
|
2010-09-30 19:23:31 +00:00
|
|
|
int i;
|
|
|
|
module_t *prefs_module;
|
2013-06-09 03:28:05 +00:00
|
|
|
expert_module_t* expert_6lowpan;
|
2010-09-30 19:23:31 +00:00
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
proto_6lowpan = proto_register_protocol("IPv6 over IEEE 802.15.4", "6LoWPAN", "6lowpan");
|
|
|
|
proto_register_field_array(proto_6lowpan, hf, array_length(hf));
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2013-06-09 03:28:05 +00:00
|
|
|
expert_6lowpan = expert_register_protocol(proto_6lowpan);
|
|
|
|
expert_register_field_array(expert_6lowpan, ei, array_length(ei));
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Register the dissector with wireshark. */
|
2014-04-18 03:33:42 +00:00
|
|
|
new_register_dissector("6lowpan", dissect_6lowpan, proto_6lowpan);
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Register the dissector init function */
|
|
|
|
register_init_routine(proto_init_6lowpan);
|
2010-09-30 19:23:31 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Initialize the context preferences. */
|
2012-04-30 19:14:14 +00:00
|
|
|
memset((gchar*)lowpan_context_prefs, 0, sizeof(lowpan_context_prefs));
|
2010-09-30 19:23:31 +00:00
|
|
|
|
|
|
|
/* Register preferences. */
|
|
|
|
prefs_module = prefs_register_protocol(proto_6lowpan, prefs_6lowpan_apply);
|
2012-09-01 11:54:16 +00:00
|
|
|
for (i = 0; i < LOWPAN_CONTEXT_MAX; i++) {
|
2012-07-27 08:47:54 +00:00
|
|
|
char *pref_name, *pref_title;
|
2010-09-30 19:23:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Inspired by the IEEE 802.11 dissector - the preferences are expecting
|
|
|
|
* that each pref has a unique string passed in, and will crash if we
|
2013-07-06 18:40:56 +00:00
|
|
|
* try to reuse any for multiple preferences.
|
2010-09-30 19:23:31 +00:00
|
|
|
*/
|
2013-07-06 18:40:56 +00:00
|
|
|
pref_name = wmem_strdup_printf(wmem_epan_scope(), "context%d", i);
|
|
|
|
pref_title = wmem_strdup_printf(wmem_epan_scope(), "Context %d", i);
|
2012-09-07 02:09:59 +00:00
|
|
|
prefs_register_string_preference(prefs_module, pref_name, pref_title,
|
2012-07-27 08:47:54 +00:00
|
|
|
"IPv6 prefix to use for stateful address decompression.",
|
|
|
|
&lowpan_context_prefs[i]);
|
2010-09-30 19:23:31 +00:00
|
|
|
}
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* proto_register_6lowpan */
|
|
|
|
|
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* proto_init_6lowpan
|
|
|
|
* DESCRIPTION
|
|
|
|
* 6LoWPAN initialization function.
|
|
|
|
* PARAMETERS
|
|
|
|
* none ;
|
|
|
|
* RETURNS
|
|
|
|
* void ;
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
proto_init_6lowpan(void)
|
|
|
|
{
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Initialize the fragment reassembly table. */
|
2013-03-22 23:59:54 +00:00
|
|
|
reassembly_table_init(&lowpan_reassembly_table,
|
|
|
|
&addresses_reassembly_table_functions);
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Initialize the context table. */
|
|
|
|
if (lowpan_context_table)
|
|
|
|
g_hash_table_destroy(lowpan_context_table);
|
|
|
|
lowpan_context_table = g_hash_table_new(lowpan_context_hash, lowpan_context_equal);
|
2012-09-07 02:09:59 +00:00
|
|
|
|
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Initialize the link-local context. */
|
|
|
|
lowpan_context_local.frame = 0;
|
|
|
|
lowpan_context_local.plen = LOWPAN_CONTEXT_LINK_LOCAL_BITS;
|
|
|
|
memcpy(&lowpan_context_local.prefix, lowpan_llprefix, sizeof(lowpan_llprefix));
|
2012-09-07 02:09:59 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Reload static contexts from our preferences. */
|
|
|
|
prefs_6lowpan_apply();
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* proto_init_6lowpan */
|
|
|
|
|
2010-09-30 19:23:31 +00:00
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* prefs_6lowpan_apply
|
|
|
|
* DESCRIPTION
|
|
|
|
* Prefs "apply" callback. Parses the context table for
|
|
|
|
* IPv6 addresses/prefixes.
|
|
|
|
* PARAMETERS
|
|
|
|
* none ;
|
|
|
|
* RETURNS
|
|
|
|
* void ;
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
prefs_6lowpan_apply(void)
|
|
|
|
{
|
2012-09-01 11:54:16 +00:00
|
|
|
int i;
|
|
|
|
struct e_in6_addr prefix;
|
2010-09-30 19:23:31 +00:00
|
|
|
|
2012-09-01 11:54:16 +00:00
|
|
|
for (i = 0; i < LOWPAN_CONTEXT_MAX; i++) {
|
|
|
|
if (!lowpan_context_prefs[i]) continue;
|
2013-12-21 16:16:56 +00:00
|
|
|
if (!str_to_ip6(lowpan_context_prefs[i], &prefix)) continue;
|
2012-09-01 11:54:16 +00:00
|
|
|
/* Set the prefix */
|
|
|
|
lowpan_context_insert(i, IEEE802154_BCAST_PAN, 64, &prefix, 0);
|
2010-09-30 19:23:31 +00:00
|
|
|
} /* for */
|
|
|
|
} /* prefs_6lowpan_apply */
|
|
|
|
|
2009-10-03 10:06:19 +00:00
|
|
|
/*FUNCTION:------------------------------------------------------
|
|
|
|
* NAME
|
|
|
|
* proto_reg_handoff_6lowpan
|
|
|
|
* DESCRIPTION
|
|
|
|
* Protocol handoff routine for 6LoWPAN. Called after all
|
2009-10-04 06:53:05 +00:00
|
|
|
* protocols have been loaded.
|
2009-10-03 10:06:19 +00:00
|
|
|
* PARAMETERS
|
|
|
|
* none ;
|
|
|
|
* RETURNS
|
|
|
|
* void ;
|
|
|
|
*---------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
proto_reg_handoff_6lowpan(void)
|
|
|
|
{
|
2009-10-04 06:53:05 +00:00
|
|
|
data_handle = find_dissector("data");
|
|
|
|
ipv6_handle = find_dissector("ipv6");
|
2009-10-03 10:06:19 +00:00
|
|
|
|
|
|
|
/* Register the 6LoWPAN dissector with IEEE 802.15.4 */
|
2014-06-20 16:43:28 +00:00
|
|
|
dissector_add_for_decode_as(IEEE802154_PROTOABBREV_WPAN_PANID, find_dissector("6lowpan"));
|
2013-12-28 12:26:37 +00:00
|
|
|
heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_6lowpan_heur, proto_6lowpan);
|
2009-10-03 10:06:19 +00:00
|
|
|
} /* proto_reg_handoff_6lowpan */
|
2009-10-04 06:53:05 +00:00
|
|
|
|
2014-03-09 20:11:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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:
|
|
|
|
*/
|