HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-6lowpan.c
blob559cf6724437a10d068bee7a25d0875c3a078ec2
1 /* packet-6lowpan.c
2 * Routines for 6LoWPAN packet disassembly
3 * By Owen Kirby <osk@exegin.com>
4 * Copyright 2009 Owen Kirby
6 * $Id$
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.
26 #include "config.h"
28 /* Need to get headers for AF_INET6 and inet_pton() */
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
31 #endif
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
34 #endif
35 #ifdef HAVE_NETINET_IN_H
36 # include <netinet/in.h>
37 #endif
38 #ifdef HAVE_ARPA_INET_H
39 #include <arpa/inet.h>
40 #endif
41 #ifdef HAVE_WINSOCK2_H
42 #include <winsock2.h>
43 #endif
44 #ifdef NEED_INET_V6DEFS_H
45 # include "wsutil/inet_v6defs.h"
46 #endif
48 #include <glib.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
110 /* HC_UDP Header */
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
170 /* NHC Patterns. */
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;
313 /* Value Strings */
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" },
324 { 0, NULL }
326 static const true_false_string lowpan_compression = {
327 "Compressed",
328 "Inline"
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" },
335 { 0, NULL }
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" },
342 { 0, NULL }
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" },
349 { 0, NULL }
351 static const true_false_string lowpan_iphc_addr_compression = {
352 "Stateful",
353 "Stateless"
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" },
360 { 0, NULL }
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" },
366 { 0, NULL }
368 static const value_string lowpan_nhc_patterns [] = {
369 { LOWPAN_NHC_PATTERN_EXT, "IPv6 extension header" },
370 { LOWPAN_NHC_PATTERN_UDP, "UDP compression header" },
371 { 0, NULL }
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" },
380 { 0, NULL }
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 */
414 NULL,
415 /* Tag */
416 "6LoWPAN fragments"
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. */
428 typedef struct {
429 guint16 pan; /* PAN Identifier */
430 guint8 cid; /* Context Identifier */
431 } lowpan_context_key;
433 /* Context hash table map data. */
434 typedef struct {
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. */
453 struct udp_hdr {
454 guint16 src_port;
455 guint16 dst_port;
456 guint16 length;
457 guint16 checksum;
460 /* Structure used to store decompressed header chains until reassembly. */
461 struct lowpan_nhdr {
462 /* List Linking */
463 struct lowpan_nhdr *next;
464 /* Next Header */
465 guint8 proto;
466 guint length;
467 guint reported;
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:------------------------------------------------------
499 * NAME
500 * lowpan_pfxcpy
501 * DESCRIPTION
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
505 * copied.
506 * PARAMETERS
507 * dst ; Destination.
508 * src ; Source.
509 * bits ; Number of bits to copy.
510 * RETURNS
511 * void ;
512 *---------------------------------------------------------------
514 static void
515 lowpan_pfxcpy(void *dst, const void *src, size_t bits)
517 memcpy(dst, src, bits>>3);
518 if (bits & 0x7) {
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:------------------------------------------------------
527 * NAME
528 * lowpan_context_hash
529 * DESCRIPTION
530 * Context table hash function.
531 * PARAMETERS
532 * key ; Pointer to a lowpan_context_key type.
533 * RETURNS
534 * guint ; The hashed key value.
535 *---------------------------------------------------------------
537 static guint
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:------------------------------------------------------
544 * NAME
545 * lowpan_context_equal
546 * DESCRIPTION
547 * Context table equals function.
548 * PARAMETERS
549 * key ; Pointer to a lowpan_context_key type.
550 * RETURNS
551 * gboolean ;
552 *---------------------------------------------------------------
554 static gboolean
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:------------------------------------------------------
562 * NAME
563 * lowpan_context_find
564 * DESCRIPTION
565 * Context table lookup function.
566 * PARAMETERS
567 * cid ; Context identifier.
568 * pan ; PAN identifier.
569 * RETURNS
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. */
583 key.pan = pan;
584 key.cid = cid;
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:------------------------------------------------------
600 * NAME
601 * lowpan_context_insert
602 * DESCRIPTION
603 * Context table insert function.
604 * PARAMETERS
605 * cid ; Context identifier.
606 * pan ; PAN identifier.
607 * plen ; Prefix length.
608 * prefix ; Compression prefix.
609 * frame ; Frame number.
610 * RETURNS
611 * void ;
612 *---------------------------------------------------------------
614 void
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;
619 gpointer pkey;
620 gpointer pdata;
622 /* Sanity! */
623 if (plen > 128) return;
624 if (!prefix) return;
626 /* Search the context table for an existing entry. */
627 key.pan = pan;
628 key.cid = cid;
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. */
634 return;
637 else {
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);
643 data->frame = frame;
644 data->plen = plen;
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:------------------------------------------------------
651 * NAME
652 * lowpan_addr16_to_ifcid
653 * DESCRIPTION
654 * Converts a short address to in interface identifier as
655 * per rfc 4944 section 6.
656 * PARAMETERS
657 * addr ; 16-bit short address.
658 * ifcid ; interface identifier (output).
659 * RETURNS
660 * void ;
661 *---------------------------------------------------------------
663 static void
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. */
668 ifcid[1] = 0x00;
669 ifcid[2] = 0x00;
670 ifcid[3] = 0xff;
671 ifcid[4] = 0xfe;
672 ifcid[5] = 0x00;
673 ifcid[6] = (addr >> 8) & 0xff;
674 ifcid[7] = (addr >> 0) & 0xff;
675 } /* lowpan_addr16_to_ifcid */
677 /*FUNCTION:------------------------------------------------------
678 * NAME
679 * lowpan_dlsrc_to_ifcid
680 * DESCRIPTION
681 * Finds an interface identifier from the data-link source
682 * addressing.
683 * PARAMETERS
684 * pinfo ; packet information.
685 * ifcid ; interface identifier (output).
686 * RETURNS
687 * gboolean ; TRUE if an interface identifier could
688 * be found.
689 *---------------------------------------------------------------
691 static gboolean
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. */
700 ifcid[0] ^= 0x02;
701 return TRUE;
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);
707 if (hints) {
708 lowpan_addr16_to_ifcid(hints->src16, ifcid);
709 return TRUE;
710 } else {
711 /* Failed to find a link-layer source address. */
712 return FALSE;
714 } /* lowpan_dlsrc_to_ifcid */
716 /*FUNCTION:------------------------------------------------------
717 * NAME
718 * lowpan_dldst_to_ifcid
719 * DESCRIPTION
720 * Finds an interface identifier from the data-link destination
721 * addressing.
722 * PARAMETERS
723 * pinfo ; packet information.
724 * ifcid ; interface identifier (output).
725 * RETURNS
726 * gboolean ; TRUE if an interface identifier could
727 * be found.
728 *---------------------------------------------------------------
730 static gboolean
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. */
739 ifcid[0] ^= 0x02;
740 return TRUE;
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);
746 if (hints) {
747 lowpan_addr16_to_ifcid(hints->dst16, ifcid);
748 return TRUE;
749 } else {
750 /* Failed to find a link-layer destination address. */
751 return FALSE;
753 } /* lowpan_dldst_to_ifcid */
755 /*FUNCTION:------------------------------------------------------
756 * NAME
757 * lowpan_reassemble_ipv6
758 * DESCRIPTION
759 * Helper function to rebuild an IPv6 packet from the IPv6
760 * header structure, and a list of next header structures.
761 * PARAMETERS
762 * ipv6 ; IPv6 Header.
763 * nhdr_list ; Next header list.
764 * RETURNS
765 * tvbuff_t * ; Reassembled IPv6 packet.
766 *---------------------------------------------------------------
768 static tvbuff_t *
769 lowpan_reassemble_ipv6(tvbuff_t *tvb, struct ip6_hdr *ipv6, struct lowpan_nhdr *nhdr_list)
771 gint length = 0;
772 gint reported = 0;
773 guint8 * buffer;
774 guint8 * cursor;
775 struct lowpan_nhdr *nhdr;
776 tvbuff_t *ret;
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);
799 return ret;
800 } /* lowpan_reassemble_ipv6 */
802 /*FUNCTION:------------------------------------------------------
803 * NAME
804 * lowpan_parse_nhc_proto
805 * DESCRIPTION
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.
809 * PARAMETERS
810 * tvb ; packet buffer.
811 * offset ; offset of the NHC.
812 * RETURNS
813 * guint8 ; IP_PROTO_* of the next header's protocol.
814 *---------------------------------------------------------------
816 static guint8
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;
825 switch (eid) {
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;
838 default:
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) {
845 return IP_PROTO_UDP;
847 /* Unknown header type. */
848 return IP_PROTO_NONE;
849 } /* lowpan_parse_nhc_proto */
851 /*FUNCTION:------------------------------------------------------
852 * NAME
853 * dissect_6lowpan_heur
854 * DESCRIPTION
855 * Heuristic dissector for 6LoWPAN. Checks if the pattern is
856 * a valid 6LoWPAN type, and not NALP.
857 * PARAMETERS
858 * tvb ; packet buffer.
859 * pinfo ; packet info.
860 * tree ; protocol display tree.
861 * RETURNS
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 *---------------------------------------------------------------
867 static gboolean
868 dissect_6lowpan_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
870 /* Check for valid patterns. */
871 do {
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. */
882 return FALSE;
883 } while(0);
885 /* If we get here, then we found a matching pattern. */
886 dissect_6lowpan(tvb, pinfo, tree);
887 return TRUE;
888 } /* dissect_6lowpan_heur */
890 /*FUNCTION:------------------------------------------------------
891 * NAME
892 * dissect_6lowpan
893 * DESCRIPTION
894 * Dissector routine for 6LoWPAN packets.
895 * PARAMETERS
896 * tvb ; packet buffer.
897 * pinfo ; packet info.
898 * tree ; protocol display tree.
899 * RETURNS
900 * void ;
901 *---------------------------------------------------------------
903 static void
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. */
918 if (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);
928 if (!next) return;
930 if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_BC0_BITS) == LOWPAN_PATTERN_BC0) {
931 next = dissect_6lowpan_bc0(next, pinfo, lowpan_tree);
932 if (!next) return;
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 */
955 else {
956 dissect_6lowpan_unknown(next, pinfo, lowpan_tree);
957 return;
960 /* The last step should have returned an uncompressed IPv6 datagram. */
961 if (next) {
962 call_dissector(ipv6_handle, next, pinfo, tree);
964 } /* dissect_6lowpan */
966 /*FUNCTION:------------------------------------------------------
967 * NAME
968 * dissect_6lowpan_ipv6
969 * DESCRIPTION
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
974 * thereof).
975 * PARAMETERS
976 * tvb ; packet buffer.
977 * pinfo ; packet info.
978 * tree ; 6LoWPAN display tree.
979 * offset ; offset to the start of the header.
980 * RETURNS
981 * tvbuff_t * ; The remaining payload to be parsed.
982 *---------------------------------------------------------------
984 static tvbuff_t *
985 dissect_6lowpan_ipv6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
987 /* Get and display the pattern. */
988 if (tree) {
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:------------------------------------------------------
997 * NAME
998 * dissect_6lowpan_hc1
999 * DESCRIPTION
1000 * Dissector routine for a 6LoWPAN HC1 header.
1001 * PARAMETERS
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.
1008 * RETURNS
1009 * tvbuff_t * ; The remaining payload to be parsed.
1010 *---------------------------------------------------------------
1012 static tvbuff_t *
1013 dissect_6lowpan_hc1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint dgram_size, guint8 *siid, guint8 *diid)
1015 gint offset = 0;
1016 gint bit_offset;
1017 int i;
1018 guint8 hc1_encoding;
1019 guint8 hc_udp_encoding = 0;
1020 guint8 next_header;
1021 proto_tree * hc_tree = NULL;
1022 proto_item * ti;
1023 tvbuff_t * ipv6_tvb;
1024 /* IPv6 header. */
1025 guint8 ipv6_class;
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. */
1034 if (tree) {
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);
1046 if (tree) {
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);
1061 if (tree) {
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);
1070 else {
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);
1073 return NULL;
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
1088 * offset.
1090 bit_offset = offset << 3;
1092 /* Parse hop limit */
1093 ipv6.ip6_hops = tvb_get_bits8(tvb, bit_offset, LOWPAN_IPV6_HOP_LIMIT_BITS);
1094 if (tree) {
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);
1110 else {
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);
1118 else {
1119 memcpy(&ipv6.ip6_src.bytes[sizeof(ipv6.ip6_src) - LOWPAN_IFC_ID_LEN], siid, LOWPAN_IFC_ID_LEN);
1121 /* Display the source address. */
1122 if (tree) {
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);
1142 else {
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);
1150 else {
1151 memcpy(&ipv6.ip6_dst.bytes[sizeof(ipv6.ip6_dst) - LOWPAN_IFC_ID_LEN], diid, LOWPAN_IFC_ID_LEN);
1153 /* Display the destination address. */
1154 if (tree) {
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. */
1165 ipv6_class = 0;
1166 ipv6.ip6_flow = 0;
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);
1170 if (tree) {
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);
1178 if (tree) {
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;
1197 else {
1198 /* Parse the next header field. */
1199 ipv6.ip6_nxt = tvb_get_bits8(tvb, bit_offset, LOWPAN_IPV6_NEXT_HEADER_BITS);
1200 if (tree) {
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)) {
1213 struct udp_hdr udp;
1214 gint length;
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;
1222 else {
1223 udp.src_port = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_PORT_BITS, ENC_BIG_ENDIAN);
1224 bit_offset += LOWPAN_UDP_PORT_BITS;
1226 if (tree) {
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;
1238 else {
1239 udp.dst_port = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_PORT_BITS, ENC_BIG_ENDIAN);
1240 bit_offset += LOWPAN_UDP_PORT_BITS;
1242 if (tree) {
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);
1251 if (tree) {
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 */
1262 return NULL;
1264 udp.length = dgram_size - (gint)sizeof(struct ip6_hdr);
1266 /* Compute the length from the tvbuff size. */
1267 else {
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);
1276 if (tree) {
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 *=====================================================
1300 else {
1301 gint length;
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);
1311 else {
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");
1323 return ipv6_tvb;
1324 } /* dissect_6lowpan_hc1 */
1326 /*FUNCTION:------------------------------------------------------
1327 * NAME
1328 * dissect_6lowpan_iphc
1329 * DESCRIPTION
1330 * Dissector routine for a 6LoWPAN IPHC header.
1332 * This header is still in the draft phase, but is expected
1333 * to replace HC1.
1335 * See draft-ietf-6lowpan-hc-15.txt
1336 * PARAMETERS
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.
1343 * RETURNS
1344 * tvbuff_t * ; The remaining payload to be parsed.
1345 *---------------------------------------------------------------
1347 static tvbuff_t *
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;
1351 guint16 hint_panid;
1352 gint offset = 0;
1353 gint length = 0;
1354 proto_tree * iphc_tree = NULL;
1355 proto_item * ti = NULL;
1356 proto_item * ti_dam = NULL;
1357 /* IPHC header fields. */
1358 guint16 iphc_flags;
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;
1369 /* IPv6 header */
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. */
1382 if (tree) {
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;
1399 if (tree) {
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;
1421 if (tree) {
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 *=====================================================
1446 offset <<= 3;
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);
1474 if (tree) {
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. */
1486 offset >>= 3;
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);
1495 if (tree) {
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) {
1504 ipv6.ip6_hlim = 1;
1506 else if (iphc_hop_limit == LOWPAN_IPHC_HLIM_64) {
1507 ipv6.ip6_hlim = 64;
1509 else if (iphc_hop_limit == LOWPAN_IPHC_HLIM_255) {
1510 ipv6.ip6_hlim = 255;
1512 else {
1513 ipv6.ip6_hlim = tvb_get_guint8(tvb, offset);
1514 if (tree) {
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 *=====================================================
1524 length = 0;
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. */
1560 if (tree) {
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);
1573 offset += length;
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 *=====================================================
1584 length = 0;
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++));
1613 else {
1614 /* Illegal destination address compression mode. */
1615 expert_add_info(pinfo, ti_dam, &ei_6lowpan_illegal_dest_addr_mode);
1616 return NULL;
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
1624 * XX = inline byte.
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++));
1638 else {
1639 /* Illegal destination address compression mode. */
1640 expert_add_info(pinfo, ti_dam, &ei_6lowpan_illegal_dest_addr_mode);
1641 return NULL;
1645 /*=====================================================
1646 * Parse and decompress a unicast destination address.
1647 *=====================================================
1649 else {
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);
1654 return NULL;
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. */
1686 if (tree) {
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);
1699 offset += length;
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. */
1719 else {
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);
1728 else {
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");
1744 return ipv6_tvb;
1745 } /* dissect_6lowpan_iphc */
1747 /*FUNCTION:------------------------------------------------------
1748 * NAME
1749 * dissect_6lowpan_iphc_nhc
1750 * DESCRIPTION
1751 * Dissector routine for a 6LoWPAN IPHC next header structure(s).
1752 * PARAMETERS
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.
1760 * RETURNS
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)
1767 gint length;
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) {
1777 guint8 ext_flags;
1778 tvbuff_t *iphc_tvb;
1780 /* Create a tree for the IPv6 extension header. */
1781 if (tree) {
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);
1790 if (tree) {
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));
1805 nhdr->next = NULL;
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);
1810 return nhdr;
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;
1818 guint8 ext_flags;
1819 guint8 ext_len;
1820 guint8 ext_proto;
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. */
1826 if (tree) {
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);
1835 if (tree) {
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);
1844 if (tree) {
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);
1854 if (tree) {
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);
1865 nhdr->next = NULL;
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. */
1891 return nhdr;
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);
1899 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);
1908 else {
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);
1918 else {
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);
1924 /* Done. */
1925 return nhdr;
1927 /*=====================================================
1928 * UDP Header
1929 *=====================================================
1931 if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_UDP_BITS) == LOWPAN_NHC_PATTERN_UDP) {
1932 struct udp_hdr udp;
1933 gint src_bitlen;
1934 gint dst_bitlen;
1935 guint8 udp_flags;
1937 /* Create a tree for the UDP header. */
1938 if (tree) {
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);
1947 if (tree) {
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);
1959 src_bitlen = 4;
1960 dst_bitlen = 4;
1961 break;
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);
1966 src_bitlen = 8;
1967 dst_bitlen = 16;
1968 break;
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);
1973 src_bitlen = 16;
1974 dst_bitlen = 8;
1975 break;
1977 default:
1978 udp.src_port = tvb_get_ntohs(tvb, offset);
1979 udp.dst_port = tvb_get_ntohs(tvb, offset+2);
1980 src_bitlen = 16;
1981 dst_bitlen = 16;
1982 break;
1983 } /* switch */
1984 if (tree) {
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);
1996 if (tree) {
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);
2002 else {
2003 udp.checksum = 0;
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));
2011 else {
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.
2023 #if 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
2027 * this time.
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)) {
2034 vec_t cksum_vec[3];
2035 struct {
2036 struct e_in6_addr src;
2037 struct e_in6_addr dst;
2038 guint32 length;
2039 guint8 zero[3];
2040 guint8 proto;
2041 } cksum_phdr;
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;
2060 #endif
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);
2065 nhdr->next = NULL;
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));
2073 return nhdr;
2075 /*=====================================================
2076 * Unknown Next Header Type
2077 *=====================================================
2079 return NULL;
2080 } /* dissect_6lowpan_iphc_nhc */
2082 /*FUNCTION:------------------------------------------------------
2083 * NAME
2084 * dissect_6lowpan_bc0
2085 * DESCRIPTION
2086 * Dissector routine for a 6LoWPAN broadcast header.
2087 * PARAMETERS
2088 * tvb ; packet buffer.
2089 * pinfo ; packet info.
2090 * tree ; 6LoWPAN display tree.
2091 * RETURNS
2092 * tvbuff_t * ; The remaining payload to be parsed.
2093 *---------------------------------------------------------------
2095 static tvbuff_t *
2096 dissect_6lowpan_bc0(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
2098 guint8 seqnum;
2099 proto_tree * bcast_tree;
2100 proto_item * ti;
2102 /* Create a tree for the broadcast header. */
2103 if (tree) {
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:------------------------------------------------------
2120 * NAME
2121 * dissect_6lowpan_mesh
2122 * DESCRIPTION
2123 * Dissector routine for a 6LoWPAN mesh header.
2124 * PARAMETERS
2125 * tvb ; packet buffer.
2126 * pinfo ; packet info.
2127 * tree ; 6LoWPAN display tree.
2128 * offset ; offset to the start of the header.
2129 * RETURNS
2130 * tvbuff_t * ; The remaining payload to be parsed.
2131 *---------------------------------------------------------------
2133 static tvbuff_t *
2134 dissect_6lowpan_mesh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2136 gint offset = 0;
2137 guint8 mesh_header;
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. */
2144 if (tree) {
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);
2151 if (tree) {
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)
2165 guint8 HopsLeft;
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);
2171 else
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);
2179 if (tree) {
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);
2185 else {
2186 guint16 addr16 = tvb_get_ntohs(tvb, offset);
2187 guint8 * ifcid;
2188 if (tree) {
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);
2193 src_ifcid = 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);
2202 if (tree) {
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);
2208 else {
2209 guint16 addr16 = tvb_get_ntohs(tvb, offset);
2210 guint8 * ifcid;
2211 if (tree) {
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);
2216 dst_ifcid = 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. */
2223 if (tree) {
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:------------------------------------------------------
2232 * NAME
2233 * dissect_6lowpan_frag_first
2234 * DESCRIPTION
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.
2240 * PARAMETERS
2241 * tvb ; packet buffer.
2242 * pinfo ; packet info.
2243 * tree ; 6LoWPAN display tree.
2244 * siid ; Source Interface ID.
2245 * diid ; Destination Interface ID.
2246 * RETURNS
2247 * tvbuff_t * ; reassembled IPv6 packet.
2248 *---------------------------------------------------------------
2250 static tvbuff_t *
2251 dissect_6lowpan_frag_first(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 *siid, guint8 *diid)
2253 gint offset = 0;
2254 gint frag_size;
2255 guint16 dgram_size;
2256 guint16 dgram_tag;
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. */
2267 if (tree) {
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);
2274 if (tree) {
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);
2282 if (tree) {
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. */
2288 if (tree) {
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 */
2314 else {
2315 dissect_6lowpan_unknown(frag_tvb, pinfo, tree);
2316 return NULL;
2319 /* Check call to dissect_6lowpan_xxx was successful */
2320 if (frag_tvb == NULL) {
2321 return 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,
2336 NULL, tree);
2338 pinfo->fragmented = save_fragmented;
2340 if (new_tvb) {
2341 /* Reassembly was successful; return the completed datagram. */
2342 return new_tvb;
2343 } else {
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));
2348 return NULL;
2350 } /* dissect_6lowpan_frag_first */
2352 /*FUNCTION:------------------------------------------------------
2353 * NAME
2354 * dissect_6lowpan_frag_middle
2355 * DESCRIPTION
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.
2361 * PARAMETERS
2362 * tvb ; packet buffer.
2363 * pinfo ; packet info.
2364 * tree ; 6LoWPAN display tree.
2365 * RETURNS
2366 * tvbuff_t * ; reassembled IPv6 packet.
2367 *---------------------------------------------------------------
2369 static tvbuff_t *
2370 dissect_6lowpan_frag_middle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2372 gint offset = 0;
2373 gint frag_size;
2374 guint16 dgram_size;
2375 guint16 dgram_tag;
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. */
2385 if (tree) {
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);
2392 if (tree) {
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);
2400 if (tree) {
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;
2407 if (tree) {
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);
2414 if (tree) {
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,
2428 NULL, tree);
2430 pinfo->fragmented = save_fragmented;
2432 /* If reassembly was successful, then return the completed datagram. */
2433 if (new_tvb) {
2434 return new_tvb;
2436 /* If reassembly failed, display the payload fragment using the data dissector. */
2437 else {
2438 new_tvb = tvb_new_subset_remaining(tvb, offset);
2439 call_dissector(data_handle, new_tvb, pinfo, proto_tree_get_root(tree));
2440 return NULL;
2442 } /* dissect_6lowpan_frag_middle */
2444 /*FUNCTION:------------------------------------------------------
2445 * NAME
2446 * dissect_6lowpan_unknown
2447 * DESCRIPTION
2448 * Dissector routine for 6LoWPAN packets after encountering
2449 * an unknown header.
2450 * PARAMETERS
2451 * tvb ; packet buffer.
2452 * pinfo ; packet info.
2453 * tree ; 6LoWPAN display tree.
2454 * RETURNS
2455 * void ;
2456 *---------------------------------------------------------------
2458 void
2459 dissect_6lowpan_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2461 tvbuff_t * data_tvb;
2463 /* Get and display the pattern. */
2464 if (tree) {
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:------------------------------------------------------
2474 * NAME
2475 * proto_register_6lowpan
2476 * DESCRIPTION
2477 * Protocol registration routine for 6LoWPAN. Called during
2478 * Wireshark initialization.
2479 * PARAMETERS
2480 * none ;
2481 * RETURNS
2482 * void ;
2483 *---------------------------------------------------------------
2485 void
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,
2569 NULL, HFILL }},
2570 { &hf_6lowpan_iphc_sctx_origin,
2571 { "Origin", "6lowpan.iphc.sctx.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2572 NULL, HFILL }},
2573 { &hf_6lowpan_iphc_dctx_prefix,
2574 { "Destination context", "6lowpan.iphc.dctx.prefix", FT_IPv6, BASE_NONE, NULL, 0x0,
2575 NULL, HFILL }},
2576 { &hf_6lowpan_iphc_dctx_origin,
2577 { "Origin", "6lowpan.iphc.dctx.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2578 NULL, HFILL }},
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 }},
2612 { &hf_6lowpan_ecn,
2613 { "ECN", "6lowpan.ecn",
2614 FT_UINT8, BASE_HEX, NULL, LOWPAN_IPHC_TRAFFIC_ECN, NULL, HFILL }},
2615 { &hf_6lowpan_dscp,
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 }},
2627 { &hf_6lowpan_dest,
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[] = {
2721 &ett_6lowpan,
2722 &ett_6lowpan_hc1,
2723 &ett_6lowpan_hc2_udp,
2724 &ett_6lowpan_iphc,
2725 &ett_6lowpan_nhc_ext,
2726 &ett_6lowpan_nhc_udp,
2727 &ett_6lowpan_bcast,
2728 &ett_6lowpan_mesh,
2729 &ett_6lowpan_mesh_flags,
2730 &ett_6lowpan_frag,
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 }},
2743 int i;
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:------------------------------------------------------
2781 * NAME
2782 * proto_init_6lowpan
2783 * DESCRIPTION
2784 * 6LoWPAN initialization function.
2785 * PARAMETERS
2786 * none ;
2787 * RETURNS
2788 * void ;
2789 *---------------------------------------------------------------
2791 static void
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:------------------------------------------------------
2814 * NAME
2815 * prefs_6lowpan_apply
2816 * DESCRIPTION
2817 * Prefs "apply" callback. Parses the context table for
2818 * IPv6 addresses/prefixes.
2819 * PARAMETERS
2820 * none ;
2821 * RETURNS
2822 * void ;
2823 *---------------------------------------------------------------
2825 void
2826 prefs_6lowpan_apply(void)
2828 int i;
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);
2836 } /* for */
2837 } /* prefs_6lowpan_apply */
2839 /*FUNCTION:------------------------------------------------------
2840 * NAME
2841 * proto_reg_handoff_6lowpan
2842 * DESCRIPTION
2843 * Protocol handoff routine for 6LoWPAN. Called after all
2844 * protocols have been loaded.
2845 * PARAMETERS
2846 * none ;
2847 * RETURNS
2848 * void ;
2849 *---------------------------------------------------------------
2851 void
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 */