Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-6lowpan.c
blob27c02ddc37f4e4f3ab0b868fce25028c9b6b6496
1 /* packet-6lowpan.c
3 * Add Selective Fragment Recovery per
4 * https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-02
5 * By James Ko <jck@exegin.com>
6 * Copyright 2019 Exegin Technologies Limited
8 * Routines for 6LoWPAN packet disassembly
9 * By Owen Kirby <osk@exegin.com>
10 * Copyright 2009 Owen Kirby
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include "config.h"
20 #include <epan/packet.h>
21 #include <epan/prefs.h>
22 #include <epan/expert.h>
23 #include <epan/reassemble.h>
24 #include <epan/ipproto.h>
25 #include <epan/addr_resolv.h>
26 #include <epan/proto_data.h>
27 #include <epan/etypes.h>
28 #include <epan/tfs.h>
29 #include <wsutil/array.h>
30 #include "packet-6lowpan.h"
31 #include "packet-btl2cap.h"
32 #include "packet-ipv6.h"
33 #include "packet-zbee.h"
35 void proto_register_6lowpan(void);
36 void proto_reg_handoff_6lowpan(void);
38 /* Definitions for 6lowpan packet disassembly structures and routines */
40 /* 6LoWPAN Patterns */
41 #define LOWPAN_PATTERN_NALP 0x00
42 #define LOWPAN_PATTERN_NALP_BITS 2
43 #define LOWPAN_PATTERN_IPV6 0x41
44 #define LOWPAN_PATTERN_IPV6_BITS 8
45 #define LOWPAN_PATTERN_HC1 0x42 /* Deprecated - replaced with IPHC. */
46 #define LOWPAN_PATTERN_HC1_BITS 8
47 #define LOWPAN_PATTERN_BC0 0x50
48 #define LOWPAN_PATTERN_BC0_BITS 8
49 #define LOWPAN_PATTERN_IPHC 0x03 /* See draft-ietf-6lowpan-hc-15.txt */
50 #define LOWPAN_PATTERN_IPHC_BITS 3
51 #define LOWPAN_PATTERN_ESC 0x7f
52 #define LOWPAN_PATTERN_ESC_BITS 8
53 #define LOWPAN_PATTERN_MESH 0x02
54 #define LOWPAN_PATTERN_MESH_BITS 2
55 #define LOWPAN_PATTERN_FRAG1 0x18
56 #define LOWPAN_PATTERN_FRAGN 0x1c
57 #define LOWPAN_PATTERN_FRAG_BITS 5
58 #define LOWPAN_PATTERN_RFRAG 0x74
59 #define LOWPAN_PATTERN_RFRAG_ACK 0x75
60 #define LOWPAN_PATTERN_RFRAG_BITS 7
62 #define LOWPAN_RFRAG_SEQUENCE_BITS 5
63 #define LOWPAN_RFRAG_FRAG_SZ_BITS 10
65 /* RFC8025 and RFC8138 */
66 #define LOWPAN_PATTERN_PAGING_DISPATCH 0xf
67 #define LOWPAN_PATTERN_PAGING_DISPATCH_BITS 4
68 #define LOWPAN_PATTERN_6LORHC 0x04
69 #define LOWPAN_PATTERN_6LORHE 0x05
70 #define LOWPAN_PATTERN_6LORHE_CLASS 0xe000
71 #define LOWPAN_PATTERN_6LORHE_CLASS_BITS 13
72 #define LOWPAN_PATTERN_6LORHE_LENGTH 0x1f00
73 #define LOWPAN_PATTERN_6LORHE_LENGTH_BITS 8
74 #define LOWPAN_PATTERN_6LORHE_TYPE 0x00ff
75 #define LOWPAN_PATTERN_6LORH_TYPE0 0x00
76 #define LOWPAN_PATTERN_6LORH_TYPE1 0x01
77 #define LOWPAN_PATTERN_6LORH_TYPE2 0x02
78 #define LOWPAN_PATTERN_6LORH_TYPE3 0x03
79 #define LOWPAN_PATTERN_6LORH_TYPE4 0x04
80 #define LOWPAN_PATTERN_6LORH_TYPE5 0x05
81 #define LOWPAN_PATTERN_6LORH_TYPE6 0x06
82 #define LOWPAN_PATTERN_6LORH_TYPE15 0x0F
83 #define LOWPAN_PATTERN_6LORH_TYPE16 0x10
84 #define LOWPAN_PATTERN_6LORH_TYPE17 0x11
85 #define LOWPAN_PATTERN_6LORH_TYPE18 0x12
86 #define LOWPAN_PATTERN_6LORH_TYPE19 0x13
87 #define LOWPAN_5_RPI_BIT_O 0x1000
88 #define LOWPAN_5_RPI_BIT_R 0x0800
89 #define LOWPAN_5_RPI_BIT_F 0x0400
90 #define LOWPAN_5_RPI_BIT_I 0x0200
91 #define LOWPAN_5_RPI_BIT_K 0x0100
92 #define LOWPAN_5_RPI_BITS_IK 0x0300
93 #define LOWPAN_6LORH_GENERAL_FORMAT 0x8000
94 #define LOWPAN_IP_IN_IP_6LORH 6
95 #define BITS_IK_0 0
96 #define BITS_IK_1 1
97 #define BITS_IK_2 2
98 #define BITS_IK_3 3
99 #define BITS_IK_4 4
100 #define IPV6_ADDR_COMPRESSED_1_BYTE 0
101 #define IPV6_ADDR_COMPRESSED_2_BYTE 1
102 #define IPV6_ADDR_COMPRESSED_4_BYTE 2
103 #define IPV6_ADDR_COMPRESSED_8_BYTE 3
104 #define IPV6_ADDR_COMPRESSED_16_BYTE 4
106 /* 6LoWPAN HC1 Header */
107 #define LOWPAN_HC1_SOURCE_PREFIX 0x80
108 #define LOWPAN_HC1_SOURCE_IFC 0x40
109 #define LOWPAN_HC1_DEST_PREFIX 0x20
110 #define LOWPAN_HC1_DEST_IFC 0x10
111 #define LOWPAN_HC1_TRAFFIC_CLASS 0x08
112 #define LOWPAN_HC1_NEXT 0x06
113 #define LOWPAN_HC1_MORE 0x01
115 /* IPv6 header field lengths (in bits) */
116 #define LOWPAN_IPV6_TRAFFIC_CLASS_BITS 8
117 #define LOWPAN_IPV6_FLOW_LABEL_BITS 20
118 #define LOWPAN_IPV6_NEXT_HEADER_BITS 8
119 #define LOWPAN_IPV6_HOP_LIMIT_BITS 8
120 #define LOWPAN_IPV6_PREFIX_BITS 64
121 #define LOWPAN_IPV6_INTERFACE_BITS 64
123 /* HC_UDP header field lengths (in bits). */
124 #define LOWPAN_UDP_PORT_BITS 16
125 #define LOWPAN_UDP_PORT_COMPRESSED_BITS 4
126 #define LOWPAN_UDP_LENGTH_BITS 16
127 #define LOWPAN_UDP_CHECKSUM_BITS 16
129 /* HC1 Next Header compression modes. */
130 #define LOWPAN_HC1_NEXT_NONE 0x00
131 #define LOWPAN_HC1_NEXT_UDP 0x01
132 #define LOWPAN_HC1_NEXT_ICMP 0x02
133 #define LOWPAN_HC1_NEXT_TCP 0x03
135 /* HC_UDP Header */
136 #define LOWPAN_HC2_UDP_SRCPORT 0x80
137 #define LOWPAN_HC2_UDP_DSTPORT 0x40
138 #define LOWPAN_HC2_UDP_LENGTH 0x20
139 #define LOWPAN_HC2_UDP_RESERVED 0x1f
141 /* IPHC Base flags */
142 #define LOWPAN_IPHC_FLAG_FLOW 0x1800
143 #define LOWPAN_IPHC_FLAG_NHDR 0x0400
144 #define LOWPAN_IPHC_FLAG_HLIM 0x0300
145 #define LOWPAN_IPHC_FLAG_CONTEXT_ID 0x0080
146 #define LOWPAN_IPHC_FLAG_SRC_COMP 0x0040
147 #define LOWPAN_IPHC_FLAG_SRC_MODE 0x0030
148 #define LOWPAN_IPHC_FLAG_MCAST_COMP 0x0008
149 #define LOWPAN_IPHC_FLAG_DST_COMP 0x0004
150 #define LOWPAN_IPHC_FLAG_DST_MODE 0x0003
151 #define LOWPAN_IPHC_FLAG_SCI 0xf0
152 #define LOWPAN_IPHC_FLAG_DCI 0x0f
153 /* Offsets for extracting integer fields. */
154 #define LOWPAN_IPHC_FLAG_OFFSET_FLOW 11
155 #define LOWPAN_IPHC_FLAG_OFFSET_HLIM 8
156 #define LOWPAN_IPHC_FLAG_OFFSET_SRC_MODE 4
157 #define LOWPAN_IPHC_FLAG_OFFSET_DST_MODE 0
158 #define LOWPAN_IPHC_FLAG_OFFSET_SCI 4
159 #define LOWPAN_IPHC_FLAG_OFFSET_DCI 0
161 /* IPHC Flow encoding values. */
162 #define LOWPAN_IPHC_FLOW_CLASS_LABEL 0x0
163 #define LOWPAN_IPHC_FLOW_ECN_LABEL 0x1
164 #define LOWPAN_IPHC_FLOW_CLASS 0x2
165 #define LOWPAN_IPHC_FLOW_COMPRESSED 0x3
167 /* IPHC Hop limit encoding. */
168 #define LOWPAN_IPHC_HLIM_INLINE 0x0
169 #define LOWPAN_IPHC_HLIM_1 0x1
170 #define LOWPAN_IPHC_HLIM_64 0x2
171 #define LOWPAN_IPHC_HLIM_255 0x3
173 /* IPHC address modes. */
174 #define LOWPAN_IPHC_ADDR_SRC_UNSPEC 0x0
175 #define LOWPAN_IPHC_ADDR_FULL_INLINE 0x0
176 #define LOWPAN_IPHC_ADDR_64BIT_INLINE 0x1
177 #define LOWPAN_IPHC_ADDR_16BIT_INLINE 0x2
178 #define LOWPAN_IPHC_ADDR_COMPRESSED 0x3
180 /* IPHC multicast address modes. */
181 #define LOWPAN_IPHC_MCAST_FULL 0x0
182 #define LOWPAN_IPHC_MCAST_48BIT 0x1
183 #define LOWPAN_IPHC_MCAST_32BIT 0x2
184 #define LOWPAN_IPHC_MCAST_8BIT 0x3
186 #define LOWPAN_IPHC_MCAST_STATEFUL_48BIT 0x0
188 /* IPHC Traffic class and flow label field sizes (in bits) */
189 #define LOWPAN_IPHC_ECN_BITS 2
190 #define LOWPAN_IPHC_DSCP_BITS 6
191 #define LOWPAN_IPHC_LABEL_BITS 20
193 /* NHC Patterns. */
194 #define LOWPAN_NHC_PATTERN_EXT 0x0e
195 #define LOWPAN_NHC_PATTERN_EXT_BITS 4
196 #define LOWPAN_NHC_PATTERN_UDP 0x1e
197 #define LOWPAN_NHC_PATTERN_UDP_BITS 5
198 /* IP-in-IP tunneling is handled as a separate NHC pattern. */
199 #define LOWPAN_NHC_PATTERN_EXT_IPV6 ((LOWPAN_NHC_PATTERN_EXT << LOWPAN_NHC_EXT_EID_BITS) | LOWPAN_NHC_EID_IPV6)
200 #define LOWPAN_NHC_PATTERN_EXT_IPV6_BITS (LOWPAN_NHC_PATTERN_EXT_BITS + LOWPAN_NHC_EXT_EID_BITS)
202 /* NHC Extension header fields. */
203 #define LOWPAN_NHC_EXT_EID 0x0e
204 #define LOWPAN_NHC_EXT_EID_OFFSET 1
205 #define LOWPAN_NHC_EXT_EID_BITS 3
206 #define LOWPAN_NHC_EXT_NHDR 0x01
208 /* Extension header ID codes. */
209 #define LOWPAN_NHC_EID_HOP_BY_HOP 0x00
210 #define LOWPAN_NHC_EID_ROUTING 0x01
211 #define LOWPAN_NHC_EID_FRAGMENT 0x02
212 #define LOWPAN_NHC_EID_DEST_OPTIONS 0x03
213 #define LOWPAN_NHC_EID_MOBILITY 0x04
214 #define LOWPAN_NHC_EID_IPV6 0x07
216 /* NHC UDP fields. */
217 #define LOWPAN_NHC_UDP_CHECKSUM 0x04
218 #define LOWPAN_NHC_UDP_PORTS 0x03
220 /* 6LoWPAN Mesh Header */
221 #define LOWPAN_MESH_HEADER_V 0x20
222 #define LOWPAN_MESH_HEADER_F 0x10
223 #define LOWPAN_MESH_HEADER_HOPS 0x0f
225 /* 6LoWPAN First Fragment Header */
226 #define LOWPAN_FRAG_DGRAM_SIZE_BITS 11
228 /* Uncompressed IPv6 Option types */
229 #define IP6OPT_PAD1 0x00
230 #define IP6OPT_PADN 0x01
232 /* UDP port compression encoding */
233 #define LOWPAN_NHC_UDP_PORT_INLINE 0x0
234 #define LOWPAN_NHC_UDP_PORT_8BIT_DST 0x1
235 #define LOWPAN_NHC_UDP_PORT_8BIT_SRC 0x2
236 #define LOWPAN_NHC_UDP_PORT_12BIT 0x3
238 /* Compressed port number offset. */
239 #define LOWPAN_PORT_8BIT_OFFSET 0xf000
240 #define LOWPAN_PORT_12BIT_OFFSET 0xf0b0
242 /* 6LoWPAN interface identifier length. */
243 #define LOWPAN_IFC_ID_LEN 8
245 /* Protocol fields handles. */
246 static int proto_6lowpan;
247 static int hf_6lowpan_pattern;
248 static int hf_6lowpan_nhc_pattern;
249 static int hf_6lowpan_padding;
251 /* Header compression fields. */
252 static int hf_6lowpan_hc1_encoding;
253 static int hf_6lowpan_hc1_source_prefix;
254 static int hf_6lowpan_hc1_source_ifc;
255 static int hf_6lowpan_hc1_dest_prefix;
256 static int hf_6lowpan_hc1_dest_ifc;
257 static int hf_6lowpan_hc1_class;
258 static int hf_6lowpan_hc1_next;
259 static int hf_6lowpan_hc1_more;
260 static int hf_6lowpan_hc2_udp_encoding;
261 static int hf_6lowpan_hc2_udp_src;
262 static int hf_6lowpan_hc2_udp_dst;
263 static int hf_6lowpan_hc2_udp_len;
265 /* 6loRH */
266 static int hf_6lowpan_pagenb;
267 static int hf_6lowpan_routing_header;
268 static int hf_6lowpan_6lorhe_length;
269 static int hf_6lowpan_6lorhe_size;
270 static int hf_6lowpan_6lorhc_size;
271 static int hf_6lowpan_6lorhe_type;
272 static int hf_6lowpan_6lorhe_hoplimit;
273 static int hf_6lowpan_6lorhe_bitmap;
274 static int hf_6lowpan_5_bit_o;
275 static int hf_6lowpan_5_bit_r;
276 static int hf_6lowpan_5_bit_f;
277 static int hf_6lowpan_5_bit_i;
278 static int hf_6lowpan_5_bit_k;
279 static int hf_6lowpan_sender_rank1;
280 static int hf_6lowpan_sender_rank2;
281 static int hf_6lowpan_rpl_instance;
282 static int hf_6lowpan_6lorhc_address_hop0;
283 static int hf_6lowpan_6lorhc_address_hop2;
284 static int hf_6lowpan_6lorhc_address_hop3;
285 static int hf_6lowpan_6lorhc_address_hop4;
286 static int hf_6lowpan_6lorhc_address_hop1;
287 static int hf_6lowpan_6lorhc_address_src;
289 /* IPHC header field. */
290 static int hf_6lowpan_iphc_flag_tf;
291 static int hf_6lowpan_iphc_flag_nhdr;
292 static int hf_6lowpan_iphc_flag_hlim;
293 static int hf_6lowpan_iphc_flag_cid;
294 static int hf_6lowpan_iphc_flag_sac;
295 static int hf_6lowpan_iphc_flag_sam;
296 static int hf_6lowpan_iphc_flag_mcast;
297 static int hf_6lowpan_iphc_flag_dac;
298 static int hf_6lowpan_iphc_flag_dam;
299 static int hf_6lowpan_iphc_sci;
300 static int hf_6lowpan_iphc_dci;
302 static int hf_6lowpan_iphc_sctx_prefix;
303 static int hf_6lowpan_iphc_sctx_origin;
304 static int hf_6lowpan_iphc_dctx_prefix;
305 static int hf_6lowpan_iphc_dctx_origin;
307 /* NHC IPv6 extension header fields. */
308 static int hf_6lowpan_nhc_ext_eid;
309 static int hf_6lowpan_nhc_ext_nh;
310 static int hf_6lowpan_nhc_ext_next;
311 static int hf_6lowpan_nhc_ext_length;
312 static int hf_6lowpan_nhc_ext_reserved;
314 /* NHC UDP compression header fields. */
315 static int hf_6lowpan_nhc_udp_checksum;
316 static int hf_6lowpan_nhc_udp_ports;
318 /* Inline IPv6 header fields. */
319 static int hf_6lowpan_traffic_class;
320 static int hf_6lowpan_flow_label;
321 static int hf_6lowpan_ecn;
322 static int hf_6lowpan_dscp;
323 static int hf_6lowpan_next_header;
324 static int hf_6lowpan_hop_limit;
325 static int hf_6lowpan_source;
326 static int hf_6lowpan_dest;
328 /* Inline UDP header fields. */
329 static int hf_6lowpan_udp_src;
330 static int hf_6lowpan_udp_dst;
331 static int hf_6lowpan_udp_len;
332 static int hf_6lowpan_udp_checksum;
334 /* Broadcast header fields. */
335 static int hf_6lowpan_bcast_seqnum;
337 /* Mesh header fields. */
338 static int hf_6lowpan_mesh_v;
339 static int hf_6lowpan_mesh_f;
340 static int hf_6lowpan_mesh_hops;
341 static int hf_6lowpan_mesh_hops8;
342 static int hf_6lowpan_mesh_orig16;
343 static int hf_6lowpan_mesh_orig64;
344 static int hf_6lowpan_mesh_dest16;
345 static int hf_6lowpan_mesh_dest64;
347 /* Fragmentation header fields. */
348 static int hf_6lowpan_frag_dgram_size;
349 static int hf_6lowpan_frag_dgram_tag;
350 static int hf_6lowpan_frag_dgram_offset;
352 /* Recoverable Fragmentation header fields. */
353 static int hf_6lowpan_rfrag_congestion;
354 static int hf_6lowpan_rfrag_ack_requested;
355 static int hf_6lowpan_rfrag_dgram_tag;
356 static int hf_6lowpan_rfrag_sequence;
357 static int hf_6lowpan_rfrag_size;
358 static int hf_6lowpan_rfrag_dgram_size;
359 static int hf_6lowpan_rfrag_offset;
360 static int hf_6lowpan_rfrag_ack_bitmap;
362 /* Protocol tree handles. */
363 static int ett_6lowpan;
364 static int ett_6lowpan_hc1;
365 static int ett_6lowpan_hc1_encoding;
366 static int ett_6lowpan_hc2_udp;
367 static int ett_6lowpan_iphc;
368 static int ett_lowpan_routing_header_dispatch;
369 static int ett_6lowpan_nhc_ext;
370 static int ett_6lowpan_nhc_udp;
371 static int ett_6lowpan_bcast;
372 static int ett_6lowpan_mesh;
373 static int ett_6lowpan_mesh_flags;
374 static int ett_6lowpan_frag;
376 static expert_field ei_6lowpan_hc1_more_bits;
377 static expert_field ei_6lowpan_illegal_dest_addr_mode;
378 static expert_field ei_6lowpan_bad_ipv6_header_length;
379 static expert_field ei_6lowpan_bad_ext_header_length;
381 /* Subdissector handles. */
382 static dissector_handle_t handle_6lowpan;
383 static dissector_handle_t ipv6_handle;
385 /* Value Strings */
386 static const value_string lowpan_patterns [] = {
387 { LOWPAN_PATTERN_NALP, "Not a LoWPAN frame" },
388 { LOWPAN_PATTERN_IPV6, "Uncompressed IPv6" },
389 { LOWPAN_PATTERN_HC1, "Header compression" },
390 { LOWPAN_PATTERN_BC0, "Broadcast" },
391 { LOWPAN_PATTERN_IPHC, "IP header compression" },
392 { LOWPAN_PATTERN_ESC, "Escape" },
393 { LOWPAN_PATTERN_MESH, "Mesh" },
394 { LOWPAN_PATTERN_FRAG1, "First fragment" },
395 { LOWPAN_PATTERN_FRAGN, "Fragment" },
396 { LOWPAN_PATTERN_RFRAG, "Recoverable Fragment" },
397 { LOWPAN_PATTERN_RFRAG_ACK, "Recoverable Fragment ACK" },
398 { 0, NULL }
400 static const true_false_string lowpan_compression = {
401 "Compressed",
402 "Inline"
404 static const value_string lowpan_hc1_next [] = {
405 { LOWPAN_HC1_NEXT_NONE, "Inline" },
406 { LOWPAN_HC1_NEXT_UDP, "UDP" },
407 { LOWPAN_HC1_NEXT_ICMP, "ICMP" },
408 { LOWPAN_HC1_NEXT_TCP, "TCP" },
409 { 0, NULL }
411 static const value_string lowpan_iphc_traffic [] = {
412 { LOWPAN_IPHC_FLOW_CLASS_LABEL, "Traffic class and flow label inline" },
413 { LOWPAN_IPHC_FLOW_ECN_LABEL, "ECN and flow label inline" },
414 { LOWPAN_IPHC_FLOW_CLASS, "Traffic class inline" },
415 { LOWPAN_IPHC_FLOW_COMPRESSED, "Version, traffic class, and flow label compressed" },
416 { 0, NULL }
418 static const value_string lowpan_iphc_hop_limit [] = {
419 { LOWPAN_IPHC_HLIM_INLINE, "Inline" },
420 { LOWPAN_IPHC_HLIM_1, "1" },
421 { LOWPAN_IPHC_HLIM_64, "64" },
422 { LOWPAN_IPHC_HLIM_255, "255" },
423 { 0, NULL }
425 static const true_false_string lowpan_iphc_addr_compression = {
426 "Stateful",
427 "Stateless"
429 static const value_string lowpan_iphc_addr_modes [] = {
430 { LOWPAN_IPHC_ADDR_FULL_INLINE, "Inline" },
431 { LOWPAN_IPHC_ADDR_64BIT_INLINE,"64-bits inline" },
432 { LOWPAN_IPHC_ADDR_16BIT_INLINE,"16-bits inline" },
433 { LOWPAN_IPHC_ADDR_COMPRESSED, "Compressed" },
434 { 0, NULL }
436 static const value_string lowpan_iphc_saddr_stateful_modes [] = {
437 { LOWPAN_IPHC_ADDR_FULL_INLINE, "Unspecified address (::)" },
438 { LOWPAN_IPHC_ADDR_64BIT_INLINE,"64-bits inline" },
439 { LOWPAN_IPHC_ADDR_16BIT_INLINE,"16-bits inline" },
440 { LOWPAN_IPHC_ADDR_COMPRESSED, "Compressed" },
441 { 0, NULL }
443 static const value_string lowpan_iphc_daddr_stateful_modes [] = {
444 { LOWPAN_IPHC_ADDR_64BIT_INLINE,"64-bits inline" },
445 { LOWPAN_IPHC_ADDR_16BIT_INLINE,"16-bits inline" },
446 { LOWPAN_IPHC_ADDR_COMPRESSED, "Compressed" },
447 { 0, NULL }
449 static const value_string lowpan_iphc_mcast_modes [] = {
450 { LOWPAN_IPHC_MCAST_FULL, "Inline" },
451 { LOWPAN_IPHC_MCAST_48BIT, "48-bits inline" },
452 { LOWPAN_IPHC_MCAST_32BIT, "32-bits inline" },
453 { LOWPAN_IPHC_MCAST_8BIT, "8-bits inline" },
454 { 0, NULL }
456 static const value_string lowpan_iphc_mcast_stateful_modes [] = {
457 { LOWPAN_IPHC_MCAST_STATEFUL_48BIT, "48-bits inline" },
458 { 0, NULL }
460 static const value_string lowpan_nhc_patterns [] = {
461 { LOWPAN_NHC_PATTERN_EXT, "IPv6 extension header" },
462 { LOWPAN_NHC_PATTERN_UDP, "UDP compression header" },
463 { 0, NULL }
465 static const value_string lowpan_nhc_eid [] = {
466 { LOWPAN_NHC_EID_HOP_BY_HOP, "IPv6 hop-by-hop options" },
467 { LOWPAN_NHC_EID_ROUTING, "IPv6 routing" },
468 { LOWPAN_NHC_EID_FRAGMENT, "IPv6 fragment" },
469 { LOWPAN_NHC_EID_DEST_OPTIONS, "IPv6 destination options" },
470 { LOWPAN_NHC_EID_MOBILITY, "IPv6 mobility header" },
471 { LOWPAN_NHC_EID_IPV6, "IPv6 header" },
472 { 0, NULL }
474 static const value_string lowpan_udp_ports [] = {
475 { LOWPAN_NHC_UDP_PORT_INLINE, "Inline" },
476 { LOWPAN_NHC_UDP_PORT_8BIT_DST, "Source port inline, first 8 bits of destination port elided" },
477 { LOWPAN_NHC_UDP_PORT_8BIT_SRC, "Destination port inline, first 8 bits of source port elided" },
478 { LOWPAN_NHC_UDP_PORT_12BIT, "12 bits of both ports elided" },
479 { 0, NULL }
481 /* 6loRH */
482 static const value_string lowpan_patterns_rh_type [] = {
483 { LOWPAN_PATTERN_6LORH_TYPE0, "Routing Header 3, 1 byte compression" },
484 { LOWPAN_PATTERN_6LORH_TYPE1, "Routing Header 3, 2 byte compression" },
485 { LOWPAN_PATTERN_6LORH_TYPE2, "Routing Header 3, 4 byte compression" },
486 { LOWPAN_PATTERN_6LORH_TYPE3, "Routing Header 3, 8 byte compression" },
487 { LOWPAN_PATTERN_6LORH_TYPE4, "Routing Header 3, 16 byte compression" },
488 { LOWPAN_PATTERN_6LORH_TYPE5, "Routing Protocol Information" },
489 { LOWPAN_PATTERN_6LORH_TYPE6, "IP in IP" },
490 { LOWPAN_PATTERN_6LORH_TYPE15, "BIER Header, bit-by-bit encoding, no control fields, 32 bits word size" },
491 { LOWPAN_PATTERN_6LORH_TYPE16, "BIER Header, Bloom filter encoding, 2* 1-byte HashID control fields, 32 bits word size" },
492 { LOWPAN_PATTERN_6LORH_TYPE17, "BIER Header, bit-by-bit encoding, no control fields, 128 bits word size" },
493 { LOWPAN_PATTERN_6LORH_TYPE18, "BIER Header, Bloom filter encoding, 8* 1-byte HashID control fields, 128 bits word size" },
494 { LOWPAN_PATTERN_6LORH_TYPE19, "BIER Header, bit-by-bit encoding, 1-byte GroupID control fields, 128 bits word size" },
495 { 0, NULL }
497 static const value_string lowpan_patterns_rh [] = {
498 { LOWPAN_PATTERN_6LORHC, "Critical Routing Header" },
499 { LOWPAN_PATTERN_6LORHE, "Elective Routing Header" },
500 { 0, NULL }
502 static const true_false_string bit_I_RPL = {
503 "Elided (RPL Instance ID: 0)",
504 "Present"
506 static const true_false_string bit_K_RPL = {
507 "1 byte",
508 "2 bytes"
511 /* Reassembly Data */
512 static int hf_6lowpan_fragments;
513 static int hf_6lowpan_fragment;
514 static int hf_6lowpan_fragment_overlap;
515 static int hf_6lowpan_fragment_overlap_conflicts;
516 static int hf_6lowpan_fragment_multiple_tails;
517 static int hf_6lowpan_fragment_too_long_fragment;
518 static int hf_6lowpan_fragment_error;
519 static int hf_6lowpan_fragment_count;
520 static int hf_6lowpan_reassembled_in;
521 static int hf_6lowpan_reassembled_length;
522 static int ett_6lowpan_fragment;
523 static int ett_6lowpan_fragments;
525 static const fragment_items lowpan_frag_items = {
526 /* Fragment subtrees */
527 &ett_6lowpan_fragment,
528 &ett_6lowpan_fragments,
529 /* Fragment fields */
530 &hf_6lowpan_fragments,
531 &hf_6lowpan_fragment,
532 &hf_6lowpan_fragment_overlap,
533 &hf_6lowpan_fragment_overlap_conflicts,
534 &hf_6lowpan_fragment_multiple_tails,
535 &hf_6lowpan_fragment_too_long_fragment,
536 &hf_6lowpan_fragment_error,
537 &hf_6lowpan_fragment_count,
538 /* Reassembled in field */
539 &hf_6lowpan_reassembled_in,
540 /* Reassembled length field */
541 &hf_6lowpan_reassembled_length,
542 /* Reassembled data field */
543 NULL,
544 /* Tag */
545 "6LoWPAN fragments"
548 static reassembly_table lowpan_reassembly_table;
549 static GHashTable *lowpan_context_table;
551 /* Link-Local prefix used by 6LoWPAN (FF80::/10) */
552 static const uint8_t lowpan_llprefix[8] = {
553 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
556 /* Context hash table map key. */
557 typedef struct {
558 uint16_t pan; /* PAN Identifier */
559 uint8_t cid; /* Context Identifier */
560 } lowpan_context_key;
562 /* Context hash table map data. */
563 typedef struct {
564 unsigned frame; /* Frame where the context was discovered. */
565 uint8_t plen; /* Prefix length. */
566 ws_in6_addr prefix; /* Compression context. */
567 } lowpan_context_data;
569 /* 6LoWPAN contexts. */
570 #define LOWPAN_CONTEXT_MAX 16
571 #define LOWPAN_CONTEXT_DEFAULT 0
572 #define LOWPAN_CONTEXT_LINK_LOCAL LOWPAN_CONTEXT_MAX
573 #define LOWPAN_CONTEXT_LINK_LOCAL_BITS 10
574 static lowpan_context_data lowpan_context_local;
575 static lowpan_context_data lowpan_context_default;
576 static const char * lowpan_context_prefs[LOWPAN_CONTEXT_MAX];
578 /* Preferences */
579 static bool rfc4944_short_address_format;
580 static bool iid_has_universal_local_bit;
581 static bool ipv6_summary_in_tree = true;
583 /* Helper macro to convert a bit offset/length into a byte count. */
584 #define BITS_TO_BYTE_LEN(bitoff, bitlen) ((bitlen)?(((bitlen) + ((bitoff)&0x07) + 7) >> 3):(0))
586 /* Structure for rebuilding UDP datagrams. */
587 struct udp_hdr {
588 uint16_t src_port;
589 uint16_t dst_port;
590 uint16_t length;
591 uint16_t checksum;
594 /* Structure used to store decompressed header chains until reassembly. */
595 struct lowpan_nhdr {
596 /* List Linking */
597 struct lowpan_nhdr *next;
598 /* Next Header */
599 uint8_t proto;
600 unsigned length;
601 unsigned reported;
603 #define LOWPAN_NHDR_DATA(nhdr) ((uint8_t *)(nhdr) + sizeof (struct lowpan_nhdr))
605 /* Dissector prototypes */
606 static void proto_init_6lowpan (void);
607 static void prefs_6lowpan_apply (void);
608 static int dissect_6lowpan (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
609 static tvbuff_t * dissect_6lowpan_ipv6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
610 static tvbuff_t * dissect_6lowpan_hc1 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int dgram_size, const uint8_t *siid, const uint8_t *diid);
611 static tvbuff_t * dissect_6lowpan_bc0 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
612 static tvbuff_t * dissect_6lowpan_iphc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int dgram_size, const uint8_t *siid, const uint8_t *diid);
613 static struct lowpan_nhdr *
614 dissect_6lowpan_iphc_nhc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int dgram_size, const uint8_t *siid, const uint8_t *diid);
615 static tvbuff_t * dissect_6lowpan_mesh (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint8_t *siid, uint8_t *diid);
616 static tvbuff_t * dissect_6lowpan_rfrag (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const uint8_t *siid, const uint8_t *diid);
617 static tvbuff_t * dissect_6lowpan_rfrag_ack (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
618 static tvbuff_t * dissect_6lowpan_frag_first (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const uint8_t *siid, const uint8_t *diid);
619 static tvbuff_t * dissect_6lowpan_frag_middle (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
620 static void dissect_6lowpan_unknown (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
621 static tvbuff_t * dissect_6lowpan_6loRH (tvbuff_t *tvb, unsigned offset, proto_tree *tree);
624 /* Helper functions. */
625 static bool lowpan_dlsrc_to_ifcid (packet_info *pinfo, uint8_t *ifcid);
626 static bool lowpan_dldst_to_ifcid (packet_info *pinfo, uint8_t *ifcid);
627 static void lowpan_addr16_to_ifcid (uint16_t addr, uint8_t *ifcid);
628 static void lowpan_addr16_with_panid_to_ifcid(uint16_t panid, uint16_t addr, uint8_t *ifcid);
629 static void lowpan_addr48_to_ifcid (const uint8_t *addr, uint8_t *ifcid);
630 static tvbuff_t * lowpan_reassemble_ipv6 (tvbuff_t *tvb, packet_info *pinfo, struct ws_ip6_hdr *ipv6, struct lowpan_nhdr *nhdr_list);
631 static uint8_t lowpan_parse_nhc_proto (tvbuff_t *tvb, int offset);
633 /* Context table helpers */
634 static unsigned lowpan_context_hash (const void *key);
635 static gboolean lowpan_context_equal (const void *a, const void *b);
636 static lowpan_context_data *lowpan_context_find(uint8_t cid, uint16_t pan);
638 /*FUNCTION:------------------------------------------------------
639 * NAME
640 * lowpan_pfxcpy
641 * DESCRIPTION
642 * A version of memcpy that takes a length in bits. If the
643 * length is not byte-aligned, the final byte will be
644 * manipulated so that only the desired number of bits are
645 * copied.
646 * PARAMETERS
647 * dst ; Destination.
648 * src ; Source.
649 * bits ; Number of bits to copy.
650 * RETURNS
651 * void ;
652 *---------------------------------------------------------------
654 static void
655 lowpan_pfxcpy(void *dst, const void *src, size_t bits)
657 memcpy(dst, src, bits>>3);
658 if (bits & 0x7) {
659 uint8_t mask = ((0xff00) >> (bits & 0x7));
660 uint8_t last = ((const uint8_t *)src)[bits>>3] & mask;
661 ((uint8_t *)dst)[bits>>3] &= ~mask;
662 ((uint8_t *)dst)[bits>>3] |= last;
664 } /* lowpan_pfxcpy */
666 /*FUNCTION:------------------------------------------------------
667 * NAME
668 * lowpan_context_hash
669 * DESCRIPTION
670 * Context table hash function.
671 * PARAMETERS
672 * key ; Pointer to a lowpan_context_key type.
673 * RETURNS
674 * unsigned ; The hashed key value.
675 *---------------------------------------------------------------
677 static unsigned
678 lowpan_context_hash(const void *key)
680 return (((const lowpan_context_key *)key)->cid) | (((const lowpan_context_key *)key)->pan << 8);
681 } /* lowpan_context_hash */
683 /*FUNCTION:------------------------------------------------------
684 * NAME
685 * lowpan_context_equal
686 * DESCRIPTION
687 * Context table equals function.
688 * PARAMETERS
689 * key ; Pointer to a lowpan_context_key type.
690 * RETURNS
691 * bool ;
692 *---------------------------------------------------------------
694 static gboolean
695 lowpan_context_equal(const void *a, const void *b)
697 return (((const lowpan_context_key *)a)->pan == ((const lowpan_context_key *)b)->pan) &&
698 (((const lowpan_context_key *)a)->cid == ((const lowpan_context_key *)b)->cid);
699 } /* lowpan_context_equal */
701 /*FUNCTION:------------------------------------------------------
702 * NAME
703 * lowpan_context_find
704 * DESCRIPTION
705 * Context table lookup function.
706 * PARAMETERS
707 * cid ; Context identifier.
708 * pan ; PAN identifier.
709 * RETURNS
710 * lowpan_context_data *;
711 *---------------------------------------------------------------
713 static lowpan_context_data *
714 lowpan_context_find(uint8_t cid, uint16_t pan)
716 lowpan_context_key key;
717 lowpan_context_data *data;
719 /* Check for the internal link-local context. */
720 if (cid == LOWPAN_CONTEXT_LINK_LOCAL) return &lowpan_context_local;
722 /* Lookup the context from the table. */
723 key.pan = pan;
724 key.cid = cid;
725 data = (lowpan_context_data *)g_hash_table_lookup(lowpan_context_table, &key);
726 if (data) return data;
728 /* If we didn't find a match, try again with the broadcast PAN. */
729 if (pan != IEEE802154_BCAST_PAN) {
730 key.pan = IEEE802154_BCAST_PAN;
731 data = (lowpan_context_data *)g_hash_table_lookup(lowpan_context_table, &key);
732 if (data) return data;
735 /* If the lookup failed, return the default context (::/0) */
736 return &lowpan_context_default;
737 } /* lowpan_context_find */
739 /*FUNCTION:------------------------------------------------------
740 * NAME
741 * lowpan_context_insert
742 * DESCRIPTION
743 * Context table insert function.
744 * PARAMETERS
745 * cid ; Context identifier.
746 * pan ; PAN identifier.
747 * plen ; Prefix length.
748 * prefix ; Compression prefix.
749 * frame ; Frame number.
750 * RETURNS
751 * void ;
752 *---------------------------------------------------------------
754 void
755 lowpan_context_insert(uint8_t cid, uint16_t pan, uint8_t plen, ws_in6_addr *prefix, unsigned frame)
757 lowpan_context_key key;
758 lowpan_context_data *data;
759 void * pkey;
760 void * pdata;
762 /* Sanity! */
763 if (plen > 128) return;
764 if (!prefix) return;
765 if (!lowpan_context_table) return;
767 /* Search the context table for an existing entry. */
768 key.pan = pan;
769 key.cid = cid;
770 if (g_hash_table_lookup_extended(lowpan_context_table, &key, NULL, &pdata)) {
771 /* Context already exists. */
772 data = (lowpan_context_data *)pdata;
773 if ( (data->plen == plen) && (memcmp(&data->prefix, prefix, (plen+7)/8) == 0) ) {
774 /* Context already exists with no change. */
775 return;
778 pkey = wmem_memdup(NULL, &key, sizeof(key));
780 /* Create a new context */
781 data = wmem_new(NULL, lowpan_context_data);
782 data->frame = frame;
783 data->plen = plen;
784 memset(&data->prefix, 0, sizeof(ws_in6_addr)); /* Ensure zero padding */
785 lowpan_pfxcpy(&data->prefix, prefix, plen);
786 g_hash_table_insert(lowpan_context_table, pkey, data);
787 } /* lowpan_context_insert */
789 /*FUNCTION:------------------------------------------------------
790 * NAME
791 * lowpan_context_free
792 * DESCRIPTION
793 * Frees the allocated memory for the context hash table
794 * PARAMETERS
795 * data ; Pointer to key or value
796 * RETURNS
797 * void ;
798 *---------------------------------------------------------------
800 static void
801 lowpan_context_free(void *data)
803 wmem_free(NULL, data);
804 } /* lowpan_context_free */
806 /*FUNCTION:------------------------------------------------------
807 * NAME
808 * lowpan_addr16_to_ifcid
809 * DESCRIPTION
810 * Converts a short address to in interface identifier as
811 * per rfc 6282 section 3.2.2.
812 * PARAMETERS
813 * addr ; 16-bit short address.
814 * ifcid ; interface identifier (output).
815 * RETURNS
816 * void ;
817 *---------------------------------------------------------------
819 static void
820 lowpan_addr16_to_ifcid(uint16_t addr, uint8_t *ifcid)
822 /* Note: The PANID is no longer used in building the IID. */
823 ifcid[0] = 0x00; /* the U/L bit must be cleared. */
824 ifcid[1] = 0x00;
825 ifcid[2] = 0x00;
826 ifcid[3] = 0xff;
827 ifcid[4] = 0xfe;
828 ifcid[5] = 0x00;
829 ifcid[6] = (addr >> 8) & 0xff;
830 ifcid[7] = (addr >> 0) & 0xff;
831 } /* lowpan_addr16_to_ifcid */
833 /*FUNCTION:------------------------------------------------------
834 * NAME
835 * lowpan_addr16_with_panid_to_ifcid
836 * DESCRIPTION
837 * Converts a short address to in interface identifier as
838 * per rfc 4944 section 6.
839 * PARAMETERS
840 * panid ; 16-bit PAN ID.
841 * addr ; 16-bit short address.
842 * ifcid ; interface identifier (output).
843 * RETURNS
844 * void ;
845 *---------------------------------------------------------------
847 static void
848 lowpan_addr16_with_panid_to_ifcid(uint16_t panid, uint16_t addr, uint8_t *ifcid)
850 /* Note: The PANID is used in building the IID following RFC 2464 section 4. */
851 ifcid[0] = (panid >> 8) & 0xfd; /* the U/L bit must be cleared. */
852 ifcid[1] = (panid >> 0) & 0xff;
853 ifcid[2] = 0x00;
854 ifcid[3] = 0xff;
855 ifcid[4] = 0xfe;
856 ifcid[5] = 0x00;
857 ifcid[6] = (addr >> 8) & 0xff;
858 ifcid[7] = (addr >> 0) & 0xff;
859 } /* lowpan_addr16_with_panid_to_ifcid */
861 /*FUNCTION:------------------------------------------------------
862 * NAME
863 * lowpan_addr48_to_ifcid
864 * DESCRIPTION
865 * Converts an IEEE 48-bit MAC identifier to an interface
866 * identifier as per RFC 4291 Appendix A.
867 * PARAMETERS
868 * addr ; 48-bit MAC identifier.
869 * ifcid ; interface identifier (output).
870 * RETURNS
871 * void ;
872 *---------------------------------------------------------------
874 static void
875 lowpan_addr48_to_ifcid(const uint8_t *addr, uint8_t *ifcid)
877 static const uint8_t unknown_addr[] = { 0, 0, 0, 0, 0, 0 };
879 /* Don't convert unknown addresses */
880 if (memcmp(addr, unknown_addr, sizeof(unknown_addr)) != 0) {
881 ifcid[0] = addr[0];
882 ifcid[1] = addr[1];
883 ifcid[2] = addr[2];
884 ifcid[3] = 0xff;
885 ifcid[4] = 0xfe;
886 ifcid[5] = addr[3];
887 ifcid[6] = addr[4];
888 ifcid[7] = addr[5];
889 if (iid_has_universal_local_bit) {
890 ifcid[0] ^= 0x02; /* Invert the U/L bit. */
892 } else {
893 memset(ifcid, 0, LOWPAN_IFC_ID_LEN);
895 } /* lowpan_ether_to_ifcid */
897 /*FUNCTION:------------------------------------------------------
898 * NAME
899 * lowpan_dlsrc_to_ifcid
900 * DESCRIPTION
901 * Finds an interface identifier from the data-link source
902 * addressing.
903 * PARAMETERS
904 * pinfo ; packet information.
905 * ifcid ; interface identifier (output).
906 * RETURNS
907 * bool ; true if an interface identifier could
908 * be found.
909 *---------------------------------------------------------------
911 static bool
912 lowpan_dlsrc_to_ifcid(packet_info *pinfo, uint8_t *ifcid)
914 ieee802154_hints_t *hints;
916 /* Check the link-layer address field. */
917 if (pinfo->dl_src.type == AT_EUI64) {
918 memcpy(ifcid, pinfo->dl_src.data, LOWPAN_IFC_ID_LEN);
919 /* RFC2464: Invert the U/L bit when using an EUI64 address. */
920 ifcid[0] ^= 0x02;
921 return true;
922 } else if (pinfo->dl_src.type == AT_ETHER) {
923 lowpan_addr48_to_ifcid((const uint8_t *)pinfo->dl_src.data, ifcid);
924 return true;
927 /* Lookup the IEEE 802.15.4 addressing hints. */
928 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
929 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
930 if (hints) {
932 /* Convert the 16-bit short address to an IID using the PAN ID (RFC 4944) or not depending on the preference */
933 if (rfc4944_short_address_format) {
934 lowpan_addr16_with_panid_to_ifcid(hints->src_pan, hints->src16, ifcid);
935 } else {
936 lowpan_addr16_to_ifcid(hints->src16, ifcid);
939 return true;
940 } else {
941 /* Failed to find a link-layer source address. */
942 memset(ifcid, 0, LOWPAN_IFC_ID_LEN);
943 return false;
945 } /* lowpan_dlsrc_to_ifcid */
947 /*FUNCTION:------------------------------------------------------
948 * NAME
949 * lowpan_dldst_to_ifcid
950 * DESCRIPTION
951 * Finds an interface identifier from the data-link destination
952 * addressing.
953 * PARAMETERS
954 * pinfo ; packet information.
955 * ifcid ; interface identifier (output).
956 * RETURNS
957 * bool ; true if an interface identifier could
958 * be found.
959 *---------------------------------------------------------------
961 static bool
962 lowpan_dldst_to_ifcid(packet_info *pinfo, uint8_t *ifcid)
964 ieee802154_hints_t *hints;
966 /* Check the link-layer address field. */
967 if (pinfo->dl_dst.type == AT_EUI64) {
968 memcpy(ifcid, pinfo->dl_dst.data, LOWPAN_IFC_ID_LEN);
969 /* RFC2464: Invert the U/L bit when using an EUI64 address. */
970 ifcid[0] ^= 0x02;
971 return true;
972 } else if (pinfo->dl_dst.type == AT_ETHER) {
973 lowpan_addr48_to_ifcid((const uint8_t *)pinfo->dl_dst.data, ifcid);
974 return true;
977 /* Lookup the IEEE 802.15.4 addressing hints. */
978 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
979 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
980 if (hints) {
982 /* Convert the 16-bit short address to an IID using the PAN ID (RFC 4944) or not depending on the preference */
983 if (rfc4944_short_address_format) {
984 lowpan_addr16_with_panid_to_ifcid(hints->src_pan, hints->dst16, ifcid);
985 } else {
986 lowpan_addr16_to_ifcid(hints->dst16, ifcid);
989 return true;
990 } else {
991 /* Failed to find a link-layer destination address. */
992 memset(ifcid, 0, LOWPAN_IFC_ID_LEN);
993 return false;
995 } /* lowpan_dldst_to_ifcid */
997 /*FUNCTION:------------------------------------------------------
998 * NAME
999 * lowpan_reassemble_ipv6
1000 * DESCRIPTION
1001 * Helper function to rebuild an IPv6 packet from the IPv6
1002 * header structure, and a list of next header structures.
1003 * PARAMETERS
1004 * ipv6 ; IPv6 Header.
1005 * nhdr_list ; Next header list.
1006 * RETURNS
1007 * tvbuff_t * ; Reassembled IPv6 packet.
1008 *---------------------------------------------------------------
1010 static tvbuff_t *
1011 lowpan_reassemble_ipv6(tvbuff_t *tvb, packet_info *pinfo, struct ws_ip6_hdr *ipv6, struct lowpan_nhdr *nhdr_list)
1013 int length = 0;
1014 int reported = 0;
1015 uint8_t * buffer;
1016 uint8_t * cursor;
1017 struct lowpan_nhdr *nhdr;
1019 /* Compute the real and reported lengths. */
1020 for (nhdr = nhdr_list; nhdr; nhdr = nhdr->next) {
1021 length += nhdr->length;
1022 reported += nhdr->reported;
1024 ipv6->ip6h_plen = g_ntohs(reported);
1026 /* Allocate a buffer for the packet and copy in the IPv6 header. */
1027 buffer = (uint8_t *)wmem_alloc(pinfo->pool, length + IPv6_HDR_SIZE);
1028 memcpy(buffer, ipv6, IPv6_HDR_SIZE);
1029 cursor = buffer + IPv6_HDR_SIZE;
1031 /* Add the next headers into the buffer. */
1032 for (nhdr = nhdr_list; nhdr; nhdr = nhdr->next) {
1033 memcpy(cursor, LOWPAN_NHDR_DATA(nhdr), nhdr->length);
1034 cursor += nhdr->length;
1037 /* Return the reassembled packet. */
1038 return tvb_new_child_real_data(tvb, buffer, length + IPv6_HDR_SIZE, reported + IPv6_HDR_SIZE);
1039 } /* lowpan_reassemble_ipv6 */
1041 /*FUNCTION:------------------------------------------------------
1042 * NAME
1043 * lowpan_parse_nhc_proto
1044 * DESCRIPTION
1045 * Parses the start of an 6LoWPAN NHC header to determine the
1046 * next header protocol identifier. Will return IP_PROTO_NONE
1047 * if no valid protocol could be determined.
1048 * PARAMETERS
1049 * tvb ; packet buffer.
1050 * offset ; offset of the NHC.
1051 * RETURNS
1052 * uint8_t ; IP_PROTO_* of the next header's protocol.
1053 *---------------------------------------------------------------
1055 static uint8_t
1056 lowpan_parse_nhc_proto(tvbuff_t *tvb, int offset)
1058 /* Ensure that at least one byte exists. */
1059 if (!tvb_bytes_exist(tvb, offset, 1)) return IP_PROTO_NONE;
1061 /* Check for IPv6 extension headers. */
1062 if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_BITS) == LOWPAN_NHC_PATTERN_EXT) {
1063 uint8_t eid = (tvb_get_uint8(tvb, offset) & LOWPAN_NHC_EXT_EID) >> LOWPAN_NHC_EXT_EID_OFFSET;
1064 switch (eid) {
1065 case LOWPAN_NHC_EID_HOP_BY_HOP:
1066 return IP_PROTO_HOPOPTS;
1067 case LOWPAN_NHC_EID_ROUTING:
1068 return IP_PROTO_ROUTING;
1069 case LOWPAN_NHC_EID_FRAGMENT:
1070 return IP_PROTO_FRAGMENT;
1071 case LOWPAN_NHC_EID_DEST_OPTIONS:
1072 return IP_PROTO_DSTOPTS;
1073 case LOWPAN_NHC_EID_MOBILITY:
1074 return IP_PROTO_MIPV6;
1075 case LOWPAN_NHC_EID_IPV6:
1076 return IP_PROTO_IPV6;
1077 default:
1078 /* Unknown protocol type. */
1079 return IP_PROTO_NONE;
1082 /* Check for compressed UDP headers. */
1083 if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_UDP_BITS) == LOWPAN_NHC_PATTERN_UDP) {
1084 return IP_PROTO_UDP;
1086 /* Unknown header type. */
1087 return IP_PROTO_NONE;
1088 } /* lowpan_parse_nhc_proto */
1090 /*FUNCTION:------------------------------------------------------
1091 * NAME
1092 * lowpan_reassembly_id
1093 * DESCRIPTION
1094 * Creates an identifier that groups fragments based on the given datagram
1095 * tag and the link layer destination address (to differentiate packets
1096 * forwarded over different links in a mesh network).
1097 * PARAMETERS
1098 * pinfo : packet info.
1099 * dgram_tag ; datagram tag (from the Fragmentation Header).
1100 * RETURNS
1101 * uint32_t ; identifier for this group of fragments.
1102 *---------------------------------------------------------------
1104 static uint32_t
1105 lowpan_reassembly_id(packet_info *pinfo, uint16_t dgram_tag)
1107 /* Start with the datagram tag for identification. If the packet is not
1108 * being forwarded, then this should be sufficient to prevent collisions
1109 * which could break reassembly. */
1110 uint32_t frag_id = dgram_tag;
1111 ieee802154_hints_t *hints;
1113 /* Forwarded packets in a mesh network have the same datagram tag, mix
1114 * the IEEE 802.15.4 destination link layer address. */
1115 if (pinfo->dl_dst.type == AT_EUI64) {
1116 /* IEEE 64-bit extended address */
1117 frag_id = add_address_to_hash(frag_id, &pinfo->dl_dst);
1118 } else {
1119 /* 16-bit short address */
1120 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
1121 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
1122 if (hints) {
1123 frag_id |= hints->dst16 << 16;
1126 return frag_id;
1127 } /* lowpan_reassembly_id */
1129 /*FUNCTION:------------------------------------------------------
1130 * NAME
1131 * dissect_6lowpan_heur
1132 * DESCRIPTION
1133 * Heuristic dissector for 6LoWPAN. Checks if the pattern is
1134 * a valid 6LoWPAN type, and not NALP.
1135 * PARAMETERS
1136 * tvb ; packet buffer.
1137 * pinfo ; packet info.
1138 * tree ; protocol display tree.
1139 * data : ieee802154_packet,
1140 * RETURNS
1141 * boolean ; true if the tvbuff was dissected as a
1142 * 6LoWPAN packet. If this returns false,
1143 * then no dissection will be attempted.
1144 *---------------------------------------------------------------
1146 static bool
1147 dissect_6lowpan_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1149 unsigned offset = 0;
1151 /* Check for valid patterns. */
1152 for (;;) {
1153 /* Parse patterns until we find a match. */
1154 if (!tvb_reported_length_remaining(tvb, offset)) return false;
1155 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_IPV6_BITS) == LOWPAN_PATTERN_IPV6) break;
1156 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_HC1_BITS) == LOWPAN_PATTERN_HC1) break;
1157 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_BC0_BITS) == LOWPAN_PATTERN_BC0) {
1158 /* Broadcast headers must be followed by another valid header. */
1159 offset += 2;
1160 continue;
1162 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) break;
1163 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_MESH_BITS) == LOWPAN_PATTERN_MESH) {
1164 /* Mesh headers must be followed by another valid header. */
1165 uint8_t mesh = tvb_get_uint8(tvb, offset++);
1166 offset += (mesh & LOWPAN_MESH_HEADER_V) ? 2 : 8;
1167 offset += (mesh & LOWPAN_MESH_HEADER_F) ? 2 : 8;
1168 if ((mesh & LOWPAN_MESH_HEADER_HOPS) == LOWPAN_MESH_HEADER_HOPS) offset++;
1169 continue;
1171 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_RFRAG_BITS) == LOWPAN_PATTERN_RFRAG) break;
1172 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_RFRAG_BITS) == LOWPAN_PATTERN_RFRAG_ACK) break;
1173 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_FRAG_BITS) == LOWPAN_PATTERN_FRAG1) {
1174 /* First fragment headers must be followed by another valid header. */
1175 offset += 4;
1176 continue;
1178 if (tvb_get_bits8(tvb, offset*8, LOWPAN_PATTERN_FRAG_BITS) == LOWPAN_PATTERN_FRAGN) break;
1180 /* If we get here, then we couldn't match to any pattern. */
1181 return false;
1182 } /* for */
1184 /* If we get here, then we found a matching pattern. */
1185 dissect_6lowpan(tvb, pinfo, tree, data);
1186 return true;
1187 } /* dissect_6lowpan_heur */
1189 /*FUNCTION:------------------------------------------------------
1190 * NAME
1191 * dissect_6lowpan
1192 * DESCRIPTION
1193 * Dissector routine for 6LoWPAN packets.
1194 * PARAMETERS
1195 * tvb ; packet buffer.
1196 * pinfo ; packet info.
1197 * tree ; protocol display tree.
1198 * data ; Packet data (ieee 802.15.4).
1199 * RETURNS
1200 * int ; Length of data processed, or 0 if not 6LoWPAN.
1201 *---------------------------------------------------------------
1203 static int
1204 dissect_6lowpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1206 proto_tree *lowpan_tree;
1207 proto_item *lowpan_root;
1208 tvbuff_t *next = tvb;
1209 unsigned offset = 0;
1210 /* Interface identifier of the encapsulating layer. */
1211 uint8_t src_iid[LOWPAN_IFC_ID_LEN];
1212 uint8_t dst_iid[LOWPAN_IFC_ID_LEN];
1214 /* Get the interface identifiers from the encapsulating layer. */
1215 lowpan_dlsrc_to_ifcid(pinfo, src_iid);
1216 lowpan_dldst_to_ifcid(pinfo, dst_iid);
1218 /* Create the protocol tree. */
1219 lowpan_root = proto_tree_add_protocol_format(tree, proto_6lowpan, tvb, 0, -1, "6LoWPAN");
1220 lowpan_tree = proto_item_add_subtree(lowpan_root, ett_6lowpan);
1222 /* Add the protocol name. */
1223 col_set_str(pinfo->cinfo, COL_PROTOCOL, "6LoWPAN");
1225 /* Mesh and Broadcast headers always come first in a 6LoWPAN frame. */
1226 if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_MESH_BITS) == LOWPAN_PATTERN_MESH) {
1227 next = dissect_6lowpan_mesh(next, pinfo, lowpan_tree, src_iid, dst_iid);
1228 if (!next) return tvb_captured_length(tvb);
1230 if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_BC0_BITS) == LOWPAN_PATTERN_BC0) {
1231 next = dissect_6lowpan_bc0(next, pinfo, lowpan_tree);
1232 if (!next) return tvb_captured_length(tvb);
1235 /* After the mesh and broadcast headers, process dispatch codes recursively. */
1236 /* Recoverable Fragmentation headers.*/
1237 if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_RFRAG_BITS) == LOWPAN_PATTERN_RFRAG) {
1238 next = dissect_6lowpan_rfrag(next, pinfo, lowpan_tree, src_iid, dst_iid);
1239 if (!next) return tvb_captured_length(tvb);
1241 else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_RFRAG_BITS) == LOWPAN_PATTERN_RFRAG_ACK) {
1242 next = dissect_6lowpan_rfrag_ack(next, pinfo, lowpan_tree);
1243 if (!next) return tvb_captured_length(tvb);
1245 /* Fragmentation headers.*/
1246 if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_FRAG_BITS) == LOWPAN_PATTERN_FRAG1) {
1247 next = dissect_6lowpan_frag_first(next, pinfo, lowpan_tree, src_iid, dst_iid);
1249 else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_FRAG_BITS) == LOWPAN_PATTERN_FRAGN) {
1250 next = dissect_6lowpan_frag_middle(next, pinfo, lowpan_tree);
1252 /* Uncompressed IPv6 packets. */
1253 else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_IPV6_BITS) == LOWPAN_PATTERN_IPV6) {
1254 next = dissect_6lowpan_ipv6(next, pinfo, lowpan_tree);
1256 else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_PAGING_DISPATCH_BITS) == LOWPAN_PATTERN_PAGING_DISPATCH) {
1257 proto_tree_add_bits_item(lowpan_tree, hf_6lowpan_pagenb, tvb, 4, 4, ENC_BIG_ENDIAN);
1258 offset += 1;
1259 next = dissect_6lowpan_6loRH(next, offset, lowpan_tree);
1260 if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) {
1261 next = dissect_6lowpan_iphc(next, pinfo, lowpan_tree, -1, src_iid, dst_iid);
1262 if (!next) return tvb_captured_length(tvb);
1264 if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_HC1_BITS) == LOWPAN_PATTERN_HC1) {
1265 next = dissect_6lowpan_hc1(next, pinfo, lowpan_tree, -1, src_iid, dst_iid);
1268 /* Compressed IPv6 packets. */
1269 else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_HC1_BITS) == LOWPAN_PATTERN_HC1) {
1270 next = dissect_6lowpan_hc1(next, pinfo, lowpan_tree, -1, src_iid, dst_iid);
1272 else if (tvb_get_bits8(next, 0, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) {
1273 next = dissect_6lowpan_iphc(next, pinfo, lowpan_tree, -1, src_iid, dst_iid);
1275 /* Unknown 6LoWPAN dispatch type */
1276 else {
1277 dissect_6lowpan_unknown(next, pinfo, lowpan_tree);
1278 return tvb_captured_length(tvb);
1281 /* The last step should have returned an uncompressed IPv6 datagram. */
1282 if (next) {
1283 call_dissector(ipv6_handle, next, pinfo, tree);
1285 return tvb_captured_length(tvb);
1286 } /* dissect_6lowpan */
1288 /*FUNCTION:------------------------------------------------------
1289 * NAME
1290 * dissect_6lowpan_6loRH
1291 * DESCRIPTION
1292 * Dissector routine for 6loRH fields in 6LoWPAN packets.
1293 * PARAMETERS
1294 * tvb ; packet buffer.
1295 * offset ; offset of the 6loRH fields
1296 * tree ; protocol display tree.
1297 * RETURNS
1298 * tvbuff_t * ; The remaining payload to be parsed.
1299 *---------------------------------------------------------------
1301 static tvbuff_t *
1302 dissect_6lowpan_6loRH(tvbuff_t *tvb, unsigned offset, proto_tree *tree)
1305 uint16_t check;
1306 int IK;
1307 uint16_t loRH_flags;
1308 proto_tree * loRH_tree;
1309 uint16_t loRHE_length;
1310 uint8_t loRHE_type;
1311 uint16_t loRHE_class;
1312 uint8_t rpl_instance;
1313 int condition = 1;
1314 int16_t loRHE_unitnums;
1316 struct ws_ip6_hdr ipv6;
1317 static int * const bits_RHC[] = {
1318 &hf_6lowpan_5_bit_o,
1319 &hf_6lowpan_5_bit_r,
1320 &hf_6lowpan_5_bit_f,
1321 &hf_6lowpan_5_bit_i,
1322 &hf_6lowpan_5_bit_k,
1323 NULL
1326 loRH_flags = tvb_get_ntohs(tvb, offset);
1327 check = loRH_flags & 0xC000;
1329 if (check == LOWPAN_6LORH_GENERAL_FORMAT) {
1331 memset(&ipv6.ip6h_src, 0, sizeof(ipv6.ip6h_src));
1333 while(condition > 0){
1334 condition -= 1 ;
1335 /*Create the tree*/
1336 loRH_tree = proto_tree_add_subtree(tree, tvb, offset, 2, ett_lowpan_routing_header_dispatch, NULL, "6LoRH:");
1338 /* Get and display the pattern. */
1339 proto_tree_add_bits_item(loRH_tree, hf_6lowpan_routing_header, tvb, 8*offset, LOWPAN_PATTERN_IPHC_BITS, ENC_BIG_ENDIAN);
1340 /*=====================================================
1341 * Parse 6LoRH Header flags.
1342 *=====================================================
1345 loRHE_class = (loRH_flags & LOWPAN_PATTERN_6LORHE_CLASS) >> LOWPAN_PATTERN_6LORHE_CLASS_BITS;
1346 loRHE_length = (loRH_flags & LOWPAN_PATTERN_6LORHE_LENGTH) >> LOWPAN_PATTERN_6LORHE_LENGTH_BITS;
1347 loRHE_unitnums = loRHE_length + 1;
1348 loRHE_type = (loRH_flags & LOWPAN_PATTERN_6LORHE_TYPE);
1349 IK = (loRH_flags & LOWPAN_5_RPI_BITS_IK) >> 8;
1351 proto_item_append_text(loRH_tree, " %s", val_to_str_const(loRHE_type, lowpan_patterns_rh_type, "Unknown"));
1353 switch (loRHE_class){
1354 case (LOWPAN_PATTERN_6LORHE):/*Elective Routing Header*/
1355 condition = 1 ;
1356 if (loRHE_type >= 15) { /* BIER implementation */
1357 proto_tree_add_uint (loRH_tree, hf_6lowpan_6lorhe_size, tvb, offset, 2, loRH_flags & LOWPAN_PATTERN_6LORHE_LENGTH);
1358 proto_tree_add_uint (loRH_tree, hf_6lowpan_6lorhe_type, tvb, offset, 2, loRHE_type);
1359 offset += 2 ;
1360 if (loRHE_type == 15) {
1361 for (int i=0; i<loRHE_unitnums; i++) {
1362 proto_tree_add_item(loRH_tree, hf_6lowpan_6lorhe_bitmap, tvb, offset, 4, ENC_BIG_ENDIAN);
1363 offset += 4;
1367 else if (loRHE_type == LOWPAN_IP_IN_IP_6LORH) {
1368 memset(&ipv6.ip6h_src, 0, sizeof(ipv6.ip6h_src));
1369 proto_tree_add_item(loRH_tree, hf_6lowpan_6lorhe_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1370 proto_tree_add_item(loRH_tree, hf_6lowpan_6lorhe_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1371 proto_tree_add_item(loRH_tree, hf_6lowpan_6lorhe_hoplimit, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
1373 if (loRHE_length > 1) {
1374 for (int i = 0; i < 16; ++i) {
1375 ipv6.ip6h_src.bytes[i] = tvb_get_uint8(tvb, offset + 3 + i);
1377 proto_tree_add_ipv6(loRH_tree, hf_6lowpan_6lorhc_address_src, tvb, offset + 3, 16,
1378 &ipv6.ip6h_src);
1380 offset += 2 + loRHE_length;
1382 else {
1383 condition -= 1;
1385 break; /* case LOWPAN_PATTERN_6LORHE */
1387 case (LOWPAN_PATTERN_6LORHC): /*Critical Routing Header*/
1388 condition = 1 ;
1389 if (loRHE_type == 5){
1390 proto_tree_add_bitmask_list (loRH_tree, tvb, offset, 2, bits_RHC, ENC_NA);
1391 proto_tree_add_item (loRH_tree, hf_6lowpan_6lorhe_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1392 offset += 2;
1393 switch (IK){
1394 case BITS_IK_0:
1395 proto_tree_add_item (loRH_tree, hf_6lowpan_rpl_instance, tvb, offset, 1, ENC_BIG_ENDIAN);
1396 proto_tree_add_item (loRH_tree, hf_6lowpan_sender_rank2, tvb, offset+1, 2, ENC_BIG_ENDIAN);
1397 offset += 3;
1398 break;
1399 case BITS_IK_1:
1400 proto_tree_add_item (loRH_tree, hf_6lowpan_rpl_instance, tvb, offset, 1, ENC_BIG_ENDIAN);
1401 proto_tree_add_item (loRH_tree, hf_6lowpan_sender_rank1, tvb, offset+1, 1, ENC_BIG_ENDIAN);
1402 offset += 2;
1403 break;
1404 case BITS_IK_2:
1405 rpl_instance = 0x00;
1406 proto_tree_add_uint (loRH_tree, hf_6lowpan_rpl_instance, tvb, offset, 0, rpl_instance);
1407 proto_tree_add_item (loRH_tree, hf_6lowpan_sender_rank2, tvb, offset, 2, ENC_BIG_ENDIAN);
1408 offset += 2;
1409 break;
1410 case BITS_IK_3:
1411 rpl_instance = 0x00;
1412 proto_tree_add_uint (loRH_tree, hf_6lowpan_rpl_instance, tvb, offset, 0, rpl_instance);
1413 proto_tree_add_item (loRH_tree, hf_6lowpan_sender_rank1, tvb, offset, 1, ENC_BIG_ENDIAN);
1414 offset +=1;
1415 break;
1418 else if (loRHE_type <= 4){
1419 memset(&ipv6.ip6h_src, 0, sizeof(ipv6.ip6h_src));
1420 proto_tree_add_uint (loRH_tree, hf_6lowpan_6lorhc_size, tvb, offset, 2, loRH_flags & LOWPAN_PATTERN_6LORHE_LENGTH);
1421 proto_tree_add_uint (loRH_tree, hf_6lowpan_6lorhe_type, tvb, offset, 2, loRHE_type);
1422 offset += 2 ;
1423 switch (loRHE_type){
1424 case IPV6_ADDR_COMPRESSED_1_BYTE: /* IPv6 address compressed to 1 byte */
1425 for (int i=0; i<loRHE_unitnums; i++) {
1426 for (int j = 0; j < 1; j++){
1427 ipv6.ip6h_src.bytes[15-j] = tvb_get_uint8(tvb, offset);
1429 proto_tree_add_ipv6(tree, hf_6lowpan_6lorhc_address_hop0, tvb, offset, 1, &ipv6.ip6h_src);
1430 offset +=1;
1432 break;
1434 case IPV6_ADDR_COMPRESSED_2_BYTE: /* IPv6 address compressed to 2 bytes */
1435 for (int i=0; i<loRHE_unitnums; i++) {
1436 for (int j = 0; j < 2; ++j){
1437 ipv6.ip6h_src.bytes[15-1+j] = tvb_get_uint8(tvb, offset);
1438 offset +=1;
1440 proto_tree_add_ipv6(tree, hf_6lowpan_6lorhc_address_hop1, tvb, offset - 2, 2, &ipv6.ip6h_src);
1442 break;
1444 case IPV6_ADDR_COMPRESSED_4_BYTE: /* IPv6 address compressed to 4 bytes */
1445 for (int i=0; i<loRHE_unitnums; i++) {
1446 for (int j = 0; j < 4; j++){
1447 ipv6.ip6h_src.bytes[15-3+j] = tvb_get_uint8(tvb, offset);
1448 offset +=1;
1450 proto_tree_add_ipv6(tree, hf_6lowpan_6lorhc_address_hop2, tvb, offset - 4, 4, &ipv6.ip6h_src);
1452 break;
1454 case IPV6_ADDR_COMPRESSED_8_BYTE: /* IPv6 address compressed to 8 bytes */
1455 for (int i=0; i<loRHE_unitnums; i++) {
1456 for (int j = 0; j < 8; j++){
1457 ipv6.ip6h_src.bytes[15-7+j] = tvb_get_uint8(tvb, offset);
1458 offset +=1;
1460 proto_tree_add_ipv6(tree, hf_6lowpan_6lorhc_address_hop3, tvb, offset - 8, 8, &ipv6.ip6h_src);
1462 break;
1463 case IPV6_ADDR_COMPRESSED_16_BYTE: /* IPv6 address compressed to 16 bytes */
1464 for (int i=0; i<loRHE_unitnums; i++) {
1465 for (int j = 0; j < 16; j++){
1466 ipv6.ip6h_src.bytes[j] = tvb_get_uint8(tvb, offset);
1467 offset +=1;
1469 proto_tree_add_ipv6(tree, hf_6lowpan_6lorhc_address_hop4, tvb, offset - 16, 16, &ipv6.ip6h_src);
1471 break; /**/
1472 } /* switch loRHE_type */
1473 } /* else if (loRHE_type <= 4) */
1474 else {
1475 condition -= 1;
1477 break; /* case LOWPAN_PATTERN_6LORHC */
1479 default:
1480 condition -= 1 ;
1481 break;
1482 } /* switch loRHE_class */
1483 loRH_flags = tvb_get_ntohs(tvb, offset);
1484 loRHE_class = (loRH_flags & LOWPAN_PATTERN_6LORHE_CLASS) >> 13;
1486 if ((loRHE_class) != LOWPAN_PATTERN_6LORHE){
1487 if ((loRHE_class) != LOWPAN_PATTERN_6LORHC){
1488 condition -= 1;
1491 } /* while (condition > 0)*/
1493 return tvb_new_subset_remaining(tvb, offset);
1494 } /* dissect_6lowpan_6loRH */
1496 /*FUNCTION:------------------------------------------------------
1497 * NAME
1498 * dissect_6lowpan_ipv6
1499 * DESCRIPTION
1500 * Dissector routine for an uncompressed IPv6 header type.
1502 * This is one of the final encapsulation types, and will
1503 * returned an uncompressed IPv6 datagram (or fragment
1504 * thereof).
1505 * PARAMETERS
1506 * tvb ; packet buffer.
1507 * pinfo ; packet info.
1508 * tree ; 6LoWPAN display tree.
1509 * offset ; offset to the start of the header.
1510 * RETURNS
1511 * tvbuff_t * ; The remaining payload to be parsed.
1512 *---------------------------------------------------------------
1514 static tvbuff_t *
1515 dissect_6lowpan_ipv6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
1517 /* Get and display the pattern. */
1518 proto_tree_add_bits_item(tree, hf_6lowpan_pattern,
1519 tvb, 0, LOWPAN_PATTERN_IPV6_BITS, ENC_BIG_ENDIAN);
1521 /* Create a tvbuff subset for the ipv6 datagram. */
1522 return tvb_new_subset_remaining(tvb, 1);
1523 } /* dissect_6lowpan_ipv6 */
1525 /*FUNCTION:------------------------------------------------------
1526 * NAME
1527 * dissect_6lowpan_hc1
1528 * DESCRIPTION
1529 * Dissector routine for a 6LoWPAN HC1 header.
1530 * PARAMETERS
1531 * tvb ; packet buffer.
1532 * pinfo ; packet info.
1533 * tree ; 6LoWPAN display tree.
1534 * dgram_size ; Datagram size (or <0 if not fragmented).
1535 * siid ; Source Interface ID.
1536 * diid ; Destination Interface ID.
1537 * RETURNS
1538 * tvbuff_t * ; The remaining payload to be parsed.
1539 *---------------------------------------------------------------
1541 static tvbuff_t *
1542 dissect_6lowpan_hc1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int dgram_size, const uint8_t *siid, const uint8_t *diid)
1544 int offset = 0;
1545 int bit_offset;
1546 int i;
1547 uint8_t hc1_encoding;
1548 uint8_t hc_udp_encoding = 0;
1549 uint8_t next_header;
1550 proto_tree * hc_tree;
1551 proto_item * hc_item;
1552 tvbuff_t * ipv6_tvb;
1553 /* IPv6 header. */
1554 uint8_t ipv6_class;
1555 uint32_t ipv6_flow;
1556 struct ws_ip6_hdr ipv6;
1557 struct lowpan_nhdr *nhdr_list;
1558 static int * const hc1_encodings[] = {
1559 &hf_6lowpan_hc1_source_prefix,
1560 &hf_6lowpan_hc1_source_ifc,
1561 &hf_6lowpan_hc1_dest_prefix,
1562 &hf_6lowpan_hc1_dest_ifc,
1563 &hf_6lowpan_hc1_class,
1564 &hf_6lowpan_hc1_next,
1565 &hf_6lowpan_hc1_more,
1566 NULL
1568 static int * const hc2_encodings[] = {
1569 &hf_6lowpan_hc2_udp_src,
1570 &hf_6lowpan_hc2_udp_dst,
1571 &hf_6lowpan_hc2_udp_len,
1572 NULL
1575 /*=====================================================
1576 * Parse HC Encoding Flags
1577 *=====================================================
1579 /* Create a tree for the HC1 Header. */
1580 hc_tree = proto_tree_add_subtree(tree, tvb, 0, 2, ett_6lowpan_hc1, &hc_item, "HC1 Encoding");
1582 /* Get and display the pattern. */
1583 proto_tree_add_bits_item(hc_tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_HC1_BITS, ENC_BIG_ENDIAN);
1584 offset += 1;
1586 /* Get and display the HC1 encoding bits. */
1587 hc1_encoding = tvb_get_uint8(tvb, offset);
1588 next_header = ((hc1_encoding & LOWPAN_HC1_NEXT) >> 1);
1589 proto_tree_add_bitmask(hc_tree, tvb, offset, hf_6lowpan_hc1_encoding,
1590 ett_6lowpan_hc1_encoding, hc1_encodings, ENC_NA);
1591 offset += 1;
1593 /* Get and display the HC2 encoding bits, if present. */
1594 if (hc1_encoding & LOWPAN_HC1_MORE) {
1595 if (next_header == LOWPAN_HC1_NEXT_UDP) {
1596 hc_udp_encoding = tvb_get_uint8(tvb, offset);
1597 proto_tree_add_bitmask(tree, tvb, offset, hf_6lowpan_hc2_udp_encoding,
1598 ett_6lowpan_hc2_udp, hc2_encodings, ENC_NA);
1599 offset += 1;
1601 else {
1602 /* HC1 states there are more bits, but an illegal next header was defined. */
1603 expert_add_info(pinfo, hc_item, &ei_6lowpan_hc1_more_bits);
1604 return NULL;
1608 /*=====================================================
1609 * Parse Uncompressed IPv6 Header Fields
1610 *=====================================================
1613 * And now all hell breaks loose. After the header encoding fields, we are
1614 * left with an assortment of optional fields from the IPv6 header,
1615 * depending on which fields are present or not, the headers may not be
1616 * aligned to an octet boundary.
1618 * From now on we have to parse the uncompressed fields relative to a bit
1619 * offset.
1621 bit_offset = offset << 3;
1623 /* Parse hop limit */
1624 ipv6.ip6h_hlim = tvb_get_bits8(tvb, bit_offset, LOWPAN_IPV6_HOP_LIMIT_BITS);
1625 proto_tree_add_uint(tree, hf_6lowpan_hop_limit, tvb, bit_offset>>3,
1626 BITS_TO_BYTE_LEN(bit_offset, LOWPAN_IPV6_HOP_LIMIT_BITS), ipv6.ip6h_hlim);
1627 bit_offset += LOWPAN_IPV6_HOP_LIMIT_BITS;
1629 /*=====================================================
1630 * Parse/Decompress IPv6 Source Address
1631 *=====================================================
1633 offset = bit_offset;
1634 if (!(hc1_encoding & LOWPAN_HC1_SOURCE_PREFIX)) {
1635 for (i=0; i<8; i++, bit_offset += 8) {
1636 ipv6.ip6h_src.bytes[i] = tvb_get_bits8(tvb, bit_offset, 8);
1639 else {
1640 memcpy(ipv6.ip6h_src.bytes, lowpan_llprefix, sizeof(lowpan_llprefix));
1642 if (!(hc1_encoding & LOWPAN_HC1_SOURCE_IFC)) {
1643 for (i=8; i<16; i++, bit_offset += 8) {
1644 ipv6.ip6h_src.bytes[i] = tvb_get_bits8(tvb, bit_offset, 8);
1647 else {
1648 memcpy(&ipv6.ip6h_src.bytes[sizeof(ipv6.ip6h_src) - LOWPAN_IFC_ID_LEN], siid, LOWPAN_IFC_ID_LEN);
1650 /* Display the source address. */
1651 proto_tree_add_ipv6(tree, hf_6lowpan_source, tvb, offset>>3,
1652 BITS_TO_BYTE_LEN(offset, (bit_offset-offset)), &ipv6.ip6h_src);
1655 * Do not set the address columns until after defragmentation, since we have
1656 * to do decompression before reassembly, and changing the address will cause
1657 * wireshark to think that the middle fragments came from another device.
1660 /*=====================================================
1661 * Parse/Decompress IPv6 Destination Address
1662 *=====================================================
1664 offset = bit_offset;
1665 if (!(hc1_encoding & LOWPAN_HC1_DEST_PREFIX)) {
1666 for (i=0; i<8; i++, bit_offset += 8) {
1667 ipv6.ip6h_dst.bytes[i] = tvb_get_bits8(tvb, bit_offset, 8);
1670 else {
1671 memcpy(ipv6.ip6h_dst.bytes, lowpan_llprefix, sizeof(lowpan_llprefix));
1673 if (!(hc1_encoding & LOWPAN_HC1_DEST_IFC)) {
1674 for (i=8; i<16; i++, bit_offset += 8) {
1675 ipv6.ip6h_dst.bytes[i] = tvb_get_bits8(tvb, bit_offset, 8);
1678 else {
1679 memcpy(&ipv6.ip6h_dst.bytes[sizeof(ipv6.ip6h_dst) - LOWPAN_IFC_ID_LEN], diid, LOWPAN_IFC_ID_LEN);
1681 /* Display the destination address. */
1682 proto_tree_add_ipv6(tree, hf_6lowpan_dest, tvb, offset>>3,
1683 BITS_TO_BYTE_LEN(offset, (bit_offset-offset)), &ipv6.ip6h_dst);
1686 * Do not set the address columns until after defragmentation, since we have
1687 * to do decompression before reassembly, and changing the address will cause
1688 * wireshark to think that the middle fragments came from another device.
1691 /* Parse the traffic class and flow label. */
1692 ipv6_class = 0;
1693 ipv6_flow = 0;
1694 if (!(hc1_encoding & LOWPAN_HC1_TRAFFIC_CLASS)) {
1695 /* Parse the traffic class. */
1696 ipv6_class = tvb_get_bits8(tvb, bit_offset, LOWPAN_IPV6_TRAFFIC_CLASS_BITS);
1697 proto_tree_add_uint(tree, hf_6lowpan_traffic_class, tvb, bit_offset>>3,
1698 BITS_TO_BYTE_LEN(bit_offset, LOWPAN_IPV6_TRAFFIC_CLASS_BITS), ipv6_class);
1699 bit_offset += LOWPAN_IPV6_TRAFFIC_CLASS_BITS;
1701 /* Parse the flow label. */
1702 ipv6_flow = tvb_get_bits32(tvb, bit_offset, LOWPAN_IPV6_FLOW_LABEL_BITS, ENC_BIG_ENDIAN);
1703 proto_tree_add_uint(tree, hf_6lowpan_flow_label, tvb, bit_offset>>3,
1704 BITS_TO_BYTE_LEN(bit_offset, LOWPAN_IPV6_FLOW_LABEL_BITS), ipv6_flow);
1705 bit_offset += LOWPAN_IPV6_FLOW_LABEL_BITS;
1708 /* Rebuild the IPv6 flow label, traffic class and version fields. */
1709 ipv6.ip6h_vc_flow = ipv6_flow;
1710 ipv6.ip6h_vc_flow |= ((uint32_t)ipv6_class << LOWPAN_IPV6_FLOW_LABEL_BITS);
1711 ipv6.ip6h_vc_flow |= ((uint32_t)0x6 << (LOWPAN_IPV6_TRAFFIC_CLASS_BITS + LOWPAN_IPV6_FLOW_LABEL_BITS));
1712 ipv6.ip6h_vc_flow = g_ntohl(ipv6.ip6h_vc_flow);
1714 /* Parse the IPv6 next header field. */
1715 if (next_header == LOWPAN_HC1_NEXT_UDP) {
1716 ipv6.ip6h_nxt = IP_PROTO_UDP;
1718 else if (next_header == LOWPAN_HC1_NEXT_ICMP) {
1719 ipv6.ip6h_nxt = IP_PROTO_ICMPV6;
1721 else if (next_header == LOWPAN_HC1_NEXT_TCP) {
1722 ipv6.ip6h_nxt = IP_PROTO_TCP;
1724 else {
1725 /* Parse the next header field. */
1726 ipv6.ip6h_nxt = tvb_get_bits8(tvb, bit_offset, LOWPAN_IPV6_NEXT_HEADER_BITS);
1727 proto_tree_add_uint_format_value(tree, hf_6lowpan_next_header, tvb, bit_offset>>3,
1728 BITS_TO_BYTE_LEN(bit_offset, LOWPAN_IPV6_NEXT_HEADER_BITS), ipv6.ip6h_nxt,
1729 "%s (0x%02x)", ipprotostr(ipv6.ip6h_nxt), ipv6.ip6h_nxt);
1730 bit_offset += LOWPAN_IPV6_NEXT_HEADER_BITS;
1733 /*=====================================================
1734 * Parse and Reconstruct the UDP Header
1735 *=====================================================
1737 if ((hc1_encoding & LOWPAN_HC1_MORE) && (next_header == LOWPAN_HC1_NEXT_UDP)) {
1738 struct udp_hdr udp;
1739 int length;
1741 /* Parse the source port. */
1742 offset = bit_offset;
1743 if (hc_udp_encoding & LOWPAN_HC2_UDP_SRCPORT) {
1744 udp.src_port = tvb_get_bits8(tvb, bit_offset, LOWPAN_UDP_PORT_COMPRESSED_BITS) + LOWPAN_PORT_12BIT_OFFSET;
1745 bit_offset += LOWPAN_UDP_PORT_COMPRESSED_BITS;
1747 else {
1748 udp.src_port = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_PORT_BITS, ENC_BIG_ENDIAN);
1749 bit_offset += LOWPAN_UDP_PORT_BITS;
1751 proto_tree_add_uint(tree, hf_6lowpan_udp_src, tvb, offset>>3,
1752 BITS_TO_BYTE_LEN(offset, (bit_offset-offset)), udp.src_port);
1753 udp.src_port = g_ntohs(udp.src_port);
1755 /* Parse the destination port. */
1756 offset = bit_offset;
1757 if (hc_udp_encoding & LOWPAN_HC2_UDP_DSTPORT) {
1758 udp.dst_port = tvb_get_bits8(tvb, bit_offset, LOWPAN_UDP_PORT_COMPRESSED_BITS) + LOWPAN_PORT_12BIT_OFFSET;
1759 bit_offset += LOWPAN_UDP_PORT_COMPRESSED_BITS;
1761 else {
1762 udp.dst_port = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_PORT_BITS, ENC_BIG_ENDIAN);
1763 bit_offset += LOWPAN_UDP_PORT_BITS;
1765 proto_tree_add_uint(tree, hf_6lowpan_udp_dst, tvb, offset>>3,
1766 BITS_TO_BYTE_LEN(offset, (bit_offset-offset)), udp.dst_port);
1767 udp.dst_port = g_ntohs(udp.dst_port);
1769 /* Parse the length, if present. */
1770 if (!(hc_udp_encoding & LOWPAN_HC2_UDP_LENGTH)) {
1771 udp.length = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_LENGTH_BITS, ENC_BIG_ENDIAN);
1772 proto_tree_add_uint(tree, hf_6lowpan_udp_len, tvb, bit_offset>>3,
1773 BITS_TO_BYTE_LEN(bit_offset, LOWPAN_UDP_LENGTH_BITS), udp.length);
1775 bit_offset += LOWPAN_UDP_LENGTH_BITS;
1777 /* Compute the length from the fragmentation headers. */
1778 else if (dgram_size >= 0) {
1779 if (dgram_size < IPv6_HDR_SIZE) {
1780 /* Datagram size is too small */
1781 return NULL;
1783 udp.length = dgram_size - IPv6_HDR_SIZE;
1785 /* Compute the length from the tvbuff size. */
1786 else {
1787 udp.length = tvb_reported_length(tvb);
1788 udp.length -= BITS_TO_BYTE_LEN(0, bit_offset + LOWPAN_UDP_CHECKSUM_BITS);
1789 udp.length += (int)sizeof(struct udp_hdr);
1791 udp.length = g_ntohs(udp.length);
1793 /* Parse the checksum. */
1794 udp.checksum = tvb_get_bits16(tvb, bit_offset, LOWPAN_UDP_CHECKSUM_BITS, ENC_BIG_ENDIAN);
1795 proto_tree_add_uint(tree, hf_6lowpan_udp_checksum, tvb, bit_offset>>3,
1796 BITS_TO_BYTE_LEN(bit_offset, LOWPAN_UDP_CHECKSUM_BITS), udp.checksum);
1797 bit_offset += LOWPAN_UDP_CHECKSUM_BITS;
1798 udp.checksum = g_ntohs(udp.checksum);
1800 /* Construct the next header for the UDP datagram. */
1801 offset = BITS_TO_BYTE_LEN(0, bit_offset);
1802 length = tvb_captured_length_remaining(tvb, offset);
1803 nhdr_list = (struct lowpan_nhdr *)wmem_alloc(pinfo->pool, sizeof(struct lowpan_nhdr) + sizeof(struct udp_hdr) + length);
1804 nhdr_list->next = NULL;
1805 nhdr_list->proto = IP_PROTO_UDP;
1806 nhdr_list->length = length + (int)sizeof(struct udp_hdr);
1807 nhdr_list->reported = g_ntohs(udp.length);
1809 /* Copy the UDP header into the buffer. */
1810 memcpy(LOWPAN_NHDR_DATA(nhdr_list), &udp, sizeof(struct udp_hdr));
1811 tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr_list) + sizeof(struct udp_hdr), offset, length);
1813 /*=====================================================
1814 * Reconstruct the IPv6 Packet
1815 *=====================================================
1817 else {
1818 int length;
1819 offset = BITS_TO_BYTE_LEN(0, bit_offset);
1820 length = tvb_captured_length_remaining(tvb, offset);
1821 nhdr_list = (struct lowpan_nhdr *)wmem_alloc(pinfo->pool, sizeof(struct lowpan_nhdr) + length);
1822 nhdr_list->next = NULL;
1823 nhdr_list->proto = ipv6.ip6h_nxt;
1824 nhdr_list->length = length;
1825 if (dgram_size < 0) {
1826 nhdr_list->reported = tvb_reported_length_remaining(tvb, offset);
1828 else {
1829 nhdr_list->reported = dgram_size - IPv6_HDR_SIZE;
1831 tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr_list), offset, nhdr_list->length);
1834 /* Link the reassembled tvbuff together. */
1835 ipv6_tvb = lowpan_reassemble_ipv6(tvb, pinfo, &ipv6, nhdr_list);
1837 /* Add a new data source for it. */
1838 add_new_data_source(pinfo, ipv6_tvb, "Decompressed 6LoWPAN HC1");
1840 return ipv6_tvb;
1841 } /* dissect_6lowpan_hc1 */
1843 /*FUNCTION:------------------------------------------------------
1844 * NAME
1845 * dissect_6lowpan_iphc
1846 * DESCRIPTION
1847 * Dissector routine for a 6LoWPAN IPHC header.
1849 * This header is still in the draft phase, but is expected
1850 * to replace HC1.
1852 * See draft-ietf-6lowpan-hc-15.txt
1853 * PARAMETERS
1854 * tvb ; packet buffer.
1855 * pinfo ; packet info.
1856 * tree ; 6LoWPAN display tree.
1857 * dgram_size ; Datagram size (or <0 if not fragmented).
1858 * siid ; Source Interface ID.
1859 * diid ; Destination Interface ID.
1860 * RETURNS
1861 * tvbuff_t * ; The remaining payload to be parsed or NULL on error.
1862 *---------------------------------------------------------------
1864 static tvbuff_t *
1865 // NOLINTNEXTLINE(misc-no-recursion)
1866 dissect_6lowpan_iphc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int dgram_size, const uint8_t *siid, const uint8_t *diid)
1868 ieee802154_hints_t *hints;
1869 uint16_t hint_panid;
1870 int offset = 0;
1871 int length = 0;
1872 proto_tree * iphc_tree;
1873 proto_item * ti_dam = NULL;
1874 proto_item * ti;
1875 /* IPHC header fields. */
1876 uint16_t iphc_flags;
1877 uint8_t iphc_traffic;
1878 uint8_t iphc_hop_limit;
1879 uint8_t iphc_src_mode;
1880 uint8_t iphc_dst_mode;
1881 uint8_t iphc_ctx = 0;
1882 /* Contexts to use for address decompression. */
1883 int iphc_sci = LOWPAN_CONTEXT_DEFAULT;
1884 int iphc_dci = LOWPAN_CONTEXT_DEFAULT;
1885 lowpan_context_data *sctx;
1886 lowpan_context_data *dctx;
1887 /* IPv6 header */
1888 uint8_t ipv6_dscp = 0;
1889 uint8_t ipv6_ecn = 0;
1890 uint32_t ipv6_flowlabel = 0;
1891 struct ws_ip6_hdr ipv6;
1892 tvbuff_t * ipv6_tvb;
1893 /* Next header chain */
1894 struct lowpan_nhdr *nhdr_list;
1896 /* Lookup the IEEE 802.15.4 addressing hints. */
1897 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
1898 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
1899 hint_panid = (hints) ? (hints->src_pan) : (IEEE802154_BCAST_PAN);
1901 /* Create a tree for the IPHC header. */
1902 iphc_tree = proto_tree_add_subtree(tree, tvb, 0, 2, ett_6lowpan_iphc, NULL, "IPHC Header");
1904 /* Display the pattern. */
1905 proto_tree_add_bits_item(iphc_tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_IPHC_BITS, ENC_BIG_ENDIAN);
1907 /*=====================================================
1908 * Parse IPHC Header flags.
1909 *=====================================================
1911 iphc_flags = tvb_get_ntohs(tvb, offset);
1912 iphc_traffic = (iphc_flags & LOWPAN_IPHC_FLAG_FLOW) >> LOWPAN_IPHC_FLAG_OFFSET_FLOW;
1913 iphc_hop_limit = (iphc_flags & LOWPAN_IPHC_FLAG_HLIM) >> LOWPAN_IPHC_FLAG_OFFSET_HLIM;
1914 iphc_src_mode = (iphc_flags & LOWPAN_IPHC_FLAG_SRC_MODE) >> LOWPAN_IPHC_FLAG_OFFSET_SRC_MODE;
1915 iphc_dst_mode = (iphc_flags & LOWPAN_IPHC_FLAG_DST_MODE) >> LOWPAN_IPHC_FLAG_OFFSET_DST_MODE;
1916 if (tree) {
1917 const value_string *am_vs;
1918 proto_tree_add_uint (iphc_tree, hf_6lowpan_iphc_flag_tf, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_FLOW);
1919 proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_nhdr, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_NHDR);
1920 proto_tree_add_uint (iphc_tree, hf_6lowpan_iphc_flag_hlim, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_HLIM);
1921 proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_cid, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_CONTEXT_ID);
1922 proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_sac, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP);
1923 am_vs = iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP ? lowpan_iphc_saddr_stateful_modes : lowpan_iphc_addr_modes;
1924 proto_tree_add_uint_format_value(iphc_tree, hf_6lowpan_iphc_flag_sam, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_SRC_MODE,
1925 "%s (0x%04x)", val_to_str_const(iphc_src_mode, am_vs, "Reserved"), iphc_src_mode);
1926 proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_mcast, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_MCAST_COMP);
1927 proto_tree_add_boolean (iphc_tree, hf_6lowpan_iphc_flag_dac, tvb, offset, 2, iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP);
1928 /* Destination address mode changes meanings depending on multicast compression. */
1929 if (iphc_flags & LOWPAN_IPHC_FLAG_MCAST_COMP) {
1930 if (iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP) {
1931 am_vs = lowpan_iphc_mcast_stateful_modes;
1932 } else {
1933 am_vs = lowpan_iphc_mcast_modes;
1935 } else {
1936 if (iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP) {
1937 am_vs = lowpan_iphc_daddr_stateful_modes;
1938 } else {
1939 am_vs = lowpan_iphc_addr_modes;
1942 ti_dam = proto_tree_add_uint_format_value(iphc_tree, hf_6lowpan_iphc_flag_dam, tvb, offset, 2,
1943 iphc_flags & LOWPAN_IPHC_FLAG_DST_MODE, "%s (0x%04x)", val_to_str_const(iphc_dst_mode, am_vs, "Reserved"), iphc_dst_mode);
1945 offset += 2;
1947 /* Display the context identifier extension, if present. */
1948 if (iphc_flags & LOWPAN_IPHC_FLAG_CONTEXT_ID) {
1949 iphc_ctx = tvb_get_uint8(tvb, offset);
1950 iphc_sci = (iphc_ctx & LOWPAN_IPHC_FLAG_SCI) >> LOWPAN_IPHC_FLAG_OFFSET_SCI;
1951 iphc_dci = (iphc_ctx & LOWPAN_IPHC_FLAG_DCI) >> LOWPAN_IPHC_FLAG_OFFSET_DCI;
1952 proto_tree_add_uint(iphc_tree, hf_6lowpan_iphc_sci, tvb, offset, 1, iphc_ctx & LOWPAN_IPHC_FLAG_SCI);
1953 proto_tree_add_uint(iphc_tree, hf_6lowpan_iphc_dci, tvb, offset, 1, iphc_ctx & LOWPAN_IPHC_FLAG_DCI);
1954 offset += 1;
1956 /* Use link-local contexts if stateless. */
1957 if (!(iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP)) {
1958 iphc_sci = LOWPAN_CONTEXT_LINK_LOCAL;
1960 if (!(iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP)) {
1961 iphc_dci = LOWPAN_CONTEXT_LINK_LOCAL;
1963 /* Lookup the contexts. */
1965 * Don't display their origin until after we decompress the address in case
1966 * the address modes indicate that we should use a different context.
1968 sctx = lowpan_context_find(iphc_sci, hint_panid);
1969 dctx = lowpan_context_find(iphc_dci, hint_panid);
1971 /*=====================================================
1972 * Parse Traffic Class and Flow Label
1973 *=====================================================
1975 offset <<= 3;
1976 /* Parse the ECN field. */
1977 if (iphc_traffic != LOWPAN_IPHC_FLOW_COMPRESSED) {
1978 ipv6_ecn = tvb_get_bits8(tvb, offset, LOWPAN_IPHC_ECN_BITS);
1979 proto_tree_add_bits_item(tree, hf_6lowpan_ecn, tvb, offset, LOWPAN_IPHC_ECN_BITS, ENC_BIG_ENDIAN);
1980 offset += LOWPAN_IPHC_ECN_BITS;
1982 /* Parse the DSCP field. */
1983 if ((iphc_traffic == LOWPAN_IPHC_FLOW_CLASS_LABEL) || (iphc_traffic == LOWPAN_IPHC_FLOW_CLASS)) {
1984 ipv6_dscp = tvb_get_bits8(tvb, offset, LOWPAN_IPHC_DSCP_BITS);
1985 proto_tree_add_bits_item(tree, hf_6lowpan_dscp, tvb, offset, LOWPAN_IPHC_DSCP_BITS, LOWPAN_IPHC_DSCP_BITS);
1986 offset += LOWPAN_IPHC_DSCP_BITS;
1988 /* Add a generated entry to show the IPv6 traffic class byte. */
1989 if (ipv6_dscp || ipv6_ecn) {
1990 proto_item *tclass_item;
1991 tclass_item = proto_tree_add_uint(tree, hf_6lowpan_traffic_class, tvb, 0, 0,
1992 (ipv6_dscp << LOWPAN_IPHC_ECN_BITS) | ipv6_ecn);
1993 proto_item_set_generated(tclass_item);
1996 /* Parse the flow label. */
1997 if ((iphc_traffic == LOWPAN_IPHC_FLOW_CLASS_LABEL) || (iphc_traffic == LOWPAN_IPHC_FLOW_ECN_LABEL)) {
1998 /* Pad to 4-bits past the start of the byte. */
1999 unsigned pad_bits = ((4 - offset) & 0x7);
2000 if (pad_bits) {
2001 proto_tree_add_bits_item(tree, hf_6lowpan_padding, tvb, offset, pad_bits, ENC_BIG_ENDIAN);
2003 offset += pad_bits;
2004 ipv6_flowlabel = tvb_get_bits32(tvb, offset, LOWPAN_IPHC_LABEL_BITS, ENC_BIG_ENDIAN);
2005 proto_tree_add_bits_item(tree, hf_6lowpan_flow_label, tvb, offset, LOWPAN_IPHC_LABEL_BITS, ENC_BIG_ENDIAN);
2006 offset += LOWPAN_IPHC_LABEL_BITS;
2009 /* Rebuild the IPv6 flow label, traffic class and version fields. */
2010 ipv6.ip6h_vc_flow = ipv6_flowlabel;
2011 ipv6.ip6h_vc_flow |= ((uint32_t)ipv6_ecn << LOWPAN_IPV6_FLOW_LABEL_BITS);
2012 ipv6.ip6h_vc_flow |= ((uint32_t)ipv6_dscp << (LOWPAN_IPHC_ECN_BITS + LOWPAN_IPV6_FLOW_LABEL_BITS));
2013 ipv6.ip6h_vc_flow |= ((uint32_t)0x6 << (LOWPAN_IPV6_TRAFFIC_CLASS_BITS + LOWPAN_IPV6_FLOW_LABEL_BITS));
2014 ipv6.ip6h_vc_flow = g_ntohl(ipv6.ip6h_vc_flow);
2016 /* Convert back to byte offsets. */
2017 offset >>= 3;
2019 /*=====================================================
2020 * Parse Next Header and Hop Limit
2021 *=====================================================
2023 /* Get the next header field, if present. */
2024 if (!(iphc_flags & LOWPAN_IPHC_FLAG_NHDR)) {
2025 ipv6.ip6h_nxt = tvb_get_uint8(tvb, offset);
2026 proto_tree_add_uint_format_value(tree, hf_6lowpan_next_header, tvb, offset, 1, ipv6.ip6h_nxt,
2027 "%s (0x%02x)", ipprotostr(ipv6.ip6h_nxt), ipv6.ip6h_nxt);
2028 offset += 1;
2031 /* Get the hop limit field, if present. */
2032 if (iphc_hop_limit == LOWPAN_IPHC_HLIM_1) {
2033 ipv6.ip6h_hlim = 1;
2035 else if (iphc_hop_limit == LOWPAN_IPHC_HLIM_64) {
2036 ipv6.ip6h_hlim = 64;
2038 else if (iphc_hop_limit == LOWPAN_IPHC_HLIM_255) {
2039 ipv6.ip6h_hlim = 255;
2041 else {
2042 ipv6.ip6h_hlim = tvb_get_uint8(tvb, offset);
2043 proto_tree_add_uint(tree, hf_6lowpan_hop_limit, tvb, offset, 1, ipv6.ip6h_hlim);
2044 offset += 1;
2047 /*=====================================================
2048 * Parse and decompress the source address.
2049 *=====================================================
2051 length = 0;
2052 memset(&ipv6.ip6h_src, 0, sizeof(ipv6.ip6h_src));
2053 /* (SAC=1 && SAM=00) -> the unspecified address (::). */
2054 if ((iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP) && (iphc_src_mode == LOWPAN_IPHC_ADDR_SRC_UNSPEC)) {
2055 sctx = &lowpan_context_default;
2057 /* The IID is derived from the encapsulating layer. */
2058 else if (iphc_src_mode == LOWPAN_IPHC_ADDR_COMPRESSED) {
2059 memcpy(&ipv6.ip6h_src.bytes[sizeof(ipv6.ip6h_src) - LOWPAN_IFC_ID_LEN], siid, LOWPAN_IFC_ID_LEN);
2061 /* Full Address inline. */
2062 else if (iphc_src_mode == LOWPAN_IPHC_ADDR_FULL_INLINE) {
2063 if (!(iphc_flags & LOWPAN_IPHC_FLAG_SRC_COMP)) sctx = &lowpan_context_default;
2064 length = (int)sizeof(ipv6.ip6h_src);
2065 tvb_memcpy(tvb, &ipv6.ip6h_src, offset, length);
2067 /* 64-bits inline. */
2068 else if (iphc_src_mode == LOWPAN_IPHC_ADDR_64BIT_INLINE) {
2069 length = 8;
2070 tvb_memcpy(tvb, &ipv6.ip6h_src.bytes[sizeof(ipv6.ip6h_src) - length], offset, length);
2072 /* 16-bits inline. */
2073 else if (iphc_src_mode == LOWPAN_IPHC_ADDR_16BIT_INLINE) {
2074 length = 2;
2075 /* Format becomes ff:fe00:xxxx */
2076 ipv6.ip6h_src.bytes[11] = 0xff;
2077 ipv6.ip6h_src.bytes[12] = 0xfe;
2078 tvb_memcpy(tvb, &ipv6.ip6h_src.bytes[sizeof(ipv6.ip6h_src) - length], offset, length);
2081 /* Copy the context bits. */
2082 lowpan_pfxcpy(&ipv6.ip6h_src, &sctx->prefix, sctx->plen);
2083 /* Update the IID of the encapsulating layer. */
2084 siid = &ipv6.ip6h_src.bytes[sizeof(ipv6.ip6h_src) - LOWPAN_IFC_ID_LEN];
2086 /* Display the source IPv6 address. */
2087 ti = proto_tree_add_ipv6(tree, hf_6lowpan_source, tvb, offset, length, &ipv6.ip6h_src);
2088 if (length == 0) {
2089 proto_item_set_generated(ti);
2091 if (ipv6_summary_in_tree) {
2092 address src_addr = ADDRESS_INIT(AT_IPv6, sizeof(ipv6.ip6h_src), &ipv6.ip6h_src);
2093 proto_item_append_text(tree, ", Src: %s", address_with_resolution_to_str(pinfo->pool, &src_addr));
2096 /* Add information about where the context came from. */
2097 /* TODO: We should display the prefix length too. */
2098 if (sctx->plen) {
2099 ti = proto_tree_add_ipv6(iphc_tree, hf_6lowpan_iphc_sctx_prefix, tvb, 0, 0, &sctx->prefix);
2100 proto_item_set_generated(ti);
2101 if ( sctx->frame ) {
2102 ti = proto_tree_add_uint(iphc_tree, hf_6lowpan_iphc_sctx_origin, tvb, 0, 0, sctx->frame);
2103 proto_item_set_generated(ti);
2106 offset += length;
2108 * Do not set the address columns until after defragmentation, since we have
2109 * to do decompression before reassembly, and changing the address will cause
2110 * wireshark to think that the middle fragments came from another device.
2113 /*=====================================================
2114 * Parse and decompress a multicast address.
2115 *=====================================================
2117 length = 0;
2118 memset(&ipv6.ip6h_dst, 0, sizeof(ipv6.ip6h_dst));
2119 /* Stateless multicast compression. */
2120 if ((iphc_flags & LOWPAN_IPHC_FLAG_MCAST_COMP) && !(iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP)) {
2121 if (iphc_dst_mode == LOWPAN_IPHC_ADDR_FULL_INLINE) {
2122 length = (int)sizeof(ipv6.ip6h_dst);
2123 tvb_memcpy(tvb, &ipv6.ip6h_dst.bytes[sizeof(ipv6.ip6h_dst) - length], offset, length);
2125 else if (iphc_dst_mode == LOWPAN_IPHC_MCAST_48BIT) {
2126 ipv6.ip6h_dst.bytes[0] = 0xff;
2127 ipv6.ip6h_dst.bytes[1] = tvb_get_uint8(tvb, offset + (length++));
2128 ipv6.ip6h_dst.bytes[11] = tvb_get_uint8(tvb, offset + (length++));
2129 ipv6.ip6h_dst.bytes[12] = tvb_get_uint8(tvb, offset + (length++));
2130 ipv6.ip6h_dst.bytes[13] = tvb_get_uint8(tvb, offset + (length++));
2131 ipv6.ip6h_dst.bytes[14] = tvb_get_uint8(tvb, offset + (length++));
2132 ipv6.ip6h_dst.bytes[15] = tvb_get_uint8(tvb, offset + (length++));
2134 else if (iphc_dst_mode == LOWPAN_IPHC_MCAST_32BIT) {
2135 ipv6.ip6h_dst.bytes[0] = 0xff;
2136 ipv6.ip6h_dst.bytes[1] = tvb_get_uint8(tvb, offset + (length++));
2137 ipv6.ip6h_dst.bytes[13] = tvb_get_uint8(tvb, offset + (length++));
2138 ipv6.ip6h_dst.bytes[14] = tvb_get_uint8(tvb, offset + (length++));
2139 ipv6.ip6h_dst.bytes[15] = tvb_get_uint8(tvb, offset + (length++));
2141 else if (iphc_dst_mode == LOWPAN_IPHC_MCAST_8BIT) {
2142 ipv6.ip6h_dst.bytes[0] = 0xff;
2143 ipv6.ip6h_dst.bytes[1] = 0x02;
2144 ipv6.ip6h_dst.bytes[15] = tvb_get_uint8(tvb, offset + (length++));
2146 else {
2147 /* Illegal destination address compression mode. */
2148 expert_add_info(pinfo, ti_dam, &ei_6lowpan_illegal_dest_addr_mode);
2149 return NULL;
2152 /* Stateful multicast compression. */
2153 else if ((iphc_flags & LOWPAN_IPHC_FLAG_MCAST_COMP) && (iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP)) {
2154 if (iphc_dst_mode == LOWPAN_IPHC_MCAST_STATEFUL_48BIT) {
2155 /* RFC 3306 unicast-prefix based multicast address of the form:
2156 * ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
2157 * XX = inline byte.
2158 * LL = prefix/context length (up to 64-bits).
2159 * PP = prefix/context byte.
2161 ipv6.ip6h_dst.bytes[0] = 0xff;
2162 ipv6.ip6h_dst.bytes[1] = tvb_get_uint8(tvb, offset + (length++));
2163 ipv6.ip6h_dst.bytes[2] = tvb_get_uint8(tvb, offset + (length++));
2164 ipv6.ip6h_dst.bytes[3] = (dctx->plen > 64) ? (64) : (dctx->plen);
2165 memcpy(&ipv6.ip6h_dst.bytes[4], &dctx->prefix, 8);
2166 ipv6.ip6h_dst.bytes[12] = tvb_get_uint8(tvb, offset + (length++));
2167 ipv6.ip6h_dst.bytes[13] = tvb_get_uint8(tvb, offset + (length++));
2168 ipv6.ip6h_dst.bytes[14] = tvb_get_uint8(tvb, offset + (length++));
2169 ipv6.ip6h_dst.bytes[15] = tvb_get_uint8(tvb, offset + (length++));
2171 else {
2172 /* Illegal destination address compression mode. */
2173 expert_add_info(pinfo, ti_dam, &ei_6lowpan_illegal_dest_addr_mode);
2174 return NULL;
2178 /*=====================================================
2179 * Parse and decompress a unicast destination address.
2180 *=====================================================
2182 else {
2183 /* (DAC=1 && DAM=00) -> reserved value. */
2184 if ((iphc_flags & LOWPAN_IPHC_FLAG_DST_COMP) && (iphc_dst_mode == LOWPAN_IPHC_ADDR_FULL_INLINE)) {
2185 /* Illegal destination address compression mode. */
2186 expert_add_info(pinfo, ti_dam, &ei_6lowpan_illegal_dest_addr_mode);
2187 return NULL;
2189 /* The IID is derived from the link-layer source. */
2190 else if (iphc_dst_mode == LOWPAN_IPHC_ADDR_COMPRESSED) {
2191 memcpy(&ipv6.ip6h_dst.bytes[sizeof(ipv6.ip6h_dst) - LOWPAN_IFC_ID_LEN], diid, LOWPAN_IFC_ID_LEN);
2193 /* Full Address inline. */
2194 else if (iphc_dst_mode == LOWPAN_IPHC_ADDR_FULL_INLINE) {
2195 dctx = &lowpan_context_default;
2196 length = (int)sizeof(ipv6.ip6h_dst);
2197 tvb_memcpy(tvb, &ipv6.ip6h_dst, offset, length);
2199 /* 64-bits inline. */
2200 else if (iphc_dst_mode == LOWPAN_IPHC_ADDR_64BIT_INLINE) {
2201 length = 8;
2202 tvb_memcpy(tvb, &ipv6.ip6h_dst.bytes[sizeof(ipv6.ip6h_dst) - length], offset, length);
2204 /* 16-bits inline. */
2205 else if (iphc_dst_mode == LOWPAN_IPHC_ADDR_16BIT_INLINE) {
2206 length = 2;
2207 /* Format becomes ff:fe00:xxxx */
2208 ipv6.ip6h_dst.bytes[11] = 0xff;
2209 ipv6.ip6h_dst.bytes[12] = 0xfe;
2210 tvb_memcpy(tvb, &ipv6.ip6h_dst.bytes[sizeof(ipv6.ip6h_dst) - length], offset, length);
2212 /* Copy the context bits. */
2213 lowpan_pfxcpy(&ipv6.ip6h_dst, &dctx->prefix, dctx->plen);
2214 /* Update the interface id of the encapsulating layer. */
2215 diid = &ipv6.ip6h_dst.bytes[sizeof(ipv6.ip6h_dst) - LOWPAN_IFC_ID_LEN];
2218 /* Display the destination IPv6 address. */
2219 ti = proto_tree_add_ipv6(tree, hf_6lowpan_dest, tvb, offset, length, &ipv6.ip6h_dst);
2220 if (length == 0) {
2221 proto_item_set_generated(ti);
2223 if (ipv6_summary_in_tree) {
2224 address dst_addr = ADDRESS_INIT(AT_IPv6, sizeof(ipv6.ip6h_dst), &ipv6.ip6h_dst);
2225 proto_item_append_text(tree, ", Dest: %s", address_with_resolution_to_str(pinfo->pool, &dst_addr));
2228 /* Add information about where the context came from. */
2229 /* TODO: We should display the prefix length too. */
2230 if (dctx->plen) {
2231 ti = proto_tree_add_ipv6(iphc_tree, hf_6lowpan_iphc_dctx_prefix, tvb, 0, 0, &dctx->prefix);
2232 proto_item_set_generated(ti);
2233 if ( dctx->frame ) {
2234 ti = proto_tree_add_uint(iphc_tree, hf_6lowpan_iphc_dctx_origin, tvb, 0, 0, dctx->frame);
2235 proto_item_set_generated(ti);
2238 offset += length;
2240 * Do not set the address columns until after defragmentation, since we have
2241 * to do decompression before reassembly, and changing the address will cause
2242 * wireshark to think that the middle fragments came from another device.
2245 /*=====================================================
2246 * Decompress extension headers.
2247 *=====================================================
2249 /* Parse the list of extension headers. */
2250 if (iphc_flags & LOWPAN_IPHC_FLAG_NHDR) {
2251 /* Parse the next header protocol identifier. */
2252 ipv6.ip6h_nxt = lowpan_parse_nhc_proto(tvb, offset);
2254 /* Parse the 6LoWPAN NHC fields. */
2255 nhdr_list = dissect_6lowpan_iphc_nhc(tvb, pinfo, tree, offset, dgram_size - IPv6_HDR_SIZE, siid, diid);
2257 /* Create an extension header for the remaining payload. */
2258 else {
2259 length = tvb_captured_length_remaining(tvb, offset);
2260 nhdr_list = (struct lowpan_nhdr *)wmem_alloc(pinfo->pool, sizeof(struct lowpan_nhdr) + length);
2261 nhdr_list->next = NULL;
2262 nhdr_list->proto = ipv6.ip6h_nxt;
2263 nhdr_list->length = length;
2264 if (dgram_size < 0) {
2265 nhdr_list->reported = tvb_reported_length_remaining(tvb, offset);
2267 else {
2268 nhdr_list->reported = dgram_size - IPv6_HDR_SIZE;
2270 tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr_list), offset, nhdr_list->length);
2273 /*=====================================================
2274 * Rebuild the IPv6 packet.
2275 *=====================================================
2277 /* Reassemble the IPv6 packet. */
2278 ipv6_tvb = lowpan_reassemble_ipv6(tvb, pinfo, &ipv6, nhdr_list);
2280 /* Add a new data source for it. */
2281 add_new_data_source(pinfo, ipv6_tvb, "Decompressed 6LoWPAN IPHC");
2283 return ipv6_tvb;
2284 } /* dissect_6lowpan_iphc */
2286 /*FUNCTION:------------------------------------------------------
2287 * NAME
2288 * dissect_6lowpan_iphc_nhc
2289 * DESCRIPTION
2290 * Dissector routine for a 6LoWPAN IPHC next header structure(s).
2291 * PARAMETERS
2292 * tvb ; packet buffer.
2293 * pinfo ; packet info.
2294 * tree ; 6LoWPAN display tree.
2295 * offset ; packet buffer offset.
2296 * dgram_size ; Remaining datagram size (or <0 if unknown).
2297 * siid ; Source Interface ID.
2298 * diid ; Destination Interface ID.
2299 * RETURNS
2300 * lowpan_nhdr * ; List of wmem_alloc'd next header structures.
2301 *---------------------------------------------------------------
2303 static struct lowpan_nhdr *
2304 // NOLINTNEXTLINE(misc-no-recursion)
2305 dissect_6lowpan_iphc_nhc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int dgram_size, const uint8_t *siid, const uint8_t *diid)
2307 int length;
2308 proto_item * ti = NULL;
2309 proto_tree * nhc_tree = NULL;
2310 struct lowpan_nhdr *nhdr;
2312 /*=====================================================
2313 * IP-in-IP Tunneling
2314 *=====================================================
2316 if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_IPV6_BITS) == LOWPAN_NHC_PATTERN_EXT_IPV6) {
2317 uint8_t ext_flags;
2318 tvbuff_t *iphc_tvb;
2320 /* Create a tree for the IPv6 extension header. */
2321 nhc_tree = proto_tree_add_subtree(tree, tvb, offset, 2, ett_6lowpan_nhc_ext, &ti, "IPv6 extension header");
2322 /* Display the IPv6 Extension Header NHC ID pattern. */
2323 proto_tree_add_bits_item(nhc_tree, hf_6lowpan_nhc_pattern, tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_BITS, ENC_BIG_ENDIAN);
2325 /* Get and display the extension header compression flags. */
2326 ext_flags = tvb_get_uint8(tvb, offset);
2327 proto_tree_add_uint(nhc_tree, hf_6lowpan_nhc_ext_eid, tvb, offset, 1, ext_flags & LOWPAN_NHC_EXT_EID);
2328 proto_tree_add_boolean(nhc_tree, hf_6lowpan_nhc_ext_nh, tvb, offset, 1, ext_flags & LOWPAN_NHC_EXT_NHDR);
2329 if (ext_flags & LOWPAN_NHC_EXT_NHDR) {
2330 /* TODO: Flag a warning, the NH bit MUST be 0 when EID==0x7 (IP-in-IP). */
2332 offset += 1;
2334 /* Decode the remainder of the packet using IPHC encoding. */
2335 increment_dissection_depth(pinfo);
2336 iphc_tvb = dissect_6lowpan_iphc(tvb_new_subset_remaining(tvb, offset), pinfo, tree, dgram_size, siid, diid);
2337 decrement_dissection_depth(pinfo);
2339 if (!iphc_tvb) return NULL;
2341 /* Create the next header structure for the tunneled IPv6 header. */
2342 nhdr = (struct lowpan_nhdr *)wmem_alloc0(pinfo->pool, sizeof(struct lowpan_nhdr) + tvb_captured_length(iphc_tvb));
2343 nhdr->next = NULL;
2344 nhdr->proto = IP_PROTO_IPV6;
2345 nhdr->length = tvb_captured_length(iphc_tvb);
2346 nhdr->reported = tvb_reported_length(iphc_tvb);
2347 tvb_memcpy(iphc_tvb, LOWPAN_NHDR_DATA(nhdr), 0, nhdr->length);
2348 return nhdr;
2350 /*=====================================================
2351 * IPv6 Extension Header
2352 *=====================================================
2354 if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_BITS) == LOWPAN_NHC_PATTERN_EXT) {
2355 struct ws_ip6_ext ipv6_ext = {0, 0};
2356 uint8_t ext_flags;
2357 uint8_t ext_hlen;
2358 uint8_t ext_len;
2359 uint8_t ext_proto;
2360 proto_item *ti_ext_len = NULL;
2362 /* Parse the IPv6 extension header protocol. */
2363 ext_proto = lowpan_parse_nhc_proto(tvb, offset);
2365 /* Create a tree for the IPv6 extension header. */
2366 nhc_tree = proto_tree_add_subtree(tree, tvb, offset, 2, ett_6lowpan_nhc_ext, NULL, "IPv6 extension header");
2367 /* Display the IPv6 Extension Header NHC ID pattern. */
2368 proto_tree_add_bits_item(nhc_tree, hf_6lowpan_nhc_pattern, tvb, offset<<3, LOWPAN_NHC_PATTERN_EXT_BITS, ENC_BIG_ENDIAN);
2370 /* Get and display the extension header compression flags. */
2371 ext_flags = tvb_get_uint8(tvb, offset);
2372 proto_tree_add_uint(nhc_tree, hf_6lowpan_nhc_ext_eid, tvb, offset, 1, ext_flags & LOWPAN_NHC_EXT_EID);
2373 proto_tree_add_boolean(nhc_tree, hf_6lowpan_nhc_ext_nh, tvb, offset, 1, ext_flags & LOWPAN_NHC_EXT_NHDR);
2374 offset += 1;
2376 /* Get and display the next header field, if present. */
2377 if (!(ext_flags & LOWPAN_NHC_EXT_NHDR)) {
2378 ipv6_ext.ip6e_nxt = tvb_get_uint8(tvb, offset);
2379 proto_tree_add_uint_format_value(nhc_tree, hf_6lowpan_nhc_ext_next, tvb, offset, 1, ipv6_ext.ip6e_nxt,
2380 "%s (0x%02x)", ipprotostr(ipv6_ext.ip6e_nxt), ipv6_ext.ip6e_nxt);
2381 proto_item_set_end(ti, tvb, offset+1);
2382 offset += 1;
2385 if (ext_proto == IP_PROTO_FRAGMENT) {
2386 /* Fragment header has a reserved byte in place of the Length field. */
2387 ext_hlen = 1;
2388 length = (uint8_t)sizeof(struct ws_ip6_frag);
2389 ext_len = length - ext_hlen;
2391 proto_tree_add_item(nhc_tree, hf_6lowpan_nhc_ext_reserved, tvb, offset, 1, ENC_NA);
2393 } else {
2394 /* Get and display the extension header length. */
2395 ext_hlen = (uint8_t)sizeof(struct ws_ip6_ext);
2396 ext_len = tvb_get_uint8(tvb, offset);
2397 ti_ext_len = proto_tree_add_uint(nhc_tree, hf_6lowpan_nhc_ext_length, tvb, offset, 1, ext_len);
2398 offset += 1;
2400 /* Compute the length of the extension header padded to an 8-byte alignment. */
2401 length = ext_hlen + ext_len;
2402 length = (length + 7) & ~0x7;
2403 ipv6_ext.ip6e_len = length>>3; /* Convert to units of 8 bytes. */
2404 ipv6_ext.ip6e_len -= 1; /* Don't include the first 8 bytes. */
2407 /* Create the next header structure for the IPv6 extension header. */
2408 nhdr = (struct lowpan_nhdr *)wmem_alloc0(pinfo->pool, sizeof(struct lowpan_nhdr) + length);
2409 nhdr->next = NULL;
2410 nhdr->proto = ext_proto;
2411 nhdr->length = length;
2412 nhdr->reported = length;
2414 /* Add the IPv6 extension header to the buffer. */
2415 if (ext_flags & LOWPAN_NHC_EXT_NHDR) {
2416 ipv6_ext.ip6e_nxt = lowpan_parse_nhc_proto(tvb, offset+ext_len);
2418 memcpy(LOWPAN_NHDR_DATA(nhdr), &ipv6_ext, ext_hlen);
2421 * If the extension header was truncated, display the remainder using
2422 * the data dissector, and end NHC dissection here.
2424 if (!tvb_bytes_exist(tvb, offset, ext_len)) {
2425 /* Call the data dissector for the remainder. */
2426 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, nhc_tree);
2428 /* Copy the remainder, and truncate the real buffer length. */
2429 nhdr->length = tvb_captured_length_remaining(tvb, offset) + ext_hlen;
2430 tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr) + ext_hlen, offset, tvb_captured_length_remaining(tvb, offset));
2432 /* There is nothing more we can do. */
2433 return nhdr;
2436 if (ext_proto == IP_PROTO_FRAGMENT) {
2437 /* Display the extension header using the data dissector. */
2438 call_data_dissector(tvb_new_subset_length(tvb, offset+1, ext_len-1), pinfo, nhc_tree);
2439 } else {
2440 /* Display the extension header using the data dissector. */
2441 call_data_dissector(tvb_new_subset_length(tvb, offset, ext_len), pinfo, nhc_tree);
2444 /* Copy the extension header into the struct. */
2445 tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr) + ext_hlen, offset, ext_len);
2446 offset += ext_len;
2448 /* Add padding option */
2449 if (length > ext_hlen + ext_len) {
2450 uint8_t padding = length - (ext_hlen + ext_len);
2451 uint8_t *pad_ptr = LOWPAN_NHDR_DATA(nhdr) + ext_hlen + ext_len;
2452 if (ext_proto != IP_PROTO_HOPOPTS && ext_proto != IP_PROTO_DSTOPTS) {
2453 expert_add_info(pinfo, ti_ext_len, &ei_6lowpan_bad_ext_header_length);
2455 if (padding == 1) {
2456 pad_ptr[0] = IP6OPT_PAD1;
2457 } else {
2458 pad_ptr[0] = IP6OPT_PADN;
2459 pad_ptr[1] = padding - 2;
2460 /* No need to write pad data, as buffer is zero-initialised */
2464 if (ext_flags & LOWPAN_NHC_EXT_NHDR) {
2466 * There are more LOWPAN_NHC structures to parse. Call ourself again
2467 * recursively to parse them and build the linked list.
2469 increment_dissection_depth(pinfo);
2470 nhdr->next = dissect_6lowpan_iphc_nhc(tvb, pinfo, tree, offset, dgram_size - nhdr->reported, siid, diid);
2471 decrement_dissection_depth(pinfo);
2473 else if (ipv6_ext.ip6e_nxt != IP_PROTO_NONE) {
2474 /* Create another next header structure for the remaining payload. */
2475 length = tvb_captured_length_remaining(tvb, offset);
2476 nhdr->next = (struct lowpan_nhdr *)wmem_alloc(pinfo->pool, sizeof(struct lowpan_nhdr) + length);
2477 nhdr->next->next = NULL;
2478 nhdr->next->proto = ipv6_ext.ip6e_nxt;
2479 nhdr->next->length = length;
2480 if (dgram_size < 0) {
2481 nhdr->next->reported = tvb_reported_length_remaining(tvb, offset);
2483 else {
2484 nhdr->next->reported = dgram_size - nhdr->reported;
2486 tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr->next), offset, nhdr->next->length);
2489 /* Done. */
2490 return nhdr;
2492 /*=====================================================
2493 * UDP Header
2494 *=====================================================
2496 if (tvb_get_bits8(tvb, offset<<3, LOWPAN_NHC_PATTERN_UDP_BITS) == LOWPAN_NHC_PATTERN_UDP) {
2497 struct udp_hdr udp;
2498 int src_bitlen;
2499 int dst_bitlen;
2500 uint8_t udp_flags;
2501 uint16_t udp_src_port, udp_dst_port;
2503 /* Create a tree for the UDP header. */
2504 nhc_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_6lowpan_nhc_udp, NULL, "UDP header compression");
2505 /* Display the UDP NHC ID pattern. */
2506 proto_tree_add_bits_item(nhc_tree, hf_6lowpan_nhc_pattern, tvb, offset<<3, LOWPAN_NHC_PATTERN_UDP_BITS, ENC_BIG_ENDIAN);
2508 /* Get and display the UDP header compression options */
2509 proto_tree_add_item(nhc_tree, hf_6lowpan_nhc_udp_checksum, tvb, offset, 1, ENC_NA);
2510 proto_tree_add_item(nhc_tree, hf_6lowpan_nhc_udp_ports, tvb, offset, 1, ENC_NA);
2511 udp_flags = tvb_get_uint8(tvb, offset);
2512 offset += 1;
2514 /* Get and display the ports. */
2515 switch (udp_flags & LOWPAN_NHC_UDP_PORTS) {
2516 case LOWPAN_NHC_UDP_PORT_INLINE:
2517 udp_src_port = tvb_get_ntohs(tvb, offset);
2518 udp_dst_port = tvb_get_ntohs(tvb, offset+2);
2519 src_bitlen = 16;
2520 dst_bitlen = 16;
2521 break;
2523 case LOWPAN_NHC_UDP_PORT_8BIT_DST:
2524 udp_src_port = tvb_get_ntohs(tvb, offset);
2525 udp_dst_port = LOWPAN_PORT_8BIT_OFFSET + tvb_get_uint8(tvb, offset + 2);
2526 src_bitlen = 16;
2527 dst_bitlen = 8;
2528 break;
2530 case LOWPAN_NHC_UDP_PORT_8BIT_SRC:
2531 udp_src_port = LOWPAN_PORT_8BIT_OFFSET + tvb_get_uint8(tvb, offset);
2532 udp_dst_port = tvb_get_ntohs(tvb, offset + 1);
2533 src_bitlen = 8;
2534 dst_bitlen = 16;
2535 break;
2537 case LOWPAN_NHC_UDP_PORT_12BIT:
2538 udp_src_port = LOWPAN_PORT_12BIT_OFFSET + (tvb_get_uint8(tvb, offset) >> 4);
2539 udp_dst_port = LOWPAN_PORT_12BIT_OFFSET + (tvb_get_uint8(tvb, offset) & 0x0f);
2540 src_bitlen = 4;
2541 dst_bitlen = 4;
2542 break;
2544 default:
2545 DISSECTOR_ASSERT_NOT_REACHED();
2546 break;
2547 } /* switch */
2549 proto_tree_add_uint(tree, hf_6lowpan_udp_src, tvb, offset, BITS_TO_BYTE_LEN(offset<<3, src_bitlen), udp_src_port);
2550 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);
2551 offset += ((src_bitlen + dst_bitlen)>>3);
2552 udp.src_port = g_htons(udp_src_port);
2553 udp.dst_port = g_htons(udp_dst_port);
2555 /* Get and display the checksum. */
2556 if (!(udp_flags & LOWPAN_NHC_UDP_CHECKSUM)) {
2557 /* Parse the checksum. */
2558 tvb_memcpy(tvb, &udp.checksum, offset, sizeof(udp.checksum));
2559 proto_tree_add_checksum(tree, tvb, offset, hf_6lowpan_udp_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
2560 offset += 2;
2562 else {
2563 /* Checksum must be != 0 or the UDP dissector will flag the packet with a PI_ERROR */
2564 udp.checksum = 0xffff;
2567 /* Compute the datagram length. */
2568 if (dgram_size < 0) {
2569 length = tvb_reported_length_remaining(tvb, offset);
2570 udp.length = g_htons(length + (int)sizeof(struct udp_hdr));
2572 else {
2573 udp.length = g_htons(dgram_size);
2577 * Although rfc768 (udp) allows a packet to be sent with a checksum of
2578 * 0 to mean that no checksum was computed, apparently IPv6 specifically
2579 * disallows sending UDP datagrams without checksums. Likewise, 6LoWPAN
2580 * requires that we recompute the checksum.
2582 * If the datagram is incomplete, then leave the checksum at 0xffff.
2584 #if 0
2586 * This has been disabled, since we might only be dissecting a fragment
2587 * of the packet, and thus we might not have the entire UDP payload at
2588 * this time.
2590 * If we want to display the checksums, they will have to be recomputed
2591 * after packet reassembly. Lots of work for not much gain, since we can
2592 * just set the UDP checksum to 0xffff (anything != 0) and Wireshark
2593 * doesn't care.
2595 if ((udp_flags & LOWPAN_NHC_UDP_CHECKSUM) && tvb_bytes_exist(tvb, offset, length)) {
2596 vec_t cksum_vec[3];
2597 struct {
2598 ws_in6_addr src;
2599 ws_in6_addr dst;
2600 uint32_t length;
2601 uint8_t zero[3];
2602 uint8_t proto;
2603 } cksum_phdr;
2605 /* Fill in the pseudo-header. */
2606 memcpy(&cksum_phdr.src, pinfo->src.data, sizeof(ws_in6_addr));
2607 memcpy(&cksum_phdr.dst, pinfo->dst.data, sizeof(ws_in6_addr));
2608 cksum_phdr.length = g_htonl(length + (int)sizeof(struct udp_hdr));
2609 memset(cksum_phdr.zero, 0, sizeof(cksum_phdr.zero));
2610 cksum_phdr.proto = IP_PROTO_UDP;
2612 /* Compute the checksum. */
2613 SET_CKSUM_VEC_PTR(cksum_vec[0], (const uint8_t *)&cksum_phdr, sizeof(cksum_phdr));
2614 SET_CKSUM_VEC_PTR(cksum_vec[1], (const uint8_t *)&udp, sizeof(struct udp_hdr));
2615 SET_CKSUM_VEC_TVB(cksum_vec[2], tvb, offset, length);
2616 udp.checksum = in_cksum(cksum_vec, 3);
2617 if (udp.checksum == 0) udp.checksum = 0xffff;
2619 #endif
2621 /* Create the next header structure for the UDP datagram. */
2622 length = tvb_captured_length_remaining(tvb, offset);
2623 nhdr = (struct lowpan_nhdr *)wmem_alloc(pinfo->pool, sizeof(struct lowpan_nhdr) + sizeof(struct udp_hdr) + length);
2624 nhdr->next = NULL;
2625 nhdr->proto = IP_PROTO_UDP;
2626 nhdr->length = length + (int)sizeof(struct udp_hdr);
2627 nhdr->reported = g_ntohs(udp.length);
2629 /* Copy the UDP header and payload into the buffer. */
2630 memcpy(LOWPAN_NHDR_DATA(nhdr), &udp, sizeof(struct udp_hdr));
2631 tvb_memcpy(tvb, LOWPAN_NHDR_DATA(nhdr) + sizeof(struct udp_hdr), offset, tvb_captured_length_remaining(tvb, offset));
2632 return nhdr;
2634 /*=====================================================
2635 * Unknown Next Header Type
2636 *=====================================================
2638 return NULL;
2639 } /* dissect_6lowpan_iphc_nhc */
2641 /*FUNCTION:------------------------------------------------------
2642 * NAME
2643 * dissect_6lowpan_bc0
2644 * DESCRIPTION
2645 * Dissector routine for a 6LoWPAN broadcast header.
2646 * PARAMETERS
2647 * tvb ; packet buffer.
2648 * pinfo ; packet info.
2649 * tree ; 6LoWPAN display tree.
2650 * RETURNS
2651 * tvbuff_t * ; The remaining payload to be parsed.
2652 *---------------------------------------------------------------
2654 static tvbuff_t *
2655 dissect_6lowpan_bc0(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
2657 uint8_t seqnum;
2658 proto_tree * bcast_tree;
2660 /* Create a tree for the broadcast header. */
2661 bcast_tree = proto_tree_add_subtree(tree, tvb, 0, 2, ett_6lowpan_bcast, NULL, "Broadcast Header");
2663 /* Get and display the pattern. */
2664 proto_tree_add_bits_item(bcast_tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_BC0_BITS, ENC_BIG_ENDIAN);
2666 /* Get and display the sequence number. */
2667 seqnum = tvb_get_uint8(tvb, 1);
2668 proto_tree_add_uint(bcast_tree, hf_6lowpan_bcast_seqnum, tvb, 1, 1, seqnum);
2670 /* Return the remaining buffer. */
2671 return tvb_new_subset_remaining(tvb, 2);
2672 } /* dissect_6lowpan_bc0 */
2674 /*FUNCTION:------------------------------------------------------
2675 * NAME
2676 * dissect_6lowpan_mesh
2677 * DESCRIPTION
2678 * Dissector routine for a 6LoWPAN mesh header.
2679 * PARAMETERS
2680 * tvb ; packet buffer.
2681 * pinfo ; packet info.
2682 * tree ; 6LoWPAN display tree.
2683 * offset ; offset to the start of the header.
2684 * siid ; Source Interface ID.
2685 * diid ; Destination Interface ID.
2686 * RETURNS
2687 * tvbuff_t * ; The remaining payload to be parsed.
2688 *---------------------------------------------------------------
2690 static tvbuff_t *
2691 dissect_6lowpan_mesh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint8_t *siid, uint8_t *diid)
2693 int offset = 0;
2694 uint8_t mesh_header;
2695 proto_tree * mesh_tree;
2696 proto_tree * flag_tree;
2697 proto_item * ti;
2699 ieee802154_hints_t *hints;
2701 /* Create a tree for the mesh header. */
2702 mesh_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_6lowpan_mesh, &ti, "Mesh Header");
2704 /* Get and display the mesh flags. */
2705 mesh_header = tvb_get_uint8(tvb, offset);
2707 /* Create the mesh header subtree. */
2708 flag_tree = proto_tree_add_subtree(mesh_tree, tvb, offset, 1, ett_6lowpan_mesh, NULL, "Flags");
2710 /* Add the mesh header fields. */
2711 proto_tree_add_bits_item(flag_tree, hf_6lowpan_pattern, tvb, offset * 8, LOWPAN_PATTERN_MESH_BITS, ENC_BIG_ENDIAN);
2712 proto_tree_add_boolean(flag_tree, hf_6lowpan_mesh_v, tvb, offset, 1, mesh_header & LOWPAN_MESH_HEADER_V);
2713 proto_tree_add_boolean(flag_tree, hf_6lowpan_mesh_f, tvb, offset, 1, mesh_header & LOWPAN_MESH_HEADER_F);
2714 proto_tree_add_uint(flag_tree, hf_6lowpan_mesh_hops, tvb, offset, 1, mesh_header & LOWPAN_MESH_HEADER_HOPS);
2715 offset += 1;
2717 if ((mesh_header & LOWPAN_MESH_HEADER_HOPS) == LOWPAN_MESH_HEADER_HOPS) {
2718 proto_tree_add_item(mesh_tree, hf_6lowpan_mesh_hops8, tvb, offset, 1, ENC_BIG_ENDIAN);
2719 offset += 1;
2722 /* Get and display the originator address. */
2723 if (!(mesh_header & LOWPAN_MESH_HEADER_V)) {
2724 proto_tree_add_item(mesh_tree, hf_6lowpan_mesh_orig64,
2725 tvb, offset, 8, ENC_BIG_ENDIAN);
2727 set_address_tvb(&pinfo->src, AT_EUI64, 8, tvb, offset);
2728 copy_address_shallow(&pinfo->net_src, &pinfo->src);
2730 /* Update source IID */
2731 tvb_memcpy(tvb, siid, offset, LOWPAN_IFC_ID_LEN);
2732 /* RFC2464: Invert the U/L bit when using an EUI64 address. */
2733 siid[0] ^= 0x02;
2734 offset += 8;
2736 else {
2737 uint16_t addr16 = tvb_get_ntohs(tvb, offset);
2738 uint8_t * ifcid;
2740 proto_tree_add_uint(mesh_tree, hf_6lowpan_mesh_orig16, tvb, offset, 2, addr16);
2741 ifcid = (uint8_t *)wmem_alloc(pinfo->pool, 8);
2743 /* Lookup the IEEE 802.15.4 addressing hints wanting RFC 2464 compatibility. */
2744 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
2745 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
2747 /* Convert the 16-bit short address to an IID using the PAN ID (RFC 4944) or not depending on the preference and the presence of hints from lower layers */
2748 if (hints && rfc4944_short_address_format) {
2749 lowpan_addr16_with_panid_to_ifcid(hints->src_pan, addr16, ifcid);
2750 } else {
2751 lowpan_addr16_to_ifcid(addr16, ifcid);
2754 set_address(&pinfo->src, AT_EUI64, 8, ifcid);
2755 copy_address_shallow(&pinfo->net_src, &pinfo->src);
2757 /* Update source IID */
2758 memcpy(siid, ifcid, LOWPAN_IFC_ID_LEN);
2759 offset += 2;
2762 /* Get and display the destination address. */
2763 if (!(mesh_header & LOWPAN_MESH_HEADER_F)) {
2764 proto_tree_add_item(mesh_tree, hf_6lowpan_mesh_dest64,
2765 tvb, offset, 8, ENC_BIG_ENDIAN);
2767 set_address_tvb(&pinfo->dst, AT_EUI64, 8, tvb, offset);
2768 copy_address_shallow(&pinfo->net_dst, &pinfo->dst);
2770 /* Update destination IID */
2771 tvb_memcpy(tvb, diid, offset, LOWPAN_IFC_ID_LEN);
2772 /* RFC2464: Invert the U/L bit when using an EUI64 address. */
2773 diid[0] ^= 0x02;
2774 offset += 8;
2776 else {
2777 uint16_t addr16 = tvb_get_ntohs(tvb, offset);
2778 uint8_t * ifcid;
2780 proto_tree_add_uint(mesh_tree, hf_6lowpan_mesh_dest16, tvb, offset, 2, addr16);
2782 ifcid = (uint8_t *)wmem_alloc(pinfo->pool, 8);
2784 /* Lookup the IEEE 802.15.4 addressing hints wanting RFC 2464 compatibility. */
2785 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
2786 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
2788 /* Convert the 16-bit short address to an IID using the PAN ID (RFC 4944) or not depending on the preference and the presence of hints from lower layers */
2789 if (hints && rfc4944_short_address_format) {
2790 lowpan_addr16_with_panid_to_ifcid(hints->src_pan, addr16, ifcid);
2791 } else {
2792 lowpan_addr16_to_ifcid(addr16, ifcid);
2795 set_address(&pinfo->dst, AT_EUI64, 8, ifcid);
2796 copy_address_shallow(&pinfo->net_dst, &pinfo->dst);
2798 /* Update destination IID */
2799 memcpy(diid, ifcid, LOWPAN_IFC_ID_LEN);
2800 offset += 2;
2803 /* Adjust the mesh header length. */
2804 proto_item_set_end(ti, tvb, offset);
2806 /* Return the remaining buffer. */
2807 return tvb_new_subset_remaining(tvb, offset);
2808 } /* dissect_6lowpan_mesh */
2810 /*FUNCTION:------------------------------------------------------
2811 * NAME
2812 * dissect_6lowpan_frag_headers
2813 * DESCRIPTION
2814 * Dissector routine for headers in the first fragment.
2815 * The first fragment can contain an uncompressed IPv6, HC1 or IPHC fragment.
2816 * PARAMETERS
2817 * tvb ; fragment buffer.
2818 * pinfo ; packet info.
2819 * tree ; 6LoWPAN display tree.
2820 * siid ; Source Interface ID.
2821 * diid ; Destination Interface ID.
2822 * RETURNS
2823 * tvbuff_t * ; buffer containing the uncompressed IPv6 headers
2824 *---------------------------------------------------------------
2826 static tvbuff_t *
2827 dissect_6lowpan_frag_headers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *length_item, const uint8_t *siid, const uint8_t *diid)
2829 tvbuff_t *frag_tvb = NULL;
2831 /* The first fragment can contain an uncompressed IPv6, HC1 or IPHC fragment. */
2832 if (tvb_get_bits8(tvb, 0, LOWPAN_PATTERN_IPV6_BITS) == LOWPAN_PATTERN_IPV6) {
2833 frag_tvb = dissect_6lowpan_ipv6(tvb, pinfo, tree);
2835 else if (tvb_get_bits8(tvb, 0, LOWPAN_PATTERN_HC1_BITS) == LOWPAN_PATTERN_HC1) {
2836 /* Check if the datagram size is sane. */
2837 if (tvb_reported_length(tvb) < IPv6_HDR_SIZE) {
2838 expert_add_info_format(pinfo, length_item, &ei_6lowpan_bad_ipv6_header_length,
2839 "Length is less than IPv6 header length %u", IPv6_HDR_SIZE);
2841 frag_tvb = dissect_6lowpan_hc1(tvb, pinfo, tree, tvb_reported_length(tvb), siid, diid);
2843 else if (tvb_get_bits8(tvb, 0, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) {
2844 /* Check if the datagram size is sane. */
2845 if (tvb_reported_length(tvb) < IPv6_HDR_SIZE) {
2846 expert_add_info_format(pinfo, length_item, &ei_6lowpan_bad_ipv6_header_length,
2847 "Length is less than IPv6 header length %u", IPv6_HDR_SIZE);
2849 frag_tvb = dissect_6lowpan_iphc(tvb, pinfo, tree, tvb_reported_length(tvb), siid, diid);
2851 /* Unknown 6LoWPAN dispatch type */
2852 else {
2853 dissect_6lowpan_unknown(tvb, pinfo, tree);
2855 return frag_tvb;
2856 } /* dissect_6lowpan_frag_headers */
2858 /*FUNCTION:------------------------------------------------------
2859 * NAME
2860 * dissect_6lowpan_rfrag
2861 * DESCRIPTION
2862 * Dissector routine for a 6LoWPAN Recoverable Fragment headers.
2864 * If reassembly could be completed, this should return an
2865 * uncompressed IPv6 packet. If reassembly had to be delayed
2866 * for more packets, this will return NULL.
2867 * PARAMETERS
2868 * tvb ; packet buffer.
2869 * pinfo ; packet info.
2870 * tree ; 6LoWPAN display tree.
2871 * siid ; Source Interface ID.
2872 * diid ; Destination Interface ID.
2873 * RETURNS
2874 * tvbuff_t * ; reassembled IPv6 packet.
2875 *---------------------------------------------------------------
2877 static tvbuff_t *
2878 dissect_6lowpan_rfrag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const uint8_t *siid, const uint8_t *diid)
2880 int offset = 0;
2881 uint32_t frag_size;
2882 uint32_t dgram_tag;
2883 proto_tree * frag_tree;
2884 proto_item * ti;
2885 proto_item * length_item;
2886 /* Reassembly parameters. */
2887 tvbuff_t * new_tvb;
2888 tvbuff_t * frag_tvb;
2889 fragment_head * frag_data;
2890 bool save_fragmented;
2891 uint16_t sequence;
2892 uint32_t frag_offset;
2894 /* Create a tree for the fragmentation header. */
2895 frag_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_6lowpan_frag, &ti, "RFRAG Header");
2897 /* Get and display the pattern and explicit congestion bit. */
2898 proto_tree_add_bits_item(frag_tree, hf_6lowpan_pattern, tvb, offset * 8, LOWPAN_PATTERN_RFRAG_BITS, ENC_BIG_ENDIAN);
2899 proto_tree_add_item(frag_tree, hf_6lowpan_rfrag_congestion, tvb, offset, 1, ENC_BIG_ENDIAN);
2900 offset += 1;
2902 /* Get and display the datagram tag. */
2903 proto_tree_add_item_ret_uint(frag_tree, hf_6lowpan_rfrag_dgram_tag, tvb, offset, 1, ENC_BIG_ENDIAN, &dgram_tag);
2904 offset += 1;
2906 proto_tree_add_item(frag_tree, hf_6lowpan_rfrag_ack_requested, tvb, offset, 2, ENC_BIG_ENDIAN);
2907 sequence = tvb_get_bits16(tvb, (offset * 8) + 1, LOWPAN_RFRAG_SEQUENCE_BITS, ENC_BIG_ENDIAN);
2908 proto_tree_add_item(frag_tree, hf_6lowpan_rfrag_sequence, tvb, offset, 2, ENC_BIG_ENDIAN);
2910 frag_size = tvb_get_bits16(tvb, (offset * 8) + 1 + LOWPAN_RFRAG_SEQUENCE_BITS, LOWPAN_RFRAG_FRAG_SZ_BITS, ENC_BIG_ENDIAN);
2911 length_item = proto_tree_add_uint(frag_tree, hf_6lowpan_rfrag_size, tvb, offset * 8, 2, frag_size);
2912 offset += 2;
2914 if (sequence) {
2915 proto_tree_add_item_ret_uint(frag_tree, hf_6lowpan_rfrag_offset, tvb, offset, 2, ENC_BIG_ENDIAN, &frag_offset);
2917 else {
2918 proto_tree_add_item_ret_uint(frag_tree, hf_6lowpan_rfrag_dgram_size, tvb, offset, 2, ENC_BIG_ENDIAN, &frag_offset);
2920 offset += 2;
2922 /* Adjust the fragmentation header length. */
2923 proto_item_set_end(ti, tvb, offset);
2925 frag_tvb = tvb_new_subset_length(tvb, offset, frag_size);
2926 if (sequence == 0) {
2927 dissect_6lowpan_frag_headers(frag_tvb, pinfo, tree, length_item, siid, diid);
2930 /* Add this datagram to the fragment table. */
2931 save_fragmented = pinfo->fragmented;
2932 pinfo->fragmented = true;
2933 uint32_t frag_id = lowpan_reassembly_id(pinfo, dgram_tag);
2934 if (sequence == 0) {
2935 frag_data = fragment_add_check(&lowpan_reassembly_table,
2936 frag_tvb, 0, pinfo, frag_id, NULL,
2937 0, frag_size, true);
2938 fragment_set_tot_len(&lowpan_reassembly_table, pinfo, frag_id, NULL, frag_offset);
2940 else {
2941 uint32_t dgram_size = fragment_get_tot_len(&lowpan_reassembly_table, pinfo, frag_id, NULL);
2942 frag_data = fragment_add_check(&lowpan_reassembly_table,
2943 frag_tvb, 0, pinfo, frag_id, NULL,
2944 frag_offset, frag_size, (frag_offset+frag_size) < dgram_size);
2947 /* Attempt reassembly. */
2948 new_tvb = process_reassembled_data(frag_tvb, 0, pinfo,
2949 "Reassembled 6LoWPAN", frag_data, &lowpan_frag_items,
2950 NULL, tree);
2952 pinfo->fragmented = save_fragmented;
2954 if (new_tvb) {
2955 /* Reassembly was successful; return the completed datagram. */
2956 return new_tvb;
2957 } else {
2958 /* Reassembly was unsuccessful; show this fragment. This may
2959 just mean that we don't yet have all the fragments, so
2960 we should not just continue dissecting. */
2961 call_data_dissector(frag_tvb, pinfo, proto_tree_get_root(tree));
2962 return NULL;
2964 } /* dissect_6lowpan_rfrag */
2966 /*FUNCTION:------------------------------------------------------
2967 * NAME
2968 * dissect_6lowpan_rfrag_ack
2969 * DESCRIPTION
2970 * Dissector routine for a 6LoWPAN ACK Dispatch type and header
2971 * PARAMETERS
2972 * tvb ; packet buffer.
2973 * pinfo ; packet info.
2974 * tree ; 6LoWPAN display tree.
2975 * RETURNS
2976 * tvbuff_t * ; reassembled IPv6 packet.
2977 *---------------------------------------------------------------
2979 static tvbuff_t *
2980 dissect_6lowpan_rfrag_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2982 int offset = 0;
2983 proto_tree * frag_tree;
2984 proto_item * ti;
2985 (void)pinfo;
2987 /* Create a tree for the fragmentation header. */
2988 frag_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_6lowpan_frag, &ti, "RFRAG ACK Header");
2990 /* Get and display the pattern and explicit congestion bit. */
2991 proto_tree_add_bits_item(frag_tree, hf_6lowpan_pattern, tvb, offset * 8, LOWPAN_PATTERN_RFRAG_BITS, ENC_BIG_ENDIAN);
2992 proto_tree_add_item(frag_tree, hf_6lowpan_rfrag_congestion, tvb, offset, 1, ENC_BIG_ENDIAN);
2993 offset += 1;
2995 /* Get and display the datagram tag. */
2996 proto_tree_add_item(frag_tree, hf_6lowpan_rfrag_dgram_tag, tvb, offset, 1, ENC_BIG_ENDIAN);
2997 offset += 1;
2999 proto_tree_add_bits_item(frag_tree, hf_6lowpan_rfrag_ack_bitmap, tvb, offset * 8, 32, ENC_BIG_ENDIAN);
3000 offset += 4;
3002 /* TODO: Match ACK bits to original fragments? */
3004 return tvb_new_subset_remaining(tvb, offset);
3005 } /* dissect_6lowpan_rfrag_ack */
3007 /*FUNCTION:------------------------------------------------------
3008 * NAME
3009 * dissect_6lowpan_frag_first
3010 * DESCRIPTION
3011 * Dissector routine for a 6LoWPAN FRAG1 headers.
3013 * If reassembly could be completed, this should return an
3014 * uncompressed IPv6 packet. If reassembly had to be delayed
3015 * for more packets, this will return NULL.
3016 * PARAMETERS
3017 * tvb ; packet buffer.
3018 * pinfo ; packet info.
3019 * tree ; 6LoWPAN display tree.
3020 * siid ; Source Interface ID.
3021 * diid ; Destination Interface ID.
3022 * RETURNS
3023 * tvbuff_t * ; reassembled IPv6 packet.
3024 *---------------------------------------------------------------
3026 static tvbuff_t *
3027 dissect_6lowpan_frag_first(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const uint8_t *siid, const uint8_t *diid)
3029 int offset = 0;
3030 int frag_size;
3031 uint16_t dgram_size;
3032 uint16_t dgram_tag;
3033 proto_tree * frag_tree;
3034 proto_item * ti;
3035 proto_item * length_item;
3036 /* Reassembly parameters. */
3037 tvbuff_t * new_tvb;
3038 tvbuff_t * frag_tvb;
3039 fragment_head * frag_data;
3040 bool save_fragmented;
3042 /* Create a tree for the fragmentation header. */
3043 frag_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_6lowpan_frag, &ti, "Fragmentation Header");
3045 /* Get and display the pattern and datagram size. */
3046 dgram_size = tvb_get_bits16(tvb, (offset * 8) + LOWPAN_PATTERN_FRAG_BITS, LOWPAN_FRAG_DGRAM_SIZE_BITS, ENC_BIG_ENDIAN);
3047 proto_tree_add_bits_item(frag_tree, hf_6lowpan_pattern, tvb, offset * 8, LOWPAN_PATTERN_FRAG_BITS, ENC_BIG_ENDIAN);
3048 length_item = proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_size, tvb, offset, 2, dgram_size);
3049 offset += 2;
3051 /* Get and display the datagram tag. */
3052 dgram_tag = tvb_get_ntohs(tvb, offset);
3053 proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_tag, tvb, offset, 2, dgram_tag);
3054 offset += 2;
3056 /* Adjust the fragmentation header length. */
3057 proto_item_set_end(ti, tvb, offset);
3060 frag_tvb = tvb_new_subset_length(tvb, offset, dgram_size);
3061 frag_tvb = dissect_6lowpan_frag_headers(frag_tvb, pinfo, tree, length_item, siid, diid);
3062 /* Check call to dissect_6lowpan_xxx was successful */
3063 if (frag_tvb == NULL) {
3064 return NULL;
3067 /* Add this datagram to the fragment table. */
3068 frag_size = tvb_captured_length(frag_tvb);
3069 tvb_set_reported_length(frag_tvb, frag_size);
3070 save_fragmented = pinfo->fragmented;
3071 pinfo->fragmented = true;
3072 uint32_t frag_id = lowpan_reassembly_id(pinfo, dgram_tag);
3073 frag_data = fragment_add_check(&lowpan_reassembly_table,
3074 frag_tvb, 0, pinfo, frag_id, NULL,
3075 0, frag_size, (frag_size < dgram_size));
3077 /* Attempt reassembly. */
3078 new_tvb = process_reassembled_data(frag_tvb, 0, pinfo,
3079 "Reassembled 6LoWPAN", frag_data, &lowpan_frag_items,
3080 NULL, tree);
3082 pinfo->fragmented = save_fragmented;
3084 if (new_tvb) {
3085 /* Reassembly was successful; return the completed datagram. */
3086 return new_tvb;
3087 } else {
3088 /* Reassembly was unsuccessful; show this fragment. This may
3089 just mean that we don't yet have all the fragments, so
3090 we should not just continue dissecting. */
3091 call_data_dissector(frag_tvb, pinfo, proto_tree_get_root(tree));
3092 return NULL;
3094 } /* dissect_6lowpan_frag_first */
3096 /*FUNCTION:------------------------------------------------------
3097 * NAME
3098 * dissect_6lowpan_frag_middle
3099 * DESCRIPTION
3100 * Dissector routine for a 6LoWPAN FRAGN headers.
3102 * If reassembly could be completed, this should return an
3103 * uncompressed IPv6 packet. If reassembly had to be delayed
3104 * for more packets, this will return NULL.
3105 * PARAMETERS
3106 * tvb ; packet buffer.
3107 * pinfo ; packet info.
3108 * tree ; 6LoWPAN display tree.
3109 * RETURNS
3110 * tvbuff_t * ; reassembled IPv6 packet.
3111 *---------------------------------------------------------------
3113 static tvbuff_t *
3114 dissect_6lowpan_frag_middle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3116 int offset = 0;
3117 int frag_size;
3118 uint16_t dgram_size;
3119 uint16_t dgram_tag;
3120 uint16_t dgram_offset = 0;
3121 proto_tree * frag_tree;
3122 proto_item * ti;
3123 /* Reassembly parameters. */
3124 tvbuff_t * new_tvb;
3125 fragment_head * frag_data;
3126 bool save_fragmented;
3128 /* Create a tree for the fragmentation header. */
3129 frag_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_6lowpan_frag, &ti, "Fragmentation Header");
3131 /* Get and display the pattern and datagram size. */
3132 dgram_size = tvb_get_bits16(tvb, (offset * 8) + LOWPAN_PATTERN_FRAG_BITS, LOWPAN_FRAG_DGRAM_SIZE_BITS, ENC_BIG_ENDIAN);
3133 proto_tree_add_bits_item(frag_tree, hf_6lowpan_pattern, tvb, offset * 8, LOWPAN_PATTERN_FRAG_BITS, ENC_BIG_ENDIAN);
3134 proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_size, tvb, offset, 2, dgram_size);
3135 offset += 2;
3137 /* Get and display the datagram tag. */
3138 dgram_tag = tvb_get_ntohs(tvb, offset);
3139 proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_tag, tvb, offset, 2, dgram_tag);
3140 offset += 2;
3142 /* Get and display the datagram offset. */
3143 dgram_offset = tvb_get_uint8(tvb, offset) * 8;
3144 proto_tree_add_uint(frag_tree, hf_6lowpan_frag_dgram_offset, tvb, offset, 1, dgram_offset);
3145 offset += 1;
3147 /* Adjust the fragmentation header length. */
3148 frag_size = tvb_reported_length_remaining(tvb, offset);
3149 proto_item_set_end(ti, tvb, offset);
3151 /* Add this datagram to the fragment table. */
3152 save_fragmented = pinfo->fragmented;
3153 pinfo->fragmented = true;
3154 uint32_t frag_id = lowpan_reassembly_id(pinfo, dgram_tag);
3155 frag_data = fragment_add_check(&lowpan_reassembly_table,
3156 tvb, offset, pinfo, frag_id, NULL,
3157 dgram_offset, frag_size, ((dgram_offset + frag_size) < dgram_size));
3159 /* Attempt reassembly. */
3160 new_tvb = process_reassembled_data(tvb, offset, pinfo,
3161 "Reassembled 6LoWPAN", frag_data, &lowpan_frag_items,
3162 NULL, tree);
3164 pinfo->fragmented = save_fragmented;
3166 /* If reassembly was successful, then return the completed datagram. */
3167 if (new_tvb) {
3168 return new_tvb;
3170 /* If reassembly failed, display the payload fragment using the data dissector. */
3171 else {
3172 new_tvb = tvb_new_subset_remaining(tvb, offset);
3173 call_data_dissector(new_tvb, pinfo, proto_tree_get_root(tree));
3174 return NULL;
3176 } /* dissect_6lowpan_frag_middle */
3178 /*FUNCTION:------------------------------------------------------
3179 * NAME
3180 * dissect_6lowpan_unknown
3181 * DESCRIPTION
3182 * Dissector routine for 6LoWPAN packets after encountering
3183 * an unknown header.
3184 * PARAMETERS
3185 * tvb ; packet buffer.
3186 * pinfo ; packet info.
3187 * tree ; 6LoWPAN display tree.
3188 * RETURNS
3189 * void ;
3190 *---------------------------------------------------------------
3192 void
3193 dissect_6lowpan_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3195 tvbuff_t * data_tvb;
3197 /* Get and display the pattern. */
3199 /* Give a special case for NALP. */
3200 if (tvb_get_bits8(tvb, 0, LOWPAN_PATTERN_IPHC_BITS) == LOWPAN_PATTERN_IPHC) {
3201 proto_tree_add_bits_item(tree, hf_6lowpan_pattern, tvb, 0, LOWPAN_PATTERN_IPHC_BITS, ENC_BIG_ENDIAN);
3203 else {
3204 uint8_t pattern = tvb_get_uint8(tvb, 0);
3205 proto_tree_add_uint_bits_format_value(tree, hf_6lowpan_pattern, tvb, 0, 8, pattern, ENC_BIG_ENDIAN, "Unknown (0x%02x)", pattern);
3208 /* Create a tvbuff subset for the remaining data. */
3209 data_tvb = tvb_new_subset_remaining(tvb, 1);
3210 call_data_dissector(data_tvb, pinfo, proto_tree_get_root(tree));
3211 } /* dissect_6lowpan_unknown */
3213 static void
3214 proto_shutdown_6lowpan(void)
3216 g_hash_table_destroy(lowpan_context_table);
3219 /*FUNCTION:------------------------------------------------------
3220 * NAME
3221 * proto_register_6lowpan
3222 * DESCRIPTION
3223 * Protocol registration routine for 6LoWPAN. Called during
3224 * Wireshark initialization.
3225 * PARAMETERS
3226 * none ;
3227 * RETURNS
3228 * void ;
3229 *---------------------------------------------------------------
3231 void
3232 proto_register_6lowpan(void)
3234 static hf_register_info hf[] = {
3235 /* Common 6LoWPAN fields. */
3236 { &hf_6lowpan_pattern,
3237 { "Pattern", "6lowpan.pattern",
3238 FT_UINT8, BASE_HEX, VALS(lowpan_patterns), 0x0, NULL, HFILL }},
3239 { &hf_6lowpan_nhc_pattern,
3240 { "Pattern", "6lowpan.nhc.pattern",
3241 FT_UINT8, BASE_HEX, VALS(lowpan_nhc_patterns), 0x0, NULL, HFILL }},
3242 { &hf_6lowpan_padding,
3243 { "Padding", "6lowpan.padding",
3244 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3246 /* HC1 header fields. */
3247 { &hf_6lowpan_hc1_encoding,
3248 { "HC1 Encoding", "6lowpan.hc1.encoding",
3249 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3250 { &hf_6lowpan_hc1_source_prefix,
3251 { "Source prefix", "6lowpan.hc1.src_prefix",
3252 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_SOURCE_PREFIX, NULL, HFILL }},
3253 { &hf_6lowpan_hc1_source_ifc,
3254 { "Source interface", "6lowpan.hc1.src_ifc",
3255 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_SOURCE_IFC, NULL, HFILL }},
3256 { &hf_6lowpan_hc1_dest_prefix,
3257 { "Destination prefix", "6lowpan.hc1.dst_prefix",
3258 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_DEST_PREFIX, NULL, HFILL }},
3259 { &hf_6lowpan_hc1_dest_ifc,
3260 { "Destination interface", "6lowpan.hc1.dst_ifc",
3261 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_DEST_IFC, NULL, HFILL }},
3262 { &hf_6lowpan_hc1_class,
3263 { "Traffic class and flow label", "6lowpan.hc1.class",
3264 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC1_TRAFFIC_CLASS, NULL, HFILL }},
3265 { &hf_6lowpan_hc1_next,
3266 { "Next header", "6lowpan.hc1.next",
3267 FT_UINT8, BASE_HEX, VALS(lowpan_hc1_next), LOWPAN_HC1_NEXT, NULL, HFILL }},
3268 { &hf_6lowpan_hc1_more,
3269 { "More HC bits", "6lowpan.hc1.more",
3270 FT_BOOLEAN, 8, NULL, LOWPAN_HC1_MORE, NULL, HFILL }},
3272 /* HC_UDP header fields. */
3273 { &hf_6lowpan_hc2_udp_encoding,
3274 { "HC_UDP Encoding", "6lowpan.hc2.udp.encoding",
3275 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3276 { &hf_6lowpan_hc2_udp_src,
3277 { "Source port", "6lowpan.hc2.udp.src",
3278 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC2_UDP_SRCPORT, NULL, HFILL }},
3279 { &hf_6lowpan_hc2_udp_dst,
3280 { "Destination port", "6lowpan.hc2.udp.dst",
3281 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC2_UDP_DSTPORT, NULL, HFILL }},
3282 { &hf_6lowpan_hc2_udp_len,
3283 { "Length", "6lowpan.hc2.udp.length",
3284 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_HC2_UDP_LENGTH, NULL, HFILL }},
3286 /* IPHC header fields. */
3287 { &hf_6lowpan_iphc_flag_tf,
3288 { "Traffic class and flow label", "6lowpan.iphc.tf",
3289 FT_UINT16, BASE_HEX, VALS(lowpan_iphc_traffic), LOWPAN_IPHC_FLAG_FLOW, "traffic class and flow control encoding", HFILL }},
3290 { &hf_6lowpan_iphc_flag_nhdr,
3291 { "Next header", "6lowpan.iphc.nh",
3292 FT_BOOLEAN, 16, TFS(&lowpan_compression), LOWPAN_IPHC_FLAG_NHDR, NULL, HFILL }},
3293 { &hf_6lowpan_iphc_flag_hlim,
3294 { "Hop limit", "6lowpan.iphc.hlim",
3295 FT_UINT16, BASE_HEX, VALS(lowpan_iphc_hop_limit), LOWPAN_IPHC_FLAG_HLIM, NULL, HFILL }},
3296 { &hf_6lowpan_iphc_flag_cid,
3297 { "Context identifier extension", "6lowpan.iphc.cid",
3298 FT_BOOLEAN, 16, NULL, LOWPAN_IPHC_FLAG_CONTEXT_ID, NULL, HFILL }},
3299 { &hf_6lowpan_iphc_flag_sac,
3300 { "Source address compression", "6lowpan.iphc.sac",
3301 FT_BOOLEAN, 16, TFS(&lowpan_iphc_addr_compression), LOWPAN_IPHC_FLAG_SRC_COMP, NULL, HFILL }},
3302 { &hf_6lowpan_iphc_flag_sam,
3303 { "Source address mode", "6lowpan.iphc.sam",
3304 FT_UINT16, BASE_HEX, VALS(lowpan_iphc_addr_modes), LOWPAN_IPHC_FLAG_SRC_MODE, NULL, HFILL }},
3305 { &hf_6lowpan_iphc_flag_mcast,
3306 { "Multicast address compression", "6lowpan.iphc.m",
3307 FT_BOOLEAN, 16, NULL, LOWPAN_IPHC_FLAG_MCAST_COMP, NULL, HFILL }},
3308 { &hf_6lowpan_iphc_flag_dac,
3309 { "Destination address compression","6lowpan.iphc.dac",
3310 FT_BOOLEAN, 16, TFS(&lowpan_iphc_addr_compression), LOWPAN_IPHC_FLAG_DST_COMP, NULL, HFILL }},
3311 { &hf_6lowpan_iphc_flag_dam,
3312 { "Destination address mode", "6lowpan.iphc.dam",
3313 FT_UINT16, BASE_HEX, VALS(lowpan_iphc_addr_modes), LOWPAN_IPHC_FLAG_DST_MODE, NULL, HFILL }},
3314 { &hf_6lowpan_iphc_sci,
3315 { "Source context identifier", "6lowpan.iphc.sci",
3316 FT_UINT8, BASE_HEX, NULL, LOWPAN_IPHC_FLAG_SCI, NULL, HFILL }},
3317 { &hf_6lowpan_iphc_dci,
3318 { "Destination context identifier", "6lowpan.iphc.dci",
3319 FT_UINT8, BASE_HEX, NULL, LOWPAN_IPHC_FLAG_DCI, NULL, HFILL }},
3321 /* Context information fields. */
3322 { &hf_6lowpan_iphc_sctx_prefix,
3323 { "Source context", "6lowpan.iphc.sctx.prefix", FT_IPv6, BASE_NONE, NULL, 0x0,
3324 NULL, HFILL }},
3325 { &hf_6lowpan_iphc_sctx_origin,
3326 { "Origin", "6lowpan.iphc.sctx.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3327 NULL, HFILL }},
3328 { &hf_6lowpan_iphc_dctx_prefix,
3329 { "Destination context", "6lowpan.iphc.dctx.prefix", FT_IPv6, BASE_NONE, NULL, 0x0,
3330 NULL, HFILL }},
3331 { &hf_6lowpan_iphc_dctx_origin,
3332 { "Origin", "6lowpan.iphc.dctx.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3333 NULL, HFILL }},
3335 /* NHC IPv6 extension header fields. */
3336 { &hf_6lowpan_nhc_ext_eid,
3337 { "Header ID", "6lowpan.nhc.ext.eid",
3338 FT_UINT8, BASE_HEX, VALS(lowpan_nhc_eid), LOWPAN_NHC_EXT_EID, NULL, HFILL }},
3339 { &hf_6lowpan_nhc_ext_nh,
3340 { "Next header", "6lowpan.nhc.ext.nh",
3341 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_NHC_EXT_NHDR, NULL, HFILL }},
3342 { &hf_6lowpan_nhc_ext_next,
3343 { "Next header", "6lowpan.nhc.ext.next",
3344 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3345 { &hf_6lowpan_nhc_ext_length,
3346 { "Header length", "6lowpan.nhc.ext.length",
3347 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3348 { &hf_6lowpan_nhc_ext_reserved,
3349 { "Reserved octet", "6lowpan.nhc.ext.reserved",
3350 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3352 /* NHC UDP header fields. */
3353 { &hf_6lowpan_nhc_udp_checksum,
3354 { "Checksum", "6lowpan.nhc.udp.checksum",
3355 FT_BOOLEAN, 8, TFS(&lowpan_compression), LOWPAN_NHC_UDP_CHECKSUM, NULL, HFILL }},
3356 { &hf_6lowpan_nhc_udp_ports,
3357 { "Ports", "6lowpan.nhc.udp.ports",
3358 FT_UINT8, BASE_DEC, VALS(lowpan_udp_ports), LOWPAN_NHC_UDP_PORTS, NULL, HFILL }},
3360 /* Uncompressed IPv6 fields. */
3361 { &hf_6lowpan_traffic_class,
3362 { "Traffic class", "6lowpan.class",
3363 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3364 { &hf_6lowpan_flow_label,
3365 { "Flow label", "6lowpan.flow",
3366 FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3367 { &hf_6lowpan_ecn,
3368 { "ECN", "6lowpan.ecn",
3369 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3370 { &hf_6lowpan_dscp,
3371 { "DSCP", "6lowpan.dscp",
3372 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3373 { &hf_6lowpan_next_header,
3374 { "Next header", "6lowpan.next",
3375 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3376 { &hf_6lowpan_hop_limit,
3377 { "Hop limit", "6lowpan.hops",
3378 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3379 { &hf_6lowpan_source,
3380 { "Source", "6lowpan.src",
3381 FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 address", HFILL }},
3382 { &hf_6lowpan_dest,
3383 { "Destination", "6lowpan.dst",
3384 FT_IPv6, BASE_NONE, NULL, 0x0, "Destination IPv6 address", HFILL }},
3386 /* Uncompressed UDP fields. */
3387 { &hf_6lowpan_udp_src,
3388 { "Source port", "6lowpan.udp.src",
3389 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3390 { &hf_6lowpan_udp_dst,
3391 { "Destination port", "6lowpan.udp.dst",
3392 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3393 { &hf_6lowpan_udp_len,
3394 { "UDP length", "6lowpan.udp.length",
3395 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3396 { &hf_6lowpan_udp_checksum,
3397 { "UDP checksum", "6lowpan.udp.checksum",
3398 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3400 /* Broadcast header fields. */
3401 { &hf_6lowpan_bcast_seqnum,
3402 { "Sequence number", "6lowpan.bcast.seqnum",
3403 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3405 /* Mesh header fields. */
3406 { &hf_6lowpan_mesh_v,
3407 { "V", "6lowpan.mesh.v",
3408 FT_BOOLEAN, 8, NULL, LOWPAN_MESH_HEADER_V, "short originator address present", HFILL }},
3409 { &hf_6lowpan_mesh_f,
3410 { "D", "6lowpan.mesh.f",
3411 FT_BOOLEAN, 8, NULL, LOWPAN_MESH_HEADER_F, "short destination address present", HFILL }},
3412 { &hf_6lowpan_mesh_hops,
3413 { "Hops left", "6lowpan.mesh.hops",
3414 FT_UINT8, BASE_DEC, NULL, LOWPAN_MESH_HEADER_HOPS, NULL, HFILL }},
3415 { &hf_6lowpan_mesh_hops8,
3416 { "Deep Hops left (Flags.Hops left == 15)", "6lowpan.mesh.hops8",
3417 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3418 { &hf_6lowpan_mesh_orig16,
3419 { "Originator", "6lowpan.mesh.orig16",
3420 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3421 { &hf_6lowpan_mesh_orig64,
3422 { "Originator", "6lowpan.mesh.orig64",
3423 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3424 { &hf_6lowpan_mesh_dest16,
3425 { "Destination", "6lowpan.mesh.dest16",
3426 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3427 { &hf_6lowpan_mesh_dest64,
3428 { "Destination", "6lowpan.mesh.dest64",
3429 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3431 /* Fragmentation header fields. */
3432 { &hf_6lowpan_frag_dgram_size,
3433 { "Datagram size", "6lowpan.frag.size",
3434 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3435 { &hf_6lowpan_frag_dgram_tag,
3436 { "Datagram tag", "6lowpan.frag.tag",
3437 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3438 { &hf_6lowpan_frag_dgram_offset,
3439 { "Datagram offset", "6lowpan.frag.offset",
3440 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3442 /* Recoverable Fragmentation header fields. */
3443 { &hf_6lowpan_rfrag_congestion,
3444 { "Congestion", "6lowpan.rfrag.congestion",
3445 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01, NULL, HFILL }},
3446 { &hf_6lowpan_rfrag_ack_requested,
3447 { "Ack requested", "6lowpan.rfrag.ack_requested",
3448 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x8000, NULL, HFILL }},
3449 { &hf_6lowpan_rfrag_dgram_tag,
3450 { "Datagram tag", "6lowpan.rfrag.tag",
3451 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3452 { &hf_6lowpan_rfrag_sequence,
3453 { "Fragment sequence", "6lowpan.rfrag.sequence",
3454 FT_UINT16, BASE_DEC, NULL, 0x7C00, NULL, HFILL }},
3455 { &hf_6lowpan_rfrag_size,
3456 { "Fragment size", "6lowpan.rfrag.size",
3457 FT_UINT16, BASE_DEC, NULL, 0x03FF, NULL, HFILL }},
3458 { &hf_6lowpan_rfrag_dgram_size,
3459 { "Datagram size", "6lowpan.rfrag.datagram_size",
3460 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3461 { &hf_6lowpan_rfrag_offset,
3462 { "Fragment offset", "6lowpan.rfrag.offset",
3463 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3464 { &hf_6lowpan_rfrag_ack_bitmap,
3465 { "Fragment ACK bitmask", "6lowpan.rfrag.ack_bitmask",
3466 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3468 /* Reassembly fields. */
3469 { &hf_6lowpan_fragments,
3470 { "Message fragments", "6lowpan.fragments",
3471 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
3472 { &hf_6lowpan_fragment,
3473 { "Message fragment", "6lowpan.fragment",
3474 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
3475 { &hf_6lowpan_fragment_overlap,
3476 { "Message fragment overlap", "6lowpan.fragment.overlap",
3477 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
3478 { &hf_6lowpan_fragment_overlap_conflicts,
3479 { "Message fragment overlapping with conflicting data", "6lowpan.fragment.overlap.conflicts",
3480 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
3481 { &hf_6lowpan_fragment_multiple_tails,
3482 { "Message has multiple tail fragments", "6lowpan.fragment.multiple_tails",
3483 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
3484 { &hf_6lowpan_fragment_too_long_fragment,
3485 { "Message fragment too long", "6lowpan.fragment.too_long_fragment",
3486 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
3487 { &hf_6lowpan_fragment_error,
3488 { "Message defragmentation error", "6lowpan.fragment.error",
3489 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
3490 { &hf_6lowpan_fragment_count,
3491 { "Message fragment count", "6lowpan.fragment.count",
3492 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
3493 { &hf_6lowpan_reassembled_in,
3494 { "Reassembled in", "6lowpan.reassembled.in",
3495 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
3496 { &hf_6lowpan_reassembled_length,
3497 { "Reassembled 6LoWPAN length", "6lowpan.reassembled.length",
3498 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
3500 /* 6loRH fields */
3501 { &hf_6lowpan_6lorhc_address_src,
3502 { "Encapsulator Address", "6lowpan.src",
3503 FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 address", HFILL }},
3504 { &hf_6lowpan_6lorhc_address_hop0,
3505 { "Source/15, Delta", "6lowpan.src",
3506 FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 address", HFILL }},
3507 { &hf_6lowpan_6lorhc_address_hop1,
3508 { "Source/14, Delta", "6lowpan.src",
3509 FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 address", HFILL }},
3510 { &hf_6lowpan_6lorhc_address_hop2,
3511 { "Source/12, Delta", "6lowpan.src",
3512 FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 address", HFILL }},
3513 { &hf_6lowpan_6lorhc_address_hop3,
3514 { "Source/8, Delta", "6lowpan.src",
3515 FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 address", HFILL }},
3516 { &hf_6lowpan_6lorhc_address_hop4,
3517 { "Source/0 Delta", "6lowpan.src",
3518 FT_IPv6, BASE_NONE, NULL, 0x0, "Source IPv6 address", HFILL }},
3519 { &hf_6lowpan_sender_rank1,
3520 { "Sender Rank", "6lowpan.sender.rank",
3521 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3522 { &hf_6lowpan_sender_rank2,
3523 { "Sender Rank", "6lowpan.sender.rank",
3524 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3525 { &hf_6lowpan_rpl_instance,
3526 { "RPL Instance", "6lowpan.rpl.instance",
3527 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3528 { &hf_6lowpan_5_bit_o,
3529 { "Packet direction (bit O)", "6lowpan.6loRH.bitO",
3530 FT_BOOLEAN, 16, TFS(&tfs_down_up), LOWPAN_5_RPI_BIT_O, NULL, HFILL }},
3531 { &hf_6lowpan_5_bit_r,
3532 { "Rank-Error (bit R)", "6lowpan.6loRH.bitR",
3533 FT_BOOLEAN, 16, TFS(&tfs_yes_no), LOWPAN_5_RPI_BIT_R, NULL, HFILL }},
3534 { &hf_6lowpan_5_bit_f,
3535 { "Forwarding-Error (bit F)", "6lowpan.6loRH.bitF",
3536 FT_BOOLEAN, 16, TFS(&tfs_yes_no), LOWPAN_5_RPI_BIT_F, NULL, HFILL }},
3537 { &hf_6lowpan_5_bit_i,
3538 { "RPL Instance (bit I)", "6lowpan.6loRH.bitI",
3539 FT_BOOLEAN, 16, TFS(&bit_I_RPL), LOWPAN_5_RPI_BIT_I, NULL, HFILL }},
3540 { &hf_6lowpan_5_bit_k,
3541 { "Sender Rank Compression size (bit K)", "6lowpan.6loRH.bitK",
3542 FT_BOOLEAN, 16, TFS(&bit_K_RPL), LOWPAN_5_RPI_BIT_K, NULL, HFILL }},
3543 { &hf_6lowpan_6lorhe_hoplimit,
3544 { "6loRH Hop Limit", "6lowpan.rhhop.limit",
3545 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3546 { &hf_6lowpan_6lorhe_bitmap,
3547 { "6loRH BIER Bitmap", "6lowpan.bitmap",
3548 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3549 { &hf_6lowpan_6lorhe_type,
3550 { "6loRH Type", "6lowpan.rhtype",
3551 FT_UINT16, BASE_HEX, VALS(lowpan_patterns_rh_type), LOWPAN_PATTERN_6LORHE_TYPE, NULL, HFILL }},
3552 { &hf_6lowpan_6lorhc_size,
3553 { "6loRH Hop Number-1", "6lowpan.HopNuevo",
3554 FT_UINT16, BASE_HEX, NULL, LOWPAN_PATTERN_6LORHE_LENGTH, NULL, HFILL }},
3555 { &hf_6lowpan_6lorhe_size,
3556 { "6loRH Bitmap Word Number-1", "6lowpan.WordNuevo",
3557 FT_UINT16, BASE_HEX, NULL, LOWPAN_PATTERN_6LORHE_LENGTH, NULL, HFILL }},
3558 { &hf_6lowpan_6lorhe_length,
3559 { "6loRH Elective Length", "6lowpan.rhElength",
3560 FT_UINT16, BASE_DEC, NULL, LOWPAN_PATTERN_6LORHE_LENGTH, NULL, HFILL }},
3561 { &hf_6lowpan_routing_header,
3562 { "Routing Header 6lo", "6lowpan.routingheader",
3563 FT_UINT8, BASE_HEX, VALS(lowpan_patterns_rh), 0x0, NULL, HFILL }},
3564 { &hf_6lowpan_pagenb,
3565 { "Page Number", "6lowpan.pagenb",
3566 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}
3569 static int *ett[] = {
3570 &ett_6lowpan,
3571 &ett_6lowpan_hc1,
3572 &ett_6lowpan_hc1_encoding,
3573 &ett_6lowpan_hc2_udp,
3574 &ett_6lowpan_iphc,
3575 &ett_lowpan_routing_header_dispatch,
3576 &ett_6lowpan_nhc_ext,
3577 &ett_6lowpan_nhc_udp,
3578 &ett_6lowpan_bcast,
3579 &ett_6lowpan_mesh,
3580 &ett_6lowpan_mesh_flags,
3581 &ett_6lowpan_frag,
3582 /* Reassembly subtrees. */
3583 &ett_6lowpan_fragment,
3584 &ett_6lowpan_fragments
3587 static ei_register_info ei[] = {
3588 { &ei_6lowpan_hc1_more_bits, { "6lowpan.hc1_more_bits", PI_MALFORMED, PI_ERROR, "HC1 more bits expected for illegal next header type.", EXPFILL }},
3589 { &ei_6lowpan_illegal_dest_addr_mode, { "6lowpan.illegal_dest_addr_mode", PI_MALFORMED, PI_ERROR, "Illegal destination address mode", EXPFILL }},
3590 { &ei_6lowpan_bad_ipv6_header_length, { "6lowpan.bad_ipv6_header_length", PI_MALFORMED, PI_ERROR, "Length is less than IPv6 header length", EXPFILL }},
3591 { &ei_6lowpan_bad_ext_header_length, { "6lowpan.bad_ext_header_length", PI_MALFORMED, PI_ERROR, "Extension header not 8-octet aligned", EXPFILL }},
3594 int i;
3595 module_t *prefs_module;
3596 expert_module_t* expert_6lowpan;
3598 lowpan_context_table = g_hash_table_new_full(lowpan_context_hash, lowpan_context_equal, lowpan_context_free, lowpan_context_free);
3600 proto_6lowpan = proto_register_protocol("IPv6 over Low power Wireless Personal Area Networks", "6LoWPAN", "6lowpan");
3601 proto_register_field_array(proto_6lowpan, hf, array_length(hf));
3602 proto_register_subtree_array(ett, array_length(ett));
3603 expert_6lowpan = expert_register_protocol(proto_6lowpan);
3604 expert_register_field_array(expert_6lowpan, ei, array_length(ei));
3606 /* Register the dissector with wireshark. */
3607 handle_6lowpan = register_dissector("6lowpan", dissect_6lowpan, proto_6lowpan);
3609 /* Initialize the fragment reassembly table. */
3610 reassembly_table_register(&lowpan_reassembly_table, &addresses_reassembly_table_functions);
3612 /* Register the dissector init function */
3613 register_init_routine(proto_init_6lowpan);
3614 register_shutdown_routine(proto_shutdown_6lowpan);
3616 /* Initialize the context preferences. */
3617 memset((char*)lowpan_context_prefs, 0, sizeof(lowpan_context_prefs));
3619 /* Register preferences. */
3620 prefs_module = prefs_register_protocol(proto_6lowpan, prefs_6lowpan_apply);
3622 prefs_register_bool_preference(prefs_module, "rfc4944_short_address_format",
3623 "Derive IID according to RFC 4944",
3624 "Derive IID from a short 16-bit address according to RFC 4944 (using the PAN ID).",
3625 &rfc4944_short_address_format);
3626 prefs_register_bool_preference(prefs_module, "iid_has_universal_local_bit",
3627 "IID has Universal/Local bit",
3628 "Linux kernels before version 4.12 does toggle the Universal/Local bit.",
3629 &iid_has_universal_local_bit);
3630 prefs_register_bool_preference(prefs_module, "summary_in_tree",
3631 "Show IPv6 summary in protocol tree",
3632 "Whether the IPv6 summary line should be shown in the protocol tree",
3633 &ipv6_summary_in_tree);
3635 for (i = 0; i < LOWPAN_CONTEXT_MAX; i++) {
3636 char *pref_name, *pref_title;
3639 * Inspired by the IEEE 802.11 dissector - the preferences are expecting
3640 * that each pref has a unique string passed in, and will crash if we
3641 * try to reuse any for multiple preferences.
3643 pref_name = wmem_strdup_printf(wmem_epan_scope(), "context%d", i);
3644 pref_title = wmem_strdup_printf(wmem_epan_scope(), "Context %d", i);
3645 prefs_register_string_preference(prefs_module, pref_name, pref_title,
3646 "IPv6 prefix to use for stateful address decompression.",
3647 &lowpan_context_prefs[i]);
3649 } /* proto_register_6lowpan */
3651 /*FUNCTION:------------------------------------------------------
3652 * NAME
3653 * proto_init_6lowpan
3654 * DESCRIPTION
3655 * 6LoWPAN initialization function.
3656 * PARAMETERS
3657 * none ;
3658 * RETURNS
3659 * void ;
3660 *---------------------------------------------------------------
3662 static void
3663 proto_init_6lowpan(void)
3665 /* Initialize the link-local context. */
3666 lowpan_context_local.frame = 0;
3667 lowpan_context_local.plen = LOWPAN_CONTEXT_LINK_LOCAL_BITS;
3668 memcpy(&lowpan_context_local.prefix, lowpan_llprefix, sizeof(lowpan_llprefix));
3670 /* Reload static contexts from our preferences. */
3671 prefs_6lowpan_apply();
3672 } /* proto_init_6lowpan */
3674 /*FUNCTION:------------------------------------------------------
3675 * NAME
3676 * prefs_6lowpan_apply
3677 * DESCRIPTION
3678 * Prefs "apply" callback. Parses the context table for
3679 * IPv6 addresses/prefixes.
3680 * PARAMETERS
3681 * none ;
3682 * RETURNS
3683 * void ;
3684 *---------------------------------------------------------------
3686 void
3687 prefs_6lowpan_apply(void)
3689 int i;
3690 ws_in6_addr prefix;
3691 char *prefix_str;
3692 char *prefix_len_str;
3693 uint32_t prefix_len;
3694 char prefix_buf[48]; /* max length of IPv6 str. plus a bit */
3696 for (i = 0; i < LOWPAN_CONTEXT_MAX; i++) {
3697 if (!lowpan_context_prefs[i]) continue;
3698 (void) g_strlcpy(prefix_buf, lowpan_context_prefs[i], 48);
3699 if ((prefix_str = strtok(prefix_buf, "/")) == NULL) continue;
3700 if ((prefix_len_str = strtok(NULL, "/")) == NULL) continue;
3701 if (sscanf(prefix_len_str, "%u", &prefix_len) != 1) continue;
3702 if (!str_to_ip6(prefix_str, &prefix)) continue;
3703 /* Set the prefix */
3704 lowpan_context_insert(i, IEEE802154_BCAST_PAN, prefix_len, &prefix, 0);
3705 } /* for */
3706 } /* prefs_6lowpan_apply */
3708 /*FUNCTION:------------------------------------------------------
3709 * NAME
3710 * proto_reg_handoff_6lowpan
3711 * DESCRIPTION
3712 * Protocol handoff routine for 6LoWPAN. Called after all
3713 * protocols have been loaded.
3714 * PARAMETERS
3715 * none ;
3716 * RETURNS
3717 * void ;
3718 *---------------------------------------------------------------
3720 void
3721 proto_reg_handoff_6lowpan(void)
3723 ipv6_handle = find_dissector_add_dependency("ipv6", proto_6lowpan);
3725 /* Register the 6LoWPAN dissector with IEEE 802.15.4 */
3726 dissector_add_for_decode_as(IEEE802154_PROTOABBREV_WPAN_PANID, handle_6lowpan);
3727 heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_6lowpan_heur, "6LoWPAN over IEEE 802.15.4", "6lowpan_wlan", proto_6lowpan, HEURISTIC_ENABLE);
3729 /* Register Ethertype (RFC 7973) */
3730 dissector_add_uint("ethertype", ETHERTYPE_6LOWPAN, handle_6lowpan);
3732 dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_LE_IPSP, handle_6lowpan);
3733 dissector_add_for_decode_as("btl2cap.cid", handle_6lowpan);
3734 } /* proto_reg_handoff_6lowpan */
3738 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3740 * Local variables:
3741 * c-basic-offset: 4
3742 * tab-width: 8
3743 * indent-tabs-mode: nil
3744 * End:
3746 * vi: set shiftwidth=4 tabstop=8 expandtab:
3747 * :indentSize=4:tabSize=8:noTabs=true: