1 /* packet-thread.c
2  * Routines for Thread over CoAP and beacon packet dissection
3  *
4  * Robert Cragie <robert.cragie@arm.com>
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 #include "config.h"
14 #include <stdlib.h>
15 #include <math.h>
16 #include <epan/packet.h>
17 #include <epan/conversation.h>
18 #include <epan/proto_data.h>
19 #include <epan/wmem_scopes.h>
20 #include <epan/expert.h>
21 #include <epan/range.h>
22 #include <epan/prefs.h>
23 #include <epan/strutil.h>
24 #include <epan/to_str.h>
25 #include "packet-coap.h"
26 #include "packet-ieee802154.h"
27 #include "packet-mle.h"
28 
29 /* Use libgcrypt for cipher libraries. */
30 #include <wsutil/wsgcrypt.h>
31 
32 /* Forward declarations */
33 void proto_register_thread_coap(void);
34 
35 void proto_register_thread_address(void);
36 void proto_reg_handoff_thread_address(void);
37 
38 void proto_register_thread_dg(void);
39 void proto_reg_handoff_thread_dg(void);
40 
41 void proto_register_thread_mc(void);
42 void proto_reg_handoff_thread_mc(void);
43 
44 void proto_register_thread_nwd(void);
45 
46 void proto_register_thread_bcn(void);
47 void proto_reg_handoff_thread_bcn(void);
48 
49 void proto_register_thread(void);
50 void proto_reg_handoff_thread(void);
51 
52 static int proto_thread_address = -1;
53 static int proto_thread_dg = -1;
54 static int proto_thread_mc = -1;
55 static int proto_thread_nwd = -1;
56 static int proto_thread_coap = -1;
57 static int proto_thread_bcn = -1;
58 static int proto_thread = -1;
59 static int proto_coap = -1;
60 
61 /* Header fields */
62 
63 /* Thread address */
64 
65 static int hf_thread_address_tlv = -1;
66 static int hf_thread_address_tlv_type = -1;
67 static int hf_thread_address_tlv_length = -1;
68 static int hf_thread_address_tlv_unknown = -1;
69 /* static int hf_thread_address_tlv_sub_tlvs = -1; */
70 
71 /* Target EID TLV fields */
72 static int hf_thread_address_tlv_target_eid = -1;
73 
74 /* Ext. MAC address TLV fields */
75 static int hf_thread_address_tlv_ext_mac_addr = -1;
76 
77 /* RLOC16 TLV fields */
78 static int hf_thread_address_tlv_rloc16 = -1;
79 
80 /* Mesh Local IID TLV fields */
81 static int hf_thread_address_tlv_ml_eid = -1;
82 
83 /* Status TLV fields */
84 static int hf_thread_address_tlv_status = -1;
85 
86 /* Attached time TLV fields */
87 /* static int hf_thread_address_tlv_attached_time = -1; */
88 
89 /* Last transaction time TLV fields */
90 static int hf_thread_address_tlv_last_transaction_time = -1;
91 
92 /* Router Mask TLV fields */
93 static int hf_thread_address_tlv_router_mask_id_seq = -1;
94 static int hf_thread_address_tlv_router_mask_assigned = -1;
95 
96 /* ND option fields */
97 static int hf_thread_address_tlv_nd_option = -1;
98 
99 /* ND data fields */
100 static int hf_thread_address_tlv_nd_data = -1;
101 
102 /* Thread diagnostics */
103 
104 static int hf_thread_dg_tlv = -1;
105 static int hf_thread_dg_tlv_type = -1;
106 static int hf_thread_dg_tlv_length8 = -1;
107 static int hf_thread_dg_tlv_length16 = -1;
108 static int hf_thread_dg_tlv_general = -1;
109 static int hf_thread_dg_tlv_unknown = -1;
110 
111 #if 0
112 /**** TBC: will be added later. For now, just use general string ****/
113 static int hf_thread_dg_tlv_source_addr = -1;
114 static int hf_thread_dg_tlv_mode_device_type = -1;
115 static int hf_thread_dg_tlv_mode_idle_rx = -1;
116 static int hf_thread_dg_tlv_mode_sec_data_req = -1;
117 static int hf_thread_dg_tlv_mode_nwk_data = -1;
118 static int hf_thread_dg_tlv_timeout = -1;
119 static int hf_thread_dg_tlv_lqi_c = -1;
120 static int hf_thread_dg_tlv_lqi_size = -1;
121 static int hf_thread_dg_tlv_neighbor = -1;
122 static int hf_thread_dg_tlv_neighbor_flagI = -1;
123 static int hf_thread_dg_tlv_neighbor_flagO = -1;
124 static int hf_thread_dg_tlv_neighbor_flagP = -1;
125 static int hf_thread_dg_tlv_neighbor_idr = -1;
126 static int hf_thread_dg_tlv_neighbor_addr = -1;
127 static int hf_thread_dg_tlv_network_param_id = -1;
128 static int hf_thread_dg_tlv_network_delay = -1;
129 static int hf_thread_dg_tlv_network_channel = -1;
130 static int hf_thread_dg_tlv_network_pan_id = -1;
131 static int hf_thread_dg_tlv_network_pmt_join = -1;
132 static int hf_thread_dg_tlv_network_bcn_payload = -1;
133 static int hf_thread_dg_tlv_network_unknown = -1;
134 static int hf_thread_dg_tlv_mle_frm_cntr = -1;
135 static int hf_thread_dg_tlv_route_tbl_id_seq = -1;
136 static int hf_thread_dg_tlv_route_tbl_id_mask = -1;
137 static int hf_thread_dg_tlv_route_tbl_entry = -1;
138 static int hf_thread_dg_tlv_route_tbl_nbr_out = -1;
139 static int hf_thread_dg_tlv_route_tbl_nbr_in = -1;
140 static int hf_thread_dg_tlv_route_tbl_cost = -1;
141 static int hf_thread_dg_tlv_route_tbl_unknown = -1;
142 static int hf_thread_dg_tlv_addr_16 = -1;
143 static int hf_thread_dg_tlv_leader_data_partition_id = -1;
144 static int hf_thread_dg_tlv_leader_data_weighting = -1;
145 static int hf_thread_dg_tlv_leader_data_version = -1;
146 static int hf_thread_dg_tlv_leader_data_stable_version = -1;
147 static int hf_thread_dg_tlv_leader_data_router_id = -1;
148 static int hf_thread_dg_tlv_network_data = -1;
149 static int hf_thread_dg_tlv_scan_mask_r = -1;
150 static int hf_thread_dg_tlv_scan_mask_e = -1;
151 static int hf_thread_dg_tlv_conn_max_child_cnt = -1;
152 static int hf_thread_dg_tlv_conn_child_cnt = -1;
153 static int hf_thread_dg_tlv_conn_lq3 = -1;
154 static int hf_thread_dg_tlv_conn_lq2 = -1;
155 static int hf_thread_dg_tlv_conn_lq1 = -1;
156 static int hf_thread_dg_tlv_conn_leader_cost = -1;
157 static int hf_thread_dg_tlv_conn_id_seq = -1;
158 static int hf_thread_dg_tlv_link_margin = -1;
159 static int hf_thread_dg_tlv_status = -1;
160 static int hf_thread_dg_tlv_version = -1;
161 static int hf_thread_dg_tlv_addr_reg_entry = -1;
162 static int hf_thread_dg_tlv_addr_reg_iid_type = -1;
163 static int hf_thread_dg_tlv_addr_reg_cid = -1;
164 static int hf_thread_dg_tlv_addr_reg_iid = -1;
165 static int hf_thread_dg_tlv_addr_reg_ipv6 = -1;
166 static int hf_thread_dg_tlv_hold_time = -1;
167 #endif
168 
169 /* Thread MeshCoP */
170 
171 static int hf_thread_mc_tlv = -1;
172 static int hf_thread_mc_tlv_type = -1;
173 static int hf_thread_mc_tlv_length8 = -1;
174 static int hf_thread_mc_tlv_length16 = -1;
175 static int hf_thread_mc_tlv_unknown = -1;
176 /* static int hf_thread_mc_tlv_sub_tlvs = -1; */
177 
178 /* Channel TLV fields */
179 static int hf_thread_mc_tlv_channel_page = -1;
180 static int hf_thread_mc_tlv_channel = -1;
181 
182 /* PAN ID TLV fields */
183 static int hf_thread_mc_tlv_pan_id = -1;
184 
185 /* Extended PAN ID TLV fields */
186 static int hf_thread_mc_tlv_xpan_id = -1;
187 
188 /* Network Name TLV fields */
189 static int hf_thread_mc_tlv_net_name = -1;
190 
191 /* PSKc TLV fields */
192 static int hf_thread_mc_tlv_pskc = -1;
193 
194 /* Master Key TLV fields */
195 static int hf_thread_mc_tlv_master_key = -1;
196 
197 /* Network Key Sequence TLV fields */
198 static int hf_thread_mc_tlv_net_key_seq_ctr = -1;
199 
200 /* Mesh Local ULA TLV fields */
201 static int hf_thread_mc_tlv_ml_prefix = -1;
202 
203 /* Steering Data TLV fields */
204 static int hf_thread_mc_tlv_steering_data = -1;
205 
206 /* Border Agent Locator TLV fields */
207 static int hf_thread_mc_tlv_ba_locator = -1;
208 
209 /* Commissioner ID TLV fields */
210 static int hf_thread_mc_tlv_commissioner_id = -1;
211 
212 /* Commissioner ID TLV fields */
213 static int hf_thread_mc_tlv_commissioner_sess_id = -1;
214 
215 /* Security Policy TLV fields */
216 static int hf_thread_mc_tlv_sec_policy_rot = -1;
217 static int hf_thread_mc_tlv_sec_policy_o = -1;
218 static int hf_thread_mc_tlv_sec_policy_n = -1;
219 static int hf_thread_mc_tlv_sec_policy_r = -1;
220 static int hf_thread_mc_tlv_sec_policy_c = -1;
221 static int hf_thread_mc_tlv_sec_policy_b = -1;
222 
223 /* State TLV fields */
224 static int hf_thread_mc_tlv_state = -1;
225 
226 /* Timestamp TLV fields */
227 static int hf_thread_mc_tlv_active_tstamp = -1;
228 static int hf_thread_mc_tlv_pending_tstamp = -1;
229 
230 /* Delay Timer TLV fields */
231 static int hf_thread_mc_tlv_delay_timer = -1;
232 
233 /* UDP Encapsulation TLV fields */
234 static int hf_thread_mc_tlv_udp_encap_src_port = -1;
235 static int hf_thread_mc_tlv_udp_encap_dst_port = -1;
236 
237 /* IPv6 Address fields */
238 static int hf_thread_mc_tlv_ipv6_addr = -1;
239 
240 /* UDP Port TLV fields */
241 static int hf_thread_mc_tlv_udp_port = -1;
242 
243 /* IID TLV fields */
244 static int hf_thread_mc_tlv_iid = -1;
245 
246 /* Joiner Router locator TLV fields */
247 static int hf_thread_mc_tlv_jr_locator = -1;
248 
249 /* KEK TLV fields */
250 static int hf_thread_mc_tlv_kek = -1;
251 
252 /* Provisioning URL TLV fields */
253 static int hf_thread_mc_tlv_provisioning_url = -1;
254 
255 /* Vendor TLV fields */
256 static int hf_thread_mc_tlv_vendor_name = -1;
257 static int hf_thread_mc_tlv_vendor_model = -1;
258 static int hf_thread_mc_tlv_vendor_sw_ver = -1;
259 static int hf_thread_mc_tlv_vendor_data = -1;
260 static int hf_thread_mc_tlv_vendor_stack_ver_oui = -1;
261 static int hf_thread_mc_tlv_vendor_stack_ver_build = -1;
262 static int hf_thread_mc_tlv_vendor_stack_ver_rev = -1;
263 static int hf_thread_mc_tlv_vendor_stack_ver_min = -1;
264 static int hf_thread_mc_tlv_vendor_stack_ver_maj = -1;
265 
266 /* Channel Mask TLV fields */
267 static int hf_thread_mc_tlv_chan_mask = -1;
268 static int hf_thread_mc_tlv_chan_mask_page = -1;
269 static int hf_thread_mc_tlv_chan_mask_len = -1;
270 static int hf_thread_mc_tlv_chan_mask_mask = -1;
271 
272 /* Count TLV fields */
273 static int hf_thread_mc_tlv_count = -1;
274 
275 /* Period TLV fields */
276 static int hf_thread_mc_tlv_period = -1;
277 
278 /* Period TLV fields */
279 static int hf_thread_mc_tlv_scan_duration = -1;
280 
281 /* Energy List TLV fields */
282 static int hf_thread_mc_tlv_energy_list = -1;
283 static int hf_thread_mc_tlv_el_count = -1;
284 
285 /* Discovery Request TLV fields */
286 static int hf_thread_mc_tlv_discovery_req_ver = -1;
287 static int hf_thread_mc_tlv_discovery_req_j = -1;
288 
289 /* Discovery Response TLV fields */
290 static int hf_thread_mc_tlv_discovery_rsp_ver = -1;
291 static int hf_thread_mc_tlv_discovery_rsp_n = -1;
292 
293 /* Thread Network Data */
294 
295 static int hf_thread_nwd_tlv = -1;
296 static int hf_thread_nwd_tlv_type = -1;
297 static int hf_thread_nwd_tlv_stable = -1;
298 static int hf_thread_nwd_tlv_length = -1;
299 static int hf_thread_nwd_tlv_unknown = -1;
300 static int hf_thread_nwd_tlv_sub_tlvs = -1;
301 
302 /* Has Route TLV fields */
303 static int hf_thread_nwd_tlv_has_route = -1;
304 static int hf_thread_nwd_tlv_has_route_br_16 = -1;
305 static int hf_thread_nwd_tlv_has_route_pref = -1;
306 
307 /* Prefix TLV fields */
308 static int hf_thread_nwd_tlv_prefix = -1;
309 static int hf_thread_nwd_tlv_prefix_domain_id = -1;
310 static int hf_thread_nwd_tlv_prefix_length = -1;
311 
312 /* Border Router TLV fields */
313 static int hf_thread_nwd_tlv_border_router = -1;
314 static int hf_thread_nwd_tlv_border_router_16 = -1;
315 static int hf_thread_nwd_tlv_border_router_pref = -1;
316 static int hf_thread_nwd_tlv_border_router_p = -1;
317 static int hf_thread_nwd_tlv_border_router_s = -1;
318 static int hf_thread_nwd_tlv_border_router_d = -1;
319 static int hf_thread_nwd_tlv_border_router_c = -1;
320 static int hf_thread_nwd_tlv_border_router_r = -1;
321 static int hf_thread_nwd_tlv_border_router_o = -1;
322 static int hf_thread_nwd_tlv_border_router_n = -1;
323 
324 /* 6LoWPAN ID TLV fields */
325 static int hf_thread_nwd_tlv_6lowpan_id_6co_context_length = -1;
326 static int hf_thread_nwd_tlv_6lowpan_id_6co_flag = -1;
327 static int hf_thread_nwd_tlv_6lowpan_id_6co_flag_c = -1;
328 static int hf_thread_nwd_tlv_6lowpan_id_6co_flag_cid = -1;
329 static int hf_thread_nwd_tlv_6lowpan_id_6co_flag_reserved = -1;
330 
331 /* Commissioning Data fields */
332 /* static int hf_thread_nwd_tlv_comm_data = -1; */
333 
334 /* Service fields */
335 static int hf_thread_nwd_tlv_service_t = -1;
336 static int hf_thread_nwd_tlv_service_s_id = -1;
337 static int hf_thread_nwd_tlv_service_s_ent_num = -1;
338 static int hf_thread_nwd_tlv_service_s_data_len = -1;
339 static int hf_thread_nwd_tlv_service_s_data = -1;
340 
341 /* Server fields */
342 static int hf_thread_nwd_tlv_server_16 = -1;
343 static int hf_thread_nwd_tlv_server_data = -1;
344 
345 /* Thread Beacon */
346 
347 static int hf_thread_bcn_protocol = -1;
348 static int hf_thread_bcn_joining = -1;
349 static int hf_thread_bcn_native = -1;
350 static int hf_thread_bcn_version = -1;
351 static int hf_thread_bcn_network_id = -1;
352 static int hf_thread_bcn_epid = -1;
353 static int hf_thread_bcn_tlv = -1;
354 static int hf_thread_bcn_tlv_type = -1;
355 static int hf_thread_bcn_tlv_length = -1;
356 static int hf_thread_bcn_tlv_steering_data = -1;
357 static int hf_thread_bcn_tlv_unknown = -1;
358 
359 /* Tree types */
360 
361 static gint ett_thread_address = -1;
362 static gint ett_thread_address_tlv = -1;
363 static gint ett_thread_dg = -1;
364 static gint ett_thread_dg_tlv = -1;
365 static gint ett_thread_mc = -1;
366 static gint ett_thread_mc_tlv = -1;
367 static gint ett_thread_mc_chan_mask = -1;
368 static gint ett_thread_mc_el_count = -1;
369 static gint ett_thread_nwd = -1;
370 static gint ett_thread_nwd_tlv = -1;
371 static gint ett_thread_nwd_has_route = -1;
372 static gint ett_thread_nwd_6co_flag = -1;
373 static gint ett_thread_nwd_border_router = -1;
374 static gint ett_thread_nwd_prefix_sub_tlvs = -1;
375 static gint ett_thread_bcn = -1;
376 static gint ett_thread_bcn_tlv = -1;
377 
378 /* Expert info. */
379 
380 /* static expert_field ei_thread_address_tlv_length_failed = EI_INIT; */
381 static expert_field ei_thread_address_len_size_mismatch = EI_INIT;
382 /* static expert_field ei_thread_dg_tlv_length_failed = EI_INIT; */
383 /* static expert_field ei_thread_dg_len_size_mismatch = EI_INIT; */
384 static expert_field ei_thread_mc_tlv_length_failed = EI_INIT;
385 static expert_field ei_thread_mc_len_size_mismatch = EI_INIT;
386 static expert_field ei_thread_mc_len_too_long      = EI_INIT;
387 /* static expert_field ei_thread_nwd_tlv_length_failed = EI_INIT; */
388 static expert_field ei_thread_nwd_len_size_mismatch = EI_INIT;
389 
390 static dissector_table_t thread_coap_namespace;
391 
392 /* Dissector handles */
393 static dissector_handle_t thread_address_nwd_handle;
394 static dissector_handle_t thread_dg_handle;
395 static dissector_handle_t thread_mc_handle;
396 static dissector_handle_t thread_dtls_handle;
397 static dissector_handle_t thread_udp_handle;
398 static dissector_handle_t thread_coap_handle;
399 static dissector_handle_t thread_address_handle;
400 
401 #define THREAD_TLV_LENGTH_ESC  0xFF
402 
403 #define THREAD_URI_NAMESPACE_IDX 1
404 
405 #define THREAD_MC_32768_TO_NSEC_FACTOR ((double)30517.578125)
406 #define THREAD_MC_TSTAMP_MASK_U_MASK 0x80
407 #define THREAD_MC_SEC_POLICY_MASK_O_MASK 0x80
408 #define THREAD_MC_SEC_POLICY_MASK_N_MASK 0x40
409 #define THREAD_MC_SEC_POLICY_MASK_R_MASK 0x20
410 #define THREAD_MC_SEC_POLICY_MASK_C_MASK 0x10
411 #define THREAD_MC_SEC_POLICY_MASK_B_MASK 0x08
412 #define THREAD_MC_STACK_VER_REV_MASK 0x0F
413 #define THREAD_MC_STACK_VER_MIN_MASK 0xF0
414 #define THREAD_MC_STACK_VER_MAJ_MASK 0x0F
415 #define THREAD_MC_DISCOVERY_REQ_MASK_VER_MASK 0xF0
416 #define THREAD_MC_DISCOVERY_REQ_MASK_J_MASK 0x08
417 #define THREAD_MC_DISCOVERY_RSP_MASK_VER_MASK 0xF0
418 #define THREAD_MC_DISCOVERY_RSP_MASK_N_MASK 0x08
419 #define THREAD_MC_INVALID_CHAN_COUNT 0xFFFF
420 
421 #define THREAD_NWD_TLV_HAS_ROUTE_PREF       0xC0
422 #define THREAD_NWD_TLV_HAS_ROUTE_SIZE       3
423 
424 #define THREAD_NWD_TLV_BORDER_ROUTER_PREF   0xC0
425 #define THREAD_NWD_TLV_BORDER_ROUTER_P      0x20
426 #define THREAD_NWD_TLV_BORDER_ROUTER_S      0x10
427 #define THREAD_NWD_TLV_BORDER_ROUTER_D      0x08
428 #define THREAD_NWD_TLV_BORDER_ROUTER_C      0x04
429 #define THREAD_NWD_TLV_BORDER_ROUTER_R      0x02
430 #define THREAD_NWD_TLV_BORDER_ROUTER_O      0x01
431 #define THREAD_NWD_TLV_BORDER_ROUTER_N      0x80
432 
433 #define THREAD_BCN_PROTOCOL_ID              0x03
434 #define THREAD_BCN_JOINING                  0x01
435 #define THREAD_BCN_NATIVE                   0x08
436 #define THREAD_BCN_PROTOCOL_VERSION         0xf0
437 #define THREAD_BCN_TLV_STEERING_DATA_S      0x80
438 #define THREAD_BCN_TLV_STEERING_DATA        8
439 
440 #define ND_OPT_6CO_FLAG_C        0x10
441 #define ND_OPT_6CO_FLAG_CID      0x0F
442 #define ND_OPT_6CO_FLAG_RESERVED 0xE0
443 
444 #define THREAD_NWD_TLV_SERVICE_T    0x80
445 #define THREAD_NWD_TLV_SERVICE_S_ID 0x0F
446 
447 typedef enum {
448     TLV_LEN_LEN8 = 1,
449     TLV_LEN_LEN16 = 3
450 } tlv_len_len_e;
451 
452 typedef struct {
453     guint16 src_port;
454     guint16 dst_port;
455     guint16 length;
456     guint16 checksum;
457 } udp_hdr_t;
458 
459 /* TLV values */
460 
461 #define THREAD_ADDRESS_TLV_TARGET_EID               0
462 #define THREAD_ADDRESS_TLV_EXT_MAC_ADDR             1
463 #define THREAD_ADDRESS_TLV_RLOC16                   2
464 #define THREAD_ADDRESS_TLV_ML_EID                   3
465 #define THREAD_ADDRESS_TLV_STATUS                   4
466 /* Gap */
467 #define THREAD_ADDRESS_TLV_LAST_TRANSACTION_TIME    6
468 #define THREAD_ADDRESS_TLV_ROUTER_MASK              7
469 #define THREAD_ADDRESS_TLV_ND_OPTION                8
470 #define THREAD_ADDRESS_TLV_ND_DATA                  9
471 #define THREAD_ADDRESS_TLV_THREAD_NETWORK_DATA      10
472 
473 static const value_string thread_address_tlv_vals[] = {
474 { THREAD_ADDRESS_TLV_TARGET_EID,            "Target EID" },
475 { THREAD_ADDRESS_TLV_EXT_MAC_ADDR,          "Extended MAC Address" },
476 { THREAD_ADDRESS_TLV_RLOC16,                "RLOC16" },
477 { THREAD_ADDRESS_TLV_ML_EID,                "ML-EID" },
478 { THREAD_ADDRESS_TLV_STATUS,                "Status" },
479 /* Gap */
480 { THREAD_ADDRESS_TLV_LAST_TRANSACTION_TIME, "Last Transaction Time" },
481 { THREAD_ADDRESS_TLV_ND_OPTION,             "ND Option" },
482 { THREAD_ADDRESS_TLV_ND_DATA,               "ND Data" },
483 { THREAD_ADDRESS_TLV_THREAD_NETWORK_DATA,   "Thread Network Data" },
484 { 0, NULL }
485 };
486 
487 static const value_string thread_address_tlv_status_vals[] = {
488 { 0, "Success" },
489 { 1, "No Address Available" },
490 { 0, NULL }
491 };
492 
493 /* Network Layer (Address) mirrors */
494 #define THREAD_DG_TLV_EXT_MAC_ADDR          0 /* As THREAD_ADDRESS_TLV_EXT_MAC_ADDR */
495 /* MLE mirrors */
496 #define THREAD_DG_TLV_ADDRESS16             1 /* As MLE_TLV_ADDRESS16 */
497 #define THREAD_DG_TLV_MODE                  2 /* As MLE_TLV_MODE */
498 #define THREAD_DG_TLV_TIMEOUT               3 /* As MLE_TLV_TIMEOUT */
499 #define THREAD_DG_TLV_CONNECTIVITY          4 /* As MLE_TLV_CONNECTIVITY */
500 #define THREAD_DG_TLV_ROUTE64               5 /* As MLE_TLV_ROUTE64 */
501 #define THREAD_DG_TLV_LEADER_DATA           6 /* As MLE_TLV_LEADER_DATA */
502 #define THREAD_DG_TLV_NETWORK_DATA          7 /* As MLE_TLV_NETWORK_DATA */
503 /* Statistics */
504 #define THREAD_DG_TLV_IPV6_ADDR_LIST        8
505 #define THREAD_DG_TLV_MAC_COUNTERS          9
506 /* Others */
507 #define THREAD_DG_TLV_BATTERY_LEVEL         14
508 #define THREAD_DG_TLV_VOLTAGE               15
509 #define THREAD_DG_TLV_CHILD_TABLE           16
510 #define THREAD_DG_TLV_CHANNEL_PAGES         17
511 #define THREAD_DG_TLV_TYPE_LIST             18
512 #define THREAD_DG_TLV_UNKNOWN               255
513 
514 static const value_string thread_dg_tlv_vals[] = {
515 /* Network Layer (Address) mirrors */
516 { THREAD_DG_TLV_EXT_MAC_ADDR,          "Extended MAC Address" },
517 /* MLE mirrors */
518 { THREAD_DG_TLV_ADDRESS16,             "Address16" },
519 { THREAD_DG_TLV_MODE,                  "Mode" },
520 { THREAD_DG_TLV_TIMEOUT,               "Timeout" },
521 { THREAD_DG_TLV_CONNECTIVITY,          "Connectivity" },
522 { THREAD_DG_TLV_ROUTE64,               "Route64" },
523 { THREAD_DG_TLV_LEADER_DATA,           "Leader Data" },
524 { THREAD_DG_TLV_NETWORK_DATA,          "Network Data" },
525 /* Statistics */
526 { THREAD_DG_TLV_IPV6_ADDR_LIST,        "IPv6 Address List" },
527 { THREAD_DG_TLV_MAC_COUNTERS,          "MAC Counters" },
528 /* Others */
529 { THREAD_DG_TLV_BATTERY_LEVEL,         "Battery level (%)" },
530 { THREAD_DG_TLV_VOLTAGE,               "Voltage (mV)" },
531 { THREAD_DG_TLV_CHILD_TABLE,           "Child Table" },
532 { THREAD_DG_TLV_CHANNEL_PAGES,         "Channel Pages" },
533 { THREAD_DG_TLV_TYPE_LIST,             "Type List" },
534 { THREAD_DG_TLV_UNKNOWN,               "Unknown" },
535 { 0, NULL }
536 };
537 
538 #define THREAD_MC_TLV_CHANNEL                      0 /* Modified for new features */
539 #define THREAD_MC_TLV_PANID                        1
540 #define THREAD_MC_TLV_XPANID                       2
541 #define THREAD_MC_TLV_NETWORK_NAME                 3
542 #define THREAD_MC_TLV_PSKC                         4
543 #define THREAD_MC_TLV_NETWORK_MASTER_KEY           5
544 #define THREAD_MC_TLV_NETWORK_KEY_SEQ_CTR          6
545 #define THREAD_MC_TLV_NETWORK_ML_PREFIX            7
546 #define THREAD_MC_TLV_STEERING_DATA                8
547 #define THREAD_MC_TLV_BORDER_AGENT_LOCATOR         9
548 #define THREAD_MC_TLV_COMMISSIONER_ID              10
549 #define THREAD_MC_TLV_COMMISSIONER_SESSION_ID      11
550 #define THREAD_MC_TLV_SECURITY_POLICY              12
551 #define THREAD_MC_TLV_GET                          13
552 #define THREAD_MC_TLV_ACTIVE_TSTAMP                14 /* Was "Commissioning Dataset Timestamp TLV" */
553 #define THREAD_MC_TLV_COMMISSIONER_UDP_PORT        15
554 #define THREAD_MC_TLV_STATE                        16
555 #define THREAD_MC_TLV_JOINER_DTLS_ENCAP            17
556 #define THREAD_MC_TLV_JOINER_UDP_PORT              18
557 #define THREAD_MC_TLV_JOINER_IID                   19
558 #define THREAD_MC_TLV_JOINER_ROUTER_LOCATOR        20
559 #define THREAD_MC_TLV_JOINER_KEK                   21
560 /* Gap */
561 #define THREAD_MC_TLV_PROVISIONING_URL             32
562 #define THREAD_MC_TLV_VENDOR_NAME                  33
563 #define THREAD_MC_TLV_VENDOR_MODEL                 34
564 #define THREAD_MC_TLV_VENDOR_SW_VERSION            35
565 #define THREAD_MC_TLV_VENDOR_DATA                  36
566 #define THREAD_MC_TLV_VENDOR_STACK_VERSION         37
567 /* Gap */
568 #define THREAD_MC_TLV_UDP_ENCAPSULATION            48
569 #define THREAD_MC_TLV_IPV6_ADDRESS                 49
570 /* Gap */
571 /* New features */
572 #define THREAD_MC_TLV_PENDING_TSTAMP               51
573 #define THREAD_MC_TLV_DELAY_TIMER                  52
574 #define THREAD_MC_TLV_CHANNEL_MASK                 53
575 #define THREAD_MC_TLV_COUNT                        54
576 #define THREAD_MC_TLV_PERIOD                       55
577 #define THREAD_MC_TLV_SCAN_DURATION                56
578 #define THREAD_MC_TLV_ENERGY_LIST                  57
579 /* Gap */
580 /* New discovery mechanism */
581 #define THREAD_MC_TLV_DISCOVERY_REQUEST            128
582 #define THREAD_MC_TLV_DISCOVERY_RESPONSE           129
583 
584 static const value_string thread_mc_tlv_vals[] = {
585 { THREAD_MC_TLV_CHANNEL,                   "Channel" },
586 { THREAD_MC_TLV_PANID,                     "PAN ID" },
587 { THREAD_MC_TLV_XPANID,                    "Extended PAN ID" },
588 { THREAD_MC_TLV_NETWORK_NAME,              "Network Name" },
589 { THREAD_MC_TLV_PSKC,                      "PSKc" },
590 { THREAD_MC_TLV_NETWORK_MASTER_KEY,        "Network Master Key" },
591 { THREAD_MC_TLV_NETWORK_KEY_SEQ_CTR,       "Network Key Sequence Counter" },
592 { THREAD_MC_TLV_NETWORK_ML_PREFIX,         "Mesh Local ULA Prefix" },
593 { THREAD_MC_TLV_STEERING_DATA,             "Steering Data" },
594 { THREAD_MC_TLV_BORDER_AGENT_LOCATOR,      "Border Agent Locator" },
595 { THREAD_MC_TLV_COMMISSIONER_ID,           "Commissioner ID" },
596 { THREAD_MC_TLV_COMMISSIONER_SESSION_ID,   "Commissioner Session ID" },
597 { THREAD_MC_TLV_SECURITY_POLICY,           "Security Policy" },
598 { THREAD_MC_TLV_GET,                       "Get" },
599 { THREAD_MC_TLV_ACTIVE_TSTAMP,             "Active Timestamp" },
600 { THREAD_MC_TLV_COMMISSIONER_UDP_PORT,     "Commissioner UDP Port" },
601 { THREAD_MC_TLV_STATE,                     "State" },
602 { THREAD_MC_TLV_JOINER_DTLS_ENCAP,         "Joiner DTLS Encapsulation" },
603 { THREAD_MC_TLV_JOINER_UDP_PORT,           "Joiner UDP Port" },
604 { THREAD_MC_TLV_JOINER_IID,                "Joiner IID" },
605 { THREAD_MC_TLV_JOINER_ROUTER_LOCATOR,     "Joiner Router Locator" },
606 { THREAD_MC_TLV_JOINER_KEK,                "Joiner KEK" },
607 { THREAD_MC_TLV_PROVISIONING_URL,          "Provisioning URL" },
608 { THREAD_MC_TLV_VENDOR_NAME,               "Vendor Name" },
609 { THREAD_MC_TLV_VENDOR_MODEL,              "Vendor Model" },
610 { THREAD_MC_TLV_VENDOR_SW_VERSION,         "Vendor Software Version" },
611 { THREAD_MC_TLV_VENDOR_DATA,               "Vendor Data" },
612 { THREAD_MC_TLV_VENDOR_STACK_VERSION,      "Vendor Stack Version" },
613 { THREAD_MC_TLV_UDP_ENCAPSULATION,         "UDP Encapsulation" },
614 { THREAD_MC_TLV_IPV6_ADDRESS,              "IPv6 Address" },
615 /* New features */
616 { THREAD_MC_TLV_PENDING_TSTAMP,            "Pending Timestamp" },
617 { THREAD_MC_TLV_DELAY_TIMER,               "Delay Timer" },
618 { THREAD_MC_TLV_CHANNEL_MASK,              "Channel Mask" },
619 { THREAD_MC_TLV_COUNT,                     "Count" },
620 { THREAD_MC_TLV_PERIOD,                    "Period" },
621 { THREAD_MC_TLV_SCAN_DURATION,             "Scan Duration" },
622 { THREAD_MC_TLV_ENERGY_LIST,               "Energy List" },
623 /* New discovery mechanism */
624 { THREAD_MC_TLV_DISCOVERY_REQUEST,         "Discovery Request" },
625 { THREAD_MC_TLV_DISCOVERY_RESPONSE,        "Discovery Response" },
626 { 0, NULL}
627 };
628 
629 static const value_string thread_mc_state_vals[] = {
630 { -1, "Reject" },
631 { 0, "Pending" },
632 { 1, "Accept" },
633 { 0, NULL}
634 };
635 
636 static const true_false_string thread_mc_tlv_join_intent = {
637     "Intending",
638     "Not Intending"
639 };
640 
641 #define THREAD_NWD_TLV_HAS_ROUTE                    0
642 #define THREAD_NWD_TLV_PREFIX                       1
643 #define THREAD_NWD_TLV_BORDER_ROUTER                2
644 #define THREAD_NWD_TLV_6LOWPAN_ID                   3
645 #define THREAD_NWD_TLV_COMMISSIONING_DATA           4
646 #define THREAD_NWD_TLV_SERVICE                      5
647 #define THREAD_NWD_TLV_SERVER                       6
648 
649 static const value_string thread_nwd_tlv_vals[] = {
650 { THREAD_NWD_TLV_HAS_ROUTE,                 "Has Route" },
651 { THREAD_NWD_TLV_PREFIX,                    "Prefix" },
652 { THREAD_NWD_TLV_BORDER_ROUTER,             "Border Router" },
653 { THREAD_NWD_TLV_6LOWPAN_ID,                "6LoWPAN ID" },
654 { THREAD_NWD_TLV_COMMISSIONING_DATA,        "Commissioning Data" },
655 { THREAD_NWD_TLV_SERVICE,                   "Service" },
656 { THREAD_NWD_TLV_SERVER,                    "Server" },
657 { 0, NULL}
658 };
659 
660 #define THREAD_NWD_TLV_TYPE_M       0xFE
661 #define THREAD_NWD_TLV_STABLE_M     0x01
662 
663 static const true_false_string tfs_thread_nwd_tlv_border_router_p = {
664     "Autoconfigured preferred",
665     "Autoconfigured deprecated"
666 };
667 
668 static const true_false_string tfs_thread_nwd_tlv_border_router_c = {
669     "Additional config. data",
670     "No additional config. data"
671 };
672 
673 static const true_false_string tfs_thread_nwd_tlv_border_router_o = {
674     "On mesh",
675     "Not on mesh"
676 };
677 
678 /* Thread Beacon TLV Values. */
679 static const value_string thread_bcn_tlv_vals[] = {
680     { THREAD_BCN_TLV_STEERING_DATA, "Steering Data" },
681     { 0, NULL }
682 };
683 
684 /* Preferences */
685 static gboolean thread_use_pan_id_in_key = FALSE;
686 static const gchar *thread_seq_ctr_str = NULL;
687 static gboolean thread_auto_acq_seq_ctr = TRUE;
688 
689 
690 static gboolean thread_seq_ctr_acqd = FALSE;
691 static guint8 thread_seq_ctr_bytes[4];
692 static const guint8 thread_well_known_key[IEEE802154_CIPHER_SIZE] =
693 { 0x78, 0x58, 0x16, 0x86, 0xfd, 0xb4, 0x58, 0x0f, 0xb0, 0x92, 0x54, 0x6a, 0xec, 0xbd, 0x15, 0x66 };
694 
set_thread_seq_ctr_from_key_index(guint8 key_index)695 static GByteArray *set_thread_seq_ctr_from_key_index(guint8 key_index)
696 {
697     GByteArray *seq_ctr_bytes = NULL;
698 
699     seq_ctr_bytes = g_byte_array_new();
700     if (thread_seq_ctr_acqd) {
701         seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
702         memcpy(seq_ctr_bytes->data, thread_seq_ctr_bytes, 4);
703     } else {
704         hex_str_to_bytes(thread_seq_ctr_str, seq_ctr_bytes, FALSE);
705         if (seq_ctr_bytes->len != 4) {
706             /* Not read correctly - assume value is 0 */
707             seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
708             memset(seq_ctr_bytes->data, 0, 4);
709         }
710     }
711     /* Replace lower part with counter based on packet key index */
712     seq_ctr_bytes->data[3] = (seq_ctr_bytes->data[3] & 0x80) + ((key_index - 1) & 0x7F);
713 
714     return seq_ctr_bytes;
715 }
716 
create_thread_temp_keys(GByteArray * seq_ctr_bytes,guint16 src_pan,ieee802154_key_t * key,unsigned char * mac_key,unsigned char * mle_key)717 static void create_thread_temp_keys(GByteArray *seq_ctr_bytes, guint16 src_pan, ieee802154_key_t* key, unsigned char *mac_key, unsigned char *mle_key)
718 {
719     GByteArray *bytes;
720     char       buffer[10];
721     gboolean   res;
722     gboolean   key_valid;
723     gboolean   verbatim_key = TRUE;
724 
725     /* Get the IEEE 802.15.4 decryption key. */
726     bytes = g_byte_array_new();
727     res = hex_str_to_bytes(key->pref_key, bytes, FALSE);
728     key_valid = (res && bytes->len >= IEEE802154_CIPHER_SIZE);
729     if (key_valid) {
730         if (thread_use_pan_id_in_key) {
731             /* Substitute the bottom two keys bytes with PAN ID */
732             bytes->data[0] = (guint8)(src_pan & 0xFF);
733             bytes->data[1] = (guint8)(src_pan >> 8);
734         }
735         if (key->hash_type != KEY_HASH_NONE) {
736             char digest[32];
737 
738             if (key->hash_type == KEY_HASH_THREAD) {
739                 memcpy(buffer, seq_ctr_bytes->data, 4);
740                 memcpy(&buffer[4], "Thread", 6); /* len("Thread") */
741 
742                 if (!ws_hmac_buffer(GCRY_MD_SHA256, digest, buffer, 10, bytes->data, IEEE802154_CIPHER_SIZE)) {
743                     /* Copy upper hashed bytes to the MAC key */
744                     if (mac_key) {
745                         memcpy(mac_key, &digest[IEEE802154_CIPHER_SIZE], IEEE802154_CIPHER_SIZE);
746                     }
747                     /* Copy lower hashed bytes to the MLE key */
748                     if (mle_key) {
749                         memcpy(mle_key, digest, IEEE802154_CIPHER_SIZE);
750                     }
751                     verbatim_key = FALSE;
752                 }
753             }
754         }
755         if (verbatim_key) {
756             /* Just copy the keys verbatim */
757             if (mac_key) {
758                 memcpy(mac_key, bytes->data, IEEE802154_CIPHER_SIZE);
759             }
760             if (mle_key) {
761                 memcpy(mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
762             }
763         }
764     }
765     g_byte_array_free(bytes, TRUE);
766 }
767 
768 /* Set MAC key for Thread hash */
set_thread_mac_key(ieee802154_packet * packet,unsigned char * key,unsigned char * alt_key,ieee802154_key_t * uat_key)769 static guint set_thread_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
770 {
771     GByteArray *seq_ctr_bytes = NULL;
772 
773     if (packet->key_id_mode == KEY_ID_MODE_KEY_INDEX) {
774         seq_ctr_bytes = set_thread_seq_ctr_from_key_index(packet->key_index);
775     } else if ((packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) &&
776                (packet->key_index == IEEE802154_THR_WELL_KNOWN_KEY_INDEX) &&
777                (packet->key_source.addr32 == IEEE802154_THR_WELL_KNOWN_KEY_SRC))
778     {
779         /* This is the well-known Thread key. No need for an alternative key */
780         memcpy(key, thread_well_known_key, IEEE802154_CIPHER_SIZE);
781         return 1;
782     }
783     if (seq_ctr_bytes != NULL) {
784         create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, key, NULL);
785         /* Create an alternate key based on the wraparound case */
786         seq_ctr_bytes->data[3] ^= 0x80;
787         create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, alt_key, NULL);
788         g_byte_array_free(seq_ctr_bytes, TRUE);
789         return 2;
790     }
791 
792     return 0;
793 }
794 
795 /* Set MLE key for Thread hash */
set_thread_mle_key(ieee802154_packet * packet,unsigned char * key,unsigned char * alt_key,ieee802154_key_t * uat_key)796 static guint set_thread_mle_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
797 {
798     GByteArray *seq_ctr_bytes = NULL;
799     if (packet->key_id_mode == KEY_ID_MODE_KEY_INDEX) {
800         seq_ctr_bytes = set_thread_seq_ctr_from_key_index(packet->key_index);
801     }
802     else if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
803         /* Reconstruct the key source from the key source in the packet */
804         seq_ctr_bytes = g_byte_array_new();
805         seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
806         seq_ctr_bytes->data[0] = (packet->key_source.addr32 >> 24) & 0xFF;
807         seq_ctr_bytes->data[1] = (packet->key_source.addr32 >> 16) & 0xFF;
808         seq_ctr_bytes->data[2] = (packet->key_source.addr32 >> 8) & 0xFF;
809         seq_ctr_bytes->data[3] = packet->key_source.addr32 & 0xFF;
810         /* Acquire the sequence counter if configured in preferences */
811         if (thread_auto_acq_seq_ctr && !thread_seq_ctr_acqd) {
812             memcpy(thread_seq_ctr_bytes, seq_ctr_bytes->data, 4);
813             thread_seq_ctr_acqd = TRUE;
814         }
815     }
816     if (seq_ctr_bytes != NULL) {
817         create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, NULL, key);
818         /* Create an alternate key based on the wraparound case */
819         seq_ctr_bytes->data[3] ^= 0x80;
820         create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, NULL, alt_key);
821         g_byte_array_free(seq_ctr_bytes, TRUE);
822         return 2;
823     }
824 
825     return 0;
826 }
827 
828 static guint
count_bits_in_byte(guint8 byte)829 count_bits_in_byte(guint8 byte)
830 {
831     static const guint8 lut[16] = {0, /* 0b0000 */
832                                    1, /* 0b0001 */
833                                    1, /* 0b0010 */
834                                    2, /* 0b0011 */
835                                    1, /* 0b0100 */
836                                    2, /* 0b0101 */
837                                    2, /* 0b0110 */
838                                    3, /* 0b0111 */
839                                    1, /* 0b1000 */
840                                    2, /* 0b1001 */
841                                    2, /* 0b1010 */
842                                    3, /* 0b1011 */
843                                    2, /* 0b1100 */
844                                    3, /* 0b1101 */
845                                    3, /* 0b1110 */
846                                    4  /* 0b1111 */};
847     return lut[byte >> 4] + lut[byte & 0xf];
848 }
849 
850 static guint
get_chancount(tvbuff_t * tvb)851 get_chancount(tvbuff_t *tvb)
852 {
853     guint         offset;
854     guint8        tlv_type;
855     guint16       tlv_len;
856     tlv_len_len_e tlv_len_len;
857     guint         chancount = THREAD_MC_INVALID_CHAN_COUNT;
858 
859     offset = 0;
860 
861     /* Thread Network Data TLVs */
862     while (tvb_offset_exists(tvb, offset)) {
863 
864         /* Get the type and length ahead of time to pass to next function so we can highlight
865            proper amount of bytes */
866         tlv_type = tvb_get_guint8(tvb, offset);
867         tlv_len = (guint16)tvb_get_guint8(tvb, offset + 1);
868 
869         /* TODO: need to make sure this applies to all MeshCoP TLVs */
870         if (THREAD_TLV_LENGTH_ESC == tlv_len) {
871             /* 16-bit length field */
872             tlv_len = tvb_get_ntohs(tvb, offset + 2);
873             tlv_len_len = TLV_LEN_LEN16;
874         } else {
875             tlv_len_len = TLV_LEN_LEN8;
876         }
877 
878         /* Skip over Type and Length */
879         offset += 1 + tlv_len_len;
880 
881         switch(tlv_type) {
882 
883             case THREAD_MC_TLV_CHANNEL_MASK:
884                 {
885                     int i, j;
886                     guint8 entries = 0;
887                     gint32 check_len = tlv_len;
888                     gint check_offset = offset + 1; /* Channel page first */
889                     guint16 masklen;
890 
891                     /* Check consistency of entries */
892                     while (check_len > 0) {
893 
894                         masklen = tvb_get_guint8(tvb, check_offset);
895                         if (masklen == 0) {
896                             break; /* Get out or we might spin forever */
897                         }
898                         masklen += 2; /* Add in page and length */
899                         check_offset += masklen;
900                         check_len -= masklen;
901                         entries++;
902                     }
903 
904                     if (check_len != 0) {
905                         /* Not an integer number of entries */
906                         /* offset += tlv_len; */
907                         return chancount;
908                     } else {
909                         chancount = 0;
910                         for (i = 0; i < entries; i++) {
911                             /* Skip over channel page */
912                             offset++;
913                             masklen = tvb_get_guint8(tvb, offset);
914                             offset++;
915                             /* Count the number of channels in the channel mask */
916                             for (j = 0; j < masklen; j++) {
917                                 chancount += count_bits_in_byte(tvb_get_guint8(tvb, offset));
918                                 offset++;
919                             }
920                         }
921                     }
922                 }
923                 break;
924 
925             default:
926                 /* Skip over any other TLVs */
927                 offset += tlv_len;
928         }
929     }
930     return chancount;
931 }
932 
933 static int
dissect_thread_address(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)934 dissect_thread_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
935 {
936     proto_item  *proto_root;
937     proto_tree  *thread_address_tree;
938     proto_tree  *tlv_tree;
939     tvbuff_t    *sub_tvb;
940     guint       offset = 0;
941     proto_item  *ti;
942     guint8      tlv_type, tlv_len;
943 
944     /* Create the protocol tree. */
945     proto_root = proto_tree_add_item(tree, proto_thread_address, tvb, 0, tvb_reported_length(tvb), ENC_NA);
946     thread_address_tree = proto_item_add_subtree(proto_root, ett_thread_address);
947 
948     /* Thread Network Data TLVs */
949     while (tvb_offset_exists(tvb, offset)) {
950 
951         /* Get the length ahead of time to pass to next function so we can highlight
952            proper amount of bytes */
953         tlv_len = tvb_get_guint8(tvb, offset + 1);
954 
955         ti = proto_tree_add_item(thread_address_tree, hf_thread_address_tlv, tvb, offset, tlv_len+2, ENC_NA);
956         tlv_tree = proto_item_add_subtree(ti, ett_thread_address_tlv);
957 
958         /* Type */
959         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
960         tlv_type = tvb_get_guint8(tvb, offset);
961         offset++;
962 
963         /* Add value name to value root label */
964         proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_address_tlv_vals, "Unknown (%d)"));
965 
966         /* Length */
967         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
968         offset++;
969 
970         switch(tlv_type) {
971             case THREAD_ADDRESS_TLV_TARGET_EID:
972                 {
973                     /* Check length is consistent */
974                     if (tlv_len != 16) {
975                         expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
976                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
977                     } else {
978                         /* Target EID */
979                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_target_eid, tvb, offset, tlv_len, ENC_NA);
980                     }
981                     offset += tlv_len;
982                 }
983                 break;
984 
985             case THREAD_ADDRESS_TLV_EXT_MAC_ADDR:
986                 {
987                     /* Check length is consistent */
988                     if (tlv_len != 8) {
989                         expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
990                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
991                     } else {
992                         /* Extended MAC address */
993                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_ext_mac_addr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
994                     }
995                     offset += tlv_len;
996                 }
997                 break;
998 
999             case THREAD_ADDRESS_TLV_RLOC16:
1000                 {
1001                     /* Check length is consistent */
1002                     if (tlv_len != 2) {
1003                         expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1004                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1005                     } else {
1006                         /* Mesh Locator */
1007                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_rloc16, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1008                     }
1009                     offset += tlv_len;
1010                 }
1011                 break;
1012 
1013             case THREAD_ADDRESS_TLV_ML_EID:
1014                 {
1015                     /* Check length is consistent */
1016                     if (tlv_len != 8) {
1017                         expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1018                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1019                     } else {
1020                         /* ML IID */
1021                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_ml_eid, tvb, offset, tlv_len, ENC_NA);
1022                     }
1023                     offset += tlv_len;
1024                 }
1025                 break;
1026 
1027             case THREAD_ADDRESS_TLV_STATUS:
1028                 {
1029                     /* Check length is consistent */
1030                     if (tlv_len != 1) {
1031                         expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1032                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1033                     } else {
1034                         /* Status */
1035                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_status, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1036                     }
1037                     offset += tlv_len;
1038                 }
1039                 break;
1040 
1041             case THREAD_ADDRESS_TLV_LAST_TRANSACTION_TIME:
1042                 {
1043                     /* Check length is consistent */
1044                     if (tlv_len != 4) {
1045                         expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1046                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1047                     } else {
1048                         /* Last transaction time */
1049                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_last_transaction_time, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1050                     }
1051                     offset += tlv_len;
1052                 }
1053                 break;
1054 
1055             case THREAD_ADDRESS_TLV_ROUTER_MASK:
1056                 {
1057                     /* Check length is consistent */
1058                     if (tlv_len != 9) {
1059                         expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1060                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1061                         offset += tlv_len;
1062                     } else {
1063                         /* Router Mask */
1064                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_router_mask_id_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
1065                         offset++;
1066 
1067                         /*
1068                          * | | | | | | | | | | |1|1|1|1|1|1|...|6|
1069                          * |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|...|3|
1070                          * ---------------------------------------
1071                          * |1|0|1|1|1|0|0|0|1|1|0|0|0|1|0|1|...
1072                          *
1073                          * is sent as 0xb8, 0xc5
1074                          * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
1075                          */
1076 
1077                         /* Just show the string of octets - best representation for a bit mask */
1078                         proto_tree_add_item(tlv_tree, hf_thread_address_tlv_router_mask_assigned, tvb, offset, 8, ENC_NA);
1079                         offset += 8;
1080                     }
1081                 }
1082                 break;
1083 
1084             case THREAD_ADDRESS_TLV_ND_OPTION:
1085                 /* Just show the data */
1086                 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_nd_option, tvb, offset, tlv_len, ENC_NA);
1087                 offset += tlv_len;
1088                 break;
1089 
1090             case THREAD_ADDRESS_TLV_ND_DATA:
1091                 /* Just show the data. Note there is no icmpv6 options dissector so would have to copy it */
1092                 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_nd_data, tvb, offset, tlv_len, ENC_NA);
1093                 offset += tlv_len;
1094                 break;
1095 
1096             case THREAD_ADDRESS_TLV_THREAD_NETWORK_DATA:
1097                 if (tlv_len > 0) {
1098                     sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
1099                     call_dissector(thread_address_nwd_handle, sub_tvb, pinfo, tlv_tree);
1100                 }
1101                 offset += tlv_len;
1102                 break;
1103 
1104             default:
1105                 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1106                 offset += tlv_len;
1107         }
1108     }
1109     return tvb_captured_length(tvb);
1110 }
1111 
1112 static int
dissect_thread_dg(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)1113 dissect_thread_dg(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
1114 {
1115     proto_item    *proto_root;
1116     proto_tree    *thread_dg_tree;
1117     proto_tree    *tlv_tree;
1118     guint         offset = 0;
1119     proto_item    *ti;
1120     guint8        tlv_type;
1121     guint16       tlv_len;
1122     tlv_len_len_e tlv_len_len;
1123 
1124     /* Create the protocol tree. */
1125     proto_root = proto_tree_add_item(tree, proto_thread_dg, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1126     thread_dg_tree = proto_item_add_subtree(proto_root, ett_thread_dg);
1127 
1128     /* Thread Network Data TLVs */
1129     while (tvb_offset_exists(tvb, offset)) {
1130 
1131         /* Get the type and length ahead of time to pass to next function so we can highlight
1132            proper amount of bytes */
1133         tlv_type = tvb_get_guint8(tvb, offset);
1134         tlv_len = (guint16)tvb_get_guint8(tvb, offset + 1);
1135 
1136         /* TODO: need to make sure this applies to all Diagnostic TLVs */
1137         if (THREAD_TLV_LENGTH_ESC == tlv_len) {
1138             /* 16-bit length field */
1139             tlv_len = tvb_get_ntohs(tvb, offset + 2);
1140             tlv_len_len = TLV_LEN_LEN16;
1141         } else {
1142             tlv_len_len = TLV_LEN_LEN8;
1143         }
1144 
1145         /* Create the tree */
1146         ti = proto_tree_add_item(thread_dg_tree, hf_thread_dg_tlv, tvb, offset, 1 + tlv_len_len + tlv_len, ENC_NA);
1147         tlv_tree = proto_item_add_subtree(ti, ett_thread_dg_tlv);
1148 
1149         /* Type */
1150         proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1151         offset++;
1152 
1153         /* Add value name to value root label */
1154         proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_dg_tlv_vals, "Unknown (%d)"));
1155 
1156         /* Length */
1157         switch (tlv_len_len) {
1158             case TLV_LEN_LEN8:
1159                 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_length8, tvb, offset, 1, ENC_BIG_ENDIAN);
1160                 break;
1161             case TLV_LEN_LEN16:
1162                 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_length16, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
1163                 break;
1164             default:
1165                 break;
1166         }
1167         offset += tlv_len_len;
1168 
1169         switch(tlv_type) {
1170             case THREAD_DG_TLV_TYPE_LIST:
1171                 {
1172                     int i;
1173 
1174                     for (i = 0; i < tlv_len; i++) {
1175                         proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1176                         offset++;
1177                     }
1178                 }
1179                 break;
1180 
1181             case THREAD_DG_TLV_EXT_MAC_ADDR:
1182             case THREAD_DG_TLV_ADDRESS16:
1183             case THREAD_DG_TLV_MODE:
1184             case THREAD_DG_TLV_TIMEOUT:
1185             case THREAD_DG_TLV_CONNECTIVITY:
1186             case THREAD_DG_TLV_ROUTE64:
1187             case THREAD_DG_TLV_LEADER_DATA:
1188             case THREAD_DG_TLV_NETWORK_DATA:
1189             case THREAD_DG_TLV_IPV6_ADDR_LIST:
1190             /* Counters */
1191             case THREAD_DG_TLV_MAC_COUNTERS:
1192             case THREAD_DG_TLV_BATTERY_LEVEL:
1193             case THREAD_DG_TLV_VOLTAGE:
1194             case THREAD_DG_TLV_CHILD_TABLE:
1195             case THREAD_DG_TLV_CHANNEL_PAGES:
1196                 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_general, tvb, offset, tlv_len, ENC_NA);
1197                 offset += tlv_len;
1198                 break;
1199 
1200             default:
1201                 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1202                 offset += tlv_len;
1203         }
1204     }
1205     return tvb_captured_length(tvb);
1206 }
1207 
1208 static int
dissect_thread_mc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1209 dissect_thread_mc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1210 {
1211     proto_item    *proto_root;
1212     proto_tree    *thread_mc_tree;
1213     proto_tree    *tlv_tree;
1214     guint         offset = 0;
1215     proto_item    *ti;
1216     proto_item    *pi;
1217     guint8        tlv_type;
1218     guint16       tlv_len;
1219     tlv_len_len_e tlv_len_len;
1220     guint         chancount;
1221 
1222 
1223     /* Create the protocol tree. */
1224     proto_root = proto_tree_add_item(tree, proto_thread_mc, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1225     thread_mc_tree = proto_item_add_subtree(proto_root, ett_thread_mc);
1226 
1227     /* Get channel count a priori so we can process energy list better */
1228     chancount = get_chancount(tvb);
1229 
1230     /* Thread Network Data TLVs */
1231     while (tvb_offset_exists(tvb, offset)) {
1232 
1233         /* Get the type and length ahead of time to pass to next function so we can highlight
1234            proper amount of bytes */
1235         tlv_type = tvb_get_guint8(tvb, offset);
1236         tlv_len = (guint16)tvb_get_guint8(tvb, offset + 1);
1237 
1238         /* TODO: need to make sure this applies to all MeshCoP TLVs */
1239         if (THREAD_TLV_LENGTH_ESC == tlv_len) {
1240             /* 16-bit length field */
1241             tlv_len = tvb_get_ntohs(tvb, offset + 2);
1242             tlv_len_len = TLV_LEN_LEN16;
1243         } else {
1244             tlv_len_len = TLV_LEN_LEN8;
1245         }
1246 
1247         /* Create the tree */
1248         ti = proto_tree_add_item(thread_mc_tree, hf_thread_mc_tlv, tvb, offset, 1 + tlv_len_len + tlv_len, ENC_NA);
1249         tlv_tree = proto_item_add_subtree(ti, ett_thread_mc_tlv);
1250 
1251         /* Type */
1252         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1253         offset++;
1254 
1255         /* Add value name to value root label */
1256         proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_mc_tlv_vals, "Unknown (%d)"));
1257 
1258         /* Length */
1259         switch (tlv_len_len) {
1260             case TLV_LEN_LEN8:
1261                 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_length8, tvb, offset, 1, ENC_BIG_ENDIAN);
1262                 break;
1263             case TLV_LEN_LEN16:
1264                 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_length16, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
1265                 break;
1266             default:
1267                 break;
1268         }
1269         offset += tlv_len_len;
1270 
1271         switch(tlv_type) {
1272             case THREAD_MC_TLV_CHANNEL:
1273                 {
1274                     /* Check length is consistent */
1275                     if (tlv_len != 3) {
1276                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1277                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1278                     } else {
1279                         /* Channel page */
1280                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_channel_page, tvb, offset, 1, ENC_BIG_ENDIAN);
1281                         /* Channel */
1282                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_channel, tvb, offset+1, 2, ENC_BIG_ENDIAN);
1283                     }
1284                     offset += tlv_len;
1285                 }
1286                 break;
1287 
1288             case THREAD_MC_TLV_PANID:
1289                 {
1290                     /* Check length is consistent */
1291                     if (tlv_len != 2) {
1292                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1293                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1294                     } else {
1295                         /* PAN ID */
1296                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_pan_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1297                     }
1298                     offset += tlv_len;
1299                 }
1300                 break;
1301 
1302             case THREAD_MC_TLV_XPANID:
1303                 {
1304                     /* Check length is consistent */
1305                     if (tlv_len != 8) {
1306                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1307                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1308                     } else {
1309                         /* PAN ID */
1310                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_xpan_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1311                     }
1312                     offset += tlv_len;
1313                 }
1314                 break;
1315 
1316             case THREAD_MC_TLV_NETWORK_NAME:
1317                 {
1318                     /* Check length is consistent */
1319                     if (tlv_len > 16) {
1320                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
1321                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1322                     } else {
1323                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
1324                     }
1325                     offset += tlv_len;
1326                 }
1327                 break;
1328 
1329             case THREAD_MC_TLV_PSKC:
1330                 {
1331                     /* Check length is consistent */
1332                     if (tlv_len != 16) {
1333                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1334                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1335                     } else {
1336                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_pskc, tvb, offset, tlv_len, ENC_NA);
1337                     }
1338                     offset += tlv_len;
1339                 }
1340                 break;
1341 
1342             case THREAD_MC_TLV_NETWORK_MASTER_KEY:
1343                 {
1344                     /* Check length is consistent */
1345                     if (tlv_len != 16) {
1346                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1347                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1348                     } else {
1349                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_master_key, tvb, offset, tlv_len, ENC_NA);
1350                     }
1351                     offset += tlv_len;
1352                 }
1353                 break;
1354 
1355             case THREAD_MC_TLV_NETWORK_KEY_SEQ_CTR:
1356                 {
1357                     /* Check length is consistent */
1358                     if (tlv_len != 4) {
1359                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1360                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1361                     } else {
1362                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_key_seq_ctr, tvb, offset, tlv_len, ENC_NA);
1363                     }
1364                     offset += tlv_len;
1365                 }
1366                 break;
1367 
1368             case THREAD_MC_TLV_NETWORK_ML_PREFIX:
1369                 {
1370                     /* Check length is consistent */
1371                     if (tlv_len != 8) {
1372                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1373                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1374                     } else {
1375                         ws_in6_addr prefix;
1376 
1377                         memset(&prefix, 0, sizeof(prefix));
1378                         tvb_memcpy(tvb, (guint8 *)&prefix.bytes, offset, tlv_len);
1379                         pi = proto_tree_add_ipv6(tlv_tree, hf_thread_mc_tlv_ml_prefix, tvb, offset, tlv_len, &prefix);
1380                         proto_item_append_text(pi, "/%d", tlv_len * 8);
1381                     }
1382                     offset += tlv_len;
1383                 }
1384                 break;
1385 
1386             case THREAD_MC_TLV_STEERING_DATA:
1387                 {
1388                     /* Check length is consistent */
1389                     if (tlv_len > 16) {
1390                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
1391                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1392                     } else {
1393                         /* Display it simply */
1394                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_steering_data, tvb, offset, tlv_len, ENC_NA);
1395                     }
1396                     offset += tlv_len;
1397                 }
1398                 break;
1399 
1400             case THREAD_MC_TLV_BORDER_AGENT_LOCATOR:
1401                 {
1402                     /* Check length is consistent */
1403                     if (tlv_len != 2) {
1404                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1405                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1406                     } else {
1407                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ba_locator, tvb, offset, tlv_len, ENC_NA);
1408                     }
1409                     offset += tlv_len;
1410                 }
1411                 break;
1412 
1413             case THREAD_MC_TLV_COMMISSIONER_ID:
1414                 {
1415                     /* Check length is consistent */
1416                     if (tlv_len > 64) {
1417                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
1418                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1419                     } else {
1420                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_id, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
1421                     }
1422                     offset += tlv_len;
1423                 }
1424                 break;
1425 
1426             case THREAD_MC_TLV_COMMISSIONER_SESSION_ID:
1427                 {
1428                     /* Check length is consistent */
1429                     if (tlv_len != 2) {
1430                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1431                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1432                     } else {
1433                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_sess_id, tvb, offset, tlv_len, ENC_NA);
1434                     }
1435                     offset += tlv_len;
1436                 }
1437                 break;
1438 
1439             case THREAD_MC_TLV_SECURITY_POLICY:
1440                 {
1441                     /* Check length is consistent */
1442                     if (tlv_len != 3) {
1443                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1444                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1445                         offset += tlv_len;
1446                     } else {
1447                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rot, tvb, offset, 2, ENC_BIG_ENDIAN);
1448                         offset += 2;
1449                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_o, tvb, offset, 1, ENC_BIG_ENDIAN);
1450                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_n, tvb, offset, 1, ENC_BIG_ENDIAN);
1451                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_r, tvb, offset, 1, ENC_BIG_ENDIAN);
1452                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_c, tvb, offset, 1, ENC_BIG_ENDIAN);
1453                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_b, tvb, offset, 1, ENC_BIG_ENDIAN);
1454                         offset++;
1455                     }
1456                 }
1457                 break;
1458 
1459             case THREAD_MC_TLV_GET:
1460                 {
1461                     int i;
1462 
1463                     for (i = 0; i < tlv_len; i++) {
1464                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1465                         offset++;
1466                     }
1467                 }
1468                 break;
1469 
1470             case THREAD_MC_TLV_ACTIVE_TSTAMP:
1471             case THREAD_MC_TLV_PENDING_TSTAMP:
1472                 {
1473                     nstime_t timestamp;
1474 
1475                     if (tlv_len != 8) {
1476                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1477                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1478                     } else {
1479                         /* Fill in the nstime_t structure */
1480                         timestamp.secs = (time_t)tvb_get_ntoh48(tvb, offset);
1481                         timestamp.nsecs = (int)lround((double)(tvb_get_ntohs(tvb, offset + 6) >> 1) * THREAD_MC_32768_TO_NSEC_FACTOR);
1482                         if (tlv_type == THREAD_MC_TLV_ACTIVE_TSTAMP) {
1483                             proto_tree_add_time(tlv_tree, hf_thread_mc_tlv_active_tstamp, tvb, offset, 8, &timestamp);
1484                         } else {
1485                             proto_tree_add_time(tlv_tree, hf_thread_mc_tlv_pending_tstamp, tvb, offset, 8, &timestamp);
1486                         }
1487                     }
1488                     offset += tlv_len;
1489                 }
1490                 break;
1491 
1492             case THREAD_MC_TLV_STATE:
1493                 {
1494                     /* Check length is consistent */
1495                     if (tlv_len != 1) {
1496                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1497                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1498                     } else {
1499                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_state, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1500                     }
1501                     offset += tlv_len;
1502                 }
1503                 break;
1504 
1505             case THREAD_MC_TLV_JOINER_DTLS_ENCAP:
1506                 {
1507                     tvbuff_t *sub_tvb;
1508 
1509                     if (tlv_len > 0) {
1510                         sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
1511                         call_dissector(thread_dtls_handle, sub_tvb, pinfo, tree);
1512                     }
1513                     offset += tlv_len;
1514                 }
1515                 break;
1516 
1517             case THREAD_MC_TLV_COMMISSIONER_UDP_PORT:
1518             case THREAD_MC_TLV_JOINER_UDP_PORT:
1519                 {
1520                     if (tlv_len != 2) {
1521                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1522                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1523                     } else {
1524                         /* UDP Port */
1525                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_port, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1526                     }
1527                     offset += tlv_len;
1528                 }
1529                 break;
1530 
1531             case THREAD_MC_TLV_JOINER_IID:
1532                 {
1533                     if (tlv_len != 8) {
1534                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1535                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1536                     } else {
1537                         /* IID */
1538                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_iid, tvb, offset, tlv_len, ENC_NA);
1539                     }
1540                     offset += tlv_len;
1541                 }
1542                 break;
1543 
1544             case THREAD_MC_TLV_JOINER_ROUTER_LOCATOR:
1545                 {
1546                     if (tlv_len != 2) {
1547                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1548                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1549                     } else {
1550                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_jr_locator, tvb, offset, tlv_len, ENC_NA);
1551                     }
1552                     offset += tlv_len;
1553                 }
1554                 break;
1555 
1556             case THREAD_MC_TLV_JOINER_KEK:
1557                 {
1558                     if (tlv_len != 16) {
1559                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1560                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1561                     } else {
1562                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_kek, tvb, offset, tlv_len, ENC_NA);
1563                     }
1564                     offset += tlv_len;
1565                 }
1566                 break;
1567 
1568             case THREAD_MC_TLV_PROVISIONING_URL:
1569                 {
1570                     /* Check length is consistent */
1571                     if (tlv_len > 64) {
1572                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
1573                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1574                     } else {
1575                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_provisioning_url, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
1576                     }
1577                     offset += tlv_len;
1578                 }
1579                 break;
1580 
1581             case THREAD_MC_TLV_VENDOR_NAME:
1582                 {
1583                     /* Check length is consistent */
1584                     if (tlv_len > 32) {
1585                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
1586                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1587                     } else {
1588                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_name, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
1589                     }
1590                     offset += tlv_len;
1591                 }
1592                 break;
1593 
1594             case THREAD_MC_TLV_VENDOR_MODEL:
1595                 {
1596                     /* Check length is consistent: TODO not specified in spec. */
1597                     if (tlv_len > 32) {
1598                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
1599                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1600                     } else {
1601                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_model, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
1602                     }
1603                     offset += tlv_len;
1604                 }
1605                 break;
1606 
1607             case THREAD_MC_TLV_VENDOR_SW_VERSION:
1608                 {
1609                     /* Check length is consistent */
1610                     if (tlv_len > 16) {
1611                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
1612                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1613                     } else {
1614                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_sw_ver, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
1615                     }
1616                     offset += tlv_len;
1617                 }
1618                 break;
1619 
1620             case THREAD_MC_TLV_VENDOR_DATA:
1621                 {
1622                     /* Check length is consistent */
1623                     if (tlv_len > 64) {
1624                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
1625                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1626                     } else {
1627                         /* Display it simply */
1628                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_data, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);
1629                     }
1630                     offset += tlv_len;
1631                 }
1632                 break;
1633 
1634             case THREAD_MC_TLV_VENDOR_STACK_VERSION:
1635                 {
1636                     /* Check length is consistent */
1637                     if (tlv_len != 6) {
1638                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1639                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1640                         offset += tlv_len;
1641                     } else {
1642                         guint8 build_u8;
1643                         guint16 build;
1644 
1645                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
1646                         offset += 3;
1647                         build_u8 = tvb_get_guint8(tvb, offset);
1648                         offset++;
1649                         build = (guint16)build_u8 << 4;
1650                         build_u8 = tvb_get_guint8(tvb, offset);
1651                         build |= (guint16)build_u8 >> 4;
1652                         pi = proto_tree_add_uint(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_build, tvb, 0, 0, build);
1653                         proto_item_set_generated(pi);
1654                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_rev, tvb, offset, 1, ENC_BIG_ENDIAN);
1655                         offset++;
1656                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_min, tvb, offset, 1, ENC_BIG_ENDIAN);
1657                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_maj, tvb, offset, 1, ENC_BIG_ENDIAN);
1658                         offset++;
1659                     }
1660                 }
1661                 break;
1662 
1663             case THREAD_MC_TLV_UDP_ENCAPSULATION:
1664                 {
1665                     tvbuff_t *sub_tvb;
1666                     guint16 src_port;
1667                     guint16 dst_port;
1668 
1669                     src_port = tvb_get_ntohs(tvb, offset);
1670                     proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_encap_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1671                     offset += 2;
1672                     dst_port = tvb_get_ntohs(tvb, offset);
1673                     proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_encap_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1674                     offset += 2;
1675 
1676                     if (tlv_len >= 4)
1677                     {
1678                         /* Allocate a buffer for the fake UDP datagram and create the fake header. */
1679                         udp_hdr_t* udp_hdr = (udp_hdr_t *)wmem_alloc(pinfo->pool, sizeof(udp_hdr_t) + (tlv_len - 4));
1680 
1681                         /* Create pseudo UDP header */
1682                         udp_hdr->src_port = g_htons(src_port);
1683                         udp_hdr->dst_port = g_htons(dst_port);
1684                         udp_hdr->length = g_htons(tlv_len + 4); /* Includes UDP header length */
1685                         udp_hdr->checksum = 0;
1686                         /* Copy UDP payload in */
1687                         tvb_memcpy(tvb, udp_hdr + 1, offset, tlv_len - 4);
1688                         /* Create child tvb */
1689                         sub_tvb = tvb_new_child_real_data(tvb, (guint8 *)udp_hdr, tlv_len + 4, tvb_reported_length(tvb) + 4);
1690                         call_dissector(thread_udp_handle, sub_tvb, pinfo, tree);
1691                     }
1692                     offset += (tlv_len-4);
1693                 }
1694                 break;
1695 
1696             case THREAD_MC_TLV_IPV6_ADDRESS:
1697                 {
1698                     /* Check length is consistent */
1699                     if (tlv_len != 16) {
1700                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1701                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1702                     } else {
1703                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, tlv_len, ENC_NA);
1704                     }
1705                     offset += tlv_len;
1706                 }
1707                 break;
1708 
1709             /* case THREAD_MC_TLV_PENDING_TSTAMP: Handled in THREAD_MC_TLV_ACTIVE_TSTAMP case */
1710 
1711             case THREAD_MC_TLV_DELAY_TIMER:
1712                 {
1713                     if (tlv_len != 4) {
1714                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1715                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1716                     } else {
1717                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_delay_timer, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1718                     }
1719                     offset += tlv_len;
1720                 }
1721                 break;
1722 
1723             case THREAD_MC_TLV_CHANNEL_MASK:
1724                 {
1725                     proto_tree *cm_tree;
1726                     int i;
1727                     guint8 entries = 0;
1728                     gint32 check_len = tlv_len;
1729                     gint check_offset = offset + 1; /* Channel page first */
1730                     guint16 masklen;
1731 
1732                     /* Check consistency of entries */
1733                     while (check_len > 0) {
1734 
1735                         masklen = tvb_get_guint8(tvb, check_offset);
1736                         if (masklen == 0) {
1737                             break; /* Get out or we might spin forever */
1738                         }
1739                         masklen += 2; /* Add in page and length */
1740                         check_offset += masklen;
1741                         check_len -= masklen;
1742                         entries++;
1743                     }
1744 
1745                     if (check_len != 0) {
1746                         /* Not an integer number of entries */
1747                         expert_add_info(pinfo, proto_root, &ei_thread_mc_tlv_length_failed);
1748                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1749                         offset += tlv_len;
1750                     } else {
1751                         for (i = 0; i < entries; i++) {
1752                             pi = proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_chan_mask, tvb, offset, 1, ENC_NA);
1753                             cm_tree = proto_item_add_subtree(pi, ett_thread_mc_chan_mask);
1754                             proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_page, tvb, offset, 1, ENC_BIG_ENDIAN);
1755                             offset++;
1756                             masklen = tvb_get_guint8(tvb, offset);
1757                             proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_len, tvb, offset, 1, ENC_BIG_ENDIAN);
1758                             offset++;
1759                             proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_mask, tvb, offset, masklen, ENC_NA);
1760                             offset += masklen;
1761                         }
1762                     }
1763                 }
1764                 break;
1765 
1766             case THREAD_MC_TLV_COUNT:
1767                 {
1768                     if (tlv_len != 1) {
1769                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1770                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1771                     } else {
1772                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_count, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1773                     }
1774                     offset += tlv_len;
1775                 }
1776                 break;
1777 
1778             case THREAD_MC_TLV_PERIOD:
1779                 {
1780                     if (tlv_len != 2) {
1781                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1782                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1783                     } else {
1784                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_period, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1785                     }
1786                     offset += tlv_len;
1787                 }
1788                 break;
1789 
1790             case THREAD_MC_TLV_SCAN_DURATION:
1791                 {
1792                     if (tlv_len != 2) {
1793                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1794                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1795                     } else {
1796                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_scan_duration, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1797                     }
1798                     offset += tlv_len;
1799                 }
1800                 break;
1801 
1802             case THREAD_MC_TLV_ENERGY_LIST:
1803                 {
1804                     proto_tree *it_tree;
1805                     int i;
1806 
1807                     if ((chancount != THREAD_MC_INVALID_CHAN_COUNT) && (chancount != 0) && ((tlv_len % chancount) == 0)) {
1808                         /* Go through the number of el_counts of scan */
1809                         for (i = 0; i < (int)(tlv_len / (guint16)chancount); i++) {
1810                             pi = proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_el_count, tvb, offset, 1, ENC_NA);
1811                             proto_item_append_text(pi, " %d", i + 1);
1812                             it_tree = proto_item_add_subtree(pi, ett_thread_mc_el_count);
1813                             proto_tree_add_item(it_tree, hf_thread_mc_tlv_energy_list, tvb, offset, chancount, ENC_NA);
1814                             offset += chancount;
1815                         }
1816                     } else {
1817                         /* This might not work but try and display as string */
1818                         /* Something wrong with channel count so just show it as a simple string */
1819                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_energy_list, tvb, offset, tlv_len, ENC_NA);
1820                     }
1821                     offset += tlv_len;
1822                 }
1823                 break;
1824 
1825             case THREAD_MC_TLV_DISCOVERY_REQUEST:
1826                 {
1827                     /* Check length is consistent */
1828                     if (tlv_len != 2) {
1829                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1830                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1831                     } else {
1832                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_req_ver, tvb, offset, 1, ENC_BIG_ENDIAN);
1833                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_req_j, tvb, offset, 1, ENC_BIG_ENDIAN);
1834                     }
1835                     offset += tlv_len;
1836                 }
1837                 break;
1838 
1839             case THREAD_MC_TLV_DISCOVERY_RESPONSE:
1840                 {
1841                     /* Check length is consistent */
1842                     if (tlv_len != 2) {
1843                         expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1844                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1845                     } else {
1846                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_rsp_ver, tvb, offset, 1, ENC_BIG_ENDIAN);
1847                         proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_rsp_n, tvb, offset, 1, ENC_BIG_ENDIAN);
1848                     }
1849                     offset += tlv_len;
1850                 }
1851                 break;
1852 
1853             default:
1854                 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1855                 offset += tlv_len;
1856         }
1857     }
1858     return tvb_captured_length(tvb);
1859 }
1860 
1861 static int
dissect_thread_nwd(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1862 dissect_thread_nwd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1863 {
1864     proto_item  *proto_root;
1865     proto_tree  *thread_nwd_tree;
1866     proto_tree  *tlv_tree;
1867     tvbuff_t    *sub_tvb;
1868     guint       offset = 0, tlv_offset;
1869     proto_item  *ti;
1870     guint8      tlv_type, tlv_len;
1871 
1872     /* Create the protocol tree. */
1873     proto_root = proto_tree_add_item(tree, proto_thread_nwd, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1874     thread_nwd_tree = proto_item_add_subtree(proto_root, ett_thread_nwd);
1875 
1876     /* Thread Network Data TLVs */
1877     while (tvb_offset_exists(tvb, offset)) {
1878 
1879         /* Get the length ahead of time to pass to next function so we can highlight
1880            proper amount of bytes */
1881         tlv_len = tvb_get_guint8(tvb, offset + 1);
1882 
1883         ti = proto_tree_add_item(thread_nwd_tree, hf_thread_nwd_tlv, tvb, offset, tlv_len+2, ENC_NA);
1884         tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_tlv);
1885 
1886         /* Type */
1887         proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1888         tlv_type = tvb_get_guint8(tvb, offset) >> 1;
1889 
1890         /* Stable */
1891         proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_stable, tvb, offset, 1, ENC_BIG_ENDIAN);
1892         offset++;
1893 
1894         /* Add value name to value root label */
1895         proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_nwd_tlv_vals, "Unknown (%d)"));
1896 
1897         /* Length */
1898         proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1899         offset++;
1900 
1901         switch(tlv_type) {
1902             case THREAD_NWD_TLV_HAS_ROUTE:
1903                 {
1904                     /* Has Route TLV can be top level TLV or sub-TLV */
1905 
1906                     /* Check length is consistent */
1907                     if ((tlv_len % THREAD_NWD_TLV_HAS_ROUTE_SIZE) != 0)
1908                     {
1909                         expert_add_info(pinfo, proto_root, &ei_thread_nwd_len_size_mismatch);
1910                         proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1911                         offset += tlv_len;
1912                     } else {
1913                         proto_tree *has_route_tree;
1914                         guint i;
1915                         guint count = tlv_len / THREAD_NWD_TLV_HAS_ROUTE_SIZE;
1916 
1917                         /* Add subtrees */
1918                         for (i = 0; i < count; i++) {
1919                             ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_has_route, tvb, offset, 1, ENC_NA);
1920                             has_route_tree = proto_item_add_subtree(ti, ett_thread_nwd_has_route);
1921                             proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_br_16, tvb, offset, 2, ENC_BIG_ENDIAN);
1922                             offset += 2;
1923                             proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_pref, tvb, offset, 1, ENC_BIG_ENDIAN);
1924                             offset += 1;
1925                         }
1926                     }
1927                 }
1928                 break;
1929 
1930             case THREAD_NWD_TLV_PREFIX:
1931                 {
1932                     guint8 prefix_len;
1933                     guint8 prefix_byte_len;
1934                     ws_in6_addr prefix;
1935                     address prefix_addr;
1936 
1937                     /* Domain ID */
1938                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_prefix_domain_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1939                     offset++;
1940                     tlv_offset = 1;
1941 
1942                     /* Prefix Length */
1943                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_prefix_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1944                     prefix_len = tvb_get_guint8(tvb, offset);
1945                     prefix_byte_len = (prefix_len + 7) / 8;
1946                     offset++;
1947                     tlv_offset++;
1948 
1949                     /* Prefix */
1950                     memset(&prefix.bytes, 0, sizeof(prefix));
1951                     if (prefix_byte_len <= sizeof(prefix))
1952                         tvb_memcpy(tvb, (guint8 *)&prefix.bytes, offset, prefix_byte_len);
1953                     proto_tree_add_ipv6(tlv_tree, hf_thread_nwd_tlv_prefix, tvb, offset, prefix_byte_len, &prefix);
1954                     set_address(&prefix_addr, AT_IPv6, 16, prefix.bytes);
1955                     proto_item_append_text(ti, " = %s/%d", address_to_str(pinfo->pool, &prefix_addr), prefix_len);
1956                     offset += prefix_byte_len;
1957                     tlv_offset += prefix_byte_len;
1958 
1959                     if (tlv_offset < tlv_len) {
1960                         proto_tree *sub_tlv_tree;
1961                         guint remaining = tlv_len - tlv_offset;
1962 
1963                         ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_sub_tlvs, tvb, offset, 1, ENC_NA);
1964                         sub_tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_prefix_sub_tlvs);
1965                         /* Call this dissector for sub-TLVs */
1966                         sub_tvb = tvb_new_subset_length(tvb, offset, remaining); /* remove prefix length (1) and prefix (prefix_byte_len) */
1967                         dissect_thread_nwd(sub_tvb, pinfo, sub_tlv_tree, data);
1968                         offset += remaining;
1969                     }
1970                 }
1971                 break;
1972 
1973             case THREAD_NWD_TLV_BORDER_ROUTER:
1974                 {
1975                     /* Border Router TLV can only be sub-TLV */
1976 
1977                     /* Check length is consistent */
1978                     if ((tlv_len % 4) != 0)
1979                     {
1980                         expert_add_info(pinfo, proto_root, &ei_thread_nwd_len_size_mismatch);
1981                         proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1982                         offset += tlv_len;
1983                     } else {
1984                         proto_tree *border_router_tree;
1985                         guint i;
1986                         guint count = tlv_len / 4;
1987 
1988                         /* Add subtrees */
1989                         for (i = 0; i < count; i++) {
1990                             ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_border_router, tvb, offset, 1, ENC_NA);
1991                             border_router_tree = proto_item_add_subtree(ti, ett_thread_nwd_border_router);
1992 
1993                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_16, tvb, offset, 2, ENC_BIG_ENDIAN);
1994                             offset += 2;
1995                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_pref, tvb, offset, 1, ENC_BIG_ENDIAN);
1996                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_p, tvb, offset, 1, ENC_BIG_ENDIAN);
1997                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_s, tvb, offset, 1, ENC_BIG_ENDIAN);
1998                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_d, tvb, offset, 1, ENC_BIG_ENDIAN);
1999                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2000                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_r, tvb, offset, 1, ENC_BIG_ENDIAN);
2001                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_o, tvb, offset, 1, ENC_BIG_ENDIAN);
2002                             offset++;
2003                             proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2004                             offset++;
2005                         }
2006                     }
2007                 }
2008                 break;
2009 
2010             case THREAD_NWD_TLV_6LOWPAN_ID:
2011                 {
2012                     static int * const nwd_6lowpan_flags[] = {
2013                         &hf_thread_nwd_tlv_6lowpan_id_6co_flag_reserved,
2014                         &hf_thread_nwd_tlv_6lowpan_id_6co_flag_c,
2015                         &hf_thread_nwd_tlv_6lowpan_id_6co_flag_cid,
2016                         NULL
2017                     };
2018 
2019                     /* 6lowpan-ND */
2020                     proto_tree_add_bitmask(tlv_tree, tvb, offset, hf_thread_nwd_tlv_6lowpan_id_6co_flag, ett_thread_nwd_6co_flag, nwd_6lowpan_flags, ENC_BIG_ENDIAN);
2021                     offset++;
2022 
2023                     /* Context Length */
2024                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_6lowpan_id_6co_context_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2025                     offset++;
2026                 }
2027                 break;
2028 
2029             case THREAD_NWD_TLV_COMMISSIONING_DATA:
2030                 {
2031                     if (tlv_len > 0) {
2032                         sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
2033                         call_dissector(thread_mc_handle, sub_tvb, pinfo, tlv_tree);
2034                     }
2035                     offset += tlv_len;
2036                 }
2037                 break;
2038 
2039             case THREAD_NWD_TLV_SERVICE:
2040                 {
2041                     guint8 flags;
2042                     guint8 s_data_len;
2043 
2044                     /* Flags and S_id */
2045                     flags = tvb_get_guint8(tvb, offset);
2046                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_t, tvb, offset, 1, ENC_BIG_ENDIAN);
2047                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2048                     offset++;
2049                     tlv_offset = 1;
2050 
2051                     /* Enterprise number */
2052                     if ((flags & THREAD_NWD_TLV_SERVICE_T) == 0) {
2053                         proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_ent_num, tvb, offset, 4, ENC_BIG_ENDIAN);
2054                         offset += 4;
2055                         tlv_offset += 4;
2056                     }
2057 
2058                     /* S_data */
2059                     s_data_len = tvb_get_guint8(tvb, offset);
2060                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_len, tvb, offset, 1, ENC_BIG_ENDIAN);
2061                     offset++;
2062                     tlv_offset++;
2063                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
2064                     offset += s_data_len;
2065                     tlv_offset += s_data_len;
2066 
2067                     /* Server sub-TLVs */
2068                     if (tlv_offset < tlv_len) {
2069                         proto_tree *sub_tlv_tree;
2070                         guint remaining = tlv_len - tlv_offset;
2071 
2072                         ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_sub_tlvs, tvb, offset, 1, ENC_NA);
2073                         sub_tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_prefix_sub_tlvs);
2074                         /* Call this dissector for sub-TLVs. Should only be server TLVs */
2075                         sub_tvb = tvb_new_subset_length(tvb, offset, remaining); /* remove prefix length (1) and prefix (prefix_byte_len) */
2076                         dissect_thread_nwd(sub_tvb, pinfo, sub_tlv_tree, data);
2077                         offset += remaining;
2078                     }
2079                 }
2080                 break;
2081 
2082             case THREAD_NWD_TLV_SERVER:
2083                 {
2084                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
2085                     offset += 2;
2086                     proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_data, tvb, offset, tlv_len - 2, ENC_NA);
2087                     offset += tlv_len - 2;
2088                 }
2089                 break;
2090 
2091             default:
2092                 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2093                 offset += tlv_len;
2094         }
2095     }
2096     return tvb_captured_length(tvb);
2097 }
2098 
2099 static int
dissect_thread_coap(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2100 dissect_thread_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2101 {
2102     coap_info           *coinfo;
2103     const gchar         *uri;
2104     gchar               **tokens;
2105 
2106     /* Obtain the CoAP info */
2107     coinfo = (coap_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_coap, 0);
2108 
2109     /* Reject the packet if not CoAP */
2110     if (!coinfo) return 0;
2111 
2112     uri = wmem_strbuf_get_str(coinfo->uri_str_strbuf);
2113 
2114     tokens = wmem_strsplit(pinfo->pool, uri, "/", 3);
2115     if (g_strv_length(tokens) == 3) {
2116         /* No need to create a subset as we are dissecting the tvb as it is. */
2117         dissector_try_string(thread_coap_namespace, tokens[THREAD_URI_NAMESPACE_IDX], tvb, pinfo, tree, NULL);
2118     }
2119 
2120     return tvb_captured_length(tvb);
2121 }
2122 
dissect_thread_bcn(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)2123 static int dissect_thread_bcn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2124 {
2125     ieee802154_packet   *packet = (ieee802154_packet *)data;
2126 
2127     proto_item  *ti, *beacon_root;
2128     proto_tree  *beacon_tree;
2129     guint       offset = 0;
2130     const guint8  *ssid;
2131     guint8      tlv_type, tlv_len;
2132     proto_tree  *tlv_tree = NULL;
2133 
2134     /* Reject the packet if data is NULL */
2135     if (!packet) return 0;
2136 
2137     /* Add ourself to the protocol column. */
2138     col_set_str(pinfo->cinfo, COL_PROTOCOL, "Thread");
2139     /* Create the tree for this beacon. */
2140     beacon_root = proto_tree_add_item(tree, proto_thread_bcn, tvb, 0, -1, ENC_NA);
2141     beacon_tree = proto_item_add_subtree(beacon_root, ett_thread_bcn);
2142 
2143     /* Update the info column. */
2144     col_clear(pinfo->cinfo, COL_INFO);
2145     col_append_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src16);
2146 
2147     /* Get and display the protocol id, must be 0x03 on all Thread beacons. */
2148     proto_tree_add_item(beacon_tree, hf_thread_bcn_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
2149     offset += 1;
2150 
2151     /* Get and display the beacon flags */
2152     proto_tree_add_item(beacon_tree, hf_thread_bcn_joining, tvb, offset, 1, ENC_BIG_ENDIAN);
2153     proto_tree_add_item(beacon_tree, hf_thread_bcn_native, tvb, offset, 1, ENC_BIG_ENDIAN);
2154     proto_tree_add_item(beacon_tree, hf_thread_bcn_version, tvb, offset, 1, ENC_BIG_ENDIAN);
2155     offset += 1;
2156 
2157     /* Get and display the network ID. */
2158     proto_tree_add_item_ret_string(beacon_tree, hf_thread_bcn_network_id, tvb, offset, 16, ENC_ASCII|ENC_NA, pinfo->pool, &ssid);
2159     col_append_fstr(pinfo->cinfo, COL_INFO, ", Network ID: %s", ssid);
2160     offset += 16;
2161 
2162     /* See if we're at the end */
2163     if (offset >= tvb_captured_length(tvb)) {
2164         return tvb_captured_length(tvb);
2165     }
2166 
2167     /* XPANID */
2168     proto_tree_add_item(beacon_tree, hf_thread_bcn_epid, tvb, offset, 8, ENC_BIG_ENDIAN);
2169     offset += 8;
2170 
2171     /* See if we're at the end */
2172     if (offset >= tvb_captured_length(tvb)) {
2173         return tvb_captured_length(tvb);
2174     }
2175 
2176     /* Steering data TLV present */
2177 
2178     /* Get the length ahead of time to pass to next function so we can highlight
2179        proper amount of bytes */
2180     tlv_len = tvb_get_guint8(tvb, offset+1);
2181 
2182     /* Type */
2183     ti = proto_tree_add_item(beacon_tree, hf_thread_bcn_tlv, tvb, offset, tlv_len+2, ENC_NA);
2184     tlv_tree = proto_item_add_subtree(ti, ett_thread_bcn_tlv);
2185     proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2186 
2187     tlv_type = tvb_get_guint8(tvb, offset);
2188     offset++;
2189 
2190     /* Add value name to value root label */
2191     proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_bcn_tlv_vals, "Unknown (%d)"));
2192 
2193     /* Length */
2194     proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2195     offset++;
2196 
2197     if (tlv_len) { /* Belt 'n' braces check */
2198         switch (tlv_type) {
2199             case THREAD_BCN_TLV_STEERING_DATA:
2200                 proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_steering_data, tvb, offset, tlv_len, ENC_NA);
2201                 /* offset += tlv_len; */
2202                 break;
2203             default:
2204                 proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2205                 /* offset += tlv_len; */
2206                 break;
2207         }
2208     }
2209     return tvb_captured_length(tvb);
2210 }
2211 
2212 static gboolean
dissect_thread_bcn_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)2213 dissect_thread_bcn_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2214 {
2215     ieee802154_packet   *packet = (ieee802154_packet *)data;
2216 
2217     /* Thread beacon frames can be 16 or 64-bit source */
2218     if (!packet) return FALSE;
2219     if (!((packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
2220           (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT))) return FALSE;
2221 
2222     if (tvb_captured_length(tvb) > 0) {
2223         /* Thread beacons begin with a protocol identifier. */
2224         if (tvb_get_guint8(tvb, 0) != THREAD_BCN_PROTOCOL_ID) return FALSE;
2225         dissect_thread_bcn(tvb, pinfo, tree, packet);
2226         return TRUE;
2227     }
2228     return FALSE;
2229 }
2230 
2231 void
proto_register_thread_address(void)2232 proto_register_thread_address(void)
2233 {
2234     static hf_register_info hf[] = {
2235 
2236         /* Generic TLV */
2237         { &hf_thread_address_tlv,
2238             { "TLV",
2239             "thread_address.tlv",
2240             FT_NONE, BASE_NONE, NULL, 0x0,
2241             "Type-Length-Value",
2242             HFILL }
2243         },
2244 
2245         { &hf_thread_address_tlv_type,
2246             { "Type",
2247             "thread_address.tlv.type",
2248             FT_UINT8, BASE_DEC, VALS(thread_address_tlv_vals), 0x0,
2249             "Type of value",
2250             HFILL }
2251         },
2252 
2253         { &hf_thread_address_tlv_length,
2254             { "Length",
2255             "thread_address.tlv.len",
2256             FT_UINT8, BASE_DEC, NULL, 0x0,
2257             "Length of value",
2258             HFILL }
2259         },
2260 
2261         { &hf_thread_address_tlv_unknown,
2262             { "Unknown",
2263             "thread_address.tlv.unknown",
2264             FT_BYTES, BASE_NONE, NULL, 0x0,
2265             "Unknown TLV, raw value",
2266             HFILL }
2267         },
2268 #if 0
2269         { &hf_thread_address_tlv_sub_tlvs,
2270             { "Sub-TLV(s)",
2271             "thread_address.tlv.sub_tlvs",
2272             FT_NONE, BASE_NONE, NULL, 0x0,
2273             NULL,
2274             HFILL }
2275         },
2276 #endif
2277         /* Type-Specific TLV Fields */
2278         { &hf_thread_address_tlv_target_eid,
2279             { "Target EID",
2280             "thread_address.tlv.target_eid",
2281             FT_IPv6, BASE_NONE, NULL, 0x0,
2282             NULL,
2283             HFILL }
2284         },
2285 
2286         { &hf_thread_address_tlv_ext_mac_addr,
2287             { "Extended MAC Address",
2288             "thread_address.tlv.ext_mac_addr",
2289             FT_EUI64, BASE_NONE, NULL, 0x0,
2290             NULL,
2291             HFILL }
2292         },
2293 
2294         { &hf_thread_address_tlv_rloc16,
2295             { "RLOC16",
2296             "thread_address.tlv.rloc16",
2297             FT_UINT16, BASE_HEX, NULL, 0x0,
2298             NULL,
2299             HFILL }
2300         },
2301 
2302         { &hf_thread_address_tlv_ml_eid,
2303             { "ML-EID",
2304             "thread_address.tlv.ml_eid",
2305             FT_BYTES, BASE_NONE, NULL, 0x0,
2306             NULL,
2307             HFILL }
2308         },
2309 
2310         { &hf_thread_address_tlv_status,
2311             { "Status",
2312             "thread_address.tlv.status",
2313             FT_UINT8, BASE_DEC, VALS(thread_address_tlv_status_vals), 0x0,
2314             NULL,
2315             HFILL }
2316         },
2317 #if 0
2318         { &hf_thread_address_tlv_attached_time,
2319             { "Attached Time",
2320             "thread_address.tlv.attached_time",
2321             FT_UINT32, BASE_DEC, NULL, 0x0,
2322             NULL,
2323             HFILL }
2324         },
2325 #endif
2326         { &hf_thread_address_tlv_last_transaction_time,
2327             { "Last Transaction Time",
2328             "thread_address.tlv.last_transaction_time",
2329             FT_UINT32, BASE_DEC, NULL, 0x0,
2330             NULL,
2331             HFILL }
2332         },
2333 
2334         { &hf_thread_address_tlv_router_mask_id_seq,
2335             { "ID Sequence",
2336             "thread_address.tlv.router_mask_id_seq",
2337             FT_UINT8, BASE_DEC, NULL, 0x0,
2338             NULL,
2339             HFILL }
2340         },
2341 
2342         { &hf_thread_address_tlv_router_mask_assigned,
2343             { "Assigned Router ID Mask",
2344             "thread_address.tlv.router_mask_assigned",
2345             FT_BYTES, BASE_NONE, NULL, 0x0,
2346             NULL,
2347             HFILL }
2348         },
2349 
2350         { &hf_thread_address_tlv_nd_option,
2351             { "ND Option",
2352             "thread_address.tlv.nd_option",
2353             FT_BYTES, BASE_NONE, NULL, 0x0,
2354             NULL,
2355             HFILL }
2356         },
2357 
2358         { &hf_thread_address_tlv_nd_data,
2359             { "ND Data",
2360             "thread_address.tlv.nd_data",
2361             FT_BYTES, BASE_NONE, NULL, 0x0,
2362             NULL,
2363             HFILL }
2364         }
2365     };
2366 
2367     static gint *ett[] = {
2368         &ett_thread_address,
2369         &ett_thread_address_tlv,
2370     };
2371 
2372     static ei_register_info ei[] = {
2373 #if 0
2374         { &ei_thread_address_tlv_length_failed, { "thread_address.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
2375 #endif
2376         { &ei_thread_address_len_size_mismatch, { "thread_address.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
2377     };
2378 
2379     expert_module_t* expert_thread_address;
2380 
2381     proto_thread_address = proto_register_protocol("Thread Address", "Thread Address", "thread_address");
2382     proto_register_field_array(proto_thread_address, hf, array_length(hf));
2383     proto_register_subtree_array(ett, array_length(ett));
2384     expert_thread_address = expert_register_protocol(proto_thread_address);
2385     expert_register_field_array(expert_thread_address, ei, array_length(ei));
2386 
2387     thread_address_handle = register_dissector("thread_address", dissect_thread_address, proto_thread_address);
2388 }
2389 
2390 void
proto_register_thread_dg(void)2391 proto_register_thread_dg(void)
2392 {
2393     static hf_register_info hf[] = {
2394 
2395         /* Generic TLV */
2396         { &hf_thread_dg_tlv,
2397             { "TLV",
2398             "thread_diagnostic.tlv",
2399             FT_NONE, BASE_NONE, NULL, 0x0,
2400             "Type-Length-Value",
2401             HFILL }
2402         },
2403 
2404         { &hf_thread_dg_tlv_type,
2405             { "Type",
2406             "thread_diagnostic.tlv.type",
2407             FT_UINT8, BASE_DEC, VALS(thread_dg_tlv_vals), 0x0,
2408             "Type of value",
2409             HFILL }
2410         },
2411 
2412         { &hf_thread_dg_tlv_length8,
2413             { "Length",
2414             "thread_diagnostic.tlv.len8",
2415             FT_UINT8, BASE_DEC, NULL, 0x0,
2416             "Length of value (8-bit)",
2417             HFILL }
2418         },
2419 
2420         { &hf_thread_dg_tlv_length16,
2421             { "Length",
2422             "thread_diagnostic.tlv.len16",
2423             FT_UINT16, BASE_DEC, NULL, 0x0,
2424             "Length of value (16-bit)",
2425             HFILL }
2426         },
2427 
2428         { &hf_thread_dg_tlv_general,
2429             { "General",
2430             "thread_diagnostic.tlv.general",
2431             FT_BYTES, BASE_NONE, NULL, 0x0,
2432             "General TLV, raw value",
2433             HFILL }
2434         },
2435 
2436         { &hf_thread_dg_tlv_unknown,
2437             { "Unknown",
2438             "thread_diagnostic.tlv.unknown",
2439             FT_BYTES, BASE_NONE, NULL, 0x0,
2440             "Unknown TLV, raw value",
2441             HFILL }
2442         }
2443     };
2444 
2445     static gint *ett[] = {
2446         &ett_thread_dg,
2447         &ett_thread_dg_tlv,
2448     };
2449 
2450 #if 0
2451     static ei_register_info ei[] = {
2452         { &ei_thread_dg_tlv_length_failed, { "thread_diagnostic.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
2453         { &ei_thread_dg_len_size_mismatch, { "thread_diagnostic.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
2454     };
2455 
2456     expert_module_t* expert_thread_dg;
2457 #endif
2458 
2459     proto_thread_dg = proto_register_protocol("Thread Diagnostics", "Thread Diagnostics", "thread_diagnostic");
2460     proto_register_field_array(proto_thread_dg, hf, array_length(hf));
2461     proto_register_subtree_array(ett, array_length(ett));
2462 #if 0
2463     expert_thread_dg = expert_register_protocol(proto_thread_dg);
2464     expert_register_field_array(expert_thread_dg, ei, array_length(ei));
2465 #endif
2466 
2467     thread_dg_handle = register_dissector("thread_diagnostic", dissect_thread_dg, proto_thread_dg);
2468 }
2469 
2470 void
proto_register_thread_mc(void)2471 proto_register_thread_mc(void)
2472 {
2473     static hf_register_info hf[] = {
2474 
2475         /* Generic TLV */
2476         { &hf_thread_mc_tlv,
2477             { "TLV",
2478             "thread_meshcop.tlv",
2479             FT_NONE, BASE_NONE, NULL, 0x0,
2480             "Type-Length-Value",
2481             HFILL }
2482         },
2483 
2484         { &hf_thread_mc_tlv_type,
2485             { "Type",
2486             "thread_meshcop.tlv.type",
2487             FT_UINT8, BASE_DEC, VALS(thread_mc_tlv_vals), 0x0,
2488             "Type of value",
2489             HFILL }
2490         },
2491 
2492         { &hf_thread_mc_tlv_length8,
2493             { "Length",
2494             "thread_meshcop.tlv.len8",
2495             FT_UINT8, BASE_DEC, NULL, 0x0,
2496             "Length of value (8-bit)",
2497             HFILL }
2498         },
2499 
2500         { &hf_thread_mc_tlv_length16,
2501             { "Length",
2502             "thread_meshcop.tlv.len16",
2503             FT_UINT16, BASE_DEC, NULL, 0x0,
2504             "Length of value (16-bit)",
2505             HFILL }
2506         },
2507 
2508         { &hf_thread_mc_tlv_unknown,
2509             { "Unknown",
2510             "thread_meshcop.tlv.unknown",
2511             FT_BYTES, BASE_NONE, NULL, 0x0,
2512             "Unknown TLV, raw value",
2513             HFILL }
2514         },
2515 #if 0
2516         { &hf_thread_mc_tlv_sub_tlvs,
2517             { "Sub-TLV(s)",
2518             "thread_meshcop.tlv.sub_tlvs",
2519             FT_NONE, BASE_NONE, NULL, 0x0,
2520             NULL,
2521             HFILL }
2522         },
2523 #endif
2524         /* Type-Specific TLV Fields */
2525         { &hf_thread_mc_tlv_channel_page,
2526             { "Channel Page",
2527             "thread_meshcop.tlv.channel_page",
2528             FT_UINT8, BASE_DEC, NULL, 0x0,
2529             NULL,
2530             HFILL }
2531         },
2532 
2533         { &hf_thread_mc_tlv_channel,
2534             { "Channel",
2535             "thread_meshcop.tlv.channel",
2536             FT_UINT16, BASE_DEC, NULL, 0x0,
2537             NULL,
2538             HFILL }
2539         },
2540 
2541         { &hf_thread_mc_tlv_pan_id,
2542             { "PAN ID",
2543             "thread_meshcop.tlv.pan_id",
2544             FT_UINT16, BASE_HEX, NULL, 0x0,
2545             NULL,
2546             HFILL }
2547         },
2548 
2549         { &hf_thread_mc_tlv_xpan_id,
2550             { "Extended PAN ID",
2551             "thread_meshcop.tlv.xpan_id",
2552             FT_UINT64, BASE_HEX, NULL, 0x0,
2553             NULL,
2554             HFILL }
2555         },
2556 
2557         { &hf_thread_mc_tlv_net_name,
2558             { "Network Name",
2559             "thread_meshcop.tlv.net_name",
2560             FT_STRING, BASE_NONE, NULL, 0x0,
2561             NULL,
2562             HFILL }
2563         },
2564 
2565         { &hf_thread_mc_tlv_pskc,
2566             { "PSKc",
2567             "thread_meshcop.tlv.pskc",
2568             FT_BYTES, BASE_NONE, NULL, 0x0,
2569             NULL,
2570             HFILL }
2571         },
2572 
2573         { &hf_thread_mc_tlv_master_key,
2574             { "Master Key",
2575             "thread_meshcop.tlv.master_key",
2576             FT_BYTES, BASE_NONE, NULL, 0x0,
2577             NULL,
2578             HFILL }
2579         },
2580 
2581         { &hf_thread_mc_tlv_net_key_seq_ctr,
2582             { "Network Key Sequence Counter",
2583             "thread_meshcop.tlv.net_key_seq_ctr",
2584             FT_BYTES, BASE_NONE, NULL, 0x0,
2585             NULL,
2586             HFILL }
2587         },
2588 
2589         { &hf_thread_mc_tlv_ml_prefix,
2590             { "Mesh Local Prefix",
2591             "thread_meshcop.tlv.ml_prefix",
2592             FT_IPv6, BASE_NONE, NULL, 0x0,
2593             NULL,
2594             HFILL }
2595         },
2596 
2597         { &hf_thread_mc_tlv_steering_data,
2598             { "Steering Data",
2599             "thread_meshcop.tlv.steering_data",
2600             FT_BYTES, BASE_NONE, NULL, 0x0,
2601             NULL,
2602             HFILL }
2603         },
2604 
2605         { &hf_thread_mc_tlv_ba_locator,
2606             { "Border Agent Locator",
2607             "thread_meshcop.tlv.ba_locator",
2608             FT_BYTES, BASE_NONE, NULL, 0x0,
2609             NULL,
2610             HFILL }
2611         },
2612 
2613         { &hf_thread_mc_tlv_commissioner_id,
2614             { "Commissioner ID",
2615             "thread_meshcop.tlv.commissioner_id",
2616             FT_STRING, BASE_NONE, NULL, 0x0,
2617             NULL,
2618             HFILL }
2619         },
2620 
2621         { &hf_thread_mc_tlv_commissioner_sess_id,
2622             { "Commissioner Session ID",
2623             "thread_meshcop.tlv.commissioner_sess_id",
2624             FT_BYTES, BASE_NONE, NULL, 0x0,
2625             NULL,
2626             HFILL }
2627         },
2628 
2629         { &hf_thread_mc_tlv_sec_policy_rot,
2630             { "Rotation Time",
2631             "thread_meshcop.tlv.sec_policy_rot",
2632             FT_UINT16, BASE_DEC, NULL, 0x0,
2633             NULL,
2634             HFILL }
2635         },
2636 
2637         { &hf_thread_mc_tlv_sec_policy_o,
2638             { "Out-of-band Commissioning",
2639             "thread_meshcop.tlv.sec_policy_o",
2640             FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_O_MASK,
2641             NULL,
2642             HFILL }
2643         },
2644 
2645         { &hf_thread_mc_tlv_sec_policy_n,
2646             { "Native Commissioning",
2647             "thread_meshcop.tlv.sec_policy_n",
2648             FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_N_MASK,
2649             NULL,
2650             HFILL }
2651         },
2652 
2653         { &hf_thread_mc_tlv_sec_policy_r,
2654             { "Thread 1.x Routers",
2655             "thread_meshcop.tlv.sec_policy_r",
2656             FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_R_MASK,
2657             NULL,
2658             HFILL }
2659         },
2660 
2661         { &hf_thread_mc_tlv_sec_policy_c,
2662             { "PSKc-based Commissioning",
2663             "thread_meshcop.tlv.sec_policy_c",
2664             FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_C_MASK,
2665             NULL,
2666             HFILL }
2667         },
2668 
2669         { &hf_thread_mc_tlv_sec_policy_b,
2670             { "Thread 1.x Beacons",
2671             "thread_meshcop.tlv.sec_policy_b",
2672             FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_B_MASK,
2673             NULL,
2674             HFILL }
2675         },
2676 
2677         { &hf_thread_mc_tlv_state,
2678             { "State",
2679             "thread_meshcop.tlv.state",
2680             FT_INT8, BASE_DEC, VALS(thread_mc_state_vals), 0x0,
2681             NULL,
2682             HFILL }
2683         },
2684 
2685         { &hf_thread_mc_tlv_active_tstamp,
2686             { "Active Timestamp",
2687             "thread_meshcop.tlv.active_tstamp",
2688             FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2689             NULL,
2690             HFILL }
2691         },
2692 
2693         { &hf_thread_mc_tlv_pending_tstamp,
2694             { "Pending Timestamp",
2695             "thread_meshcop.tlv.pending_tstamp",
2696             FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2697             NULL,
2698             HFILL }
2699         },
2700 
2701         { &hf_thread_mc_tlv_udp_port,
2702             { "UDP Port",
2703             "thread_meshcop.tlv.udp_port",
2704             FT_UINT16, BASE_DEC, NULL, 0x0,
2705             NULL,
2706             HFILL }
2707         },
2708 
2709         { &hf_thread_mc_tlv_iid,
2710             { "Interface Identifier",
2711             "thread_meshcop.tlv.iid",
2712             FT_BYTES, BASE_NONE, NULL, 0x0,
2713             NULL,
2714             HFILL }
2715         },
2716 
2717         { &hf_thread_mc_tlv_jr_locator,
2718             { "Joiner Router Locator",
2719             "thread_meshcop.tlv.jr_locator",
2720             FT_BYTES, BASE_NONE, NULL, 0x0,
2721             NULL,
2722             HFILL }
2723         },
2724 
2725         { &hf_thread_mc_tlv_kek,
2726             { "Key Encryption Key (KEK)",
2727             "thread_meshcop.tlv.kek",
2728             FT_BYTES, BASE_NONE, NULL, 0x0,
2729             NULL,
2730             HFILL }
2731         },
2732 
2733         { &hf_thread_mc_tlv_provisioning_url,
2734             { "Provisioning URL",
2735             "thread_meshcop.tlv.provisioning_url",
2736             FT_STRING, BASE_NONE, NULL, 0x0,
2737             NULL,
2738             HFILL }
2739         },
2740 
2741         { &hf_thread_mc_tlv_vendor_name,
2742             { "Vendor Name",
2743             "thread_meshcop.tlv.vendor_name",
2744             FT_STRING, BASE_NONE, NULL, 0x0,
2745             NULL,
2746             HFILL }
2747         },
2748 
2749         { &hf_thread_mc_tlv_vendor_model,
2750             { "Vendor Model",
2751             "thread_meshcop.tlv.vendor_model",
2752             FT_STRING, BASE_NONE, NULL, 0x0,
2753             NULL,
2754             HFILL }
2755         },
2756 
2757         { &hf_thread_mc_tlv_vendor_sw_ver,
2758             { "Vendor Software Version",
2759             "thread_meshcop.tlv.vendor_sw_ver",
2760             FT_STRING, BASE_NONE, NULL, 0x0,
2761             NULL,
2762             HFILL }
2763         },
2764 
2765         { &hf_thread_mc_tlv_vendor_data,
2766             { "Vendor Data",
2767             "thread_meshcop.tlv.vendor_model",
2768             FT_STRING, BASE_NONE, NULL, 0x0,
2769             NULL,
2770             HFILL }
2771         },
2772 
2773         { &hf_thread_mc_tlv_vendor_stack_ver_oui,
2774             { "OUI",
2775             "thread_meshcop.tlv.vendor_stack_ver_oui",
2776             FT_UINT24, BASE_OUI, NULL, 0x0,
2777             NULL,
2778             HFILL }
2779         },
2780 
2781         { &hf_thread_mc_tlv_vendor_stack_ver_build,
2782             { "Build",
2783             "thread_meshcop.tlv.vendor_stack_ver_build",
2784             FT_UINT16, BASE_DEC, NULL, 0x0,
2785             NULL,
2786             HFILL }
2787         },
2788 
2789         { &hf_thread_mc_tlv_vendor_stack_ver_rev,
2790             { "Revision",
2791             "thread_meshcop.tlv.vendor_stack_ver_rev",
2792             FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_REV_MASK,
2793             NULL,
2794             HFILL }
2795         },
2796 
2797         { &hf_thread_mc_tlv_vendor_stack_ver_min,
2798             { "Minor",
2799             "thread_meshcop.tlv.vendor_stack_ver_min",
2800             FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_MIN_MASK,
2801             NULL,
2802             HFILL }
2803         },
2804 
2805         { &hf_thread_mc_tlv_vendor_stack_ver_maj,
2806             { "Major",
2807             "thread_meshcop.tlv.vendor_stack_ver_maj",
2808             FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_MAJ_MASK,
2809             NULL,
2810             HFILL }
2811         },
2812 
2813         { &hf_thread_mc_tlv_udp_encap_src_port,
2814             { "Source UDP Port",
2815             "thread_meshcop.tlv.udp_encap_src_port",
2816             FT_UINT16, BASE_DEC, NULL, 0x0,
2817             NULL,
2818             HFILL }
2819         },
2820 
2821         { &hf_thread_mc_tlv_udp_encap_dst_port,
2822             { "Destination UDP Port",
2823             "thread_meshcop.tlv.udp_encap_dst_port",
2824             FT_UINT16, BASE_DEC, NULL, 0x0,
2825             NULL,
2826             HFILL }
2827         },
2828 
2829         { &hf_thread_mc_tlv_ipv6_addr,
2830             { "IPv6 Address",
2831             "thread_meshcop.tlv.ipv6_addr",
2832             FT_IPv6, BASE_NONE, NULL, 0x0,
2833             NULL,
2834             HFILL }
2835         },
2836 
2837         { &hf_thread_mc_tlv_delay_timer,
2838             { "Delay Timer",
2839             "thread_meshcop.tlv.delay_timer",
2840             FT_UINT32, BASE_DEC, NULL, 0x0,
2841             NULL,
2842             HFILL }
2843         },
2844 
2845         { &hf_thread_mc_tlv_chan_mask,
2846             { "Channel Mask",
2847             "thread_meshcop.tlv.chan_mask",
2848             FT_NONE, BASE_NONE, NULL, 0x0,
2849             NULL,
2850             HFILL }
2851         },
2852 
2853         { &hf_thread_mc_tlv_chan_mask_page,
2854             { "Channel Page",
2855             "thread_meshcop.tlv.chan_mask_page",
2856             FT_UINT8, BASE_DEC, NULL, 0,
2857             NULL,
2858             HFILL }
2859         },
2860 
2861         { &hf_thread_mc_tlv_chan_mask_len,
2862             { "Mask Length",
2863             "thread_meshcop.tlv.chan_mask_len",
2864             FT_UINT8, BASE_DEC, NULL, 0,
2865             NULL,
2866             HFILL }
2867         },
2868 
2869         { &hf_thread_mc_tlv_chan_mask_mask,
2870             { "Mask",
2871             "thread_meshcop.tlv.chan_mask_mask",
2872             FT_BYTES, BASE_NONE, NULL, 0x0,
2873             NULL,
2874             HFILL }
2875         },
2876 
2877         { &hf_thread_mc_tlv_el_count,
2878             { "Count",
2879             "thread_meshcop.tlv.el_count",
2880             FT_NONE, BASE_NONE, NULL, 0x0,
2881             NULL,
2882             HFILL }
2883         },
2884 
2885         { &hf_thread_mc_tlv_count,
2886             { "Count",
2887             "thread_meshcop.tlv.count",
2888             FT_UINT8, BASE_DEC, NULL, 0,
2889             NULL,
2890             HFILL }
2891         },
2892 
2893         { &hf_thread_mc_tlv_period,
2894             { "Period",
2895             "thread_meshcop.tlv.period",
2896             FT_UINT16, BASE_DEC, NULL, 0,
2897             NULL,
2898             HFILL }
2899         },
2900 
2901         { &hf_thread_mc_tlv_scan_duration,
2902             { "Scan Duration",
2903             "thread_meshcop.tlv.scan_duration",
2904             FT_UINT16, BASE_DEC, NULL, 0,
2905             NULL,
2906             HFILL }
2907         },
2908 
2909         { &hf_thread_mc_tlv_energy_list,
2910             { "Energy List",
2911             "thread_meshcop.tlv.energy_list",
2912             FT_BYTES, BASE_NONE, NULL, 0x0,
2913             NULL,
2914             HFILL }
2915         },
2916 
2917         { &hf_thread_mc_tlv_discovery_req_ver,
2918             { "Version",
2919             "thread_meshcop.tlv.discovery_req_ver",
2920             FT_UINT8, BASE_DEC, NULL, THREAD_MC_DISCOVERY_REQ_MASK_VER_MASK,
2921             NULL,
2922             HFILL }
2923         },
2924 
2925         { &hf_thread_mc_tlv_discovery_req_j,
2926             { "Joiner Flag",
2927             "thread_meshcop.tlv.discovery_req_j",
2928             FT_BOOLEAN, 8, TFS(&thread_mc_tlv_join_intent), THREAD_MC_DISCOVERY_REQ_MASK_J_MASK,
2929             NULL,
2930             HFILL }
2931         },
2932 
2933         { &hf_thread_mc_tlv_discovery_rsp_ver,
2934             { "Version",
2935             "thread_meshcop.tlv.discovery_rsp_ver",
2936             FT_UINT8, BASE_DEC, NULL, THREAD_MC_DISCOVERY_RSP_MASK_VER_MASK,
2937             NULL,
2938             HFILL }
2939         },
2940 
2941         { &hf_thread_mc_tlv_discovery_rsp_n,
2942             { "Native Commissioning",
2943             "thread_meshcop.tlv.discovery_rsp_n",
2944             FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_DISCOVERY_RSP_MASK_N_MASK,
2945             NULL,
2946             HFILL }
2947         }
2948     };
2949 
2950     static gint *ett[] = {
2951         &ett_thread_mc,
2952         &ett_thread_mc_tlv,
2953         &ett_thread_mc_chan_mask,
2954         &ett_thread_mc_el_count
2955     };
2956 
2957     static ei_register_info ei[] = {
2958         { &ei_thread_mc_tlv_length_failed, { "thread_meshcop.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
2959         { &ei_thread_mc_len_size_mismatch, { "thread_meshcop.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
2960         { &ei_thread_mc_len_too_long, { "thread_meshcop.len_too_long", PI_UNDECODED, PI_WARN, "TLV Length too long", EXPFILL }}
2961     };
2962 
2963     expert_module_t* expert_thread_mc;
2964 
2965     proto_thread_mc = proto_register_protocol("Thread MeshCoP", "Thread MeshCoP", "thread_meshcop");
2966     proto_register_field_array(proto_thread_mc, hf, array_length(hf));
2967     proto_register_subtree_array(ett, array_length(ett));
2968     expert_thread_mc = expert_register_protocol(proto_thread_mc);
2969     expert_register_field_array(expert_thread_mc, ei, array_length(ei));
2970 
2971     thread_mc_handle = register_dissector("thread_meshcop", dissect_thread_mc, proto_thread_mc);
2972 }
2973 
2974 void
proto_register_thread_nwd(void)2975 proto_register_thread_nwd(void)
2976 {
2977     static hf_register_info hf[] = {
2978 
2979     /* Generic TLV */
2980         { &hf_thread_nwd_tlv,
2981             { "TLV",
2982             "thread_nwd.tlv",
2983             FT_NONE, BASE_NONE, NULL, 0x0,
2984             "Type-Length-Value",
2985             HFILL }
2986         },
2987 
2988         { &hf_thread_nwd_tlv_type,
2989             { "Type",
2990             "thread_nwd.tlv.type",
2991             FT_UINT8, BASE_DEC, VALS(thread_nwd_tlv_vals), THREAD_NWD_TLV_TYPE_M,
2992             "Type of value",
2993             HFILL }
2994         },
2995 
2996         { &hf_thread_nwd_tlv_stable,
2997             { "Stable",
2998             "thread_nwd.tlv.stable",
2999             FT_BOOLEAN, 8, NULL, THREAD_NWD_TLV_STABLE_M,
3000             "Stability or transience of network data",
3001             HFILL }
3002         },
3003 
3004         { &hf_thread_nwd_tlv_length,
3005             { "Length",
3006             "thread_nwd.tlv.len",
3007             FT_UINT8, BASE_DEC, NULL, 0x0,
3008             "Length of value",
3009             HFILL }
3010         },
3011 
3012         { &hf_thread_nwd_tlv_unknown,
3013             { "Unknown",
3014             "thread_nwd.tlv.unknown",
3015             FT_BYTES, BASE_NONE, NULL, 0x0,
3016             "Unknown TLV, raw value",
3017             HFILL }
3018         },
3019 
3020         { &hf_thread_nwd_tlv_sub_tlvs,
3021             { "Sub-TLV(s)",
3022             "thread_nwd.tlv.sub_tlvs",
3023             FT_NONE, BASE_NONE, NULL, 0x0,
3024             NULL,
3025             HFILL }
3026         },
3027 
3028         /* Type-Specific TLV Fields */
3029         { &hf_thread_nwd_tlv_has_route,
3030             { "Has Route",
3031             "thread_nwd.tlv.has_route",
3032             FT_NONE, BASE_NONE, NULL, 0x0,
3033             NULL,
3034             HFILL }
3035         },
3036 
3037         { &hf_thread_nwd_tlv_has_route_br_16,
3038             { "Border Router 16",
3039             "thread_nwd.tlv.has_route.br_16",
3040             FT_UINT16, BASE_HEX, NULL, 0x0,
3041             "Has Route Border Router 16-bit address",
3042             HFILL }
3043         },
3044 
3045         { &hf_thread_nwd_tlv_has_route_pref,
3046             { "Preference",
3047             "thread_nwd.tlv.has_route.pref",
3048             FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_HAS_ROUTE_PREF,
3049             "Has Route preference",
3050             HFILL }
3051         },
3052 
3053         { &hf_thread_nwd_tlv_prefix_domain_id,
3054             { "Domain ID",
3055             "thread_nwd.tlv.prefix.domain_id",
3056             FT_UINT8, BASE_DEC, NULL, 0x0,
3057             "Prefix Domain ID",
3058             HFILL }
3059         },
3060 
3061         { &hf_thread_nwd_tlv_prefix_length,
3062             { "Prefix Length",
3063             "thread_nwd.tlv.prefix.length",
3064             FT_UINT8, BASE_DEC, NULL, 0x0,
3065             "Length of Prefix",
3066             HFILL }
3067         },
3068 
3069         { &hf_thread_nwd_tlv_prefix,
3070             { "Prefix",
3071             "thread_nwd.tlv.prefix",
3072             FT_IPv6, BASE_NONE, NULL, 0x0,
3073             "IPv6 prefix",
3074             HFILL }
3075         },
3076 
3077         { &hf_thread_nwd_tlv_border_router,
3078             { "Border Router",
3079             "thread_nwd.tlv.border_router",
3080             FT_NONE, BASE_NONE, NULL, 0x0,
3081             NULL,
3082             HFILL }
3083         },
3084 
3085         { &hf_thread_nwd_tlv_border_router_16,
3086             { "Border Router 16",
3087             "thread_nwd.tlv.border_router.16",
3088             FT_UINT16, BASE_HEX, NULL, 0x0,
3089             "Border Router 16-bit address",
3090             HFILL }
3091         },
3092 
3093         { &hf_thread_nwd_tlv_border_router_pref,
3094             { "Preference",
3095             "thread_nwd.tlv.border_router.pref",
3096             FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_BORDER_ROUTER_PREF,
3097             "Value of P_preference",
3098             HFILL }
3099         },
3100 
3101         { &hf_thread_nwd_tlv_border_router_p,
3102             { "P Flag",
3103             "thread_nwd.tlv.border_router.flag.p",
3104             FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_p), THREAD_NWD_TLV_BORDER_ROUTER_P,
3105             "Value of P_preferred",
3106             HFILL }
3107         },
3108 
3109         { &hf_thread_nwd_tlv_border_router_s,
3110             { "SLAAC",
3111             "thread_nwd.tlv.border_router.flag.s",
3112             FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_NWD_TLV_BORDER_ROUTER_S,
3113             "Value of P_slaac",
3114             HFILL }
3115         },
3116 
3117         { &hf_thread_nwd_tlv_border_router_d,
3118             { "DHCPv6",
3119             "thread_nwd.tlv.border_router.flag.d",
3120             FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_NWD_TLV_BORDER_ROUTER_D,
3121             "Value of P_dhcp",
3122             HFILL }
3123         },
3124 
3125         { &hf_thread_nwd_tlv_border_router_c,
3126             { "C Flag",
3127             "thread_nwd.tlv.border_router.flag.c",
3128             FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_c), THREAD_NWD_TLV_BORDER_ROUTER_C,
3129             "Value of P_configure",
3130             HFILL }
3131         },
3132 
3133         { &hf_thread_nwd_tlv_border_router_r,
3134             { "Default route",
3135             "thread_nwd.tlv.border_router.flag.r",
3136             FT_BOOLEAN, 8, TFS(&tfs_yes_no), THREAD_NWD_TLV_BORDER_ROUTER_R,
3137             "Value of P_default",
3138             HFILL }
3139         },
3140 
3141         { &hf_thread_nwd_tlv_border_router_o,
3142             { "O Flag",
3143             "thread_nwd.tlv.border_router.flag.o",
3144             FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_o), THREAD_NWD_TLV_BORDER_ROUTER_O,
3145             "Value of P_on_mesh",
3146             HFILL }
3147         },
3148 
3149         { &hf_thread_nwd_tlv_border_router_n,
3150             { "DNS",
3151             "thread_nwd.tlv.border_router.flag.n",
3152             FT_BOOLEAN, 8, TFS(&tfs_available_not_available), THREAD_NWD_TLV_BORDER_ROUTER_N,
3153             "Value of P_nd_dns",
3154             HFILL }
3155         },
3156 
3157         { &hf_thread_nwd_tlv_6lowpan_id_6co_flag,
3158             { "Flag",
3159             "thread_nwd.tlv.6co.flag",
3160             FT_UINT8, BASE_HEX, NULL, 0x00,
3161             NULL,
3162             HFILL }
3163         },
3164 
3165         { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_c,
3166             { "Compression Flag",
3167             "thread_nwd.tlv.6co.flag.c",
3168             FT_BOOLEAN, 8, TFS(&tfs_set_notset), ND_OPT_6CO_FLAG_C,
3169             "This flag indicates if the context is valid for use in compression",
3170             HFILL }
3171         },
3172 
3173         { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_cid,
3174             { "CID",
3175             "thread_nwd.tlv.6co.flag.cid",
3176             FT_UINT8, BASE_DEC, NULL, ND_OPT_6CO_FLAG_CID,
3177             "Context Identifier for this prefix information",
3178             HFILL }
3179         },
3180 
3181         { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_reserved,
3182             { "Reserved",
3183             "thread_nwd.tlv.6co.flag.reserved",
3184             FT_UINT8, BASE_DEC, NULL, ND_OPT_6CO_FLAG_RESERVED,
3185             "Must be zero",
3186             HFILL }
3187         },
3188 
3189         { &hf_thread_nwd_tlv_6lowpan_id_6co_context_length,
3190             { "Context Length",
3191             "thread_nwd.tlv.6co.context_length",
3192             FT_UINT8, BASE_DEC, NULL, 0x00,
3193             "The number of leading bits in the Context Prefix field that are valid",
3194             HFILL }
3195         },
3196 #if 0
3197         { &hf_thread_nwd_tlv_comm_data,
3198             { "Commissioning Data",
3199             "thread_nwd.tlv.comm_data",
3200             FT_BYTES, BASE_NONE, NULL, 0x0,
3201             "Contains Thread Commissioning data",
3202             HFILL }
3203         },
3204 #endif
3205         { &hf_thread_nwd_tlv_service_t,
3206             { "T flag",
3207             "thread_nwd.tlv.service.t",
3208             FT_UINT8, BASE_HEX, NULL, THREAD_NWD_TLV_SERVICE_T,
3209             NULL,
3210             HFILL }
3211         },
3212 
3213         { &hf_thread_nwd_tlv_service_s_id,
3214             { "Service Type ID",
3215             "thread_nwd.tlv.service.s_id",
3216             FT_UINT8, BASE_HEX, NULL, THREAD_NWD_TLV_SERVICE_S_ID,
3217             NULL,
3218             HFILL }
3219         },
3220 
3221         { &hf_thread_nwd_tlv_service_s_ent_num,
3222             { "Enterprise Number",
3223             "thread_nwd.tlv.service.s_ent_num",
3224             FT_UINT32, BASE_DEC, NULL, 0,
3225             NULL,
3226             HFILL }
3227         },
3228 
3229         { &hf_thread_nwd_tlv_service_s_data_len,
3230             { "Service Data Length",
3231             "thread_nwd.tlv.service.s_data_len",
3232             FT_UINT8, BASE_DEC, NULL, 0,
3233             NULL,
3234             HFILL }
3235         },
3236 
3237         { &hf_thread_nwd_tlv_service_s_data,
3238             { "Service Data",
3239             "thread_nwd.tlv.service.s_data",
3240             FT_BYTES, BASE_NONE, NULL, 0x0,
3241             "Service data in raw bytes",
3242             HFILL }
3243         },
3244 
3245         { &hf_thread_nwd_tlv_server_16,
3246             { "Server 16",
3247             "thread_nwd.tlv.server.16",
3248             FT_UINT16, BASE_HEX, NULL, 0x0,
3249             "Server 16-bit address",
3250             HFILL }
3251         },
3252 
3253         { &hf_thread_nwd_tlv_server_data,
3254             { "Server Data",
3255             "thread_nwd.tlv.server.data",
3256             FT_BYTES, BASE_NONE, NULL, 0x0,
3257             "Server data in raw bytes",
3258             HFILL }
3259         }
3260     };
3261 
3262     static gint *ett[] = {
3263         &ett_thread_nwd,
3264         &ett_thread_nwd_tlv,
3265         &ett_thread_nwd_has_route,
3266         &ett_thread_nwd_6co_flag,
3267         &ett_thread_nwd_border_router,
3268         &ett_thread_nwd_prefix_sub_tlvs
3269     };
3270 
3271     static ei_register_info ei[] = {
3272 #if 0
3273         { &ei_thread_nwd_tlv_length_failed, { "thread_nwd.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
3274 #endif
3275         { &ei_thread_nwd_len_size_mismatch, { "thread_nwd.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
3276     };
3277 
3278     expert_module_t* expert_thread_nwd;
3279 
3280     proto_thread_nwd = proto_register_protocol("Thread Network Data", "Thread NWD", "thread_nwd");
3281     proto_register_field_array(proto_thread_nwd, hf, array_length(hf));
3282     proto_register_subtree_array(ett, array_length(ett));
3283     expert_thread_nwd = expert_register_protocol(proto_thread_nwd);
3284     expert_register_field_array(expert_thread_nwd, ei, array_length(ei));
3285 
3286     thread_address_nwd_handle = register_dissector("thread_nwd", dissect_thread_nwd, proto_thread_nwd);
3287 }
3288 
proto_register_thread_bcn(void)3289 void proto_register_thread_bcn(void)
3290 {
3291     static hf_register_info hf[] = {
3292 
3293         { &hf_thread_bcn_protocol,
3294         { "Protocol ID",          "thread_bcn.protocol", FT_UINT8, BASE_DEC, NULL, 0x0,
3295           NULL, HFILL }},
3296 
3297         { &hf_thread_bcn_joining,
3298         { "Joining",              "thread_bcn.joining", FT_BOOLEAN, 8, NULL, THREAD_BCN_JOINING,
3299           NULL, HFILL }},
3300 
3301         { &hf_thread_bcn_native,
3302         { "Native",               "thread_bcn.native", FT_BOOLEAN, 8, NULL, THREAD_BCN_NATIVE,
3303           NULL, HFILL }},
3304 
3305         { &hf_thread_bcn_version,
3306         { "Version",              "thread_bcn.version", FT_UINT8, BASE_DEC, NULL, THREAD_BCN_PROTOCOL_VERSION,
3307           NULL, HFILL }},
3308 
3309         { &hf_thread_bcn_network_id,
3310         { "Network Name",         "thread_bcn.network_name", FT_STRING, BASE_NONE, NULL, 0x0,
3311           "A string that uniquely identifies this network.", HFILL }},
3312 
3313         { &hf_thread_bcn_epid,
3314         { "Extended PAN ID",      "thread_bcn.epid", FT_EUI64, BASE_NONE, NULL, 0x0,
3315           NULL, HFILL }},
3316 
3317         { &hf_thread_bcn_tlv,
3318         { "TLV",                  "thread_bcn.tlv", FT_NONE, BASE_NONE, NULL, 0x0,
3319           "Type-Length-Value", HFILL }},
3320 
3321         { &hf_thread_bcn_tlv_type,
3322         { "Type",                 "thread_bcn.tlv.type", FT_UINT8, BASE_DEC, VALS(thread_bcn_tlv_vals), 0x0,
3323           "Type of Value", HFILL }},
3324 
3325         { &hf_thread_bcn_tlv_length,
3326         { "Length",               "thread_bcn.tlv.len", FT_UINT8, BASE_DEC, NULL, 0x0,
3327           "Length of Value", HFILL }},
3328 
3329         { &hf_thread_bcn_tlv_steering_data,
3330         { "Steering Data",         "thread_bcn.tlv.steering_data", FT_BYTES, BASE_NONE, NULL, 0x0,
3331           "Steering data for joining devices", HFILL }},
3332 
3333         { &hf_thread_bcn_tlv_unknown,
3334         { "Unknown",              "thread_bcn.tlv.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
3335           "Unknown TLV, raw value", HFILL }}
3336     };
3337 
3338     /*  NWK Layer subtrees */
3339     static gint *ett[] = {
3340         &ett_thread_bcn,
3341         &ett_thread_bcn_tlv
3342     };
3343 
3344     /* Register the protocol with Wireshark. */
3345     proto_thread_bcn = proto_register_protocol("Thread Beacon", "Thread Beacon", "thread_bcn");
3346     proto_register_field_array(proto_thread_bcn, hf, array_length(hf));
3347     proto_register_subtree_array(ett, array_length(ett));
3348 
3349     /* Register the dissectors with Wireshark. */
3350     register_dissector("thread_bcn", dissect_thread_bcn, proto_thread_bcn);
3351 }
3352 
3353 static void
proto_init_thread(void)3354 proto_init_thread(void)
3355 {
3356     /* Reset the sequence counter variables */
3357     thread_seq_ctr_acqd = FALSE;
3358     memset(thread_seq_ctr_bytes, 0, 4);
3359 }
3360 
3361 void
proto_register_thread(void)3362 proto_register_thread(void)
3363 {
3364     module_t *thread_module;
3365 
3366     proto_thread = proto_register_protocol("Thread", "Thread", "thread");
3367 
3368     thread_module = prefs_register_protocol(proto_thread, proto_reg_handoff_thread);
3369     prefs_register_obsolete_preference(thread_module, "thr_coap_decode");
3370     prefs_register_string_preference(thread_module, "thr_seq_ctr",
3371                                      "Thread sequence counter",
3372                                      "32-bit sequence counter for hash",
3373                                      (const char **)&thread_seq_ctr_str);
3374 
3375     prefs_register_bool_preference(thread_module, "thr_use_pan_id_in_key",
3376                                    "Use PAN ID as first two octets of master key",
3377                                    "Set if the PAN ID should be used as the first two octets of the master key (PAN ID LSB), (PAN ID MSB), Key[2]...",
3378                                    &thread_use_pan_id_in_key);
3379 
3380     prefs_register_bool_preference(thread_module, "thr_auto_acq_thr_seq_ctr",
3381                                    "Automatically acquire Thread sequence counter",
3382                                    "Set if the Thread sequence counter should be automatically acquired from Key ID mode 2 MLE messages.",
3383                                    &thread_auto_acq_seq_ctr);
3384 
3385     register_init_routine(proto_init_thread);
3386 }
3387 
3388 void
proto_register_thread_coap(void)3389 proto_register_thread_coap(void)
3390 {
3391     proto_thread_coap = proto_register_protocol("Thread CoAP", "Thread CoAP", "thread_coap");
3392     thread_coap_handle = register_dissector("thread_coap", dissect_thread_coap, proto_thread_coap);
3393 
3394     thread_coap_namespace = register_dissector_table("thread.coap_namespace", "Thread CoAP namespace", proto_thread_coap, FT_STRING, BASE_NONE);
3395 }
3396 
3397 void
proto_reg_handoff_thread_mc(void)3398 proto_reg_handoff_thread_mc(void)
3399 {
3400     thread_dtls_handle = find_dissector_add_dependency("dtls", proto_thread_mc);
3401     thread_udp_handle = find_dissector_add_dependency("udp", proto_thread_mc);
3402 
3403     dissector_add_string("thread.coap_namespace", "c", thread_mc_handle);
3404 }
3405 
3406 void
proto_reg_handoff_thread_address(void)3407 proto_reg_handoff_thread_address(void)
3408 {
3409     dissector_add_string("thread.coap_namespace", "a", thread_address_handle);
3410     dissector_add_string("thread.coap_namespace", "n", thread_address_handle);
3411 }
3412 
3413 void
proto_reg_handoff_thread_dg(void)3414 proto_reg_handoff_thread_dg(void)
3415 {
3416     dissector_add_string("thread.coap_namespace", "d", thread_dg_handle);
3417 }
3418 
proto_reg_handoff_thread_bcn(void)3419 void proto_reg_handoff_thread_bcn(void)
3420 {
3421     /* Register our dissector with IEEE 802.15.4 */
3422     heur_dissector_add(IEEE802154_PROTOABBREV_WPAN_BEACON, dissect_thread_bcn_heur, "Thread Beacon", "thread_wlan_beacon", proto_thread_bcn, HEURISTIC_ENABLE);
3423 
3424     register_mle_key_hash_handler(KEY_HASH_THREAD, set_thread_mle_key);
3425     register_ieee802154_mac_key_hash_handler(KEY_HASH_THREAD, set_thread_mac_key);
3426 }
3427 
3428 void
proto_reg_handoff_thread(void)3429 proto_reg_handoff_thread(void)
3430 {
3431     /* Thread Content-Format is opaque byte string, i.e. application/octet-stream */
3432     /* Enable decoding "Internet media type" as Thread over CoAP */
3433     dissector_add_for_decode_as("media_type", thread_coap_handle);
3434 
3435     proto_coap = proto_get_id_by_filter_name("coap");
3436 }
3437 
3438 /*
3439  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3440  *
3441  * Local variables:
3442  * c-basic-offset: 4
3443  * tab-width: 8
3444  * indent-tabs-mode: nil
3445  * End:
3446  *
3447  * vi: set shiftwidth=4 tabstop=8 expandtab:
3448  * :indentSize=4:tabSize=8:noTabs=true:
3449  */
3450