2 * Routines for 6LoWPAN packet disassembly
3 * By Owen Kirby <osk@exegin.com>
4 * Copyright 2009 Owen Kirby
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 /* Need to get headers for AF_INET6 and inet_pton() */
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
35 #ifdef HAVE_NETINET_IN_H
36 # include <netinet/in.h>
38 #ifdef HAVE_ARPA_INET_H
39 #include <arpa/inet.h>
41 #ifdef HAVE_WINSOCK2_H
44 #ifdef NEED_INET_V6DEFS_H
45 # include "wsutil/inet_v6defs.h"
49 #include <epan/packet.h>
50 #include <epan/prefs.h>
51 #include <epan/expert.h>
52 #include <epan/reassemble.h>
53 #include <epan/ipproto.h>
54 #include <epan/in_cksum.h>
55 #include <epan/wmem/wmem.h>
56 #include "packet-ipv6.h"
57 #include "packet-ieee802154.h"
58 #include "packet-6lowpan.h"
60 /* Definitions for 6lowpan packet disassembly structures and routines */
62 /* 6LoWPAN Patterns */
63 #define LOWPAN_PATTERN_NALP 0x00
64 #define LOWPAN_PATTERN_NALP_BITS 2
65 #define LOWPAN_PATTERN_IPV6 0x41
66 #define LOWPAN_PATTERN_IPV6_BITS 8
67 #define LOWPAN_PATTERN_HC1 0x42 /* Deprecated - replaced with IPHC. */
68 #define LOWPAN_PATTERN_HC1_BITS 8
69 #define LOWPAN_PATTERN_BC0 0x50
70 #define LOWPAN_PATTERN_BC0_BITS 8
71 #define LOWPAN_PATTERN_IPHC 0x03 /* See draft-ietf-6lowpan-hc-15.txt */
72 #define LOWPAN_PATTERN_IPHC_BITS 3
73 #define LOWPAN_PATTERN_ESC 0x7f
74 #define LOWPAN_PATTERN_ESC_BITS 8
75 #define LOWPAN_PATTERN_MESH 0x02
76 #define LOWPAN_PATTERN_MESH_BITS 2
77 #define LOWPAN_PATTERN_FRAG1 0x18
78 #define LOWPAN_PATTERN_FRAGN 0x1c
79 #define LOWPAN_PATTERN_FRAG_BITS 5
81 /* 6LoWPAN HC1 Header */
82 #define LOWPAN_HC1_SOURCE_PREFIX 0x80
83 #define LOWPAN_HC1_SOURCE_IFC 0x40
84 #define LOWPAN_HC1_DEST_PREFIX 0x20
85 #define LOWPAN_HC1_DEST_IFC 0x10
86 #define LOWPAN_HC1_TRAFFIC_CLASS 0x08
87 #define LOWPAN_HC1_NEXT 0x06
88 #define LOWPAN_HC1_MORE 0x01
90 /* IPv6 header field lengths (in bits) */
91 #define LOWPAN_IPV6_TRAFFIC_CLASS_BITS 8
92 #define LOWPAN_IPV6_FLOW_LABEL_BITS 20
93 #define LOWPAN_IPV6_NEXT_HEADER_BITS 8
94 #define LOWPAN_IPV6_HOP_LIMIT_BITS 8
95 #define LOWPAN_IPV6_PREFIX_BITS 64
96 #define LOWPAN_IPV6_INTERFACE_BITS 64
98 /* HC_UDP header field lengths (in bits). */
99 #define LOWPAN_UDP_PORT_BITS 16
100 #define LOWPAN_UDP_PORT_COMPRESSED_BITS 4
101 #define LOWPAN_UDP_LENGTH_BITS 16
102 #define LOWPAN_UDP_CHECKSUM_BITS 16
104 /* HC1 Next Header compression modes. */
105 #define LOWPAN_HC1_NEXT_NONE 0x00
106 #define LOWPAN_HC1_NEXT_UDP 0x01
107 #define LOWPAN_HC1_NEXT_ICMP 0x02
108 #define LOWPAN_HC1_NEXT_TCP 0x03
111 #define LOWPAN_HC2_UDP_SRCPORT 0x80
112 #define LOWPAN_HC2_UDP_DSTPORT 0x40
113 #define LOWPAN_HC2_UDP_LENGTH 0x20
114 #define LOWPAN_HC2_UDP_RESERVED 0x1f
116 /* IPHC Base flags */
117 #define LOWPAN_IPHC_FLAG_FLOW 0x1800
118 #define LOWPAN_IPHC_FLAG_NHDR 0x0400
119 #define LOWPAN_IPHC_FLAG_HLIM 0x0300
120 #define LOWPAN_IPHC_FLAG_CONTEXT_ID 0x0080
121 #define LOWPAN_IPHC_FLAG_SRC_COMP 0x0040
122 #define LOWPAN_IPHC_FLAG_SRC_MODE 0x0030
123 #define LOWPAN_IPHC_FLAG_MCAST_COMP 0x0008
124 #define LOWPAN_IPHC_FLAG_DST_COMP 0x0004
125 #define LOWPAN_IPHC_FLAG_DST_MODE 0x0003
126 #define LOWPAN_IPHC_FLAG_SCI 0xf0
127 #define LOWPAN_IPHC_FLAG_DCI 0x0f
128 /* Offsets for extracting integer fields. */
129 #define LOWPAN_IPHC_FLAG_OFFSET_FLOW 11
130 #define LOWPAN_IPHC_FLAG_OFFSET_HLIM 8
131 #define LOWPAN_IPHC_FLAG_OFFSET_SRC_MODE 4
132 #define LOWPAN_IPHC_FLAG_OFFSET_DST_MODE 0
133 #define LOWPAN_IPHC_FLAG_OFFSET_SCI 4
134 #define LOWPAN_IPHC_FLAG_OFFSET_DCI 0
136 /* IPHC Flow encoding values. */
137 #define LOWPAN_IPHC_FLOW_CLASS_LABEL 0x0
138 #define LOWPAN_IPHC_FLOW_ECN_LABEL 0x1
139 #define LOWPAN_IPHC_FLOW_CLASS 0x2
140 #define LOWPAN_IPHC_FLOW_COMPRESSED 0x3
142 /* IPHC Hop limit encoding. */
143 #define LOWPAN_IPHC_HLIM_INLINE 0x0
144 #define LOWPAN_IPHC_HLIM_1 0x1
145 #define LOWPAN_IPHC_HLIM_64 0x2
146 #define LOWPAN_IPHC_HLIM_255 0x3
148 /* IPHC address modes. */
149 #define LOWPAN_IPHC_ADDR_SRC_UNSPEC 0x0
150 #define LOWPAN_IPHC_ADDR_FULL_INLINE 0x0
151 #define LOWPAN_IPHC_ADDR_64BIT_INLINE 0x1
152 #define LOWPAN_IPHC_ADDR_16BIT_INLINE 0x2
153 #define LOWPAN_IPHC_ADDR_COMPRESSED 0x3
155 /* IPHC multicast address modes. */
156 #define LOWPAN_IPHC_MCAST_48BIT 0x1
157 #define LOWPAN_IPHC_MCAST_32BIT 0x2
158 #define LOWPAN_IPHC_MCAST_8BIT 0x3
160 #define LOWPAN_IPHC_MCAST_STATEFUL_48BIT 0x1
162 /* IPHC Traffic class and flow label field sizes (in bits) */
163 #define LOWPAN_IPHC_ECN_BITS 2
164 #define LOWPAN_IPHC_DSCP_BITS 6
165 #define LOWPAN_IPHC_LABEL_BITS 20
166 /* Bitmasks for the reconstructed traffic class field. */
167 #define LOWPAN_IPHC_TRAFFIC_ECN 0x03
168 #define LOWPAN_IPHC_TRAFFIC_DSCP 0xfc
171 #define LOWPAN_NHC_PATTERN_EXT 0x0e
172 #define LOWPAN_NHC_PATTERN_EXT_BITS 4
173 #define LOWPAN_NHC_PATTERN_UDP 0x1e
174 #define LOWPAN_NHC_PATTERN_UDP_BITS 5
175 /* IP-in-IP tunneling is handled as a separate NHC pattern. */
176 #define LOWPAN_NHC_PATTERN_EXT_IPV6 ((LOWPAN_NHC_PATTERN_EXT << LOWPAN_NHC_EXT_EID_BITS) | LOWPAN_NHC_EID_IPV6)
177 #define LOWPAN_NHC_PATTERN_EXT_IPV6_BITS (LOWPAN_NHC_PATTERN_EXT_BITS + LOWPAN_NHC_EXT_EID_BITS)
179 /* NHC Extension header fields. */
180 #define LOWPAN_NHC_EXT_EID 0x0e
181 #define LOWPAN_NHC_EXT_EID_OFFSET 1
182 #define LOWPAN_NHC_EXT_EID_BITS 3
183 #define LOWPAN_NHC_EXT_NHDR 0x01
185 /* Extension header ID codes. */
186 #define LOWPAN_NHC_EID_HOP_BY_HOP 0x00
187 #define LOWPAN_NHC_EID_ROUTING 0x01
188 #define LOWPAN_NHC_EID_FRAGMENT 0x02
189 #define LOWPAN_NHC_EID_DEST_OPTIONS 0x03
190 #define LOWPAN_NHC_EID_MOBILITY 0x04
191 #define LOWPAN_NHC_EID_IPV6 0x07
193 /* NHC UDP fields. */
194 #define LOWPAN_NHC_UDP_CHECKSUM 0x04
195 #define LOWPAN_NHC_UDP_SRCPORT 0x02
196 #define LOWPAN_NHC_UDP_DSTPORT 0x01
198 /* 6LoWPAN Mesh Header */
199 #define LOWPAN_MESH_HEADER_V 0x20
200 #define LOWPAN_MESH_HEADER_F 0x10
201 #define LOWPAN_MESH_HEADER_HOPS 0x0f
203 /* 6LoWPAN First Fragment Header */
204 #define LOWPAN_FRAG_DGRAM_SIZE_BITS 11
206 /* Compressed port number offset. */
207 #define LOWPAN_PORT_8BIT_OFFSET 0xf000
208 #define LOWPAN_PORT_12BIT_OFFSET (LOWPAN_PORT_8BIT_OFFSET | 0xb0)
210 /* 6LoWPAN interface identifier length. */
211 #define LOWPAN_IFC_ID_LEN 8
212 /* Protocol fields handles. */
213 static int proto_6lowpan
= -1;
214 static int hf_6lowpan_pattern
= -1;
215 static int hf_6lowpan_nhc_pattern
= -1;
217 /* Header compression fields. */
218 static int hf_6lowpan_hc1_source_prefix
= -1;
219 static int hf_6lowpan_hc1_source_ifc
= -1;
220 static int hf_6lowpan_hc1_dest_prefix
= -1;
221 static int hf_6lowpan_hc1_dest_ifc
= -1;
222 static int hf_6lowpan_hc1_class
= -1;
223 static int hf_6lowpan_hc1_next
= -1;
224 static int hf_6lowpan_hc1_more
= -1;
225 static int hf_6lowpan_hc2_udp_src
= -1;
226 static int hf_6lowpan_hc2_udp_dst
= -1;
227 static int hf_6lowpan_hc2_udp_len
= -1;
229 /* IPHC header field. */
230 static int hf_6lowpan_iphc_flag_tf
= -1;
231 static int hf_6lowpan_iphc_flag_nhdr
= -1;
232 static int hf_6lowpan_iphc_flag_hlim
= -1;
233 static int hf_6lowpan_iphc_flag_cid
= -1;
234 static int hf_6lowpan_iphc_flag_sac
= -1;
235 static int hf_6lowpan_iphc_flag_sam
= -1;
236 static int hf_6lowpan_iphc_flag_mcast
= -1;
237 static int hf_6lowpan_iphc_flag_dac
= -1;
238 static int hf_6lowpan_iphc_flag_dam
= -1;
239 static int hf_6lowpan_iphc_sci
= -1;
240 static int hf_6lowpan_iphc_dci
= -1;
242 static int hf_6lowpan_iphc_sctx_prefix
= -1;
243 static int hf_6lowpan_iphc_sctx_origin
= -1;
244 static int hf_6lowpan_iphc_dctx_prefix
= -1;
245 static int hf_6lowpan_iphc_dctx_origin
= -1;
247 /* NHC IPv6 extension header fields. */
248 static int hf_6lowpan_nhc_ext_eid
= -1;
249 static int hf_6lowpan_nhc_ext_nh
= -1;
250 static int hf_6lowpan_nhc_ext_next
= -1;
251 static int hf_6lowpan_nhc_ext_length
= -1;
253 /* NHC UDP compression header fields. */
254 static int hf_6lowpan_nhc_udp_checksum
= -1;
255 static int hf_6lowpan_nhc_udp_src
= -1;
256 static int hf_6lowpan_nhc_udp_dst
= -1;
258 /* Inline IPv6 header fields. */
259 static int hf_6lowpan_traffic_class
= -1;
260 static int hf_6lowpan_flow_label
= -1;
261 static int hf_6lowpan_ecn
= -1;
262 static int hf_6lowpan_dscp
= -1;
263 static int hf_6lowpan_next_header
= -1;
264 static int hf_6lowpan_hop_limit
= -1;
265 static int hf_6lowpan_source
= -1;
266 static int hf_6lowpan_dest
= -1;
268 /* Inline UDP header fields. */
269 static int hf_6lowpan_udp_src
= -1;
270 static int hf_6lowpan_udp_dst
= -1;
271 static int hf_6lowpan_udp_len
= -1;
272 static int hf_6lowpan_udp_checksum
= -1;
274 /* Broadcast header fields. */
275 static int hf_6lowpan_bcast_seqnum
= -1;
277 /* Mesh header fields. */
278 static int hf_6lowpan_mesh_v
= -1;
279 static int hf_6lowpan_mesh_f
= -1;
280 static int hf_6lowpan_mesh_hops
= -1;
281 static int hf_6lowpan_mesh_hops8
= -1;
282 static int hf_6lowpan_mesh_orig16
= -1;
283 static int hf_6lowpan_mesh_orig64
= -1;
284 static int hf_6lowpan_mesh_dest16
= -1;
285 static int hf_6lowpan_mesh_dest64
= -1;
287 /* Fragmentation header fields. */
288 static int hf_6lowpan_frag_dgram_size
= -1;
289 static int hf_6lowpan_frag_dgram_tag
= -1;
290 static int hf_6lowpan_frag_dgram_offset
= -1;
292 /* Protocol tree handles. */
293 static gint ett_6lowpan
= -1;
294 static gint ett_6lowpan_hc1
= -1;
295 static gint ett_6lowpan_hc2_udp
= -1;
296 static gint ett_6lowpan_iphc
= -1;
297 static gint ett_6lowpan_nhc_ext
= -1;
298 static gint ett_6lowpan_nhc_udp
= -1;
299 static gint ett_6lowpan_bcast
= -1;
300 static gint ett_6lowpan_mesh
= -1;
301 static gint ett_6lowpan_mesh_flags
= -1;
302 static gint ett_6lowpan_frag
= -1;
303 static gint ett_6lopwan_traffic_class
= -1;
305 static expert_field ei_6lowpan_hc1_more_bits
= EI_INIT
;
306 static expert_field ei_6lowpan_illegal_dest_addr_mode
= EI_INIT
;
307 static expert_field ei_6lowpan_bad_ipv6_header_length
= EI_INIT
;
309 /* Subdissector handles. */
310 static dissector_handle_t data_handle
;
311 static dissector_handle_t ipv6_handle
;
314 static const value_string lowpan_patterns
[] = {
315 { LOWPAN_PATTERN_NALP
, "Not a LoWPAN frame" },
316 { LOWPAN_PATTERN_IPV6
, "Uncompressed IPv6" },
317 { LOWPAN_PATTERN_HC1
, "Header compression" },
318 { LOWPAN_PATTERN_BC0
, "Broadcast" },
319 { LOWPAN_PATTERN_IPHC
, "IP header compression" },
320 { LOWPAN_PATTERN_ESC
, "Escape" },
321 { LOWPAN_PATTERN_MESH
, "Mesh" },
322 { LOWPAN_PATTERN_FRAG1
, "First fragment" },
323 { LOWPAN_PATTERN_FRAGN
, "Fragment" },
326 static const true_false_string lowpan_compression
= {
330 static const value_string lowpan_hc1_next
[] = {
331 { LOWPAN_HC1_NEXT_NONE
, "Inline" },
332 { LOWPAN_HC1_NEXT_UDP
, "UDP" },
333 { LOWPAN_HC1_NEXT_ICMP
, "ICMP" },
334 { LOWPAN_HC1_NEXT_TCP
, "TCP" },
337 static const value_string lowpan_iphc_traffic
[] = {
338 { LOWPAN_IPHC_FLOW_CLASS_LABEL
, "Traffic class and flow label inline" },
339 { LOWPAN_IPHC_FLOW_ECN_LABEL
, "ECN and flow label inline" },
340 { LOWPAN_IPHC_FLOW_CLASS
, "Traffic class inline" },
341 { LOWPAN_IPHC_FLOW_COMPRESSED
, "Version, traffic class, and flow label compressed" },
344 static const value_string lowpan_iphc_hop_limit
[] = {
345 { LOWPAN_IPHC_HLIM_INLINE
, "Inline" },
346 { LOWPAN_IPHC_HLIM_1
, "1" },
347 { LOWPAN_IPHC_HLIM_64
, "64" },
348 { LOWPAN_IPHC_HLIM_255
, "255" },
351 static const true_false_string lowpan_iphc_addr_compression
= {
355 static const value_string lowpan_iphc_addr_modes
[] = {
356 { LOWPAN_IPHC_ADDR_FULL_INLINE
, "Inline" },
357 { LOWPAN_IPHC_ADDR_64BIT_INLINE
,"64-bits inline" },
358 { LOWPAN_IPHC_ADDR_16BIT_INLINE
,"16-bits inline" },
359 { LOWPAN_IPHC_ADDR_COMPRESSED
, "Compressed" },
362 static const value_string lowpan_iphc_mcast_modes
[] = {
363 { LOWPAN_IPHC_MCAST_48BIT
, "48-bits inline" },
364 { LOWPAN_IPHC_MCAST_32BIT
, "32-bits inline" },
365 { LOWPAN_IPHC_MCAST_8BIT
, "8-bits inline" },
368 static const value_string lowpan_nhc_patterns
[] = {
369 { LOWPAN_NHC_PATTERN_EXT
, "IPv6 extension header" },
370 { LOWPAN_NHC_PATTERN_UDP
, "UDP compression header" },
373 static const value_string lowpan_nhc_eid
[] = {
374 { LOWPAN_NHC_EID_HOP_BY_HOP
, "IPv6 hop-by-hop options" },
375 { LOWPAN_NHC_EID_ROUTING
, "IPv6 routing" },
376 { LOWPAN_NHC_EID_FRAGMENT
, "IPv6 fragment" },
377 { LOWPAN_NHC_EID_DEST_OPTIONS
, "IPv6 destination options" },
378 { LOWPAN_NHC_EID_MOBILITY
, "IPv6 mobility header" },
379 { LOWPAN_NHC_EID_IPV6
, "IPv6 header" },
382 /* Reassembly Data */
383 static int hf_6lowpan_fragments
= -1;
384 static int hf_6lowpan_fragment
= -1;
385 static int hf_6lowpan_fragment_overlap
= -1;
386 static int hf_6lowpan_fragment_overlap_conflicts
= -1;
387 static int hf_6lowpan_fragment_multiple_tails
= -1;
388 static int hf_6lowpan_fragment_too_long_fragment
= -1;
389 static int hf_6lowpan_fragment_error
= -1;
390 static int hf_6lowpan_fragment_count
= -1;
391 static int hf_6lowpan_reassembled_in
= -1;
392 static int hf_6lowpan_reassembled_length
= -1;
393 static gint ett_6lowpan_fragment
= -1;
394 static gint ett_6lowpan_fragments
= -1;
396 static const fragment_items lowpan_frag_items
= {
397 /* Fragment subtrees */
398 &ett_6lowpan_fragment
,
399 &ett_6lowpan_fragments
,
400 /* Fragment fields */
401 &hf_6lowpan_fragments
,
402 &hf_6lowpan_fragment
,
403 &hf_6lowpan_fragment_overlap
,
404 &hf_6lowpan_fragment_overlap_conflicts
,
405 &hf_6lowpan_fragment_multiple_tails
,
406 &hf_6lowpan_fragment_too_long_fragment
,
407 &hf_6lowpan_fragment_error
,
408 &hf_6lowpan_fragment_count
,
409 /* Reassembled in field */
410 &hf_6lowpan_reassembled_in
,
411 /* Reassembled length field */
412 &hf_6lowpan_reassembled_length
,
413 /* Reassembled data field */
419 static reassembly_table lowpan_reassembly_table
;
420 static GHashTable
*lowpan_context_table
= NULL
;
422 /* Link-Local prefix used by 6LoWPAN (FF80::/10) */
423 static const guint8 lowpan_llprefix
[8] = {
424 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
427 /* Context hash table map key. */
429 guint16 pan
; /* PAN Identifier */
430 guint8 cid
; /* Context Identifier */
431 } lowpan_context_key
;
433 /* Context hash table map data. */
435 guint frame
; /* Frame where the context was discovered. */
436 guint8 plen
; /* Prefix length. */
437 struct e_in6_addr prefix
; /* Compression context. */
438 } lowpan_context_data
;
440 /* 6LoWPAN contexts. */
441 #define LOWPAN_CONTEXT_MAX 16
442 #define LOWPAN_CONTEXT_DEFAULT 0
443 #define LOWPAN_CONTEXT_LINK_LOCAL LOWPAN_CONTEXT_MAX
444 #define LOWPAN_CONTEXT_LINK_LOCAL_BITS 10
445 static lowpan_context_data lowpan_context_local
;
446 static lowpan_context_data lowpan_context_default
;
447 static const gchar
* lowpan_context_prefs
[LOWPAN_CONTEXT_MAX
];
449 /* Helper macro to convert a bit offset/length into a byte count. */
450 #define BITS_TO_BYTE_LEN(bitoff, bitlen) ((bitlen)?(((bitlen) + ((bitoff)&0x07) + 7) >> 3):(0))
452 /* Structure for rebuilding UDP datagrams. */
460 /* Structure used to store decompressed header chains until reassembly. */
463 struct lowpan_nhdr
*next
;
469 #define LOWPAN_NHDR_DATA(nhdr) ((guint8 *)(nhdr) + sizeof (struct lowpan_nhdr))
471 /* Dissector prototypes */
472 static void proto_init_6lowpan (void);
473 static void prefs_6lowpan_apply (void);
474 static void dissect_6lowpan (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
475 static tvbuff_t
* dissect_6lowpan_ipv6 (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
476 static tvbuff_t
* dissect_6lowpan_hc1 (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gint dgram_size
, guint8
*siid
, guint8
*diid
);
477 static tvbuff_t
* dissect_6lowpan_bc0 (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
478 static tvbuff_t
* dissect_6lowpan_iphc (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gint dgram_size
, guint8
*siid
, guint8
*diid
);
479 static struct lowpan_nhdr
*
480 dissect_6lowpan_iphc_nhc (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gint offset
, gint dgram_size
, guint8
*siid
, guint8
*diid
);
481 static tvbuff_t
* dissect_6lowpan_mesh (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
482 static tvbuff_t
* dissect_6lowpan_frag_first (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint8
*siid
, guint8
*diid
);
483 static tvbuff_t
* dissect_6lowpan_frag_middle (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
484 static void dissect_6lowpan_unknown (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
486 /* Helper functions. */
487 static gboolean
lowpan_dlsrc_to_ifcid (packet_info
*pinfo
, guint8
*ifcid
);
488 static gboolean
lowpan_dldst_to_ifcid (packet_info
*pinfo
, guint8
*ifcid
);
489 static void lowpan_addr16_to_ifcid (guint16 addr
, guint8
*ifcid
);
490 static tvbuff_t
* lowpan_reassemble_ipv6 (tvbuff_t
*tvb
, struct ip6_hdr
* ipv6
, struct lowpan_nhdr
* nhdr_list
);
491 static guint8
lowpan_parse_nhc_proto (tvbuff_t
*tvb
, gint offset
);
493 /* Context table helpers */
494 static guint
lowpan_context_hash (gconstpointer key
);
495 static gboolean
lowpan_context_equal (gconstpointer a
, gconstpointer b
);
496 static lowpan_context_data
*lowpan_context_find(guint8 cid
, guint16 pan
);
498 /*FUNCTION:------------------------------------------------------
502 * A version of memcpy that takes a length in bits. If the
503 * length is not byte-aligned, the final byte will be
504 * manipulated so that only the desired number of bits are
509 * bits ; Number of bits to copy.
512 *---------------------------------------------------------------
515 lowpan_pfxcpy(void *dst
, const void *src
, size_t bits
)
517 memcpy(dst
, src
, bits
>>3);
519 guint8 mask
= ((0xff00) >> (bits
& 0x7));
520 guint8 last
= ((guint8
*)src
)[bits
>>3] & mask
;
521 ((guint8
*)dst
)[bits
>>3] &= ~mask
;
522 ((guint8
*)dst
)[bits
>>3] |= last
;
524 } /* lowpan_pfxcpy */
526 /*FUNCTION:------------------------------------------------------
528 * lowpan_context_hash
530 * Context table hash function.
532 * key ; Pointer to a lowpan_context_key type.
534 * guint ; The hashed key value.
535 *---------------------------------------------------------------
538 lowpan_context_hash(gconstpointer key
)
540 return (((lowpan_context_key
*)key
)->cid
) | (((lowpan_context_key
*)key
)->pan
<< 8);
541 } /* lowpan_context_hash */
543 /*FUNCTION:------------------------------------------------------
545 * lowpan_context_equal
547 * Context table equals function.
549 * key ; Pointer to a lowpan_context_key type.
552 *---------------------------------------------------------------
555 lowpan_context_equal(gconstpointer a
, gconstpointer b
)
557 return (((lowpan_context_key
*)a
)->pan
== ((lowpan_context_key
*)b
)->pan
) &&
558 (((lowpan_context_key
*)a
)->cid
== ((lowpan_context_key
*)b
)->cid
);
559 } /* lowpan_context_equal */
561 /*FUNCTION:------------------------------------------------------
563 * lowpan_context_find
565 * Context table lookup function.
567 * cid ; Context identifier.
568 * pan ; PAN identifier.
570 * lowpan_context_data *;
571 *---------------------------------------------------------------
573 static lowpan_context_data
*
574 lowpan_context_find(guint8 cid
, guint16 pan
)
576 lowpan_context_key key
;
577 lowpan_context_data
*data
;
579 /* Check for the internal link-local context. */
580 if (cid
== LOWPAN_CONTEXT_LINK_LOCAL
) return &lowpan_context_local
;
582 /* Lookup the context from the table. */
585 data
= (lowpan_context_data
*)g_hash_table_lookup(lowpan_context_table
, &key
);
586 if (data
) return data
;
588 /* If we didn't find a match, try again with the broadcast PAN. */
589 if (pan
!= IEEE802154_BCAST_PAN
) {
590 key
.pan
= IEEE802154_BCAST_PAN
;
591 data
= (lowpan_context_data
*)g_hash_table_lookup(lowpan_context_table
, &key
);
592 if (data
) return data
;
595 /* If the lookup failed, return the default context (::/0) */
596 return &lowpan_context_default
;
597 } /* lowpan_context_find */
599 /*FUNCTION:------------------------------------------------------
601 * lowpan_context_insert
603 * Context table insert function.
605 * cid ; Context identifier.
606 * pan ; PAN identifier.
607 * plen ; Prefix length.
608 * prefix ; Compression prefix.
609 * frame ; Frame number.
612 *---------------------------------------------------------------
615 lowpan_context_insert(guint8 cid
, guint16 pan
, guint8 plen
, struct e_in6_addr
*prefix
, guint frame
)
617 lowpan_context_key key
;
618 lowpan_context_data
*data
;
623 if (plen
> 128) return;
626 /* Search the context table for an existing entry. */
629 if (g_hash_table_lookup_extended(lowpan_context_table
, &key
, &pkey
, &pdata
)) {
630 /* Context already exists. */
631 data
= (lowpan_context_data
*)pdata
;
632 if ( (data
->plen
== plen
) && (memcmp(&data
->prefix
, prefix
, (plen
+7)/8) == 0) ) {
633 /* Context already exists with no change. */
638 pkey
= wmem_memdup(wmem_file_scope(), &key
, sizeof(key
));
641 /* Create a new context */
642 data
= wmem_new(wmem_file_scope(), lowpan_context_data
);
645 memset(&data
->prefix
, 0, sizeof(struct e_in6_addr
)); /* Ensure zero paddeding */
646 lowpan_pfxcpy(&data
->prefix
, prefix
, plen
);
647 g_hash_table_insert(lowpan_context_table
, pkey
, data
);
648 } /* lowpan_context_insert */
650 /*FUNCTION:------------------------------------------------------
652 * lowpan_addr16_to_ifcid
654 * Converts a short address to in interface identifier as
655 * per rfc 4944 section 6.
657 * addr ; 16-bit short address.
658 * ifcid ; interface identifier (output).
661 *---------------------------------------------------------------
664 lowpan_addr16_to_ifcid(guint16 addr
, guint8
*ifcid
)
666 /* Note: The PANID is no longer used in building the IID. */
667 ifcid
[0] = 0x00; /* the U/L bit must be cleared. */
673 ifcid
[6] = (addr
>> 8) & 0xff;
674 ifcid
[7] = (addr
>> 0) & 0xff;
675 } /* lowpan_addr16_to_ifcid */
677 /*FUNCTION:------------------------------------------------------
679 * lowpan_dlsrc_to_ifcid
681 * Finds an interface identifier from the data-link source
684 * pinfo ; packet information.
685 * ifcid ; interface identifier (output).
687 * gboolean ; TRUE if an interface identifier could
689 *---------------------------------------------------------------
692 lowpan_dlsrc_to_ifcid(packet_info
*pinfo
, guint8
*ifcid
)
694 ieee802154_hints_t
*hints
;
696 /* Check the link-layer address field. */
697 if (pinfo
->dl_src
.type
== AT_EUI64
) {
698 memcpy(ifcid
, pinfo
->dl_src
.data
, LOWPAN_IFC_ID_LEN
);
699 /* RFC2464: Invert the U/L bit when using an EUI64 address. */
704 /* Lookup the IEEE 802.15.4 addressing hints. */
705 hints
= (ieee802154_hints_t
*)p_get_proto_data(pinfo
->fd
,
706 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN
), 0);
708 lowpan_addr16_to_ifcid(hints
->src16
, ifcid
);
711 /* Failed to find a link-layer source address. */
714 } /* lowpan_dlsrc_to_ifcid */
716 /*FUNCTION:------------------------------------------------------
718 * lowpan_dldst_to_ifcid
720 * Finds an interface identifier from the data-link destination
723 * pinfo ; packet information.
724 * ifcid ; interface identifier (output).
726 * gboolean ; TRUE if an interface identifier could
728 *---------------------------------------------------------------
731 lowpan_dldst_to_ifcid(packet_info
*pinfo
, guint8
*ifcid
)
733 ieee802154_hints_t
*hints
;
735 /* Check the link-layer address field. */
736 if (pinfo
->dl_dst
.type
== AT_EUI64
) {
737 memcpy(ifcid
, pinfo
->dl_dst
.data
, LOWPAN_IFC_ID_LEN
);
738 /* RFC2464: Invert the U/L bit when using an EUI64 address. */
743 /* Lookup the IEEE 802.15.4 addressing hints. */
744 hints
= (ieee802154_hints_t
*)p_get_proto_data(pinfo
->fd
,
745 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN
), 0);
747 lowpan_addr16_to_ifcid(hints
->dst16
, ifcid
);
750 /* Failed to find a link-layer destination address. */
753 } /* lowpan_dldst_to_ifcid */
755 /*FUNCTION:------------------------------------------------------
757 * lowpan_reassemble_ipv6
759 * Helper function to rebuild an IPv6 packet from the IPv6
760 * header structure, and a list of next header structures.
762 * ipv6 ; IPv6 Header.
763 * nhdr_list ; Next header list.
765 * tvbuff_t * ; Reassembled IPv6 packet.
766 *---------------------------------------------------------------
769 lowpan_reassemble_ipv6(tvbuff_t
*tvb
, struct ip6_hdr
*ipv6
, struct lowpan_nhdr
*nhdr_list
)
775 struct lowpan_nhdr
*nhdr
;
778 /* Compute the real and reported lengths. */
779 for (nhdr
= nhdr_list
; nhdr
; nhdr
= nhdr
->next
) {
780 length
+= nhdr
->length
;
781 reported
+= nhdr
->reported
;
783 ipv6
->ip6_plen
= g_ntohs(reported
);
785 /* Allocate a buffer for the packet and copy in the IPv6 header. */
786 buffer
= (guint8
*)g_malloc(length
+ sizeof(struct ip6_hdr
));
787 memcpy(buffer
, ipv6
, sizeof(struct ip6_hdr
));
788 cursor
= buffer
+ sizeof(struct ip6_hdr
);
790 /* Add the next headers into the buffer. */
791 for (nhdr
= nhdr_list
; nhdr
; nhdr
= nhdr
->next
) {
792 memcpy(cursor
, LOWPAN_NHDR_DATA(nhdr
), nhdr
->length
);
793 cursor
+= nhdr
->length
;
796 /* Return the reassembed packet. */
797 ret
= tvb_new_child_real_data(tvb
, buffer
, length
+ (int)sizeof(struct ip6_hdr
), reported
+ (int)sizeof(struct ip6_hdr
));
798 tvb_set_free_cb(ret
, g_free
);
800 } /* lowpan_reassemble_ipv6 */
802 /*FUNCTION:------------------------------------------------------
804 * lowpan_parse_nhc_proto
806 * Parses the start of an 6LoWPAN NHC header to determine the
807 * next header protocol identifier. Will return IP_PROTO_NONE
808 * if no valid protocol could be determined.
810 * tvb ; packet buffer.
811 * offset ; offset of the NHC.
813 * guint8 ; IP_PROTO_* of the next header's protocol.
814 *---------------------------------------------------------------
817 lowpan_parse_nhc_proto(tvbuff_t
*tvb
, gint offset
)
819 /* Ensure that at least one byte exists. */
820 if (!tvb_bytes_exist(tvb
, offset
, sizeof(guint8
))) return IP_PROTO_NONE
;
822 /* Check for IPv6 extension headers. */
823 if (tvb_get_bits8(tvb
, offset
<<3, LOWPAN_NHC_PATTERN_EXT_BITS
) == LOWPAN_NHC_PATTERN_EXT
) {
824 guint8 eid
= (tvb_get_guint8(tvb
, offset
) & LOWPAN_NHC_EXT_EID
) >> LOWPAN_NHC_EXT_EID_OFFSET
;
826 case LOWPAN_NHC_EID_HOP_BY_HOP
:
827 return IP_PROTO_HOPOPTS
;
828 case LOWPAN_NHC_EID_ROUTING
:
829 return IP_PROTO_ROUTING
;
830 case LOWPAN_NHC_EID_FRAGMENT
:
831 return IP_PROTO_FRAGMENT
;
832 case LOWPAN_NHC_EID_DEST_OPTIONS
:
833 return IP_PROTO_DSTOPTS
;
834 case LOWPAN_NHC_EID_MOBILITY
:
835 return IP_PROTO_MIPV6
;
836 case LOWPAN_NHC_EID_IPV6
:
837 return IP_PROTO_IPV6
;
839 /* Unknown protocol type. */
840 return IP_PROTO_NONE
;
843 /* Check for compressed UDP headers. */
844 if (tvb_get_bits8(tvb
, offset
<<3, LOWPAN_NHC_PATTERN_UDP_BITS
) == LOWPAN_NHC_PATTERN_UDP
) {
847 /* Unknown header type. */
848 return IP_PROTO_NONE
;
849 } /* lowpan_parse_nhc_proto */
851 /*FUNCTION:------------------------------------------------------
853 * dissect_6lowpan_heur
855 * Heuristic dissector for 6LoWPAN. Checks if the pattern is
856 * a valid 6LoWPAN type, and not NALP.
858 * tvb ; packet buffer.
859 * pinfo ; packet info.
860 * tree ; protocol display tree.
862 * boolean ; TRUE if the tvbuff was dissected as a
863 * 6LoWPAN packet. If this returns FALSE,
864 * then no dissection will be attempted.
865 *---------------------------------------------------------------
868 dissect_6lowpan_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
870 /* Check for valid patterns. */
872 /* Parse patterns until we find a match. */
873 if (tvb_get_bits8(tvb
, 0, LOWPAN_PATTERN_IPV6_BITS
) == LOWPAN_PATTERN_IPV6
) break;
874 if (tvb_get_bits8(tvb
, 0, LOWPAN_PATTERN_HC1_BITS
) == LOWPAN_PATTERN_HC1
) break;
875 if (tvb_get_bits8(tvb
, 0, LOWPAN_PATTERN_BC0_BITS
) == LOWPAN_PATTERN_BC0
) break;
876 if (tvb_get_bits8(tvb
, 0, LOWPAN_PATTERN_IPHC_BITS
) == LOWPAN_PATTERN_IPHC
) break;
877 if (tvb_get_bits8(tvb
, 0, LOWPAN_PATTERN_MESH_BITS
) == LOWPAN_PATTERN_MESH
) break;
878 if (tvb_get_bits8(tvb
, 0, LOWPAN_PATTERN_FRAG_BITS
) == LOWPAN_PATTERN_FRAG1
) break;
879 if (tvb_get_bits8(tvb
, 0, LOWPAN_PATTERN_FRAG_BITS
) == LOWPAN_PATTERN_FRAGN
) break;
881 /* If we get here, then we couldn't match to any pattern. */
885 /* If we get here, then we found a matching pattern. */
886 dissect_6lowpan(tvb
, pinfo
, tree
);
888 } /* dissect_6lowpan_heur */
890 /*FUNCTION:------------------------------------------------------
894 * Dissector routine for 6LoWPAN packets.
896 * tvb ; packet buffer.
897 * pinfo ; packet info.
898 * tree ; protocol display tree.
901 *---------------------------------------------------------------
904 dissect_6lowpan(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
906 proto_tree
*volatile lowpan_tree
= NULL
;
907 proto_item
*volatile lowpan_root
= NULL
;
908 tvbuff_t
* next
= tvb
;
909 /* Interface identifier of the encapsulating layer. */
910 guint8 src_iid
[LOWPAN_IFC_ID_LEN
];
911 guint8 dst_iid
[LOWPAN_IFC_ID_LEN
];
913 /* Get the interface identifiers from the encapsulating layer. */
914 lowpan_dlsrc_to_ifcid(pinfo
, src_iid
);
915 lowpan_dldst_to_ifcid(pinfo
, dst_iid
);
917 /* Create the protocol tree. */
919 lowpan_root
= proto_tree_add_protocol_format(tree
, proto_6lowpan
, tvb
, 0, tvb_length(tvb
), "6LoWPAN");
920 lowpan_tree
= proto_item_add_subtree(lowpan_root
, ett_6lowpan
);
922 /* Add the protocol name. */
923 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "6LoWPAN");
925 /* Mesh and Broadcast headers always come first in a 6LoWPAN frame. */
926 if (tvb_get_bits8(next
, 0, LOWPAN_PATTERN_MESH_BITS
) == LOWPAN_PATTERN_MESH
) {
927 next
= dissect_6lowpan_mesh(next
, pinfo
, lowpan_tree
);
930 if (tvb_get_bits8(next
, 0, LOWPAN_PATTERN_BC0_BITS
) == LOWPAN_PATTERN_BC0
) {
931 next
= dissect_6lowpan_bc0(next
, pinfo
, lowpan_tree
);
935 /* After the mesh and broadcast headers, process dispatch codes recursively. */
936 /* Fragmentation headers.*/
937 if (tvb_get_bits8(next
, 0, LOWPAN_PATTERN_FRAG_BITS
) == LOWPAN_PATTERN_FRAG1
) {
938 next
= dissect_6lowpan_frag_first(next
, pinfo
, lowpan_tree
, src_iid
, dst_iid
);
940 else if (tvb_get_bits8(next
, 0, LOWPAN_PATTERN_FRAG_BITS
) == LOWPAN_PATTERN_FRAGN
) {
941 next
= dissect_6lowpan_frag_middle(next
, pinfo
, lowpan_tree
);
943 /* Uncompressed IPv6 packets. */
944 else if (tvb_get_bits8(next
, 0, LOWPAN_PATTERN_IPV6_BITS
) == LOWPAN_PATTERN_IPV6
) {
945 next
= dissect_6lowpan_ipv6(next
, pinfo
, lowpan_tree
);
947 /* Compressed IPv6 packets. */
948 else if (tvb_get_bits8(next
, 0, LOWPAN_PATTERN_HC1_BITS
) == LOWPAN_PATTERN_HC1
) {
949 next
= dissect_6lowpan_hc1(next
, pinfo
, lowpan_tree
, -1, src_iid
, dst_iid
);
951 else if (tvb_get_bits8(next
, 0, LOWPAN_PATTERN_IPHC_BITS
) == LOWPAN_PATTERN_IPHC
) {
952 next
= dissect_6lowpan_iphc(next
, pinfo
, lowpan_tree
, -1, src_iid
, dst_iid
);
954 /* Unknown 6LoWPAN dispatch type */
956 dissect_6lowpan_unknown(next
, pinfo
, lowpan_tree
);
960 /* The last step should have returned an uncompressed IPv6 datagram. */
962 call_dissector(ipv6_handle
, next
, pinfo
, tree
);
964 } /* dissect_6lowpan */
966 /*FUNCTION:------------------------------------------------------
968 * dissect_6lowpan_ipv6
970 * Dissector routine for an uncompressed IPv6 header type.
972 * This is one of the final encapsulation types, and will
973 * returned an uncompressed IPv6 datagram (or fragment
976 * tvb ; packet buffer.
977 * pinfo ; packet info.
978 * tree ; 6LoWPAN display tree.
979 * offset ; offset to the start of the header.
981 * tvbuff_t * ; The remaining payload to be parsed.
982 *---------------------------------------------------------------
985 dissect_6lowpan_ipv6(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
987 /* Get and display the pattern. */
989 proto_tree_add_bits_item(tree
, hf_6lowpan_pattern
, tvb
, 0, LOWPAN_PATTERN_IPV6_BITS
, ENC_BIG_ENDIAN
);
992 /* Create a tvbuff subset for the ipv6 datagram. */
993 return tvb_new_subset_remaining(tvb
, sizeof(guint8
));
994 } /* dissect_6lowpan_ipv6 */
996 /*FUNCTION:------------------------------------------------------
998 * dissect_6lowpan_hc1
1000 * Dissector routine for a 6LoWPAN HC1 header.
1002 * tvb ; packet buffer.
1003 * pinfo ; packet info.
1004 * tree ; 6LoWPAN display tree.
1005 * dgram_size ; Datagram size (or <0 if not fragmented).
1006 * siid ; Source Interface ID.
1007 * diid ; Destination Interface ID.
1009 * tvbuff_t * ; The remaining payload to be parsed.
1010 *---------------------------------------------------------------
1013 dissect_6lowpan_hc1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gint dgram_size
, guint8
*siid
, guint8
*diid
)
1018 guint8 hc1_encoding
;
1019 guint8 hc_udp_encoding
= 0;
1021 proto_tree
* hc_tree
= NULL
;
1023 tvbuff_t
* ipv6_tvb
;
1026 struct ip6_hdr ipv6
;
1027 struct lowpan_nhdr
*nhdr_list
;
1029 /*=====================================================
1030 * Parse HC Encoding Flags
1031 *=====================================================
1033 /* Create a tree for the HC1 Header. */
1035 ti
= proto_tree_add_text(tree
, tvb
, 0, (int)sizeof(guint16
), "HC1 Encoding");
1036 hc_tree
= proto_item_add_subtree(ti
, ett_6lowpan_hc1
);
1038 /* Get and display the pattern. */
1039 proto_tree_add_bits_item(hc_tree
, hf_6lowpan_pattern
, tvb
, 0, LOWPAN_PATTERN_HC1_BITS
, ENC_BIG_ENDIAN
);
1041 offset
+= (int)sizeof(guint8
);
1043 /* Get and display the HC1 encoding bits. */
1044 hc1_encoding
= tvb_get_guint8(tvb
, offset
);
1045 next_header
= ((hc1_encoding
& LOWPAN_HC1_NEXT
) >> 1);
1047 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc1_source_prefix
, tvb
, offset
, (int)sizeof(guint8
), hc1_encoding
& LOWPAN_HC1_SOURCE_PREFIX
);
1048 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc1_source_ifc
, tvb
, offset
, (int)sizeof(guint8
), hc1_encoding
& LOWPAN_HC1_SOURCE_IFC
);
1049 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc1_dest_prefix
, tvb
, offset
, (int)sizeof(guint8
), hc1_encoding
& LOWPAN_HC1_DEST_PREFIX
);
1050 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc1_dest_ifc
, tvb
, offset
, (int)sizeof(guint8
), hc1_encoding
& LOWPAN_HC1_DEST_IFC
);
1051 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc1_class
, tvb
, offset
, (int)sizeof(guint8
), hc1_encoding
& LOWPAN_HC1_TRAFFIC_CLASS
);
1052 proto_tree_add_uint(hc_tree
, hf_6lowpan_hc1_next
, tvb
, offset
, (int)sizeof(guint8
), hc1_encoding
& LOWPAN_HC1_NEXT
);
1053 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc1_more
, tvb
, offset
, (int)sizeof(guint8
), hc1_encoding
& LOWPAN_HC1_MORE
);
1055 offset
+= (int)sizeof(guint8
);
1057 /* Get and display the HC2 encoding bits, if present. */
1058 if (hc1_encoding
& LOWPAN_HC1_MORE
) {
1059 if (next_header
== LOWPAN_HC1_NEXT_UDP
) {
1060 hc_udp_encoding
= tvb_get_guint8(tvb
, offset
);
1062 ti
= proto_tree_add_text(tree
, tvb
, offset
, (int)sizeof(guint8
), "HC_UDP Encoding");
1063 hc_tree
= proto_item_add_subtree(ti
, ett_6lowpan_hc2_udp
);
1064 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc2_udp_src
, tvb
, offset
, (int)sizeof(guint8
), hc_udp_encoding
& LOWPAN_HC2_UDP_SRCPORT
);
1065 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc2_udp_dst
, tvb
, offset
, (int)sizeof(guint8
), hc_udp_encoding
& LOWPAN_HC2_UDP_DSTPORT
);
1066 proto_tree_add_boolean(hc_tree
, hf_6lowpan_hc2_udp_len
, tvb
, offset
, (int)sizeof(guint8
), hc_udp_encoding
& LOWPAN_HC2_UDP_LENGTH
);
1068 offset
+= (int)sizeof(guint8
);
1071 /* HC1 states there are more bits, but an illegal next header was defined. */
1072 expert_add_info(pinfo
, NULL
, &ei_6lowpan_hc1_more_bits
);
1077 /*=====================================================
1078 * Parse Uncompressed IPv6 Header Fields
1079 *=====================================================
1082 * And now all hell breaks loose. After the header encoding fields, we are
1083 * left with an assortment of optional fields from the IPv6 header,
1084 * depending on which fields are present or not, the headers may not be
1085 * aligned to an octet boundary.
1087 * From now on we have to parse the uncompressed fields relative to a bit
1090 bit_offset
= offset
<< 3;
1092 /* Parse hop limit */
1093 ipv6
.ip6_hops
= tvb_get_bits8(tvb
, bit_offset
, LOWPAN_IPV6_HOP_LIMIT_BITS
);
1095 proto_tree_add_uint(tree
, hf_6lowpan_hop_limit
, tvb
, bit_offset
>>3,
1096 BITS_TO_BYTE_LEN(bit_offset
, LOWPAN_IPV6_HOP_LIMIT_BITS
), ipv6
.ip6_hops
);
1098 bit_offset
+= LOWPAN_IPV6_HOP_LIMIT_BITS
;
1100 /*=====================================================
1101 * Parse/Decompress IPv6 Source Address
1102 *=====================================================
1104 offset
= bit_offset
;
1105 if (!(hc1_encoding
& LOWPAN_HC1_SOURCE_PREFIX
)) {
1106 for (i
=0; i
<8; i
++, bit_offset
+= 8) {
1107 ipv6
.ip6_src
.bytes
[i
] = tvb_get_bits8(tvb
, bit_offset
, 8);
1111 memcpy(ipv6
.ip6_src
.bytes
, lowpan_llprefix
, sizeof(lowpan_llprefix
));
1113 if (!(hc1_encoding
& LOWPAN_HC1_SOURCE_IFC
)) {
1114 for (i
=8; i
<16; i
++, bit_offset
+= 8) {
1115 ipv6
.ip6_src
.bytes
[i
] = tvb_get_bits8(tvb
, bit_offset
, 8);
1119 memcpy(&ipv6
.ip6_src
.bytes
[sizeof(ipv6
.ip6_src
) - LOWPAN_IFC_ID_LEN
], siid
, LOWPAN_IFC_ID_LEN
);
1121 /* Display the source address. */
1123 proto_tree_add_ipv6(tree
, hf_6lowpan_source
, tvb
, offset
>>3,
1124 BITS_TO_BYTE_LEN(offset
, (bit_offset
-offset
)), (guint8
*)&ipv6
.ip6_src
);
1127 * Do not set the address columns until after defragmentation, since we have
1128 * to do decompression before reassembly, and changing the address will cause
1129 * wireshark to think that the middle fragments came from another device.
1132 /*=====================================================
1133 * Parse/Decompress IPv6 Destination Address
1134 *=====================================================
1136 offset
= bit_offset
;
1137 if (!(hc1_encoding
& LOWPAN_HC1_DEST_PREFIX
)) {
1138 for (i
=0; i
<8; i
++, bit_offset
+= 8) {
1139 ipv6
.ip6_dst
.bytes
[i
] = tvb_get_bits8(tvb
, bit_offset
, 8);
1143 memcpy(ipv6
.ip6_dst
.bytes
, lowpan_llprefix
, sizeof(lowpan_llprefix
));
1145 if (!(hc1_encoding
& LOWPAN_HC1_DEST_IFC
)) {
1146 for (i
=8; i
<16; i
++, bit_offset
+= 8) {
1147 ipv6
.ip6_dst
.bytes
[i
] = tvb_get_bits8(tvb
, bit_offset
, 8);
1151 memcpy(&ipv6
.ip6_dst
.bytes
[sizeof(ipv6
.ip6_dst
) - LOWPAN_IFC_ID_LEN
], diid
, LOWPAN_IFC_ID_LEN
);
1153 /* Display the destination address. */
1155 proto_tree_add_ipv6(tree
, hf_6lowpan_dest
, tvb
, offset
>>3,
1156 BITS_TO_BYTE_LEN(offset
, (bit_offset
-offset
)), (guint8
*)&ipv6
.ip6_dst
);
1159 * Do not set the address columns until after defragmentation, since we have
1160 * to do decompression before reassembly, and changing the address will cause
1161 * wireshark to think that the middle fragments came from another device.
1164 /* Parse the traffic class and flow label. */
1167 if (!(hc1_encoding
& LOWPAN_HC1_TRAFFIC_CLASS
)) {
1168 /* Parse the traffic class. */
1169 ipv6_class
= tvb_get_bits8(tvb
, bit_offset
, LOWPAN_IPV6_TRAFFIC_CLASS_BITS
);
1171 proto_tree_add_uint(tree
, hf_6lowpan_traffic_class
, tvb
, bit_offset
>>3,
1172 BITS_TO_BYTE_LEN(bit_offset
, LOWPAN_IPV6_TRAFFIC_CLASS_BITS
), ipv6_class
);
1174 bit_offset
+= LOWPAN_IPV6_TRAFFIC_CLASS_BITS
;
1176 /* Parse the flow label. */
1177 ipv6
.ip6_flow
= tvb_get_bits32(tvb
, bit_offset
, LOWPAN_IPV6_FLOW_LABEL_BITS
, ENC_BIG_ENDIAN
);
1179 proto_tree_add_uint(tree
, hf_6lowpan_flow_label
, tvb
, bit_offset
>>3,
1180 BITS_TO_BYTE_LEN(bit_offset
, LOWPAN_IPV6_FLOW_LABEL_BITS
), ipv6
.ip6_flow
);
1182 bit_offset
+= LOWPAN_IPV6_FLOW_LABEL_BITS
;
1184 ipv6
.ip6_flow
= g_ntohl(ipv6
.ip6_flow
| (ipv6_class
<< LOWPAN_IPV6_FLOW_LABEL_BITS
));
1185 ipv6
.ip6_vfc
= ((0x6 << 4) | (ipv6_class
>> 4));
1187 /* Parse the IPv6 next header field. */
1188 if (next_header
== LOWPAN_HC1_NEXT_UDP
) {
1189 ipv6
.ip6_nxt
= IP_PROTO_UDP
;
1191 else if (next_header
== LOWPAN_HC1_NEXT_ICMP
) {
1192 ipv6
.ip6_nxt
= IP_PROTO_ICMPV6
;
1194 else if (next_header
== LOWPAN_HC1_NEXT_TCP
) {
1195 ipv6
.ip6_nxt
= IP_PROTO_TCP
;
1198 /* Parse the next header field. */
1199 ipv6
.ip6_nxt
= tvb_get_bits8(tvb
, bit_offset
, LOWPAN_IPV6_NEXT_HEADER_BITS
);
1201 proto_tree_add_uint_format_value(tree
, hf_6lowpan_next_header
, tvb
, bit_offset
>>3,
1202 BITS_TO_BYTE_LEN(bit_offset
, LOWPAN_IPV6_NEXT_HEADER_BITS
), ipv6
.ip6_nxt
,
1203 "%s (0x%02x)", ipprotostr(ipv6
.ip6_nxt
), ipv6
.ip6_nxt
);
1205 bit_offset
+= LOWPAN_IPV6_NEXT_HEADER_BITS
;
1208 /*=====================================================
1209 * Parse and Reconstruct the UDP Header
1210 *=====================================================
1212 if ((hc1_encoding
& LOWPAN_HC1_MORE
) && (next_header
== LOWPAN_HC1_NEXT_UDP
)) {
1216 /* Parse the source port. */
1217 offset
= bit_offset
;
1218 if (hc_udp_encoding
& LOWPAN_HC2_UDP_SRCPORT
) {
1219 udp
.src_port
= tvb_get_bits8(tvb
, bit_offset
, LOWPAN_UDP_PORT_COMPRESSED_BITS
) + LOWPAN_PORT_12BIT_OFFSET
;
1220 bit_offset
+= LOWPAN_UDP_PORT_COMPRESSED_BITS
;
1223 udp
.src_port
= tvb_get_bits16(tvb
, bit_offset
, LOWPAN_UDP_PORT_BITS
, ENC_BIG_ENDIAN
);
1224 bit_offset
+= LOWPAN_UDP_PORT_BITS
;
1227 proto_tree_add_uint(tree
, hf_6lowpan_udp_src
, tvb
, offset
>>3,
1228 BITS_TO_BYTE_LEN(offset
, (bit_offset
-offset
)), udp
.src_port
);
1230 udp
.src_port
= g_ntohs(udp
.src_port
);
1232 /* Parse the destination port. */
1233 offset
= bit_offset
;
1234 if (hc_udp_encoding
& LOWPAN_HC2_UDP_DSTPORT
) {
1235 udp
.dst_port
= tvb_get_bits8(tvb
, bit_offset
, LOWPAN_UDP_PORT_COMPRESSED_BITS
) + LOWPAN_PORT_12BIT_OFFSET
;
1236 bit_offset
+= LOWPAN_UDP_PORT_COMPRESSED_BITS
;
1239 udp
.dst_port
= tvb_get_bits16(tvb
, bit_offset
, LOWPAN_UDP_PORT_BITS
, ENC_BIG_ENDIAN
);
1240 bit_offset
+= LOWPAN_UDP_PORT_BITS
;
1243 proto_tree_add_uint(tree
, hf_6lowpan_udp_dst
, tvb
, offset
>>3,
1244 BITS_TO_BYTE_LEN(offset
, (bit_offset
-offset
)), udp
.dst_port
);
1246 udp
.dst_port
= g_ntohs(udp
.dst_port
);
1248 /* Parse the length, if present. */
1249 if (!(hc_udp_encoding
& LOWPAN_HC2_UDP_LENGTH
)) {
1250 udp
.length
= tvb_get_bits16(tvb
, bit_offset
, LOWPAN_UDP_LENGTH_BITS
, ENC_BIG_ENDIAN
);
1252 proto_tree_add_uint(tree
, hf_6lowpan_udp_len
, tvb
, bit_offset
>>3,
1253 BITS_TO_BYTE_LEN(bit_offset
, LOWPAN_UDP_LENGTH_BITS
), udp
.length
);
1256 bit_offset
+= LOWPAN_UDP_LENGTH_BITS
;
1258 /* Compute the length from the fragmentation headers. */
1259 else if (dgram_size
>= 0) {
1260 if (dgram_size
< (gint
)sizeof(struct ip6_hdr
)) {
1261 /* Datagram size is too small */
1264 udp
.length
= dgram_size
- (gint
)sizeof(struct ip6_hdr
);
1266 /* Compute the length from the tvbuff size. */
1268 udp
.length
= tvb_reported_length(tvb
);
1269 udp
.length
-= BITS_TO_BYTE_LEN(0, bit_offset
+ LOWPAN_UDP_CHECKSUM_BITS
);
1270 udp
.length
+= (int)sizeof(struct udp_hdr
);
1272 udp
.length
= g_ntohs(udp
.length
);
1274 /* Parse the checksum. */
1275 udp
.checksum
= tvb_get_bits16(tvb
, bit_offset
, LOWPAN_UDP_CHECKSUM_BITS
, ENC_BIG_ENDIAN
);
1277 proto_tree_add_uint(tree
, hf_6lowpan_udp_checksum
, tvb
, bit_offset
>>3,
1278 BITS_TO_BYTE_LEN(bit_offset
, LOWPAN_UDP_CHECKSUM_BITS
), udp
.checksum
);
1280 bit_offset
+= LOWPAN_UDP_CHECKSUM_BITS
;
1281 udp
.checksum
= g_ntohs(udp
.checksum
);
1283 /* Construct the next header for the UDP datagram. */
1284 offset
= BITS_TO_BYTE_LEN(0, bit_offset
);
1285 length
= (gint
)tvb_ensure_length_remaining(tvb
, offset
);
1286 nhdr_list
= (struct lowpan_nhdr
*)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr
) + sizeof(struct udp_hdr
) + length
);
1287 nhdr_list
->next
= NULL
;
1288 nhdr_list
->proto
= IP_PROTO_UDP
;
1289 nhdr_list
->length
= length
+ (int)sizeof(struct udp_hdr
);
1290 nhdr_list
->reported
= g_ntohs(udp
.length
);
1292 /* Copy the UDP header into the buffer. */
1293 memcpy(LOWPAN_NHDR_DATA(nhdr_list
), &udp
, sizeof(struct udp_hdr
));
1294 tvb_memcpy(tvb
, LOWPAN_NHDR_DATA(nhdr_list
) + sizeof(struct udp_hdr
), offset
, length
);
1296 /*=====================================================
1297 * Reconstruct the IPv6 Packet
1298 *=====================================================
1302 offset
= BITS_TO_BYTE_LEN(0, bit_offset
);
1303 length
= (gint
)tvb_ensure_length_remaining(tvb
, offset
);
1304 nhdr_list
= (struct lowpan_nhdr
*)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr
) + length
);
1305 nhdr_list
->next
= NULL
;
1306 nhdr_list
->proto
= ipv6
.ip6_nxt
;
1307 nhdr_list
->length
= length
;
1308 if (dgram_size
< 0) {
1309 nhdr_list
->reported
= tvb_reported_length_remaining(tvb
, offset
);
1312 nhdr_list
->reported
= dgram_size
- (int)sizeof(struct ip6_hdr
);
1314 tvb_memcpy(tvb
, LOWPAN_NHDR_DATA(nhdr_list
), offset
, nhdr_list
->length
);
1317 /* Link the reassembled tvbuff together. */
1318 ipv6_tvb
= lowpan_reassemble_ipv6(tvb
, &ipv6
, nhdr_list
);
1320 /* Add a new data source for it. */
1321 add_new_data_source(pinfo
, ipv6_tvb
, "Decompressed 6LoWPAN HC1");
1324 } /* dissect_6lowpan_hc1 */
1326 /*FUNCTION:------------------------------------------------------
1328 * dissect_6lowpan_iphc
1330 * Dissector routine for a 6LoWPAN IPHC header.
1332 * This header is still in the draft phase, but is expected
1335 * See draft-ietf-6lowpan-hc-15.txt
1337 * tvb ; packet buffer.
1338 * pinfo ; packet info.
1339 * tree ; 6LoWPAN display tree.
1340 * dgram_size ; Datagram size (or <0 if not fragmented).
1341 * siid ; Source Interface ID.
1342 * diid ; Destination Interface ID.
1344 * tvbuff_t * ; The remaining payload to be parsed.
1345 *---------------------------------------------------------------
1348 dissect_6lowpan_iphc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gint dgram_size
, guint8
*siid
, guint8
*diid
)
1350 ieee802154_hints_t
*hints
;
1354 proto_tree
* iphc_tree
= NULL
;
1355 proto_item
* ti
= NULL
;
1356 proto_item
* ti_dam
= NULL
;
1357 /* IPHC header fields. */
1359 guint8 iphc_traffic
;
1360 guint8 iphc_hop_limit
;
1361 guint8 iphc_src_mode
;
1362 guint8 iphc_dst_mode
;
1363 guint8 iphc_ctx
= 0;
1364 /* Contexts to use for address decompression. */
1365 gint iphc_sci
= LOWPAN_CONTEXT_DEFAULT
;
1366 gint iphc_dci
= LOWPAN_CONTEXT_DEFAULT
;
1367 lowpan_context_data
*sctx
;
1368 lowpan_context_data
*dctx
;
1370 guint8 ipv6_class
= 0;
1371 struct ip6_hdr ipv6
;
1372 tvbuff_t
* ipv6_tvb
;
1373 /* Next header chain */
1374 struct lowpan_nhdr
*nhdr_list
;
1376 /* Lookup the IEEE 802.15.4 addressing hints. */
1377 hints
= (ieee802154_hints_t
*)p_get_proto_data(pinfo
->fd
,
1378 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN
), 0);
1379 hint_panid
= (hints
) ? (hints
->src_pan
) : (IEEE802154_BCAST_PAN
);
1381 /* Create a tree for the IPHC header. */
1383 ti
= proto_tree_add_text(tree
, tvb
, 0, (int)sizeof(guint16
), "IPHC Header");
1384 iphc_tree
= proto_item_add_subtree(ti
, ett_6lowpan_iphc
);
1386 /* Display the pattern. */
1387 proto_tree_add_bits_item(iphc_tree
, hf_6lowpan_pattern
, tvb
, 0, LOWPAN_PATTERN_IPHC_BITS
, ENC_BIG_ENDIAN
);
1390 /*=====================================================
1391 * Parse IPHC Header flags.
1392 *=====================================================
1394 iphc_flags
= tvb_get_ntohs(tvb
, offset
);
1395 iphc_traffic
= (iphc_flags
& LOWPAN_IPHC_FLAG_FLOW
) >> LOWPAN_IPHC_FLAG_OFFSET_FLOW
;
1396 iphc_hop_limit
= (iphc_flags
& LOWPAN_IPHC_FLAG_HLIM
) >> LOWPAN_IPHC_FLAG_OFFSET_HLIM
;
1397 iphc_src_mode
= (iphc_flags
& LOWPAN_IPHC_FLAG_SRC_MODE
) >> LOWPAN_IPHC_FLAG_OFFSET_SRC_MODE
;
1398 iphc_dst_mode
= (iphc_flags
& LOWPAN_IPHC_FLAG_DST_MODE
) >> LOWPAN_IPHC_FLAG_OFFSET_DST_MODE
;
1400 const value_string
*dam_vs
;
1401 proto_tree_add_uint (iphc_tree
, hf_6lowpan_iphc_flag_tf
, tvb
, offset
, (int)sizeof(guint16
), iphc_flags
& LOWPAN_IPHC_FLAG_FLOW
);
1402 proto_tree_add_boolean (iphc_tree
, hf_6lowpan_iphc_flag_nhdr
, tvb
, offset
, (int)sizeof(guint16
), iphc_flags
& LOWPAN_IPHC_FLAG_NHDR
);
1403 proto_tree_add_uint (iphc_tree
, hf_6lowpan_iphc_flag_hlim
, tvb
, offset
, (int)sizeof(guint16
), iphc_flags
& LOWPAN_IPHC_FLAG_HLIM
);
1404 proto_tree_add_boolean (iphc_tree
, hf_6lowpan_iphc_flag_cid
, tvb
, offset
, (int)sizeof(guint16
), iphc_flags
& LOWPAN_IPHC_FLAG_CONTEXT_ID
);
1405 proto_tree_add_boolean (iphc_tree
, hf_6lowpan_iphc_flag_sac
, tvb
, offset
, (int)sizeof(guint16
), iphc_flags
& LOWPAN_IPHC_FLAG_SRC_COMP
);
1406 proto_tree_add_uint(iphc_tree
, hf_6lowpan_iphc_flag_sam
, tvb
, offset
, (int)sizeof(guint16
), iphc_flags
& LOWPAN_IPHC_FLAG_SRC_MODE
);
1407 proto_tree_add_boolean (iphc_tree
, hf_6lowpan_iphc_flag_mcast
, tvb
, offset
, (int)sizeof(guint16
), iphc_flags
& LOWPAN_IPHC_FLAG_MCAST_COMP
);
1408 proto_tree_add_boolean (iphc_tree
, hf_6lowpan_iphc_flag_dac
, tvb
, offset
, (int)sizeof(guint16
), iphc_flags
& LOWPAN_IPHC_FLAG_DST_COMP
);
1409 /* Destination address mode changes meanings depending on multicast compression. */
1410 dam_vs
= (iphc_flags
& LOWPAN_IPHC_FLAG_MCAST_COMP
) ? (lowpan_iphc_mcast_modes
) : (lowpan_iphc_addr_modes
);
1411 ti_dam
= proto_tree_add_uint_format_value(iphc_tree
, hf_6lowpan_iphc_flag_dam
, tvb
, offset
, (int)sizeof(guint16
),
1412 iphc_flags
& LOWPAN_IPHC_FLAG_DST_MODE
, "%s (0x%04x)", val_to_str_const(iphc_dst_mode
, dam_vs
, "Reserved"), iphc_dst_mode
);
1414 offset
+= (int)sizeof(guint16
);
1416 /* Display the context identifier extension, if present. */
1417 if (iphc_flags
& LOWPAN_IPHC_FLAG_CONTEXT_ID
) {
1418 iphc_ctx
= tvb_get_guint8(tvb
, offset
);
1419 iphc_sci
= (iphc_ctx
& LOWPAN_IPHC_FLAG_SCI
) >> LOWPAN_IPHC_FLAG_OFFSET_SCI
;
1420 iphc_dci
= (iphc_ctx
& LOWPAN_IPHC_FLAG_DCI
) >> LOWPAN_IPHC_FLAG_OFFSET_DCI
;
1422 proto_tree_add_uint(iphc_tree
, hf_6lowpan_iphc_sci
, tvb
, offset
, (int)sizeof(guint8
), iphc_ctx
& LOWPAN_IPHC_FLAG_SCI
);
1423 proto_tree_add_uint(iphc_tree
, hf_6lowpan_iphc_dci
, tvb
, offset
, (int)sizeof(guint8
), iphc_ctx
& LOWPAN_IPHC_FLAG_DCI
);
1425 offset
+= (int)sizeof(guint8
);
1427 /* Use link-local contexts if stateless. */
1428 if (!(iphc_flags
& LOWPAN_IPHC_FLAG_SRC_COMP
)) {
1429 iphc_sci
= LOWPAN_CONTEXT_LINK_LOCAL
;
1431 if (!(iphc_flags
& LOWPAN_IPHC_FLAG_DST_COMP
)) {
1432 iphc_dci
= LOWPAN_CONTEXT_LINK_LOCAL
;
1434 /* Lookup the contexts. */
1436 * Don't display their origin until after we decompress the address in case
1437 * the address modes indicate that we should use a different context.
1439 sctx
= lowpan_context_find(iphc_sci
, hint_panid
);
1440 dctx
= lowpan_context_find(iphc_dci
, hint_panid
);
1442 /*=====================================================
1443 * Parse Traffic Class and Flow Label
1444 *=====================================================
1447 /* Parse the ECN field. */
1448 if (iphc_traffic
!= LOWPAN_IPHC_FLOW_COMPRESSED
) {
1449 ipv6_class
|= tvb_get_bits8(tvb
, offset
, LOWPAN_IPHC_ECN_BITS
);
1450 offset
+= LOWPAN_IPHC_ECN_BITS
;
1452 /* Parse the DSCP field. */
1453 if ((iphc_traffic
== LOWPAN_IPHC_FLOW_CLASS_LABEL
) || (iphc_traffic
== LOWPAN_IPHC_FLOW_CLASS
)) {
1454 ipv6_class
|= (tvb_get_bits8(tvb
, offset
, LOWPAN_IPHC_DSCP_BITS
) << LOWPAN_IPHC_ECN_BITS
);
1455 offset
+= LOWPAN_IPHC_DSCP_BITS
;
1457 /* Display the traffic class field only if included inline. */
1458 if ((tree
) && (iphc_traffic
!= LOWPAN_IPHC_FLOW_COMPRESSED
)) {
1459 /* Create a tree for the traffic class. */
1460 proto_tree
* tf_tree
;
1461 ti
= proto_tree_add_uint(tree
, hf_6lowpan_traffic_class
, tvb
, offset
>>3, (int)sizeof(guint8
), ipv6_class
);
1462 tf_tree
= proto_item_add_subtree(ti
, ett_6lopwan_traffic_class
);
1464 /* Add the ECN and DSCP fields. */
1465 proto_tree_add_uint(tf_tree
, hf_6lowpan_ecn
, tvb
, offset
>>3, (int)sizeof(guint8
), ipv6_class
& LOWPAN_IPHC_TRAFFIC_ECN
);
1466 proto_tree_add_uint(tf_tree
, hf_6lowpan_dscp
, tvb
, offset
>>3, (int)sizeof(guint8
), ipv6_class
& LOWPAN_IPHC_TRAFFIC_DSCP
);
1469 /* Parse and display the traffic label. */
1470 if ((iphc_traffic
== LOWPAN_IPHC_FLOW_CLASS_LABEL
) || (iphc_traffic
== LOWPAN_IPHC_FLOW_ECN_LABEL
)) {
1471 /* Pad to 4-bits past the start of the byte. */
1472 offset
+= ((4 - offset
) & 0x7);
1473 ipv6
.ip6_flow
= tvb_get_bits32(tvb
, offset
, LOWPAN_IPHC_LABEL_BITS
, ENC_BIG_ENDIAN
);
1475 proto_tree_add_bits_item(tree
, hf_6lowpan_flow_label
, tvb
, offset
, LOWPAN_IPHC_LABEL_BITS
, ENC_BIG_ENDIAN
);
1477 offset
+= LOWPAN_IPHC_LABEL_BITS
;
1479 else ipv6
.ip6_flow
= 0;
1481 /* Rebuild the IPv6 flow label and traffic class fields. */
1482 ipv6
.ip6_flow
= g_ntohl(ipv6
.ip6_flow
) | (ipv6_class
<< LOWPAN_IPV6_FLOW_LABEL_BITS
);
1483 ipv6
.ip6_vfc
= (0x6 << 4) | (ipv6_class
>> 4);
1485 /* Convert back to byte offsets. */
1488 /*=====================================================
1489 * Parse Next Header and Hop Limit
1490 *=====================================================
1492 /* Get the next header field, if present. */
1493 if (!(iphc_flags
& LOWPAN_IPHC_FLAG_NHDR
)) {
1494 ipv6
.ip6_nxt
= tvb_get_guint8(tvb
, offset
);
1496 proto_tree_add_uint_format_value(tree
, hf_6lowpan_next_header
, tvb
, offset
, (int)sizeof(guint8
), ipv6
.ip6_nxt
,
1497 "%s (0x%02x)", ipprotostr(ipv6
.ip6_nxt
), ipv6
.ip6_nxt
);
1499 offset
+= (int)sizeof(guint8
);
1502 /* Get the hop limit field, if present. */
1503 if (iphc_hop_limit
== LOWPAN_IPHC_HLIM_1
) {
1506 else if (iphc_hop_limit
== LOWPAN_IPHC_HLIM_64
) {
1509 else if (iphc_hop_limit
== LOWPAN_IPHC_HLIM_255
) {
1510 ipv6
.ip6_hlim
= 255;
1513 ipv6
.ip6_hlim
= tvb_get_guint8(tvb
, offset
);
1515 proto_tree_add_uint(tree
, hf_6lowpan_hop_limit
, tvb
, offset
, (int)sizeof(guint8
), ipv6
.ip6_hlim
);
1517 offset
+= (int)sizeof(guint8
);
1520 /*=====================================================
1521 * Parse and decompress the source address.
1522 *=====================================================
1525 memset(&ipv6
.ip6_src
, 0, sizeof(ipv6
.ip6_src
));
1526 /* (SAC=1 && SAM=00) -> the unspecified address (::). */
1527 if ((iphc_flags
& LOWPAN_IPHC_FLAG_SRC_COMP
) && (iphc_src_mode
== LOWPAN_IPHC_ADDR_SRC_UNSPEC
)) {
1528 sctx
= &lowpan_context_default
;
1530 /* The IID is derived from the encapsulating layer. */
1531 else if (iphc_src_mode
== LOWPAN_IPHC_ADDR_COMPRESSED
) {
1532 memcpy(&ipv6
.ip6_src
.bytes
[sizeof(ipv6
.ip6_src
) - LOWPAN_IFC_ID_LEN
], siid
, LOWPAN_IFC_ID_LEN
);
1534 /* Full Address inline. */
1535 else if (iphc_src_mode
== LOWPAN_IPHC_ADDR_FULL_INLINE
) {
1536 if (!(iphc_flags
& LOWPAN_IPHC_FLAG_SRC_COMP
)) sctx
= &lowpan_context_default
;
1537 length
= (int)sizeof(ipv6
.ip6_src
);
1538 tvb_memcpy(tvb
, &ipv6
.ip6_src
, offset
, length
);
1540 /* 64-bits inline. */
1541 else if (iphc_src_mode
== LOWPAN_IPHC_ADDR_64BIT_INLINE
) {
1542 length
= (int)sizeof(guint64
);
1543 tvb_memcpy(tvb
, &ipv6
.ip6_src
.bytes
[sizeof(ipv6
.ip6_src
) - length
], offset
, length
);
1545 /* 16-bits inline. */
1546 else if (iphc_src_mode
== LOWPAN_IPHC_ADDR_16BIT_INLINE
) {
1547 length
= (int)sizeof(guint16
);
1548 /* Format becomes ff:fe00:xxxx */
1549 ipv6
.ip6_src
.bytes
[11] = 0xff;
1550 ipv6
.ip6_src
.bytes
[12] = 0xfe;
1551 tvb_memcpy(tvb
, &ipv6
.ip6_src
.bytes
[sizeof(ipv6
.ip6_src
) - length
], offset
, length
);
1554 /* Copy the context bits. */
1555 lowpan_pfxcpy(&ipv6
.ip6_src
, &sctx
->prefix
, sctx
->plen
);
1556 /* Update the IID of the encapsulating layer. */
1557 siid
= &ipv6
.ip6_src
.bytes
[sizeof(ipv6
.ip6_src
) - LOWPAN_IFC_ID_LEN
];
1559 /* Display the source IPv6 address. */
1561 proto_tree_add_ipv6(tree
, hf_6lowpan_source
, tvb
, offset
, length
, (guint8
*)&ipv6
.ip6_src
);
1563 /* Add information about where the context came from. */
1564 /* TODO: We should display the prefix length too. */
1565 if (tree
&& sctx
->plen
) {
1566 ti
= proto_tree_add_ipv6(iphc_tree
, hf_6lowpan_iphc_sctx_prefix
, tvb
, 0, 0, (guint8
*)&sctx
->prefix
);
1567 PROTO_ITEM_SET_GENERATED(ti
);
1568 if ( sctx
->frame
) {
1569 ti
= proto_tree_add_uint(iphc_tree
, hf_6lowpan_iphc_sctx_origin
, tvb
, 0, 0, sctx
->frame
);
1570 PROTO_ITEM_SET_GENERATED(ti
);
1575 * Do not set the address columns until after defragmentation, since we have
1576 * to do decompression before reassembly, and changing the address will cause
1577 * wireshark to think that the middle fragments came from another device.
1580 /*=====================================================
1581 * Parse and decompress a multicast address.
1582 *=====================================================
1585 memset(&ipv6
.ip6_dst
, 0, sizeof(ipv6
.ip6_dst
));
1586 /* Stateless multicast compression. */
1587 if ((iphc_flags
& LOWPAN_IPHC_FLAG_MCAST_COMP
) && !(iphc_flags
& LOWPAN_IPHC_FLAG_DST_COMP
)) {
1588 if (iphc_dst_mode
== LOWPAN_IPHC_ADDR_FULL_INLINE
) {
1589 length
= (int)sizeof(ipv6
.ip6_dst
);
1590 tvb_memcpy(tvb
, &ipv6
.ip6_dst
.bytes
[sizeof(ipv6
.ip6_dst
) - length
], offset
, length
);
1592 else if (iphc_dst_mode
== LOWPAN_IPHC_MCAST_48BIT
) {
1593 ipv6
.ip6_dst
.bytes
[0] = 0xff;
1594 ipv6
.ip6_dst
.bytes
[1] = tvb_get_guint8(tvb
, offset
+ (length
++));
1595 ipv6
.ip6_dst
.bytes
[11] = tvb_get_guint8(tvb
, offset
+ (length
++));
1596 ipv6
.ip6_dst
.bytes
[12] = tvb_get_guint8(tvb
, offset
+ (length
++));
1597 ipv6
.ip6_dst
.bytes
[13] = tvb_get_guint8(tvb
, offset
+ (length
++));
1598 ipv6
.ip6_dst
.bytes
[14] = tvb_get_guint8(tvb
, offset
+ (length
++));
1599 ipv6
.ip6_dst
.bytes
[15] = tvb_get_guint8(tvb
, offset
+ (length
++));
1601 else if (iphc_dst_mode
== LOWPAN_IPHC_MCAST_32BIT
) {
1602 ipv6
.ip6_dst
.bytes
[0] = 0xff;
1603 ipv6
.ip6_dst
.bytes
[1] = tvb_get_guint8(tvb
, offset
+ (length
++));
1604 ipv6
.ip6_dst
.bytes
[13] = tvb_get_guint8(tvb
, offset
+ (length
++));
1605 ipv6
.ip6_dst
.bytes
[14] = tvb_get_guint8(tvb
, offset
+ (length
++));
1606 ipv6
.ip6_dst
.bytes
[15] = tvb_get_guint8(tvb
, offset
+ (length
++));
1608 else if (iphc_dst_mode
== LOWPAN_IPHC_MCAST_8BIT
) {
1609 ipv6
.ip6_dst
.bytes
[0] = 0xff;
1610 ipv6
.ip6_dst
.bytes
[1] = 0x02;
1611 ipv6
.ip6_dst
.bytes
[15] = tvb_get_guint8(tvb
, offset
+ (length
++));
1614 /* Illegal destination address compression mode. */
1615 expert_add_info(pinfo
, ti_dam
, &ei_6lowpan_illegal_dest_addr_mode
);
1619 /* Stateful multicast compression. */
1620 else if ((iphc_flags
& LOWPAN_IPHC_FLAG_MCAST_COMP
) && (iphc_flags
& LOWPAN_IPHC_FLAG_DST_COMP
)) {
1621 if (iphc_dst_mode
== LOWPAN_IPHC_MCAST_STATEFUL_48BIT
) {
1622 /* RFC 3306 unicast-prefix based multicast address of the form:
1623 * ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
1625 * LL = prefix/context length (up to 64-bits).
1626 * PP = prefix/context byte.
1628 ipv6
.ip6_dst
.bytes
[0] = 0xff;
1629 ipv6
.ip6_dst
.bytes
[1] = tvb_get_guint8(tvb
, offset
+ (length
++));
1630 ipv6
.ip6_dst
.bytes
[2] = tvb_get_guint8(tvb
, offset
+ (length
++));
1631 ipv6
.ip6_dst
.bytes
[3] = (dctx
->plen
> 64) ? (64) : (dctx
->plen
);
1632 memcpy(&ipv6
.ip6_dst
.bytes
[4], &dctx
->prefix
, 8);
1633 ipv6
.ip6_dst
.bytes
[12] = tvb_get_guint8(tvb
, offset
+ (length
++));
1634 ipv6
.ip6_dst
.bytes
[13] = tvb_get_guint8(tvb
, offset
+ (length
++));
1635 ipv6
.ip6_dst
.bytes
[14] = tvb_get_guint8(tvb
, offset
+ (length
++));
1636 ipv6
.ip6_dst
.bytes
[15] = tvb_get_guint8(tvb
, offset
+ (length
++));
1639 /* Illegal destination address compression mode. */
1640 expert_add_info(pinfo
, ti_dam
, &ei_6lowpan_illegal_dest_addr_mode
);
1645 /*=====================================================
1646 * Parse and decompress a unicast destination address.
1647 *=====================================================
1650 /* (DAC=1 && DAM=00) -> reserved value. */
1651 if ((iphc_flags
& LOWPAN_IPHC_FLAG_DST_COMP
) && (iphc_dst_mode
== LOWPAN_IPHC_ADDR_FULL_INLINE
)) {
1652 /* Illegal destination address compression mode. */
1653 expert_add_info(pinfo
, ti_dam
, &ei_6lowpan_illegal_dest_addr_mode
);
1656 /* The IID is derived from the link-layer source. */
1657 else if (iphc_dst_mode
== LOWPAN_IPHC_ADDR_COMPRESSED
) {
1658 memcpy(&ipv6
.ip6_dst
.bytes
[sizeof(ipv6
.ip6_dst
) - LOWPAN_IFC_ID_LEN
], diid
, LOWPAN_IFC_ID_LEN
);
1660 /* Full Address inline. */
1661 else if (iphc_dst_mode
== LOWPAN_IPHC_ADDR_FULL_INLINE
) {
1662 dctx
= &lowpan_context_default
;
1663 length
= (int)sizeof(ipv6
.ip6_dst
);
1664 tvb_memcpy(tvb
, &ipv6
.ip6_dst
, offset
, length
);
1666 /* 64-bits inline. */
1667 else if (iphc_dst_mode
== LOWPAN_IPHC_ADDR_64BIT_INLINE
) {
1668 length
= (int)sizeof(guint64
);
1669 tvb_memcpy(tvb
, &ipv6
.ip6_dst
.bytes
[sizeof(ipv6
.ip6_dst
) - length
], offset
, length
);
1671 /* 16-bits inline. */
1672 else if (iphc_dst_mode
== LOWPAN_IPHC_ADDR_16BIT_INLINE
) {
1673 length
= (int)sizeof(guint16
);
1674 /* Format becomes ff:fe00:xxxx */
1675 ipv6
.ip6_dst
.bytes
[11] = 0xff;
1676 ipv6
.ip6_dst
.bytes
[12] = 0xfe;
1677 tvb_memcpy(tvb
, &ipv6
.ip6_dst
.bytes
[sizeof(ipv6
.ip6_dst
) - length
], offset
, length
);
1679 /* Copy the context bits. */
1680 lowpan_pfxcpy(&ipv6
.ip6_dst
, &dctx
->prefix
, dctx
->plen
);
1681 /* Update the interface id of the encapsulating layer. */
1682 diid
= &ipv6
.ip6_dst
.bytes
[sizeof(ipv6
.ip6_dst
) - LOWPAN_IFC_ID_LEN
];
1685 /* Display the destination IPv6 address. */
1687 proto_tree_add_ipv6(tree
, hf_6lowpan_dest
, tvb
, offset
, length
, (guint8
*)&ipv6
.ip6_dst
);
1689 /* Add information about where the context came from. */
1690 /* TODO: We should display the prefix length too. */
1691 if (tree
&& dctx
->plen
) {
1692 ti
= proto_tree_add_ipv6(iphc_tree
, hf_6lowpan_iphc_dctx_prefix
, tvb
, 0, 0, (guint8
*)&dctx
->prefix
);
1693 PROTO_ITEM_SET_GENERATED(ti
);
1694 if ( dctx
->frame
) {
1695 ti
= proto_tree_add_uint(iphc_tree
, hf_6lowpan_iphc_dctx_origin
, tvb
, 0, 0, dctx
->frame
);
1696 PROTO_ITEM_SET_GENERATED(ti
);
1701 * Do not set the address columns until after defragmentation, since we have
1702 * to do decompression before reassembly, and changing the address will cause
1703 * wireshark to think that the middle fragments came from another device.
1706 /*=====================================================
1707 * Decompress extension headers.
1708 *=====================================================
1710 /* Parse the list of extension headers. */
1711 if (iphc_flags
& LOWPAN_IPHC_FLAG_NHDR
) {
1712 /* Parse the next header protocol identifier. */
1713 ipv6
.ip6_nxt
= lowpan_parse_nhc_proto(tvb
, offset
);
1715 /* Parse the 6LoWPAN NHC fields. */
1716 nhdr_list
= dissect_6lowpan_iphc_nhc(tvb
, pinfo
, tree
, offset
, dgram_size
- (int)sizeof(struct ip6_hdr
), siid
, diid
);
1718 /* Create an extension header for the remaining payload. */
1720 length
= (gint
)tvb_ensure_length_remaining(tvb
, offset
);
1721 nhdr_list
= (struct lowpan_nhdr
*)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr
) + length
);
1722 nhdr_list
->next
= NULL
;
1723 nhdr_list
->proto
= ipv6
.ip6_nxt
;
1724 nhdr_list
->length
= length
;
1725 if (dgram_size
< 0) {
1726 nhdr_list
->reported
= tvb_reported_length_remaining(tvb
, offset
);
1729 nhdr_list
->reported
= dgram_size
- (int)sizeof(struct ip6_hdr
);
1731 tvb_memcpy(tvb
, LOWPAN_NHDR_DATA(nhdr_list
), offset
, nhdr_list
->length
);
1734 /*=====================================================
1735 * Rebuild the IPv6 packet.
1736 *=====================================================
1738 /* Reassemble the IPv6 packet. */
1739 ipv6_tvb
= lowpan_reassemble_ipv6(tvb
, &ipv6
, nhdr_list
);
1741 /* Add a new data source for it. */
1742 add_new_data_source(pinfo
, ipv6_tvb
, "Decompressed 6LoWPAN IPHC");
1745 } /* dissect_6lowpan_iphc */
1747 /*FUNCTION:------------------------------------------------------
1749 * dissect_6lowpan_iphc_nhc
1751 * Dissector routine for a 6LoWPAN IPHC next header structure(s).
1753 * tvb ; packet buffer.
1754 * pinfo ; packet info.
1755 * tree ; 6LoWPAN display tree.
1756 * offset ; packet buffer offset.
1757 * dgram_size ; Remaining datagram size (or <0 if unknown).
1758 * siid ; Source Interface ID.
1759 * diid ; Destination Interface ID.
1761 * lowpan_nhdr * ; List of wmem_alloc'd next header structures.
1762 *---------------------------------------------------------------
1764 static struct lowpan_nhdr
*
1765 dissect_6lowpan_iphc_nhc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gint offset
, gint dgram_size
, guint8
*siid
, guint8
*diid
)
1768 proto_item
* ti
= NULL
;
1769 proto_tree
* nhc_tree
= NULL
;
1770 struct lowpan_nhdr
*nhdr
;
1772 /*=====================================================
1773 * IP-in-IP Tunneling
1774 *=====================================================
1776 if (tvb_get_bits8(tvb
, offset
<<3, LOWPAN_NHC_PATTERN_EXT_IPV6_BITS
) == LOWPAN_NHC_PATTERN_EXT_IPV6
) {
1780 /* Create a tree for the IPv6 extension header. */
1782 ti
= proto_tree_add_text(tree
, tvb
, offset
, (int)sizeof(guint16
), "IPv6 extension header");
1783 nhc_tree
= proto_item_add_subtree(ti
, ett_6lowpan_nhc_ext
);
1784 /* Display the NHC-UDP pattern. */
1785 proto_tree_add_bits_item(nhc_tree
, hf_6lowpan_nhc_pattern
, tvb
, offset
<<3, LOWPAN_NHC_PATTERN_EXT_BITS
, ENC_BIG_ENDIAN
);
1788 /* Get and display the extension header compression flags. */
1789 ext_flags
= tvb_get_guint8(tvb
, offset
);
1791 proto_tree_add_uint(nhc_tree
, hf_6lowpan_nhc_ext_eid
, tvb
, offset
, (int)sizeof(guint8
), ext_flags
& LOWPAN_NHC_EXT_EID
);
1792 proto_tree_add_boolean(nhc_tree
, hf_6lowpan_nhc_ext_nh
, tvb
, offset
, (int)sizeof(guint8
), ext_flags
& LOWPAN_NHC_EXT_NHDR
);
1793 if (ext_flags
& LOWPAN_NHC_EXT_NHDR
) {
1794 /* TODO: Flag a warning, the NH bit MUST be 0 when EID==0x7 (IP-in-IP). */
1797 offset
+= (int)sizeof(guint8
);
1799 /* Decode the remainder of the packet using IPHC encoding. */
1800 iphc_tvb
= dissect_6lowpan_iphc(tvb_new_subset_remaining(tvb
, offset
), pinfo
, tree
, dgram_size
, siid
, diid
);
1801 if (!iphc_tvb
) return NULL
;
1803 /* Create the next header structure for the tunneled IPv6 header. */
1804 nhdr
= (struct lowpan_nhdr
*)wmem_alloc0(wmem_packet_scope(), sizeof(struct lowpan_nhdr
) + tvb_length(iphc_tvb
));
1806 nhdr
->proto
= IP_PROTO_IPV6
;
1807 nhdr
->length
= tvb_length(iphc_tvb
);
1808 nhdr
->reported
= tvb_reported_length(iphc_tvb
);
1809 tvb_memcpy(iphc_tvb
, LOWPAN_NHDR_DATA(nhdr
), 0, nhdr
->length
);
1812 /*=====================================================
1813 * IPv6 Extension Header
1814 *=====================================================
1816 if (tvb_get_bits8(tvb
, offset
<<3, LOWPAN_NHC_PATTERN_EXT_BITS
) == LOWPAN_NHC_PATTERN_EXT
) {
1817 struct ip6_ext ipv6_ext
;
1822 /* Parse the IPv6 extension header protocol. */
1823 ext_proto
= lowpan_parse_nhc_proto(tvb
, offset
);
1825 /* Create a tree for the IPv6 extension header. */
1827 ti
= proto_tree_add_text(tree
, tvb
, offset
, (int)sizeof(guint16
), "IPv6 extension header");
1828 nhc_tree
= proto_item_add_subtree(ti
, ett_6lowpan_nhc_ext
);
1829 /* Display the NHC-UDP pattern. */
1830 proto_tree_add_bits_item(nhc_tree
, hf_6lowpan_nhc_pattern
, tvb
, offset
<<3, LOWPAN_NHC_PATTERN_EXT_BITS
, ENC_BIG_ENDIAN
);
1833 /* Get and display the extension header compression flags. */
1834 ext_flags
= tvb_get_guint8(tvb
, offset
);
1836 proto_tree_add_uint(nhc_tree
, hf_6lowpan_nhc_ext_eid
, tvb
, offset
, (int)sizeof(guint8
), ext_flags
& LOWPAN_NHC_EXT_EID
);
1837 proto_tree_add_boolean(nhc_tree
, hf_6lowpan_nhc_ext_nh
, tvb
, offset
, (int)sizeof(guint8
), ext_flags
& LOWPAN_NHC_EXT_NHDR
);
1839 offset
+= (int)sizeof(guint8
);
1841 /* Get and display the next header field, if present. */
1842 if (!(ext_flags
& LOWPAN_NHC_EXT_NHDR
)) {
1843 ipv6_ext
.ip6e_nxt
= tvb_get_guint8(tvb
, offset
);
1845 proto_tree_add_uint_format_value(nhc_tree
, hf_6lowpan_nhc_ext_next
, tvb
, offset
, (int)sizeof(guint8
), ipv6_ext
.ip6e_nxt
,
1846 "%s (0x%02x)", ipprotostr(ipv6_ext
.ip6e_nxt
), ipv6_ext
.ip6e_nxt
);
1847 proto_item_set_end(ti
, tvb
, offset
+(int)sizeof(guint8
));
1849 offset
+= (int)sizeof(guint8
);
1852 /* Get and display the extension header length. */
1853 ext_len
= tvb_get_guint8(tvb
, offset
);
1855 proto_tree_add_uint(nhc_tree
, hf_6lowpan_nhc_ext_length
, tvb
, offset
, (int)sizeof(guint8
), ext_len
);
1857 offset
+= (int)sizeof(guint8
);
1859 /* Compute the length of the extension header padded to an 8-byte alignment. */
1860 length
= (int)sizeof(struct ip6_ext
) + ext_len
;
1861 length
= (length
+ 7) & ~0x7;
1863 /* Create the next header structure for the IPv6 extension header. */
1864 nhdr
= (struct lowpan_nhdr
*)wmem_alloc0(wmem_packet_scope(), sizeof(struct lowpan_nhdr
) + length
);
1866 nhdr
->proto
= ext_proto
;
1867 nhdr
->length
= length
;
1868 nhdr
->reported
= length
;
1870 /* Add the IPv6 extension header to the buffer. */
1871 if (ext_flags
& LOWPAN_NHC_EXT_NHDR
) {
1872 ipv6_ext
.ip6e_nxt
= lowpan_parse_nhc_proto(tvb
, offset
+ext_len
);
1874 ipv6_ext
.ip6e_len
= nhdr
->reported
>>3; /* Convert to units of 8 bytes. */
1875 ipv6_ext
.ip6e_len
-= 1; /* Don't include the first 8 bytes. */
1876 memcpy(LOWPAN_NHDR_DATA(nhdr
), &ipv6_ext
, sizeof(struct ip6_ext
));
1879 * If the extension header was truncated, display the remainder using
1880 * the data dissector, and end NHC dissection here.
1882 if (!tvb_bytes_exist(tvb
, offset
, ext_len
)) {
1883 /* Call the data dissector for the remainder. */
1884 call_dissector(data_handle
, tvb_new_subset_remaining(tvb
, offset
), pinfo
, nhc_tree
);
1886 /* Copy the remainder, and truncate the real buffer length. */
1887 nhdr
->length
= tvb_length_remaining(tvb
, offset
) + (int)sizeof(struct ip6_ext
);
1888 tvb_memcpy(tvb
, LOWPAN_NHDR_DATA(nhdr
) + sizeof(struct ip6_ext
), offset
, tvb_length_remaining(tvb
, offset
));
1890 /* There is nothing more we can do. */
1894 /* Display the extension header using the data dissector. */
1895 call_dissector(data_handle
, tvb_new_subset(tvb
, offset
, ext_len
, ext_len
), pinfo
, nhc_tree
);
1897 /* Copy the extension header into the struct. */
1898 tvb_memcpy(tvb
, LOWPAN_NHDR_DATA(nhdr
) + sizeof(struct ip6_ext
), offset
, ext_len
);
1901 if (ext_flags
& LOWPAN_NHC_EXT_NHDR
) {
1903 * There are more LOWPAN_NHC structures to parse. Call ourself again
1904 * recursively to parse them and build the linked list.
1906 nhdr
->next
= dissect_6lowpan_iphc_nhc(tvb
, pinfo
, tree
, offset
, dgram_size
- ext_len
- (int)sizeof(struct ip6_ext
), siid
, diid
);
1909 /* Create another next header structure for the remaining payload. */
1910 length
= (gint
)tvb_ensure_length_remaining(tvb
, offset
);
1911 nhdr
->next
= (struct lowpan_nhdr
*)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr
) + length
);
1912 nhdr
->next
->next
= NULL
;
1913 nhdr
->next
->proto
= ipv6_ext
.ip6e_nxt
;
1914 nhdr
->next
->length
= length
;
1915 if (dgram_size
< 0) {
1916 nhdr
->next
->reported
= tvb_reported_length_remaining(tvb
, offset
);
1919 nhdr
->next
->reported
= dgram_size
- ext_len
- (int)sizeof(struct ip6_ext
);
1921 tvb_memcpy(tvb
, LOWPAN_NHDR_DATA(nhdr
->next
), offset
, nhdr
->next
->length
);
1927 /*=====================================================
1929 *=====================================================
1931 if (tvb_get_bits8(tvb
, offset
<<3, LOWPAN_NHC_PATTERN_UDP_BITS
) == LOWPAN_NHC_PATTERN_UDP
) {
1937 /* Create a tree for the UDP header. */
1939 ti
= proto_tree_add_text(tree
, tvb
, 0, (int)sizeof(guint8
), "UDP header compression");
1940 nhc_tree
= proto_item_add_subtree(ti
, ett_6lowpan_nhc_udp
);
1941 /* Display the NHC-UDP pattern. */
1942 proto_tree_add_bits_item(nhc_tree
, hf_6lowpan_nhc_pattern
, tvb
, offset
<<3, LOWPAN_NHC_PATTERN_UDP_BITS
, ENC_BIG_ENDIAN
);
1945 /* Get and display the UDP header compression options */
1946 udp_flags
= tvb_get_guint8(tvb
, offset
);
1948 proto_tree_add_boolean(nhc_tree
, hf_6lowpan_nhc_udp_checksum
, tvb
, offset
, (int)sizeof(guint8
), udp_flags
& LOWPAN_NHC_UDP_CHECKSUM
);
1949 proto_tree_add_boolean(nhc_tree
, hf_6lowpan_nhc_udp_src
, tvb
, offset
, (int)sizeof(guint8
), udp_flags
& LOWPAN_NHC_UDP_SRCPORT
);
1950 proto_tree_add_boolean(nhc_tree
, hf_6lowpan_nhc_udp_dst
, tvb
, offset
, (int)sizeof(guint8
), udp_flags
& LOWPAN_NHC_UDP_DSTPORT
);
1952 offset
+= (int)sizeof(guint8
);
1954 /* Get and display the ports. */
1955 switch (udp_flags
& (LOWPAN_NHC_UDP_SRCPORT
| LOWPAN_NHC_UDP_DSTPORT
)) {
1956 case (LOWPAN_NHC_UDP_SRCPORT
| LOWPAN_NHC_UDP_DSTPORT
):
1957 udp
.src_port
= LOWPAN_PORT_12BIT_OFFSET
+ (tvb_get_guint8(tvb
, offset
) >> 4);
1958 udp
.dst_port
= LOWPAN_PORT_12BIT_OFFSET
+ (tvb_get_guint8(tvb
, offset
) & 0x0f);
1963 case LOWPAN_NHC_UDP_SRCPORT
:
1964 udp
.src_port
= LOWPAN_PORT_8BIT_OFFSET
+ tvb_get_guint8(tvb
, offset
);
1965 udp
.dst_port
= tvb_get_ntohs(tvb
, offset
+ 1);
1970 case LOWPAN_NHC_UDP_DSTPORT
:
1971 udp
.src_port
= tvb_get_ntohs(tvb
, offset
);
1972 udp
.dst_port
= LOWPAN_PORT_8BIT_OFFSET
+ tvb_get_guint8(tvb
, offset
+ 2);
1978 udp
.src_port
= tvb_get_ntohs(tvb
, offset
);
1979 udp
.dst_port
= tvb_get_ntohs(tvb
, offset
+2);
1985 proto_tree_add_uint(tree
, hf_6lowpan_udp_src
, tvb
, offset
, BITS_TO_BYTE_LEN(offset
<<3, src_bitlen
), udp
.src_port
);
1986 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
);
1988 offset
+= ((src_bitlen
+ dst_bitlen
)>>3);
1989 udp
.src_port
= g_ntohs(udp
.src_port
);
1990 udp
.dst_port
= g_ntohs(udp
.dst_port
);
1992 /* Get and display the checksum. */
1993 if (!(udp_flags
& LOWPAN_NHC_UDP_CHECKSUM
)) {
1994 /* Parse the checksum. */
1995 udp
.checksum
= tvb_get_ntohs(tvb
, offset
);
1997 proto_tree_add_uint(tree
, hf_6lowpan_udp_checksum
, tvb
, offset
, (int)sizeof(guint16
), udp
.checksum
);
1999 offset
+= (int)sizeof(guint16
);
2000 udp
.checksum
= g_ntohs(udp
.checksum
);
2006 /* Compute the datagram length. */
2007 if (dgram_size
< 0) {
2008 length
= tvb_reported_length_remaining(tvb
, offset
);
2009 udp
.length
= g_htons(length
+ (int)sizeof(struct udp_hdr
));
2012 udp
.length
= g_htons(dgram_size
);
2016 * Although rfc768 (udp) allows a packet to be sent with a checksum of
2017 * 0 to mean that no checksum was computed, apparently IPv6 specifically
2018 * disallows sending UDP datagrams without checksums. Likewise, 6LoWPAN
2019 * requires that we recompute the checksum.
2021 * If the datagram is incomplete, then leave the checsum at 0.
2025 * This has been disabled, since we might only be dissecting a fragment
2026 * of the packet, and thus we might not have the entire UDP payload at
2029 * If we want to display the checksums, they will have to be recomputed
2030 * after packet reassembly. Lots of work for not much gain, since we can
2031 * just set the UDP checksum to 0 and Wireshark doesn't care.
2033 if ((udp_flags
& LOWPAN_NHC_UDP_CHECKSUM
) && tvb_bytes_exist(tvb
, offset
, length
)) {
2036 struct e_in6_addr src
;
2037 struct e_in6_addr dst
;
2043 /* Fill in the pseudo-header. */
2044 memcpy(&cksum_phdr
.src
, pinfo
->src
.data
, sizeof(struct e_in6_addr
));
2045 memcpy(&cksum_phdr
.dst
, pinfo
->dst
.data
, sizeof(struct e_in6_addr
));
2046 cksum_phdr
.length
= g_htonl(length
+ (int)sizeof(struct udp_hdr
));
2047 memset(cksum_phdr
.zero
, 0, sizeof(cksum_phdr
.zero
));
2048 cksum_phdr
.proto
= IP_PROTO_UDP
;
2050 /* Compute the checksum. */
2051 cksum_vec
[0].ptr
= (const guint8
*)&cksum_phdr
;
2052 cksum_vec
[0].len
= sizeof(cksum_phdr
);
2053 cksum_vec
[1].ptr
= (const guint8
*)&udp
;
2054 cksum_vec
[1].len
= sizeof(struct udp_hdr
);
2055 cksum_vec
[2].ptr
= tvb_get_ptr(tvb
, offset
, length
);
2056 cksum_vec
[2].len
= length
;
2057 udp
.checksum
= in_cksum(cksum_vec
, 3);
2058 if (udp
.checksum
== 0) udp
.checksum
= 0xffff;
2062 /* Create the next header structure for the UDP datagram. */
2063 length
= (gint
)tvb_ensure_length_remaining(tvb
, offset
);
2064 nhdr
= (struct lowpan_nhdr
*)wmem_alloc(wmem_packet_scope(), sizeof(struct lowpan_nhdr
) + sizeof(struct udp_hdr
) + length
);
2066 nhdr
->proto
= IP_PROTO_UDP
;
2067 nhdr
->length
= length
+ (int)sizeof(struct udp_hdr
);
2068 nhdr
->reported
= g_ntohs(udp
.length
);
2070 /* Copy the UDP header and payload into the buffer. */
2071 memcpy(LOWPAN_NHDR_DATA(nhdr
), &udp
, sizeof(struct udp_hdr
));
2072 tvb_memcpy(tvb
, LOWPAN_NHDR_DATA(nhdr
) + sizeof(struct udp_hdr
), offset
, tvb_length_remaining(tvb
, offset
));
2075 /*=====================================================
2076 * Unknown Next Header Type
2077 *=====================================================
2080 } /* dissect_6lowpan_iphc_nhc */
2082 /*FUNCTION:------------------------------------------------------
2084 * dissect_6lowpan_bc0
2086 * Dissector routine for a 6LoWPAN broadcast header.
2088 * tvb ; packet buffer.
2089 * pinfo ; packet info.
2090 * tree ; 6LoWPAN display tree.
2092 * tvbuff_t * ; The remaining payload to be parsed.
2093 *---------------------------------------------------------------
2096 dissect_6lowpan_bc0(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
2099 proto_tree
* bcast_tree
;
2102 /* Create a tree for the broadcast header. */
2104 ti
= proto_tree_add_text(tree
, tvb
, 0, (int)sizeof(guint16
), "Broadcast Header");
2105 bcast_tree
= proto_item_add_subtree(ti
, ett_6lowpan_bcast
);
2107 /* Get and display the pattern. */
2108 proto_tree_add_bits_item(bcast_tree
, hf_6lowpan_pattern
, tvb
, 0, LOWPAN_PATTERN_BC0_BITS
, ENC_BIG_ENDIAN
);
2110 /* Get and display the sequence number. */
2111 seqnum
= tvb_get_guint8(tvb
, (int)sizeof(guint8
));
2112 proto_tree_add_uint(bcast_tree
, hf_6lowpan_bcast_seqnum
, tvb
, (int)sizeof(guint8
), (int)sizeof(guint8
), seqnum
);
2115 /* Return the remaining buffer. */
2116 return tvb_new_subset_remaining(tvb
, sizeof(guint16
));
2117 } /* dissect_6lowpan_bc0 */
2119 /*FUNCTION:------------------------------------------------------
2121 * dissect_6lowpan_mesh
2123 * Dissector routine for a 6LoWPAN mesh header.
2125 * tvb ; packet buffer.
2126 * pinfo ; packet info.
2127 * tree ; 6LoWPAN display tree.
2128 * offset ; offset to the start of the header.
2130 * tvbuff_t * ; The remaining payload to be parsed.
2131 *---------------------------------------------------------------
2134 dissect_6lowpan_mesh(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
2138 proto_tree
* mesh_tree
= NULL
;
2139 proto_item
* ti
= NULL
;
2140 const guint8
* src_ifcid
;
2141 const guint8
* dst_ifcid
;
2143 /* Create a tree for the mesh header. */
2145 ti
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Mesh Header");
2146 mesh_tree
= proto_item_add_subtree(ti
, ett_6lowpan_mesh
);
2149 /* Get and display the mesh flags. */
2150 mesh_header
= tvb_get_guint8(tvb
, offset
);
2152 proto_item
* flag_item
;
2153 proto_tree
* flag_tree
;
2155 /* Create the mesh header subtree. */
2156 flag_item
= proto_tree_add_text(mesh_tree
, tvb
, offset
, (int)sizeof(guint8
), "Flags");
2157 flag_tree
= proto_item_add_subtree(flag_item
, ett_6lowpan_mesh
);
2159 /* Add the mesh header fields. */
2160 proto_tree_add_bits_item(flag_tree
, hf_6lowpan_pattern
, tvb
, offset
* 8, LOWPAN_PATTERN_MESH_BITS
, ENC_BIG_ENDIAN
);
2161 proto_tree_add_boolean(flag_tree
, hf_6lowpan_mesh_v
, tvb
, offset
, (int)sizeof(guint8
), mesh_header
& LOWPAN_MESH_HEADER_V
);
2162 proto_tree_add_boolean(flag_tree
, hf_6lowpan_mesh_f
, tvb
, offset
, (int)sizeof(guint8
), mesh_header
& LOWPAN_MESH_HEADER_F
);
2163 if ((mesh_header
& LOWPAN_MESH_HEADER_HOPS
)==15)
2166 proto_tree_add_uint(flag_tree
, hf_6lowpan_mesh_hops
, tvb
, offset
, (int)sizeof(guint8
), mesh_header
& LOWPAN_MESH_HEADER_HOPS
);
2167 offset
+= (int)sizeof(guint8
);
2168 HopsLeft
=tvb_get_guint8(tvb
, offset
);
2169 proto_tree_add_uint(mesh_tree
, hf_6lowpan_mesh_hops8
, tvb
, offset
, (int)sizeof(guint8
), HopsLeft
);
2172 proto_tree_add_uint(flag_tree
, hf_6lowpan_mesh_hops
, tvb
, offset
, (int)sizeof(guint8
), mesh_header
& LOWPAN_MESH_HEADER_HOPS
);
2174 offset
+= (int)sizeof(guint8
);
2176 /* Get and display the originator address. */
2177 if (!(mesh_header
& LOWPAN_MESH_HEADER_V
)) {
2178 guint64 addr64
= tvb_get_ntoh64(tvb
, offset
);
2180 proto_tree_add_uint64(mesh_tree
, hf_6lowpan_mesh_orig64
, tvb
, offset
, (int)sizeof(guint64
), addr64
);
2182 src_ifcid
= tvb_get_ptr(tvb
, offset
, (int)sizeof(guint64
));
2183 offset
+= (int)sizeof(guint64
);
2186 guint16 addr16
= tvb_get_ntohs(tvb
, offset
);
2189 proto_tree_add_uint(mesh_tree
, hf_6lowpan_mesh_orig16
, tvb
, offset
, (int)sizeof(guint16
), addr16
);
2191 ifcid
= (guint8
*)wmem_alloc(pinfo
->pool
, sizeof(guint64
));
2192 lowpan_addr16_to_ifcid(addr16
, ifcid
);
2194 offset
+= (int)sizeof(guint16
);
2196 SET_ADDRESS(&pinfo
->src
, AT_EUI64
, sizeof(guint64
), src_ifcid
);
2197 SET_ADDRESS(&pinfo
->net_src
, AT_EUI64
, sizeof(guint64
), src_ifcid
);
2199 /* Get and display the destination address. */
2200 if (!(mesh_header
& LOWPAN_MESH_HEADER_F
)) {
2201 guint64 addr64
= tvb_get_ntoh64(tvb
, offset
);
2203 proto_tree_add_uint64(mesh_tree
, hf_6lowpan_mesh_dest64
, tvb
, offset
, (int)sizeof(guint64
), addr64
);
2205 dst_ifcid
= tvb_get_ptr(tvb
, offset
, (int)sizeof(guint64
));
2206 offset
+= (int)sizeof(guint64
);
2209 guint16 addr16
= tvb_get_ntohs(tvb
, offset
);
2212 proto_tree_add_uint(mesh_tree
, hf_6lowpan_mesh_dest16
, tvb
, offset
, (int)sizeof(guint16
), addr16
);
2214 ifcid
= (guint8
*)wmem_alloc(pinfo
->pool
, (int)sizeof(guint64
));
2215 lowpan_addr16_to_ifcid(addr16
, ifcid
);
2217 offset
+= (int)sizeof(guint16
);
2219 SET_ADDRESS(&pinfo
->dst
, AT_EUI64
, sizeof(guint64
), dst_ifcid
);
2220 SET_ADDRESS(&pinfo
->net_dst
, AT_EUI64
, sizeof(guint64
), dst_ifcid
);
2222 /* Adjust the mesh header length. */
2224 proto_item_set_end(ti
, tvb
, offset
);
2227 /* Return the remaining buffer. */
2228 return tvb_new_subset_remaining(tvb
, offset
);
2229 } /* dissect_6lowpan_mesh */
2231 /*FUNCTION:------------------------------------------------------
2233 * dissect_6lowpan_frag_first
2235 * Dissector routine for a 6LoWPAN FRAG1 headers.
2237 * If reassembly could be completed, this should return an
2238 * uncompressed IPv6 packet. If reassembly had to be delayed
2239 * for more packets, this will return NULL.
2241 * tvb ; packet buffer.
2242 * pinfo ; packet info.
2243 * tree ; 6LoWPAN display tree.
2244 * siid ; Source Interface ID.
2245 * diid ; Destination Interface ID.
2247 * tvbuff_t * ; reassembled IPv6 packet.
2248 *---------------------------------------------------------------
2251 dissect_6lowpan_frag_first(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint8
*siid
, guint8
*diid
)
2257 proto_tree
* frag_tree
= NULL
;
2258 proto_item
* ti
= NULL
;
2259 proto_item
* length_item
= NULL
;
2260 /* Reassembly parameters. */
2261 tvbuff_t
* new_tvb
= NULL
;
2262 tvbuff_t
* frag_tvb
= NULL
;
2263 fragment_head
* frag_data
= NULL
;
2264 gboolean save_fragmented
;
2266 /* Create a tree for the fragmentation header. */
2268 ti
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Fragmentation Header");
2269 frag_tree
= proto_item_add_subtree(ti
, ett_6lowpan_frag
);
2272 /* Get and display the pattern and datagram size. */
2273 dgram_size
= tvb_get_bits16(tvb
, (offset
* 8) + LOWPAN_PATTERN_FRAG_BITS
, LOWPAN_FRAG_DGRAM_SIZE_BITS
, ENC_BIG_ENDIAN
);
2275 proto_tree_add_bits_item(frag_tree
, hf_6lowpan_pattern
, tvb
, offset
* 8, LOWPAN_PATTERN_FRAG_BITS
, ENC_BIG_ENDIAN
);
2276 length_item
= proto_tree_add_uint(frag_tree
, hf_6lowpan_frag_dgram_size
, tvb
, offset
, (int)sizeof(guint16
), dgram_size
);
2278 offset
+= (int)sizeof(guint16
);
2280 /* Get and display the datagram tag. */
2281 dgram_tag
= tvb_get_ntohs(tvb
, offset
);
2283 proto_tree_add_uint(frag_tree
, hf_6lowpan_frag_dgram_tag
, tvb
, offset
, (int)sizeof(guint16
), dgram_tag
);
2285 offset
+= (int)sizeof(guint16
);
2287 /* Adjust the fragmentation header length. */
2289 proto_item_set_end(ti
, tvb
, offset
);
2292 /* The first fragment can contain an uncompressed IPv6, HC1 or IPHC fragment. */
2293 frag_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2294 if (tvb_get_bits8(frag_tvb
, 0, LOWPAN_PATTERN_IPV6_BITS
) == LOWPAN_PATTERN_IPV6
) {
2295 frag_tvb
= dissect_6lowpan_ipv6(frag_tvb
, pinfo
, tree
);
2297 else if (tvb_get_bits8(frag_tvb
, 0, LOWPAN_PATTERN_HC1_BITS
) == LOWPAN_PATTERN_HC1
) {
2298 /* Check if the datagram size is sane. */
2299 if (dgram_size
< (gint
)sizeof(struct ip6_hdr
)) {
2300 expert_add_info_format(pinfo
, length_item
, &ei_6lowpan_bad_ipv6_header_length
,
2301 "Length is less than IPv6 header length %u", (guint
)sizeof(struct ip6_hdr
));
2303 frag_tvb
= dissect_6lowpan_hc1(frag_tvb
, pinfo
, tree
, dgram_size
, siid
, diid
);
2305 else if (tvb_get_bits8(frag_tvb
, 0, LOWPAN_PATTERN_IPHC_BITS
) == LOWPAN_PATTERN_IPHC
) {
2306 /* Check if the datagram size is sane. */
2307 if (dgram_size
< (gint
)sizeof(struct ip6_hdr
)) {
2308 expert_add_info_format(pinfo
, length_item
, &ei_6lowpan_bad_ipv6_header_length
,
2309 "Length is less than IPv6 header length %u", (guint
)sizeof(struct ip6_hdr
));
2311 frag_tvb
= dissect_6lowpan_iphc(frag_tvb
, pinfo
, tree
, dgram_size
, siid
, diid
);
2313 /* Unknown 6LoWPAN dispatch type */
2315 dissect_6lowpan_unknown(frag_tvb
, pinfo
, tree
);
2319 /* Check call to dissect_6lowpan_xxx was successful */
2320 if (frag_tvb
== NULL
) {
2324 /* Add this datagram to the fragment table. */
2325 frag_size
= tvb_length(frag_tvb
);
2326 tvb_set_reported_length(frag_tvb
, frag_size
);
2327 save_fragmented
= pinfo
->fragmented
;
2328 pinfo
->fragmented
= TRUE
;
2329 frag_data
= fragment_add_check(&lowpan_reassembly_table
,
2330 frag_tvb
, 0, pinfo
, dgram_tag
, NULL
,
2331 0, frag_size
, (frag_size
< dgram_size
));
2333 /* Attempt reassembly. */
2334 new_tvb
= process_reassembled_data(frag_tvb
, 0, pinfo
,
2335 "Reassembled 6LoWPAN", frag_data
, &lowpan_frag_items
,
2338 pinfo
->fragmented
= save_fragmented
;
2341 /* Reassembly was successful; return the completed datagram. */
2344 /* Reassembly was unsuccessful; show this fragment. This may
2345 just mean that we don't yet have all the fragments, so
2346 we should not just continue dissecting. */
2347 call_dissector(data_handle
, frag_tvb
, pinfo
, proto_tree_get_root(tree
));
2350 } /* dissect_6lowpan_frag_first */
2352 /*FUNCTION:------------------------------------------------------
2354 * dissect_6lowpan_frag_middle
2356 * Dissector routine for a 6LoWPAN FRAGN headers.
2358 * If reassembly could be completed, this should return an
2359 * uncompressed IPv6 packet. If reassembly had to be delayed
2360 * for more packets, this will return NULL.
2362 * tvb ; packet buffer.
2363 * pinfo ; packet info.
2364 * tree ; 6LoWPAN display tree.
2366 * tvbuff_t * ; reassembled IPv6 packet.
2367 *---------------------------------------------------------------
2370 dissect_6lowpan_frag_middle(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
2376 guint16 dgram_offset
= 0;
2377 proto_tree
* frag_tree
= NULL
;
2378 proto_item
* ti
= NULL
;
2379 /* Reassembly parameters. */
2380 tvbuff_t
* new_tvb
= NULL
;
2381 fragment_head
* frag_data
= NULL
;
2382 gboolean save_fragmented
;
2384 /* Create a tree for the fragmentation header. */
2386 ti
= proto_tree_add_text(tree
, tvb
, offset
, 0, "Fragmentation Header");
2387 frag_tree
= proto_item_add_subtree(ti
, ett_6lowpan_frag
);
2390 /* Get and display the pattern and datagram size. */
2391 dgram_size
= tvb_get_bits16(tvb
, (offset
* 8) + LOWPAN_PATTERN_FRAG_BITS
, LOWPAN_FRAG_DGRAM_SIZE_BITS
, ENC_BIG_ENDIAN
);
2393 proto_tree_add_bits_item(frag_tree
, hf_6lowpan_pattern
, tvb
, offset
* 8, LOWPAN_PATTERN_FRAG_BITS
, ENC_BIG_ENDIAN
);
2394 proto_tree_add_uint(frag_tree
, hf_6lowpan_frag_dgram_size
, tvb
, offset
, (int)sizeof(guint16
), dgram_size
);
2396 offset
+= (int)sizeof(guint16
);
2398 /* Get and display the datagram tag. */
2399 dgram_tag
= tvb_get_ntohs(tvb
, offset
);
2401 proto_tree_add_uint(frag_tree
, hf_6lowpan_frag_dgram_tag
, tvb
, offset
, (int)sizeof(guint16
), dgram_tag
);
2403 offset
+= (int)sizeof(guint16
);
2405 /* Get and display the datagram offset. */
2406 dgram_offset
= tvb_get_guint8(tvb
, offset
) * 8;
2408 proto_tree_add_uint(frag_tree
, hf_6lowpan_frag_dgram_offset
, tvb
, offset
, (int)sizeof(guint8
), dgram_offset
);
2410 offset
+= (int)sizeof(guint8
);
2412 /* Adjust the fragmentation header length. */
2413 frag_size
= tvb_reported_length_remaining(tvb
, offset
);
2415 proto_item_set_end(ti
, tvb
, offset
);
2418 /* Add this datagram to the fragment table. */
2419 save_fragmented
= pinfo
->fragmented
;
2420 pinfo
->fragmented
= TRUE
;
2421 frag_data
= fragment_add_check(&lowpan_reassembly_table
,
2422 tvb
, offset
, pinfo
, dgram_tag
, NULL
,
2423 dgram_offset
, frag_size
, ((dgram_offset
+ frag_size
) < dgram_size
));
2425 /* Attempt reassembly. */
2426 new_tvb
= process_reassembled_data(tvb
, offset
, pinfo
,
2427 "Reassembled 6LoWPAN", frag_data
, &lowpan_frag_items
,
2430 pinfo
->fragmented
= save_fragmented
;
2432 /* If reassembly was successful, then return the completed datagram. */
2436 /* If reassembly failed, display the payload fragment using the data dissector. */
2438 new_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2439 call_dissector(data_handle
, new_tvb
, pinfo
, proto_tree_get_root(tree
));
2442 } /* dissect_6lowpan_frag_middle */
2444 /*FUNCTION:------------------------------------------------------
2446 * dissect_6lowpan_unknown
2448 * Dissector routine for 6LoWPAN packets after encountering
2449 * an unknown header.
2451 * tvb ; packet buffer.
2452 * pinfo ; packet info.
2453 * tree ; 6LoWPAN display tree.
2456 *---------------------------------------------------------------
2459 dissect_6lowpan_unknown(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
2461 tvbuff_t
* data_tvb
;
2463 /* Get and display the pattern. */
2465 proto_tree_add_bits_item(tree
, hf_6lowpan_pattern
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
2468 /* Create a tvbuff subset for the remaining data. */
2469 data_tvb
= tvb_new_subset_remaining(tvb
, (int)sizeof(guint8
));
2470 call_dissector(data_handle
, data_tvb
, pinfo
, proto_tree_get_root(tree
));
2471 } /* dissect_6lowpan_unknown */
2473 /*FUNCTION:------------------------------------------------------
2475 * proto_register_6lowpan
2477 * Protocol registration routine for 6LoWPAN. Called during
2478 * Wireshark initialization.
2483 *---------------------------------------------------------------
2486 proto_register_6lowpan(void)
2488 static hf_register_info hf
[] = {
2489 /* Common 6LoWPAN fields. */
2490 { &hf_6lowpan_pattern
,
2491 { "Pattern", "6lowpan.pattern",
2492 FT_UINT8
, BASE_HEX
, VALS(lowpan_patterns
), 0x0, NULL
, HFILL
}},
2493 { &hf_6lowpan_nhc_pattern
,
2494 { "Pattern", "6lowpan.nhc.pattern",
2495 FT_UINT8
, BASE_HEX
, VALS(lowpan_nhc_patterns
), 0x0, NULL
, HFILL
}},
2497 /* HC1 header fields. */
2498 { &hf_6lowpan_hc1_source_prefix
,
2499 { "Source prefix", "6lowpan.hc1.src_prefix",
2500 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_HC1_SOURCE_PREFIX
, NULL
, HFILL
}},
2501 { &hf_6lowpan_hc1_source_ifc
,
2502 { "Source interface", "6lowpan.hc1.src_ifc",
2503 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_HC1_SOURCE_IFC
, NULL
, HFILL
}},
2504 { &hf_6lowpan_hc1_dest_prefix
,
2505 { "Destination prefix", "6lowpan.hc1.dst_prefix",
2506 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_HC1_DEST_PREFIX
, NULL
, HFILL
}},
2507 { &hf_6lowpan_hc1_dest_ifc
,
2508 { "Destination interface", "6lowpan.hc1.dst_ifc",
2509 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_HC1_DEST_IFC
, NULL
, HFILL
}},
2510 { &hf_6lowpan_hc1_class
,
2511 { "Traffic class and flow label", "6lowpan.hc1.class",
2512 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_HC1_TRAFFIC_CLASS
, NULL
, HFILL
}},
2513 { &hf_6lowpan_hc1_next
,
2514 { "Next header", "6lowpan.hc1.next",
2515 FT_UINT8
, BASE_HEX
, VALS(lowpan_hc1_next
), LOWPAN_HC1_NEXT
, NULL
, HFILL
}},
2516 { &hf_6lowpan_hc1_more
,
2517 { "More HC bits", "6lowpan.hc1.more",
2518 FT_BOOLEAN
, 8, NULL
, LOWPAN_HC1_MORE
, NULL
, HFILL
}},
2520 /* HC_UDP header fields. */
2521 { &hf_6lowpan_hc2_udp_src
,
2522 { "Source port", "6lowpan.hc2.udp.src",
2523 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_HC2_UDP_SRCPORT
, NULL
, HFILL
}},
2524 { &hf_6lowpan_hc2_udp_dst
,
2525 { "Destination port", "6lowpan.hc2.udp.dst",
2526 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_HC2_UDP_DSTPORT
, NULL
, HFILL
}},
2527 { &hf_6lowpan_hc2_udp_len
,
2528 { "Length", "6lowpan.hc2.udp.length",
2529 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_HC2_UDP_LENGTH
, NULL
, HFILL
}},
2531 /* IPHC header fields. */
2532 { &hf_6lowpan_iphc_flag_tf
,
2533 { "Traffic class and flow label", "6lowpan.iphc.tf",
2534 FT_UINT16
, BASE_HEX
, VALS(lowpan_iphc_traffic
), LOWPAN_IPHC_FLAG_FLOW
, "traffic class and flow control encoding", HFILL
}},
2535 { &hf_6lowpan_iphc_flag_nhdr
,
2536 { "Next header", "6lowpan.iphc.nh",
2537 FT_BOOLEAN
, 16, TFS(&lowpan_compression
), LOWPAN_IPHC_FLAG_NHDR
, NULL
, HFILL
}},
2538 { &hf_6lowpan_iphc_flag_hlim
,
2539 { "Hop limit", "6lowpan.iphc.hlim",
2540 FT_UINT16
, BASE_HEX
, VALS(lowpan_iphc_hop_limit
), LOWPAN_IPHC_FLAG_HLIM
, NULL
, HFILL
}},
2541 { &hf_6lowpan_iphc_flag_cid
,
2542 { "Context identifier extension", "6lowpan.iphc.cid",
2543 FT_BOOLEAN
, 16, NULL
, LOWPAN_IPHC_FLAG_CONTEXT_ID
, NULL
, HFILL
}},
2544 { &hf_6lowpan_iphc_flag_sac
,
2545 { "Source address compression", "6lowpan.iphc.sac",
2546 FT_BOOLEAN
, 16, TFS(&lowpan_iphc_addr_compression
), LOWPAN_IPHC_FLAG_SRC_COMP
, NULL
, HFILL
}},
2547 { &hf_6lowpan_iphc_flag_sam
,
2548 { "Source address mode", "6lowpan.iphc.sam",
2549 FT_UINT16
, BASE_HEX
, VALS(lowpan_iphc_addr_modes
), LOWPAN_IPHC_FLAG_SRC_MODE
, NULL
, HFILL
}},
2550 { &hf_6lowpan_iphc_flag_mcast
,
2551 { "Multicast address compression", "6lowpan.iphc.m",
2552 FT_BOOLEAN
, 16, NULL
, LOWPAN_IPHC_FLAG_MCAST_COMP
, NULL
, HFILL
}},
2553 { &hf_6lowpan_iphc_flag_dac
,
2554 { "Destination address compression","6lowpan.iphc.dac",
2555 FT_BOOLEAN
, 16, TFS(&lowpan_iphc_addr_compression
), LOWPAN_IPHC_FLAG_DST_COMP
, NULL
, HFILL
}},
2556 { &hf_6lowpan_iphc_flag_dam
,
2557 { "Destination address mode", "6lowpan.iphc.dam",
2558 FT_UINT16
, BASE_HEX
, VALS(lowpan_iphc_addr_modes
), LOWPAN_IPHC_FLAG_DST_MODE
, NULL
, HFILL
}},
2559 { &hf_6lowpan_iphc_sci
,
2560 { "Source context identifier", "6lowpan.iphc.sci",
2561 FT_UINT8
, BASE_HEX
, NULL
, LOWPAN_IPHC_FLAG_SCI
, NULL
, HFILL
}},
2562 { &hf_6lowpan_iphc_dci
,
2563 { "Destination context identifier", "6lowpan.iphc.dci",
2564 FT_UINT8
, BASE_HEX
, NULL
, LOWPAN_IPHC_FLAG_DCI
, NULL
, HFILL
}},
2566 /* Context information fields. */
2567 { &hf_6lowpan_iphc_sctx_prefix
,
2568 { "Source context", "6lowpan.iphc.sctx.prefix", FT_IPv6
, BASE_NONE
, NULL
, 0x0,
2570 { &hf_6lowpan_iphc_sctx_origin
,
2571 { "Origin", "6lowpan.iphc.sctx.origin", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
2573 { &hf_6lowpan_iphc_dctx_prefix
,
2574 { "Destination context", "6lowpan.iphc.dctx.prefix", FT_IPv6
, BASE_NONE
, NULL
, 0x0,
2576 { &hf_6lowpan_iphc_dctx_origin
,
2577 { "Origin", "6lowpan.iphc.dctx.origin", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
2580 /* NHC IPv6 extension header fields. */
2581 { &hf_6lowpan_nhc_ext_eid
,
2582 { "Header ID", "6lowpan.nhc.ext.eid",
2583 FT_UINT8
, BASE_HEX
, VALS(lowpan_nhc_eid
), LOWPAN_NHC_EXT_EID
, NULL
, HFILL
}},
2584 { &hf_6lowpan_nhc_ext_nh
,
2585 { "Next header", "6lowpan.nhc.ext.nh",
2586 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_NHC_EXT_NHDR
, NULL
, HFILL
}},
2587 { &hf_6lowpan_nhc_ext_next
,
2588 { "Next header", "6lowpan.nhc.ext.next",
2589 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2590 { &hf_6lowpan_nhc_ext_length
,
2591 { "Header length", "6lowpan.nhc.ext.length",
2592 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2594 /* NHC UDP header fields. */
2595 { &hf_6lowpan_nhc_udp_checksum
,
2596 { "Checksum", "6lowpan.nhc.udp.checksum",
2597 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_NHC_UDP_CHECKSUM
, NULL
, HFILL
}},
2598 { &hf_6lowpan_nhc_udp_src
,
2599 { "Source port", "6lowpan.nhc.udp.src",
2600 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_NHC_UDP_SRCPORT
, NULL
, HFILL
}},
2601 { &hf_6lowpan_nhc_udp_dst
,
2602 { "Destination port", "6lowpan.nhc.udp.dst",
2603 FT_BOOLEAN
, 8, TFS(&lowpan_compression
), LOWPAN_NHC_UDP_DSTPORT
, NULL
, HFILL
}},
2605 /* Uncompressed IPv6 fields. */
2606 { &hf_6lowpan_traffic_class
,
2607 { "Traffic class", "6lowpan.class",
2608 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2609 { &hf_6lowpan_flow_label
,
2610 { "Flow label", "6lowpan.flow",
2611 FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2613 { "ECN", "6lowpan.ecn",
2614 FT_UINT8
, BASE_HEX
, NULL
, LOWPAN_IPHC_TRAFFIC_ECN
, NULL
, HFILL
}},
2616 { "DSCP", "6lowpan.dscp",
2617 FT_UINT8
, BASE_HEX
, NULL
, LOWPAN_IPHC_TRAFFIC_DSCP
, NULL
, HFILL
}},
2618 { &hf_6lowpan_next_header
,
2619 { "Next header", "6lowpan.next",
2620 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2621 { &hf_6lowpan_hop_limit
,
2622 { "Hop limit", "6lowpan.hops",
2623 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2624 { &hf_6lowpan_source
,
2625 { "Source", "6lowpan.src",
2626 FT_IPv6
, BASE_NONE
, NULL
, 0x0, "Source IPv6 address", HFILL
}},
2628 { "Destination", "6lowpan.dst",
2629 FT_IPv6
, BASE_NONE
, NULL
, 0x0, "Destination IPv6 address", HFILL
}},
2631 /* Uncompressed UDP fields. */
2632 { &hf_6lowpan_udp_src
,
2633 { "Source port", "6lowpan.udp.src",
2634 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2635 { &hf_6lowpan_udp_dst
,
2636 { "Destination port", "6lowpan.udp.dst",
2637 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2638 { &hf_6lowpan_udp_len
,
2639 { "UDP length", "6lowpan.udp.length",
2640 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2641 { &hf_6lowpan_udp_checksum
,
2642 { "UDP checksum", "6lowpan.udp.checksum",
2643 FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2645 /* Broadcast header fields. */
2646 { &hf_6lowpan_bcast_seqnum
,
2647 { "Sequence number", "6lowpan.bcast.seqnum",
2648 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2650 /* Mesh header fields. */
2651 { &hf_6lowpan_mesh_v
,
2652 { "V", "6lowpan.mesh.v",
2653 FT_BOOLEAN
, 8, NULL
, LOWPAN_MESH_HEADER_V
, "short originator address present", HFILL
}},
2654 { &hf_6lowpan_mesh_f
,
2655 { "D", "6lowpan.mesh.f",
2656 FT_BOOLEAN
, 8, NULL
, LOWPAN_MESH_HEADER_F
, "short destination address present", HFILL
}},
2657 { &hf_6lowpan_mesh_hops
,
2658 { "Hops left", "6lowpan.mesh.hops",
2659 FT_UINT8
, BASE_DEC
, NULL
, LOWPAN_MESH_HEADER_HOPS
, NULL
, HFILL
}},
2660 { &hf_6lowpan_mesh_hops8
,
2661 { "Deep Hops left (Flags.Hops left == 15)", "6lowpan.mesh.hops8",
2662 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2663 { &hf_6lowpan_mesh_orig16
,
2664 { "Originator", "6lowpan.mesh.orig16",
2665 FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2666 { &hf_6lowpan_mesh_orig64
,
2667 { "Originator", "6lowpan.mesh.orig64",
2668 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2669 { &hf_6lowpan_mesh_dest16
,
2670 { "Destination", "6lowpan.mesh.dest16",
2671 FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2672 { &hf_6lowpan_mesh_dest64
,
2673 { "Destination", "6lowpan.mesh.dest64",
2674 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2676 /* Fragmentation header fields. */
2677 { &hf_6lowpan_frag_dgram_size
,
2678 { "Datagram size", "6lowpan.frag.size",
2679 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2680 { &hf_6lowpan_frag_dgram_tag
,
2681 { "Datagram tag", "6lowpan.frag.tag",
2682 FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2683 { &hf_6lowpan_frag_dgram_offset
,
2684 { "Datagram offset", "6lowpan.frag.offset",
2685 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2687 /* Reassembly fields. */
2688 { &hf_6lowpan_fragments
,
2689 { "Message fragments", "6lowpan.fragments",
2690 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
2691 { &hf_6lowpan_fragment
,
2692 { "Message fragment", "6lowpan.fragment",
2693 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
2694 { &hf_6lowpan_fragment_overlap
,
2695 { "Message fragment overlap", "6lowpan.fragment.overlap",
2696 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
2697 { &hf_6lowpan_fragment_overlap_conflicts
,
2698 { "Message fragment overlapping with conflicting data", "6lowpan.fragment.overlap.conflicts",
2699 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
2700 { &hf_6lowpan_fragment_multiple_tails
,
2701 { "Message has multiple tail fragments", "6lowpan.fragment.multiple_tails",
2702 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
2703 { &hf_6lowpan_fragment_too_long_fragment
,
2704 { "Message fragment too long", "6lowpan.fragment.too_long_fragment",
2705 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
2706 { &hf_6lowpan_fragment_error
,
2707 { "Message defragmentation error", "6lowpan.fragment.error",
2708 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
2709 { &hf_6lowpan_fragment_count
,
2710 { "Message fragment count", "6lowpan.fragment.count",
2711 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
2712 { &hf_6lowpan_reassembled_in
,
2713 { "Reassembled in", "6lowpan.reassembled.in",
2714 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
2715 { &hf_6lowpan_reassembled_length
,
2716 { "Reassembled 6LoWPAN length", "6lowpan.reassembled.length",
2717 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}}
2720 static gint
*ett
[] = {
2723 &ett_6lowpan_hc2_udp
,
2725 &ett_6lowpan_nhc_ext
,
2726 &ett_6lowpan_nhc_udp
,
2729 &ett_6lowpan_mesh_flags
,
2731 &ett_6lopwan_traffic_class
,
2732 /* Reassembly subtrees. */
2733 &ett_6lowpan_fragment
,
2734 &ett_6lowpan_fragments
2737 static ei_register_info ei
[] = {
2738 { &ei_6lowpan_hc1_more_bits
, { "6lowpan.hc1_more_bits", PI_MALFORMED
, PI_ERROR
, "HC1 more bits expected for illegal next header type.", EXPFILL
}},
2739 { &ei_6lowpan_illegal_dest_addr_mode
, { "6lowpan.illegal_dest_addr_mode", PI_MALFORMED
, PI_ERROR
, "Illegal destination address mode", EXPFILL
}},
2740 { &ei_6lowpan_bad_ipv6_header_length
, { "6lowpan.bad_ipv6_header_length", PI_MALFORMED
, PI_ERROR
, "Length is less than IPv6 header length", EXPFILL
}},
2744 module_t
*prefs_module
;
2745 expert_module_t
* expert_6lowpan
;
2747 proto_6lowpan
= proto_register_protocol("IPv6 over IEEE 802.15.4", "6LoWPAN", "6lowpan");
2748 proto_register_field_array(proto_6lowpan
, hf
, array_length(hf
));
2749 proto_register_subtree_array(ett
, array_length(ett
));
2750 expert_6lowpan
= expert_register_protocol(proto_6lowpan
);
2751 expert_register_field_array(expert_6lowpan
, ei
, array_length(ei
));
2753 /* Register the dissector with wireshark. */
2754 register_dissector("6lowpan", dissect_6lowpan
, proto_6lowpan
);
2756 /* Register the dissector init function */
2757 register_init_routine(proto_init_6lowpan
);
2759 /* Initialize the context preferences. */
2760 memset((gchar
*)lowpan_context_prefs
, 0, sizeof(lowpan_context_prefs
));
2762 /* Register preferences. */
2763 prefs_module
= prefs_register_protocol(proto_6lowpan
, prefs_6lowpan_apply
);
2764 for (i
= 0; i
< LOWPAN_CONTEXT_MAX
; i
++) {
2765 char *pref_name
, *pref_title
;
2768 * Inspired by the IEEE 802.11 dissector - the preferences are expecting
2769 * that each pref has a unique string passed in, and will crash if we
2770 * try to reuse any for multiple preferences.
2772 pref_name
= wmem_strdup_printf(wmem_epan_scope(), "context%d", i
);
2773 pref_title
= wmem_strdup_printf(wmem_epan_scope(), "Context %d", i
);
2774 prefs_register_string_preference(prefs_module
, pref_name
, pref_title
,
2775 "IPv6 prefix to use for stateful address decompression.",
2776 &lowpan_context_prefs
[i
]);
2778 } /* proto_register_6lowpan */
2780 /*FUNCTION:------------------------------------------------------
2782 * proto_init_6lowpan
2784 * 6LoWPAN initialization function.
2789 *---------------------------------------------------------------
2792 proto_init_6lowpan(void)
2794 /* Initialize the fragment reassembly table. */
2795 reassembly_table_init(&lowpan_reassembly_table
,
2796 &addresses_reassembly_table_functions
);
2798 /* Initialize the context table. */
2799 if (lowpan_context_table
)
2800 g_hash_table_destroy(lowpan_context_table
);
2801 lowpan_context_table
= g_hash_table_new(lowpan_context_hash
, lowpan_context_equal
);
2804 /* Initialize the link-local context. */
2805 lowpan_context_local
.frame
= 0;
2806 lowpan_context_local
.plen
= LOWPAN_CONTEXT_LINK_LOCAL_BITS
;
2807 memcpy(&lowpan_context_local
.prefix
, lowpan_llprefix
, sizeof(lowpan_llprefix
));
2809 /* Reload static contexts from our preferences. */
2810 prefs_6lowpan_apply();
2811 } /* proto_init_6lowpan */
2813 /*FUNCTION:------------------------------------------------------
2815 * prefs_6lowpan_apply
2817 * Prefs "apply" callback. Parses the context table for
2818 * IPv6 addresses/prefixes.
2823 *---------------------------------------------------------------
2826 prefs_6lowpan_apply(void)
2829 struct e_in6_addr prefix
;
2831 for (i
= 0; i
< LOWPAN_CONTEXT_MAX
; i
++) {
2832 if (!lowpan_context_prefs
[i
]) continue;
2833 if (inet_pton(AF_INET6
, lowpan_context_prefs
[i
], &prefix
) <= 0) continue;
2834 /* Set the prefix */
2835 lowpan_context_insert(i
, IEEE802154_BCAST_PAN
, 64, &prefix
, 0);
2837 } /* prefs_6lowpan_apply */
2839 /*FUNCTION:------------------------------------------------------
2841 * proto_reg_handoff_6lowpan
2843 * Protocol handoff routine for 6LoWPAN. Called after all
2844 * protocols have been loaded.
2849 *---------------------------------------------------------------
2852 proto_reg_handoff_6lowpan(void)
2854 data_handle
= find_dissector("data");
2855 ipv6_handle
= find_dissector("ipv6");
2857 /* Register the 6LoWPAN dissector with IEEE 802.15.4 */
2858 heur_dissector_add("wpan", dissect_6lowpan_heur
, proto_6lowpan
);
2859 } /* proto_reg_handoff_6lowpan */