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