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
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
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 */
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 */
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
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
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
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
dissect_tetra_INTEGER_0_3(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_INTEGER_0_63(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 {
dissect_tetra_AACH(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_System_Code(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_Colour_Code(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
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;
dissect_tetra_Timeslot_Number(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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;
dissect_tetra_Frame_Number(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
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);
dissect_tetra_Multiple_Frame_Number(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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) {
dissect_tetra_Sharing_Mod(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 */
dissect_tetra_TS_Reserved_Frames(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }
dissect_tetra_U_Plane_DTX(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }
dissect_tetra_Frame_18_Extension(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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:
dissect_tetra_Reserved(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }
dissect_tetra_INTEGER_0_1023(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_INTEGER_0_16383(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_INTEGER_0_1(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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));
dissect_tetra_MLE_Sync(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 {
dissect_tetra_BSCH(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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;
dissect_tetra_INTEGER_0_4095(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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:
dissect_tetra_Offset(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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++;
dissect_tetra_Reverse_Operation(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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, ×tamp);
dissect_tetra_Sencond_Ctl_Carrier(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1484 } else {
1485 proto_tree_add_time(tlv_tree, hf_thread_mc_tlv_pending_tstamp, tvb, offset, 8, ×tamp);
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:
dissect_tetra_MS_TXPWR_MAX_CELL(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_RXLEV_ACCESS_MIN(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }
dissect_tetra_ACCESS_PARAMETER(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 {
dissect_tetra_RADIO_DOWNLINK_TIMEOUT(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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;
dissect_tetra_INTEGER_0_65535(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 {
dissect_tetra_T_hyperframe_or_cck(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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;
dissect_tetra_FRAME(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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;
dissect_tetra_TS_COMMON_FRAMES(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }
dissect_tetra_IMM(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
dissect_tetra_WT(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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;
dissect_tetra_NU(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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) {
dissect_tetra_Frame_Len_Factor(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_Timeslot_Pointer(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_Min_Pdu_Priority(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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;
dissect_tetra_Default_Code_A(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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_tetra_INTEGER_0_255(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _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
2100 dissect_thread_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2101 {
dissect_tetra_INTEGER_0_16777215(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
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
dissect_tetra_Address(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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. */
dissect_tetra_NULL(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_UPDATE_TYPE(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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);
dissect_tetra_BOOLEAN(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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++;
dissect_tetra_T_cipher_control(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }
dissect_tetra_T_class_of_MS(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2211
2212 static gboolean
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
2232 proto_register_thread_address(void)
dissect_tetra_T_energy_saving_mode_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
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,
dissect_tetra_T_group_identity_uplink(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 },
dissect_tetra_T_proprietary_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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[] = {
dissect_tetra_T_type3_elements_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
dissect_tetra_T_type3_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2467 thread_dg_handle = register_dissector("thread_diagnostic", dissect_thread_dg, proto_thread_dg);
2468 }
2469
2470 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",
dissect_tetra_T_type2_parameters_04(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
dissect_tetra_T_optional_elements_06(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_U_LOCATION_UPDATE_DEMAND(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_scanning_on_off(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_U_MM_STATUS(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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",
dissect_tetra_INTEGER_0_2047(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
dissect_tetra_T_attach_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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",
dissect_tetra_T_detach_uplike(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
dissect_tetra_T_detach_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_attach_detach_identifier_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_gssi_extension_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_address_type_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_GROUP_IDENTITY_UPLINK(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_type3_elements_02(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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",
dissect_tetra_T_type3_02(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_type2_element(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }
dissect_tetra_T_optional_elements_07(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 },
dissect_tetra_U_ATTACH_DETACH_GROUP_IDENTITY(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_type3_elements_03(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_type3_03(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
dissect_tetra_T_type2_element_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_optional_elements_08(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }
dissect_tetra_U_ATTACH_DETACH_GROUP_IDENTITY_ACK(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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",
dissect_tetra_U_MM_PDU(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_T_simplex_duplex_selection(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
dissect_tetra_CIRCUIT(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
3289 void proto_register_thread_bcn(void)
3290 {
3291 static hf_register_info hf[] = {
3292
dissect_tetra_U_CONNECT(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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,
dissect_tetra_INTEGER_0_31(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 }},
dissect_tetra_T_prop_05(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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 };
dissect_tetra_T_type2_parameters_10(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
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
3362 proto_register_thread(void)
3363 {
dissect_tetra_T_optional_elements_14(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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",
dissect_tetra_U_DISCONNECT(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
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
3398 proto_reg_handoff_thread_mc(void)
3399 {
dissect_tetra_U_INFO(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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
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
3414 proto_reg_handoff_thread_dg(void)
dissect_tetra_U_RELEASE(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)3415 {
3416 dissector_add_string("thread.coap_namespace", "d", thread_dg_handle);
3417 }
3418
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
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 /*
dissect_tetra_T_simple_duplex_selection(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)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