Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-thread.c
blob430d501f778a0554b95ff61ded2f0f8f98e76c09
1 /* packet-thread.c
2 * Routines for Thread over CoAP and beacon packet dissection
4 * Robert Cragie <robert.cragie@arm.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
14 #include <stdlib.h>
15 #include <math.h>
16 #include <epan/packet.h>
17 #include <epan/proto_data.h>
18 #include <epan/wmem_scopes.h>
19 #include <epan/expert.h>
20 #include <epan/prefs.h>
21 #include <epan/strutil.h>
22 #include <epan/to_str.h>
23 #include <epan/tfs.h>
24 #include <wsutil/array.h>
25 #include "packet-coap.h"
26 #include "packet-ieee802154.h"
27 #include "packet-mle.h"
29 /* Use libgcrypt for cipher libraries. */
30 #include <wsutil/wsgcrypt.h>
32 /* Thread Vendor Sub IE Fields */
33 #define THREAD_IE_ID_MASK 0xFFC0
34 #define THREAD_IE_LENGTH_MASK 0x003F
36 /* Forward declarations */
37 void proto_register_thread_coap(void);
39 void proto_register_thread_address(void);
40 void proto_reg_handoff_thread_address(void);
42 void proto_register_thread_dg(void);
43 void proto_reg_handoff_thread_dg(void);
45 void proto_register_thread_mc(void);
46 void proto_reg_handoff_thread_mc(void);
48 void proto_register_thread_nwd(void);
50 void proto_register_thread_bcn(void);
51 void proto_reg_handoff_thread_bcn(void);
53 void proto_register_thread(void);
54 void proto_reg_handoff_thread(void);
56 void proto_register_thread_nm(void);
57 void proto_reg_handoff_thread_nm(void);
59 void proto_register_thread_bl(void);
60 void proto_reg_handoff_thread_bl(void);
62 static int proto_thread_address;
63 static int proto_thread_dg;
64 static int proto_thread_mc;
65 static int proto_thread_nwd;
66 static int proto_thread_coap;
67 static int proto_thread_bcn;
68 static int proto_thread_nm;
69 static int proto_thread_bl;
70 static int proto_thread;
71 static int proto_thread_ie;
72 static int proto_coap;
74 /* Header fields */
76 /* Thread address */
78 static int hf_thread_address_tlv;
79 static int hf_thread_address_tlv_type;
80 static int hf_thread_address_tlv_length;
81 static int hf_thread_address_tlv_unknown;
82 /* static int hf_thread_address_tlv_sub_tlvs; */
84 /* Target EID TLV fields */
85 static int hf_thread_address_tlv_target_eid;
87 /* Ext. MAC address TLV fields */
88 static int hf_thread_address_tlv_ext_mac_addr;
90 /* RLOC16 TLV fields */
91 static int hf_thread_address_tlv_rloc16;
93 /* Mesh Local IID TLV fields */
94 static int hf_thread_address_tlv_ml_eid;
96 /* Status TLV fields */
97 static int hf_thread_address_tlv_status;
99 /* Attached time TLV fields */
100 /* static int hf_thread_address_tlv_attached_time; */
102 /* Last transaction time TLV fields */
103 static int hf_thread_address_tlv_last_transaction_time;
105 /* Router Mask TLV fields */
106 static int hf_thread_address_tlv_router_mask_id_seq;
107 static int hf_thread_address_tlv_router_mask_assigned;
109 /* ND option fields */
110 static int hf_thread_address_tlv_nd_option;
112 /* ND data fields */
113 static int hf_thread_address_tlv_nd_data;
114 static int hf_thread_address_tlv_timeout;
116 /* Thread diagnostics */
118 static int hf_thread_dg_tlv;
119 static int hf_thread_dg_tlv_type;
120 static int hf_thread_dg_tlv_length8;
121 static int hf_thread_dg_tlv_length16;
122 static int hf_thread_dg_tlv_general;
123 static int hf_thread_dg_tlv_unknown;
125 #if 0
126 /**** TBC: will be added later. For now, just use general string ****/
127 static int hf_thread_dg_tlv_source_addr;
128 static int hf_thread_dg_tlv_mode_device_type;
129 static int hf_thread_dg_tlv_mode_idle_rx;
130 static int hf_thread_dg_tlv_mode_sec_data_req;
131 static int hf_thread_dg_tlv_mode_nwk_data;
132 static int hf_thread_dg_tlv_timeout;
133 static int hf_thread_dg_tlv_lqi_c;
134 static int hf_thread_dg_tlv_lqi_size;
135 static int hf_thread_dg_tlv_neighbor;
136 static int hf_thread_dg_tlv_neighbor_flagI;
137 static int hf_thread_dg_tlv_neighbor_flagO;
138 static int hf_thread_dg_tlv_neighbor_flagP;
139 static int hf_thread_dg_tlv_neighbor_idr;
140 static int hf_thread_dg_tlv_neighbor_addr;
141 static int hf_thread_dg_tlv_network_param_id;
142 static int hf_thread_dg_tlv_network_delay;
143 static int hf_thread_dg_tlv_network_channel;
144 static int hf_thread_dg_tlv_network_pan_id;
145 static int hf_thread_dg_tlv_network_pmt_join;
146 static int hf_thread_dg_tlv_network_bcn_payload;
147 static int hf_thread_dg_tlv_network_unknown;
148 static int hf_thread_dg_tlv_mle_frm_cntr;
149 static int hf_thread_dg_tlv_route_tbl_id_seq;
150 static int hf_thread_dg_tlv_route_tbl_id_mask;
151 static int hf_thread_dg_tlv_route_tbl_entry;
152 static int hf_thread_dg_tlv_route_tbl_nbr_out;
153 static int hf_thread_dg_tlv_route_tbl_nbr_in;
154 static int hf_thread_dg_tlv_route_tbl_cost;
155 static int hf_thread_dg_tlv_route_tbl_unknown;
156 static int hf_thread_dg_tlv_addr_16;
157 static int hf_thread_dg_tlv_leader_data_partition_id;
158 static int hf_thread_dg_tlv_leader_data_weighting;
159 static int hf_thread_dg_tlv_leader_data_version;
160 static int hf_thread_dg_tlv_leader_data_stable_version;
161 static int hf_thread_dg_tlv_leader_data_router_id;
162 static int hf_thread_dg_tlv_network_data;
163 static int hf_thread_dg_tlv_scan_mask_r;
164 static int hf_thread_dg_tlv_scan_mask_e;
165 static int hf_thread_dg_tlv_conn_max_child_cnt;
166 static int hf_thread_dg_tlv_conn_child_cnt;
167 static int hf_thread_dg_tlv_conn_lq3;
168 static int hf_thread_dg_tlv_conn_lq2;
169 static int hf_thread_dg_tlv_conn_lq1;
170 static int hf_thread_dg_tlv_conn_leader_cost;
171 static int hf_thread_dg_tlv_conn_id_seq;
172 static int hf_thread_dg_tlv_link_margin;
173 static int hf_thread_dg_tlv_status;
174 static int hf_thread_dg_tlv_version;
175 static int hf_thread_dg_tlv_addr_reg_entry;
176 static int hf_thread_dg_tlv_addr_reg_iid_type;
177 static int hf_thread_dg_tlv_addr_reg_cid;
178 static int hf_thread_dg_tlv_addr_reg_iid;
179 static int hf_thread_dg_tlv_addr_reg_ipv6;
180 static int hf_thread_dg_tlv_hold_time;
181 #endif
183 /* Thread MeshCoP */
185 static int hf_thread_mc_tlv;
186 static int hf_thread_mc_tlv_type;
187 static int hf_thread_mc_tlv_length8;
188 static int hf_thread_mc_tlv_length16;
189 static int hf_thread_mc_tlv_unknown;
190 /* static int hf_thread_mc_tlv_sub_tlvs; */
192 /* Channel TLV fields */
193 static int hf_thread_mc_tlv_channel_page;
194 static int hf_thread_mc_tlv_channel;
196 /* PAN ID TLV fields */
197 static int hf_thread_mc_tlv_pan_id;
199 /* Extended PAN ID TLV fields */
200 static int hf_thread_mc_tlv_xpan_id;
202 /* Network Name TLV fields */
203 static int hf_thread_mc_tlv_net_name;
205 /* PSKc TLV fields */
206 static int hf_thread_mc_tlv_pskc;
208 /* Master Key TLV fields */
209 static int hf_thread_mc_tlv_master_key;
211 /* Network Key Sequence TLV fields */
212 static int hf_thread_mc_tlv_net_key_seq_ctr;
214 /* Mesh Local ULA TLV fields */
215 static int hf_thread_mc_tlv_ml_prefix;
217 /* Steering Data TLV fields */
218 static int hf_thread_mc_tlv_steering_data;
220 /* Border Agent Locator TLV fields */
221 static int hf_thread_mc_tlv_ba_locator;
223 /* Commissioner ID TLV fields */
224 static int hf_thread_mc_tlv_commissioner_id;
226 /* Commissioner ID TLV fields */
227 static int hf_thread_mc_tlv_commissioner_sess_id;
229 /* Security Policy TLV fields */
230 static int hf_thread_mc_tlv_sec_policy_rot;
231 static int hf_thread_mc_tlv_sec_policy_o;
232 static int hf_thread_mc_tlv_sec_policy_n;
233 static int hf_thread_mc_tlv_sec_policy_r;
234 static int hf_thread_mc_tlv_sec_policy_c;
235 static int hf_thread_mc_tlv_sec_policy_b;
236 static int hf_thread_mc_tlv_sec_policy_ccm;
237 static int hf_thread_mc_tlv_sec_policy_ae;
238 static int hf_thread_mc_tlv_sec_policy_nmp;
239 static int hf_thread_mc_tlv_sec_policy_l;
240 static int hf_thread_mc_tlv_sec_policy_ncr;
241 static int hf_thread_mc_tlv_sec_policy_rsv;
242 static int hf_thread_mc_tlv_sec_policy_rsv1;
243 static int hf_thread_mc_tlv_sec_policy_vr;
246 /* State TLV fields */
247 static int hf_thread_mc_tlv_state;
249 /* Timestamp TLV fields */
250 static int hf_thread_mc_tlv_active_tstamp;
251 static int hf_thread_mc_tlv_pending_tstamp;
253 /* Delay Timer TLV fields */
254 static int hf_thread_mc_tlv_delay_timer;
256 /* UDP Encapsulation TLV fields */
257 static int hf_thread_mc_tlv_udp_encap_src_port;
258 static int hf_thread_mc_tlv_udp_encap_dst_port;
260 /* IPv6 Address fields */
261 static int hf_thread_mc_tlv_ipv6_addr;
263 /* UDP Port TLV fields */
264 static int hf_thread_mc_tlv_udp_port;
266 /* IID TLV fields */
267 static int hf_thread_mc_tlv_iid;
269 /* Joiner Router locator TLV fields */
270 static int hf_thread_mc_tlv_jr_locator;
272 /* KEK TLV fields */
273 static int hf_thread_mc_tlv_kek;
275 /* Provisioning URL TLV fields */
276 static int hf_thread_mc_tlv_provisioning_url;
278 /* Vendor TLV fields */
279 static int hf_thread_mc_tlv_vendor_name;
280 static int hf_thread_mc_tlv_vendor_model;
281 static int hf_thread_mc_tlv_vendor_sw_ver;
282 static int hf_thread_mc_tlv_vendor_data;
283 static int hf_thread_mc_tlv_vendor_stack_ver_oui;
284 static int hf_thread_mc_tlv_vendor_stack_ver_build;
285 static int hf_thread_mc_tlv_vendor_stack_ver_rev;
286 static int hf_thread_mc_tlv_vendor_stack_ver_min;
287 static int hf_thread_mc_tlv_vendor_stack_ver_maj;
289 /* Channel Mask TLV fields */
290 static int hf_thread_mc_tlv_chan_mask;
291 static int hf_thread_mc_tlv_chan_mask_page;
292 static int hf_thread_mc_tlv_chan_mask_len;
293 static int hf_thread_mc_tlv_chan_mask_mask;
295 /* Count TLV fields */
296 static int hf_thread_mc_tlv_count;
298 /* Period TLV fields */
299 static int hf_thread_mc_tlv_period;
301 /* Period TLV fields */
302 static int hf_thread_mc_tlv_scan_duration;
304 /* Energy List TLV fields */
305 static int hf_thread_mc_tlv_energy_list;
306 static int hf_thread_mc_tlv_el_count;
308 /* Domain Name TLV fields */
309 static int hf_thread_mc_tlv_domain_name;
311 /* AE Steering Data TLV fields */
312 static int hf_thread_mc_tlv_ae_steering_data;
314 /* NMKP Steering Data TLV fields */
315 static int hf_thread_mc_tlv_nmkp_steering_data;
317 /* Commissioner Signature TLV fields */
318 static int hf_thread_mc_tlv_commissioner_signature;
320 /* AE UDP Port TLV fields */
321 static int hf_thread_mc_tlv_ae_udp_port;
323 /* NMKP UDP Port TLV fields */
324 static int hf_thread_mc_tlv_nmkp_udp_port;
326 /* Registrar IPv6 Address fields */
327 static int hf_thread_mc_tlv_registrar_ipv6_addr;
329 /* Registrar Hostname fields */
330 static int hf_thread_mc_tlv_registrar_hostname;
332 /* Discovery Request TLV fields */
333 static int hf_thread_mc_tlv_discovery_req_ver;
334 static int hf_thread_mc_tlv_discovery_req_j;
336 /* Discovery Response TLV fields */
337 static int hf_thread_mc_tlv_discovery_rsp_ver;
338 static int hf_thread_mc_tlv_discovery_rsp_n;
339 static int hf_thread_mc_tlv_discovery_rsp_c;
341 /* Thread Network Data */
343 static int hf_thread_nwd_tlv;
344 static int hf_thread_nwd_tlv_type;
345 static int hf_thread_nwd_tlv_stable;
346 static int hf_thread_nwd_tlv_length;
347 static int hf_thread_nwd_tlv_unknown;
348 static int hf_thread_nwd_tlv_sub_tlvs;
350 /* Has Route TLV fields */
351 static int hf_thread_nwd_tlv_has_route;
352 static int hf_thread_nwd_tlv_has_route_br_16;
353 static int hf_thread_nwd_tlv_has_route_pref;
354 static int hf_thread_nwd_tlv_has_route_np;
355 static int hf_thread_nwd_tlv_has_route_reserved;
358 /* Prefix TLV fields */
359 static int hf_thread_nwd_tlv_prefix;
360 static int hf_thread_nwd_tlv_prefix_domain_id;
361 static int hf_thread_nwd_tlv_prefix_length;
363 /* Border Router TLV fields */
364 static int hf_thread_nwd_tlv_border_router;
365 static int hf_thread_nwd_tlv_border_router_16;
366 static int hf_thread_nwd_tlv_border_router_pref;
367 static int hf_thread_nwd_tlv_border_router_p;
368 static int hf_thread_nwd_tlv_border_router_s;
369 static int hf_thread_nwd_tlv_border_router_d;
370 static int hf_thread_nwd_tlv_border_router_c;
371 static int hf_thread_nwd_tlv_border_router_r;
372 static int hf_thread_nwd_tlv_border_router_o;
373 static int hf_thread_nwd_tlv_border_router_n;
374 static int hf_thread_nwd_tlv_border_router_dp;
376 /* 6LoWPAN ID TLV fields */
377 static int hf_thread_nwd_tlv_6lowpan_id_6co_context_length;
378 static int hf_thread_nwd_tlv_6lowpan_id_6co_flag;
379 static int hf_thread_nwd_tlv_6lowpan_id_6co_flag_c;
380 static int hf_thread_nwd_tlv_6lowpan_id_6co_flag_cid;
381 static int hf_thread_nwd_tlv_6lowpan_id_6co_flag_reserved;
383 /* Commissioning Data fields */
384 /* static int hf_thread_nwd_tlv_comm_data; */
386 /* Service fields */
387 static int hf_thread_nwd_tlv_service_t;
388 static int hf_thread_nwd_tlv_service_s_id;
389 static int hf_thread_nwd_tlv_service_s_ent_num;
390 static int hf_thread_nwd_tlv_service_s_data_len;
391 static int hf_thread_nwd_tlv_service_s_data;
392 static int hf_thread_nwd_tlv_service_s_data_seqno;
393 static int hf_thread_nwd_tlv_service_s_data_rrdelay;
394 static int hf_thread_nwd_tlv_service_s_data_mlrtimeout;
396 // Thread 1.3 Service TLV code
397 static int hf_thread_nwd_tlv_service_srp_dataset_identifier;
398 static int hf_thread_nwd_tlv_service_anycast_seqno;
399 static int hf_thread_nwd_tlv_service_unicast_ipv6_address;
400 static int hf_thread_nwd_tlv_service_unicast_port_number;
402 /* Server fields */
403 static int hf_thread_nwd_tlv_server_16;
404 static int hf_thread_nwd_tlv_server_data;
406 /* Thread Beacon */
408 static int hf_thread_bcn_protocol;
409 static int hf_thread_bcn_joining;
410 static int hf_thread_bcn_native;
411 static int hf_thread_bcn_version;
412 static int hf_thread_bcn_network_id;
413 static int hf_thread_bcn_epid;
414 static int hf_thread_bcn_tlv;
415 static int hf_thread_bcn_tlv_type;
416 static int hf_thread_bcn_tlv_length;
417 static int hf_thread_bcn_tlv_steering_data;
418 static int hf_thread_bcn_tlv_unknown;
420 /* Tree types */
422 static int ett_thread_address;
423 static int ett_thread_address_tlv;
424 static int ett_thread_dg;
425 static int ett_thread_dg_tlv;
426 static int ett_thread_mc;
427 static int ett_thread_mc_tlv;
428 static int ett_thread_mc_chan_mask;
429 static int ett_thread_mc_el_count;
430 static int ett_thread_nwd;
431 static int ett_thread_nwd_tlv;
432 static int ett_thread_nwd_has_route;
433 static int ett_thread_nwd_6co_flag;
434 static int ett_thread_nwd_border_router;
435 static int ett_thread_nwd_prefix_sub_tlvs;
436 static int ett_thread_bcn;
437 static int ett_thread_bcn_tlv;
438 static int ett_thread_nm;
439 static int ett_thread_nm_tlv;
440 static int ett_thread_bl;
441 static int ett_thread_bl_tlv;
443 static int ett_thread;
444 /* static int ett_thread_header_ie; */
445 static int ett_thread_ie_fields;
449 /* Expert info. */
451 /* static expert_field ei_thread_address_tlv_length_failed; */
452 static expert_field ei_thread_address_len_size_mismatch;
453 /* static expert_field ei_thread_dg_tlv_length_failed; */
454 /* static expert_field ei_thread_dg_len_size_mismatch; */
455 static expert_field ei_thread_mc_tlv_length_failed;
456 static expert_field ei_thread_mc_len_size_mismatch;
457 static expert_field ei_thread_mc_len_too_long;
458 /* static expert_field ei_thread_nwd_tlv_length_failed; */
459 static expert_field ei_thread_nwd_len_size_mismatch;
460 static expert_field ei_thread_nm_len_size_mismatch;
461 static expert_field ei_thread_bl_len_size_mismatch;
464 static dissector_table_t thread_coap_namespace;
466 /* Dissector handles */
467 static dissector_handle_t thread_address_nwd_handle;
468 static dissector_handle_t thread_dg_handle;
469 static dissector_handle_t thread_mc_handle;
470 static dissector_handle_t thread_dtls_handle;
471 static dissector_handle_t thread_udp_handle;
472 static dissector_handle_t thread_coap_handle;
473 static dissector_handle_t thread_address_handle;
474 static dissector_handle_t thread_nm_handle;
475 static dissector_handle_t thread_bl_handle;
477 /* 802.15.4 Thread ID */
478 static int hf_ieee802154_thread_ie;
479 static int hf_ieee802154_thread_ie_id;
480 static int hf_ieee802154_thread_ie_length;
482 #define THREAD_SERVICE_DATA_BBR 0x1
484 #define THREAD_TLV_LENGTH_ESC 0xFF
486 #define THREAD_URI_NAMESPACE_IDX 1
488 #define THREAD_MC_32768_TO_NSEC_FACTOR ((double)30517.578125)
489 #define THREAD_MC_TSTAMP_MASK_U_MASK 0x80
490 #define THREAD_MC_SEC_POLICY_MASK_O_MASK 0x80
491 #define THREAD_MC_SEC_POLICY_MASK_N_MASK 0x40
492 #define THREAD_MC_SEC_POLICY_MASK_R_MASK 0x20
493 #define THREAD_MC_SEC_POLICY_MASK_C_MASK 0x10
494 #define THREAD_MC_SEC_POLICY_MASK_B_MASK 0x08
495 #define THREAD_MC_SEC_POLICY_MASK_CCM_MASK 0x04
496 #define THREAD_MC_SEC_POLICY_MASK_AE_MASK 0x02
497 #define THREAD_MC_SEC_POLICY_MASK_NMP_MASK 0x01
498 #define THREAD_MC_SEC_POLICY_MASK_L_MASK 0x80
499 #define THREAD_MC_SEC_POLICY_MASK_NCR_MASK 0x40
500 #define THREAD_MC_SEC_POLICY_MASK_RSV_MASK 0x38
501 #define THREAD_MC_SEC_POLICY_MASK_RSV1_MASK 0x07
502 #define THREAD_MC_SEC_POLICY_MASK_VR_MASK 0x07
503 #define THREAD_MC_STACK_VER_REV_MASK 0x0F
504 #define THREAD_MC_STACK_VER_MIN_MASK 0xF0
505 #define THREAD_MC_STACK_VER_MAJ_MASK 0x0F
506 #define THREAD_MC_DISCOVERY_REQ_MASK_VER_MASK 0xF0
507 #define THREAD_MC_DISCOVERY_REQ_MASK_J_MASK 0x08
508 #define THREAD_MC_DISCOVERY_RSP_MASK_VER_MASK 0xF0
509 #define THREAD_MC_DISCOVERY_RSP_MASK_N_MASK 0x08
510 #define THREAD_MC_DISCOVERY_RSP_MASK_C_MASK 0x04
511 #define THREAD_MC_INVALID_CHAN_COUNT 0xFFFF
513 #define THREAD_NWD_TLV_HAS_ROUTE_PREF 0xC0
514 #define THREAD_NWD_TLV_HAS_ROUTE_NP 0x20
515 #define THREAD_NWD_TLV_HAS_ROUTE_RESERVED 0x1F
516 #define THREAD_NWD_TLV_HAS_ROUTE_SIZE 3
518 #define THREAD_NWD_TLV_BORDER_ROUTER_PREF 0xC0
519 #define THREAD_NWD_TLV_HAS_ROUTE_NP 0x20
520 #define THREAD_NWD_TLV_HAS_ROUTE_RESERVED 0x1F
521 #define THREAD_NWD_TLV_BORDER_ROUTER_P 0x20
522 #define THREAD_NWD_TLV_BORDER_ROUTER_S 0x10
523 #define THREAD_NWD_TLV_BORDER_ROUTER_D 0x08
524 #define THREAD_NWD_TLV_BORDER_ROUTER_C 0x04
525 #define THREAD_NWD_TLV_BORDER_ROUTER_R 0x02
526 #define THREAD_NWD_TLV_BORDER_ROUTER_O 0x01
527 #define THREAD_NWD_TLV_BORDER_ROUTER_N 0x80
528 #define THREAD_NWD_TLV_BORDER_ROUTER_DP 0x40 //Thread 1.2 Draft5
530 #define THREAD_BCN_PROTOCOL_ID 0x03
531 #define THREAD_BCN_JOINING 0x01
532 #define THREAD_BCN_NATIVE 0x08
533 #define THREAD_BCN_PROTOCOL_VERSION 0xf0
534 #define THREAD_BCN_TLV_STEERING_DATA_S 0x80
535 #define THREAD_BCN_TLV_STEERING_DATA 8
537 #define ND_OPT_6CO_FLAG_C 0x10
538 #define ND_OPT_6CO_FLAG_CID 0x0F
539 #define ND_OPT_6CO_FLAG_RESERVED 0xE0
541 #define THREAD_NWD_TLV_SERVICE_T 0x80
542 #define THREAD_NWD_TLV_SERVICE_S_ID 0x0F
544 typedef enum {
545 TLV_LEN_LEN8 = 1,
546 TLV_LEN_LEN16 = 3
547 } tlv_len_len_e;
549 typedef struct {
550 uint16_t src_port;
551 uint16_t dst_port;
552 uint16_t length;
553 uint16_t checksum;
554 } udp_hdr_t;
556 /* TLV values */
558 #define THREAD_ADDRESS_TLV_TARGET_EID 0
559 #define THREAD_ADDRESS_TLV_EXT_MAC_ADDR 1
560 #define THREAD_ADDRESS_TLV_RLOC16 2
561 #define THREAD_ADDRESS_TLV_ML_EID 3
562 #define THREAD_ADDRESS_TLV_STATUS 4
563 /* Gap */
564 #define THREAD_ADDRESS_TLV_LAST_TRANSACTION_TIME 6
565 #define THREAD_ADDRESS_TLV_ROUTER_MASK 7
566 #define THREAD_ADDRESS_TLV_ND_OPTION 8
567 #define THREAD_ADDRESS_TLV_ND_DATA 9
568 #define THREAD_ADDRESS_TLV_THREAD_NETWORK_DATA 10
569 #define THREAD_ADDRESS_TLV_TIMEOUT 11
570 #define THREAD_ADDRESS_TLV_THREAD_NETWORK_NAME 12
571 #define THREAD_ADDRESS_TLV_IPV6_ADDRESS 14
573 static const value_string thread_address_tlv_vals[] = {
574 { THREAD_ADDRESS_TLV_TARGET_EID, "Target EID" },
575 { THREAD_ADDRESS_TLV_EXT_MAC_ADDR, "Extended MAC Address" },
576 { THREAD_ADDRESS_TLV_RLOC16, "RLOC16" },
577 { THREAD_ADDRESS_TLV_ML_EID, "ML-EID" },
578 { THREAD_ADDRESS_TLV_STATUS, "Status" },
579 /* Gap */
580 { THREAD_ADDRESS_TLV_LAST_TRANSACTION_TIME, "Last Transaction Time" },
581 { THREAD_ADDRESS_TLV_ROUTER_MASK, "Router Mask" },
582 { THREAD_ADDRESS_TLV_ND_OPTION, "ND Option" },
583 { THREAD_ADDRESS_TLV_ND_DATA, "ND Data" },
584 { THREAD_ADDRESS_TLV_THREAD_NETWORK_DATA, "Thread Network Data" },
585 { THREAD_ADDRESS_TLV_TIMEOUT, "Timeout"},
586 { THREAD_ADDRESS_TLV_THREAD_NETWORK_NAME, "Thread Network Name" },
587 { THREAD_ADDRESS_TLV_IPV6_ADDRESS, "IPv6 Address"},
588 { 0, NULL }
591 static const value_string thread_address_tlv_status_vals[] = {
592 { 0, "Success" },
593 { 1, "No Address Available" },
594 { 2, "TOO_FEW_ROUTERS" },
595 { 3, "HAVE_CHILD_ID_REQUEST" },
596 { 4, "PARENT_PARTITION_CHANGE" },
597 { 0, NULL }
600 /* Network Layer (Address) mirrors */
601 #define THREAD_DG_TLV_EXT_MAC_ADDR 0 /* As THREAD_ADDRESS_TLV_EXT_MAC_ADDR */
602 /* MLE mirrors */
603 #define THREAD_DG_TLV_ADDRESS16 1 /* As MLE_TLV_ADDRESS16 */
604 #define THREAD_DG_TLV_MODE 2 /* As MLE_TLV_MODE */
605 #define THREAD_DG_TLV_TIMEOUT 3 /* As MLE_TLV_TIMEOUT */
606 #define THREAD_DG_TLV_CONNECTIVITY 4 /* As MLE_TLV_CONNECTIVITY */
607 #define THREAD_DG_TLV_ROUTE64 5 /* As MLE_TLV_ROUTE64 */
608 #define THREAD_DG_TLV_LEADER_DATA 6 /* As MLE_TLV_LEADER_DATA */
609 #define THREAD_DG_TLV_NETWORK_DATA 7 /* As MLE_TLV_NETWORK_DATA */
610 /* Statistics */
611 #define THREAD_DG_TLV_IPV6_ADDR_LIST 8
612 #define THREAD_DG_TLV_MAC_COUNTERS 9
613 /* Others */
614 #define THREAD_DG_TLV_BATTERY_LEVEL 14
615 #define THREAD_DG_TLV_VOLTAGE 15
616 #define THREAD_DG_TLV_CHILD_TABLE 16
617 #define THREAD_DG_TLV_CHANNEL_PAGES 17
618 #define THREAD_DG_TLV_TYPE_LIST 18
619 #define THREAD_DG_TLV_MAX_CHILD_TIMEOUT 19
620 #define THREAD_DG_TLV_LDEVID_SUBJECT_PUBLIC_KEY_INFO 20
621 #define THREAD_DG_TLV_IDEVID_CERTIFICATE 21
622 /* Reserved 22*/
623 #define THREAD_DG_TLV_EUI_64 23
624 #define THREAD_DG_TLV_VERSION 24
625 #define THREAD_DG_TLV_VENDOR_NAME 25
626 #define THREAD_DG_TLV_VENDOR_MODEL 26
627 #define THREAD_DG_TLV_VENDOR_SW_VERSION 27
628 #define THREAD_DG_TLV_THREAD_STACK_VERSION 28
629 #define THREAD_DG_TLV_CHILD 29
630 #define THREAD_DG_TLV_CHILD_IPV6_ADDRESS_LIST 30
631 #define THREAD_DG_TLV_ROUTER_NEIGHBOR 31
632 #define THREAD_DG_TLV_ANSWER 32
633 #define THREAD_DG_TLV_QUERY_ID 33
634 #define THREAD_DG_TLV_MLE_COUNTERS 34
635 #define THREAD_DG_TLV_UNKNOWN 255
637 static const value_string thread_dg_tlv_vals[] = {
638 /* Network Layer (Address) mirrors */
639 { THREAD_DG_TLV_EXT_MAC_ADDR, "Extended MAC Address" },
640 /* MLE mirrors */
641 { THREAD_DG_TLV_ADDRESS16, "Address16" },
642 { THREAD_DG_TLV_MODE, "Mode" },
643 { THREAD_DG_TLV_TIMEOUT, "Timeout" },
644 { THREAD_DG_TLV_CONNECTIVITY, "Connectivity" },
645 { THREAD_DG_TLV_ROUTE64, "Route64" },
646 { THREAD_DG_TLV_LEADER_DATA, "Leader Data" },
647 { THREAD_DG_TLV_NETWORK_DATA, "Network Data" },
648 /* Statistics */
649 { THREAD_DG_TLV_IPV6_ADDR_LIST, "IPv6 Address List" },
650 { THREAD_DG_TLV_MAC_COUNTERS, "MAC Counters" },
651 /* Others */
652 { THREAD_DG_TLV_BATTERY_LEVEL, "Battery level (%)" },
653 { THREAD_DG_TLV_VOLTAGE, "Voltage (mV)" },
654 { THREAD_DG_TLV_CHILD_TABLE, "Child Table" },
655 { THREAD_DG_TLV_CHANNEL_PAGES, "Channel Pages" },
656 { THREAD_DG_TLV_TYPE_LIST, "Type List" },
657 { THREAD_DG_TLV_MAX_CHILD_TIMEOUT, "Max Child Timeout"},
658 { THREAD_DG_TLV_LDEVID_SUBJECT_PUBLIC_KEY_INFO, "LDevID Subject Public Key Info"},
659 { THREAD_DG_TLV_IDEVID_CERTIFICATE, "IDevID Certificate"},
660 { THREAD_DG_TLV_EUI_64, "EUI-64"},
661 { THREAD_DG_TLV_VERSION, "Version"},
662 { THREAD_DG_TLV_VENDOR_NAME, "Vendor Name"},
663 { THREAD_DG_TLV_VENDOR_MODEL, "Vendor Model"},
664 { THREAD_DG_TLV_VENDOR_SW_VERSION, "Vendor SW Version"},
665 { THREAD_DG_TLV_THREAD_STACK_VERSION, "Thread Stack Version"},
666 { THREAD_DG_TLV_CHILD, "Child"},
667 { THREAD_DG_TLV_CHILD_IPV6_ADDRESS_LIST, "Child IPV6 Address List"},
668 { THREAD_DG_TLV_ROUTER_NEIGHBOR, "Router Neighbor"},
669 { THREAD_DG_TLV_ANSWER, "Answer"},
670 { THREAD_DG_TLV_QUERY_ID, "Query ID"},
671 { THREAD_DG_TLV_MLE_COUNTERS, "MLE Counters"},
672 { THREAD_DG_TLV_UNKNOWN, "Unknown" },
673 { 0, NULL }
676 #define THREAD_MC_TLV_CHANNEL 0 /* Modified for new features */
677 #define THREAD_MC_TLV_PANID 1
678 #define THREAD_MC_TLV_XPANID 2
679 #define THREAD_MC_TLV_NETWORK_NAME 3
680 #define THREAD_MC_TLV_PSKC 4
681 #define THREAD_MC_TLV_NETWORK_MASTER_KEY 5
682 #define THREAD_MC_TLV_NETWORK_KEY_SEQ_CTR 6
683 #define THREAD_MC_TLV_NETWORK_ML_PREFIX 7
684 #define THREAD_MC_TLV_STEERING_DATA 8
685 #define THREAD_MC_TLV_BORDER_AGENT_LOCATOR 9
686 #define THREAD_MC_TLV_COMMISSIONER_ID 10
687 #define THREAD_MC_TLV_COMMISSIONER_SESSION_ID 11
688 #define THREAD_MC_TLV_SECURITY_POLICY 12
689 #define THREAD_MC_TLV_GET 13
690 #define THREAD_MC_TLV_ACTIVE_TSTAMP 14 /* Was "Commissioning Dataset Timestamp TLV" */
691 #define THREAD_MC_TLV_COMMISSIONER_UDP_PORT 15
692 #define THREAD_MC_TLV_STATE 16
693 #define THREAD_MC_TLV_JOINER_DTLS_ENCAP 17
694 #define THREAD_MC_TLV_JOINER_UDP_PORT 18
695 #define THREAD_MC_TLV_JOINER_IID 19
696 #define THREAD_MC_TLV_JOINER_ROUTER_LOCATOR 20
697 #define THREAD_MC_TLV_JOINER_KEK 21
698 /* Gap */
699 #define THREAD_MC_TLV_PROVISIONING_URL 32
700 #define THREAD_MC_TLV_VENDOR_NAME 33
701 #define THREAD_MC_TLV_VENDOR_MODEL 34
702 #define THREAD_MC_TLV_VENDOR_SW_VERSION 35
703 #define THREAD_MC_TLV_VENDOR_DATA 36
704 #define THREAD_MC_TLV_VENDOR_STACK_VERSION 37
705 /* Gap */
706 #define THREAD_MC_TLV_UDP_ENCAPSULATION 48
707 #define THREAD_MC_TLV_IPV6_ADDRESS 49
708 /* Gap */
709 /* New features */
710 #define THREAD_MC_TLV_PENDING_TSTAMP 51
711 #define THREAD_MC_TLV_DELAY_TIMER 52
712 #define THREAD_MC_TLV_CHANNEL_MASK 53
713 #define THREAD_MC_TLV_COUNT 54
714 #define THREAD_MC_TLV_PERIOD 55
715 #define THREAD_MC_TLV_SCAN_DURATION 56
716 #define THREAD_MC_TLV_ENERGY_LIST 57
717 #define THREAD_MC_TLV_DOMAIN_NAME 59
718 #define THREAD_MC_TLV_DOMAIN_PREFIX 60
719 #define THREAD_MC_TLV_AE_STEERING_DATA 61
720 #define THREAD_MC_TLV_NMKP_STEERING_DATA 62
721 #define THREAD_MC_TLV_COMMISSIONER_TOKEN 63
722 #define THREAD_MC_TLV_COMMISSIONER_SIGNATURE 64
723 #define THREAD_MC_TLV_AE_UDP_PORT 65
724 #define THREAD_MC_TLV_NMKP_UDP_PORT 66
725 #define THREAD_MC_TLV_TRI_HOSTNAME 67
726 #define THREAD_MC_TLV_REGISTRAR_IPV6_ADDRESS 68
727 #define THREAD_MC_TLV_REGISTRAR_HOSTNAME 69
728 #define THREAD_MC_TLV_COMMISSIONER_PEN_SIGNATURE 70
729 #define THREAD_MC_TLV_COMMISSIONER_PEN_TOKEN 71
731 /* Gap */
732 /* New discovery mechanism */
733 #define THREAD_MC_TLV_DISCOVERY_REQUEST 128
734 #define THREAD_MC_TLV_DISCOVERY_RESPONSE 129
736 static const value_string thread_mc_tlv_vals[] = {
737 { THREAD_MC_TLV_CHANNEL, "Channel" },
738 { THREAD_MC_TLV_PANID, "PAN ID" },
739 { THREAD_MC_TLV_XPANID, "Extended PAN ID" },
740 { THREAD_MC_TLV_NETWORK_NAME, "Network Name" },
741 { THREAD_MC_TLV_PSKC, "PSKc" },
742 { THREAD_MC_TLV_NETWORK_MASTER_KEY, "Network Master Key" },
743 { THREAD_MC_TLV_NETWORK_KEY_SEQ_CTR, "Network Key Sequence Counter" },
744 { THREAD_MC_TLV_NETWORK_ML_PREFIX, "Mesh Local ULA Prefix" },
745 { THREAD_MC_TLV_STEERING_DATA, "Steering Data" },
746 { THREAD_MC_TLV_BORDER_AGENT_LOCATOR, "Border Agent Locator" },
747 { THREAD_MC_TLV_COMMISSIONER_ID, "Commissioner ID" },
748 { THREAD_MC_TLV_COMMISSIONER_SESSION_ID, "Commissioner Session ID" },
749 { THREAD_MC_TLV_SECURITY_POLICY, "Security Policy" },
750 { THREAD_MC_TLV_GET, "Get" },
751 { THREAD_MC_TLV_ACTIVE_TSTAMP, "Active Timestamp" },
752 { THREAD_MC_TLV_COMMISSIONER_UDP_PORT, "Commissioner UDP Port" },
753 { THREAD_MC_TLV_STATE, "State" },
754 { THREAD_MC_TLV_JOINER_DTLS_ENCAP, "Joiner DTLS Encapsulation" },
755 { THREAD_MC_TLV_JOINER_UDP_PORT, "Joiner UDP Port" },
756 { THREAD_MC_TLV_JOINER_IID, "Joiner IID" },
757 { THREAD_MC_TLV_JOINER_ROUTER_LOCATOR, "Joiner Router Locator" },
758 { THREAD_MC_TLV_JOINER_KEK, "Joiner KEK" },
759 { THREAD_MC_TLV_PROVISIONING_URL, "Provisioning URL" },
760 { THREAD_MC_TLV_VENDOR_NAME, "Vendor Name" },
761 { THREAD_MC_TLV_VENDOR_MODEL, "Vendor Model" },
762 { THREAD_MC_TLV_VENDOR_SW_VERSION, "Vendor Software Version" },
763 { THREAD_MC_TLV_VENDOR_DATA, "Vendor Data" },
764 { THREAD_MC_TLV_VENDOR_STACK_VERSION, "Vendor Stack Version" },
765 { THREAD_MC_TLV_UDP_ENCAPSULATION, "UDP Encapsulation" },
766 { THREAD_MC_TLV_IPV6_ADDRESS, "IPv6 Address" },
767 /* New features */
768 { THREAD_MC_TLV_PENDING_TSTAMP, "Pending Timestamp" },
769 { THREAD_MC_TLV_DELAY_TIMER, "Delay Timer" },
770 { THREAD_MC_TLV_CHANNEL_MASK, "Channel Mask" },
771 { THREAD_MC_TLV_COUNT, "Count" },
772 { THREAD_MC_TLV_PERIOD, "Period" },
773 { THREAD_MC_TLV_SCAN_DURATION, "Scan Duration" },
774 { THREAD_MC_TLV_ENERGY_LIST, "Energy List" },
775 { THREAD_MC_TLV_DOMAIN_NAME, "Domain Name" },
776 { THREAD_MC_TLV_DOMAIN_PREFIX, "Domain Prefix" },
777 { THREAD_MC_TLV_AE_STEERING_DATA, "AE Steering Data" },
778 { THREAD_MC_TLV_NMKP_STEERING_DATA, "NMKP Steering Data" },
779 { THREAD_MC_TLV_COMMISSIONER_TOKEN, "Commissioner Token" },
780 { THREAD_MC_TLV_COMMISSIONER_SIGNATURE, "Commissioner Signature" },
781 { THREAD_MC_TLV_AE_UDP_PORT, "AE UDP Port" },
782 { THREAD_MC_TLV_NMKP_UDP_PORT, "NMKP UDP Port" },
783 { THREAD_MC_TLV_TRI_HOSTNAME, "TRI Hostname" },
784 { THREAD_MC_TLV_REGISTRAR_IPV6_ADDRESS, "Registrar IPv6 Address" },
785 { THREAD_MC_TLV_REGISTRAR_HOSTNAME, "Registrar Hostname" },
786 { THREAD_MC_TLV_COMMISSIONER_PEN_SIGNATURE,"Commissioner PEN Signature" },
787 { THREAD_MC_TLV_COMMISSIONER_PEN_TOKEN, "Commissioner PEN Token" },
788 /* New discovery mechanism */
789 { THREAD_MC_TLV_DISCOVERY_REQUEST, "Discovery Request" },
790 { THREAD_MC_TLV_DISCOVERY_RESPONSE, "Discovery Response" },
791 { 0, NULL}
794 static const value_string thread_mc_state_vals[] = {
795 { -1, "Reject" },
796 { 0, "Pending" },
797 { 1, "Accept" },
798 { 0, NULL}
801 static const true_false_string thread_mc_tlv_join_intent = {
802 "Intending",
803 "Not Intending"
806 #define THREAD_NWD_TLV_HAS_ROUTE 0
807 #define THREAD_NWD_TLV_PREFIX 1
808 #define THREAD_NWD_TLV_BORDER_ROUTER 2
809 #define THREAD_NWD_TLV_6LOWPAN_ID 3
810 #define THREAD_NWD_TLV_COMMISSIONING_DATA 4
811 #define THREAD_NWD_TLV_SERVICE 5
812 #define THREAD_NWD_TLV_SERVER 6
814 static const value_string thread_nwd_tlv_vals[] = {
815 { THREAD_NWD_TLV_HAS_ROUTE, "Has Route" },
816 { THREAD_NWD_TLV_PREFIX, "Prefix" },
817 { THREAD_NWD_TLV_BORDER_ROUTER, "Border Router" },
818 { THREAD_NWD_TLV_6LOWPAN_ID, "6LoWPAN ID" },
819 { THREAD_NWD_TLV_COMMISSIONING_DATA, "Commissioning Data" },
820 { THREAD_NWD_TLV_SERVICE, "Service" },
821 { THREAD_NWD_TLV_SERVER, "Server" },
822 { 0, NULL}
825 #define THREAD_NWD_TLV_TYPE_M 0xFE
826 #define THREAD_NWD_TLV_STABLE_M 0x01
828 static const true_false_string tfs_thread_nwd_tlv_border_router_p = {
829 "Autoconfigured preferred",
830 "Autoconfigured deprecated"
833 static const true_false_string tfs_thread_nwd_tlv_border_router_c = {
834 "Additional config. data",
835 "No additional config. data"
838 static const true_false_string tfs_thread_nwd_tlv_border_router_o = {
839 "On mesh",
840 "Not on mesh"
843 /*Network Management TLVs*/
844 static int hf_thread_nm_tlv;
845 static int hf_thread_nm_tlv_type;
846 static int hf_thread_nm_tlv_length;
847 static int hf_thread_nm_tlv_unknown;
848 /* static int hf_thread_nm_tlv_sub_tlvs; */
850 /* Target EID TLV fields */
851 static int hf_thread_nm_tlv_target_eid;
853 /* Ext. MAC address TLV fields */
854 static int hf_thread_nm_tlv_ext_mac_addr;
856 /* RLOC16 TLV fields */
857 static int hf_thread_nm_tlv_rloc16;
859 /* Mesh Local IID TLV fields */
860 static int hf_thread_nm_tlv_ml_eid;
862 /* Status TLV fields */
863 static int hf_thread_nm_tlv_status;
865 /* Last transaction time TLV fields */
866 static int hf_thread_nm_tlv_last_transaction_time;
868 /* Router Mask TLV fields */
869 static int hf_thread_nm_tlv_router_mask_id_seq;
870 static int hf_thread_nm_tlv_router_mask_assigned;
872 /* ND option fields */
873 static int hf_thread_nm_tlv_nd_option;
875 /* ND data fields */
876 static int hf_thread_nm_tlv_nd_data;
878 static int hf_thread_nm_tlv_timeout;
880 /* TLV values */
882 #define THREAD_NM_TLV_TARGET_EID 0
883 #define THREAD_NM_TLV_EXT_MAC_ADDR 1
884 #define THREAD_NM_TLV_RLOC16 2
885 #define THREAD_NM_TLV_ML_EID 3
886 #define THREAD_NM_TLV_STATUS 4
887 /* Gap */
888 #define THREAD_NM_TLV_LAST_TRANSACTION_TIME 6
889 #define THREAD_NM_TLV_ROUTER_MASK 7
890 #define THREAD_NM_TLV_ND_OPTION 8
891 #define THREAD_NM_TLV_ND_DATA 9
892 #define THREAD_NM_TLV_THREAD_NETWORK_DATA 10
893 #define THREAD_NM_TLV_TIMEOUT 11
894 #define THREAD_NM_TLV_THREAD_NETWORK_NAME 12
895 #define THREAD_NM_TLV_IPV6_ADDRESS 14
896 #define THREAD_NM_TLV_COMMISSIONER_SESSION_ID 15
898 static const value_string thread_nm_tlv_vals[] = {
899 { THREAD_NM_TLV_TARGET_EID, "Target EID" },
900 { THREAD_NM_TLV_EXT_MAC_ADDR, "Extended MAC Address" },
901 { THREAD_NM_TLV_RLOC16, "RLOC16" },
902 { THREAD_NM_TLV_ML_EID, "ML-EID" },
903 { THREAD_NM_TLV_STATUS, "Status" },
904 /* Gap */
905 { THREAD_NM_TLV_LAST_TRANSACTION_TIME, "Last Transaction Time" },
906 { THREAD_NM_TLV_ROUTER_MASK, "Router Mask" },
907 { THREAD_NM_TLV_ND_OPTION, "ND Option" },
908 { THREAD_NM_TLV_ND_DATA, "ND Data" },
909 { THREAD_NM_TLV_THREAD_NETWORK_DATA, "Thread Network Data" },
910 { THREAD_NM_TLV_TIMEOUT, "Timeout"},
911 { THREAD_NM_TLV_THREAD_NETWORK_NAME, "Thread Network Name" },
912 { THREAD_NM_TLV_IPV6_ADDRESS, "IPv6 Address"},
913 { THREAD_NM_TLV_COMMISSIONER_SESSION_ID, "Commissioner Session ID"},
914 { 0, NULL }
918 static const value_string thread_nm_tlv_status_vals[] = {
919 { 0, "Successful registration" },
920 { 1, "Registration was accepted but immediate reregistration is required \
921 to resolve any potential conflicting state across Domain BBRs." },
922 { 2, "Registration rejected: Target EID is not a valid DUA" },
923 { 3, "Registration rejected: DUA is already in use by another Device" },
924 { 4, "Registration rejected: BBR resource shortage" },
925 { 5, "Registration rejected: BBR is not Primary at this moment" },
926 { 6, "Registration failure: Reason(s) not further specified" },
927 { 0, NULL }
930 /* Network Management TLVs end*/
932 /*Backbone Link TLVs*/
934 static int hf_thread_bl_tlv;
935 static int hf_thread_bl_tlv_type;
936 static int hf_thread_bl_tlv_length;
937 static int hf_thread_bl_tlv_unknown;
938 /* static int hf_thread_bl_tlv_sub_tlvs; */
940 /* Target EID TLV fields */
941 static int hf_thread_bl_tlv_target_eid;
943 /* Ext. MAC address TLV fields */
944 static int hf_thread_bl_tlv_ext_mac_addr;
946 /* RLOC16 TLV fields */
947 static int hf_thread_bl_tlv_rloc16;
949 /* Mesh Local IID TLV fields */
950 static int hf_thread_bl_tlv_ml_eid;
952 /* Status TLV fields */
953 static int hf_thread_bl_tlv_status;
955 /* Attached time TLV fields */
956 /* static int hf_thread_bl_tlv_attached_time; */
958 /* Last transaction time TLV fields */
959 static int hf_thread_bl_tlv_last_transaction_time;
961 /* Router Mask TLV fields */
962 static int hf_thread_bl_tlv_router_mask_id_seq;
963 static int hf_thread_bl_tlv_router_mask_assigned;
965 /* ND option fields */
966 static int hf_thread_bl_tlv_nd_option;
968 /* ND data fields */
969 static int hf_thread_bl_tlv_nd_data;
971 static int hf_thread_bl_tlv_timeout;
973 /* TLV values */
974 #define THREAD_BL_TLV_TARGET_EID 0
975 #define THREAD_BL_TLV_EXT_MAC_ADDR 1
976 #define THREAD_BL_TLV_RLOC16 2
977 #define THREAD_BL_TLV_ML_EID 3
978 #define THREAD_BL_TLV_STATUS 4
979 /* Gap */
980 #define THREAD_BL_TLV_LAST_TRANSACTION_TIME 6
981 #define THREAD_BL_TLV_ROUTER_MASK 7
982 #define THREAD_BL_TLV_ND_OPTION 8
983 #define THREAD_BL_TLV_ND_DATA 9
984 #define THREAD_BL_TLV_THREAD_NETWORK_DATA 10
985 #define THREAD_BL_TLV_TIMEOUT 11
986 #define THREAD_BL_TLV_THREAD_NETWORK_NAME 12
987 #define THREAD_BL_TLV_IPV6_ADDRESS 14
989 static const value_string thread_bl_tlv_vals[] = {
990 { THREAD_BL_TLV_TARGET_EID, "Target EID" },
991 { THREAD_BL_TLV_EXT_MAC_ADDR, "Extended MAC Address" },
992 { THREAD_BL_TLV_RLOC16, "RLOC16" },
993 { THREAD_BL_TLV_ML_EID, "ML-EID" },
994 { THREAD_BL_TLV_STATUS, "Status" },
995 /* Gap */
996 { THREAD_BL_TLV_LAST_TRANSACTION_TIME, "Last Transaction Time" },
997 { THREAD_BL_TLV_ROUTER_MASK, "Router Mask" },
998 { THREAD_BL_TLV_ND_OPTION, "ND Option" },
999 { THREAD_BL_TLV_ND_DATA, "ND Data" },
1000 { THREAD_BL_TLV_THREAD_NETWORK_DATA, "Thread Network Data" },
1001 { THREAD_BL_TLV_TIMEOUT, "Timeout"},
1002 { THREAD_BL_TLV_THREAD_NETWORK_NAME, "Thread Network Name" },
1003 { THREAD_BL_TLV_IPV6_ADDRESS, "IPv6 Address"},
1004 { 0, NULL }
1007 static const value_string thread_bl_tlv_status_vals[] = {
1008 { 0, "Success" },
1009 { 1, "No Address Available" },
1010 { 2, "TOO_FEW_ROUTERS" },
1011 { 3, "HAVE_CHILD_ID_REQUEST" },
1012 { 4, "PARENT_PARTITION_CHANGE" },
1013 { 0, NULL }
1015 /* Backbone Link TLVs end*/
1017 /* Thread Beacon TLV Values. */
1018 static const value_string thread_bcn_tlv_vals[] = {
1019 { THREAD_BCN_TLV_STEERING_DATA, "Steering Data" },
1020 { 0, NULL }
1023 static int
1024 dissect_thread_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
1026 /* Preferences */
1027 static bool thread_use_pan_id_in_key;
1028 static const char *thread_seq_ctr_str;
1029 static bool thread_auto_acq_seq_ctr = true;
1032 static bool thread_seq_ctr_acqd;
1033 static uint8_t thread_seq_ctr_bytes[4];
1034 static const uint8_t thread_well_known_key[IEEE802154_CIPHER_SIZE] =
1035 { 0x78, 0x58, 0x16, 0x86, 0xfd, 0xb4, 0x58, 0x0f, 0xb0, 0x92, 0x54, 0x6a, 0xec, 0xbd, 0x15, 0x66 };
1037 static GByteArray *set_thread_seq_ctr_from_key_index(uint8_t key_index)
1039 GByteArray *seq_ctr_bytes = NULL;
1041 seq_ctr_bytes = g_byte_array_new();
1042 if (thread_seq_ctr_acqd) {
1043 seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
1044 memcpy(seq_ctr_bytes->data, thread_seq_ctr_bytes, 4);
1045 } else {
1046 hex_str_to_bytes(thread_seq_ctr_str, seq_ctr_bytes, false);
1047 if (seq_ctr_bytes->len != 4) {
1048 /* Not read correctly - assume value is 0 */
1049 seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
1050 memset(seq_ctr_bytes->data, 0, 4);
1053 /* Replace lower part with counter based on packet key index */
1054 seq_ctr_bytes->data[3] = (seq_ctr_bytes->data[3] & 0x80) + ((key_index - 1) & 0x7F);
1056 return seq_ctr_bytes;
1059 static void create_thread_temp_keys(GByteArray *seq_ctr_bytes, uint16_t src_pan, ieee802154_key_t* key, unsigned char *mac_key, unsigned char *mle_key)
1061 GByteArray *bytes;
1062 char buffer[10];
1063 bool res;
1064 bool key_valid;
1065 bool verbatim_key = true;
1067 /* Get the IEEE 802.15.4 decryption key. */
1068 bytes = g_byte_array_new();
1069 res = hex_str_to_bytes(key->pref_key, bytes, false);
1070 key_valid = (res && bytes->len >= IEEE802154_CIPHER_SIZE);
1071 if (key_valid) {
1072 if (thread_use_pan_id_in_key) {
1073 /* Substitute the bottom two keys bytes with PAN ID */
1074 bytes->data[0] = (uint8_t)(src_pan & 0xFF);
1075 bytes->data[1] = (uint8_t)(src_pan >> 8);
1077 if (key->hash_type != KEY_HASH_NONE) {
1078 char digest[32];
1080 if (key->hash_type == KEY_HASH_THREAD) {
1081 memcpy(buffer, seq_ctr_bytes->data, 4);
1082 memcpy(&buffer[4], "Thread", 6); /* len("Thread") */
1084 if (!ws_hmac_buffer(GCRY_MD_SHA256, digest, buffer, 10, bytes->data, IEEE802154_CIPHER_SIZE)) {
1085 /* Copy upper hashed bytes to the MAC key */
1086 if (mac_key) {
1087 memcpy(mac_key, &digest[IEEE802154_CIPHER_SIZE], IEEE802154_CIPHER_SIZE);
1089 /* Copy lower hashed bytes to the MLE key */
1090 if (mle_key) {
1091 memcpy(mle_key, digest, IEEE802154_CIPHER_SIZE);
1093 verbatim_key = false;
1097 if (verbatim_key) {
1098 /* Just copy the keys verbatim */
1099 if (mac_key) {
1100 memcpy(mac_key, bytes->data, IEEE802154_CIPHER_SIZE);
1102 if (mle_key) {
1103 memcpy(mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
1107 g_byte_array_free(bytes, true);
1110 /* Set MAC key for Thread hash */
1111 static unsigned set_thread_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
1113 GByteArray *seq_ctr_bytes = NULL;
1115 if (packet->key_id_mode == KEY_ID_MODE_KEY_INDEX) {
1116 seq_ctr_bytes = set_thread_seq_ctr_from_key_index(packet->key_index);
1117 } else if ((packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) &&
1118 (packet->key_index == IEEE802154_THR_WELL_KNOWN_KEY_INDEX) &&
1119 (packet->key_source.addr32 == IEEE802154_THR_WELL_KNOWN_KEY_SRC))
1121 /* This is the well-known Thread key. No need for an alternative key */
1122 memcpy(key, thread_well_known_key, IEEE802154_CIPHER_SIZE);
1123 return 1;
1125 if (seq_ctr_bytes != NULL) {
1126 create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, key, NULL);
1127 /* Create an alternate key based on the wraparound case */
1128 seq_ctr_bytes->data[3] ^= 0x80;
1129 create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, alt_key, NULL);
1130 g_byte_array_free(seq_ctr_bytes, true);
1131 return 2;
1134 return 0;
1137 /* Set MLE key for Thread hash */
1138 static unsigned set_thread_mle_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
1140 GByteArray *seq_ctr_bytes = NULL;
1141 if (packet->key_id_mode == KEY_ID_MODE_KEY_INDEX) {
1142 seq_ctr_bytes = set_thread_seq_ctr_from_key_index(packet->key_index);
1144 else if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
1145 /* Reconstruct the key source from the key source in the packet */
1146 seq_ctr_bytes = g_byte_array_new();
1147 seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
1148 seq_ctr_bytes->data[0] = (packet->key_source.addr32 >> 24) & 0xFF;
1149 seq_ctr_bytes->data[1] = (packet->key_source.addr32 >> 16) & 0xFF;
1150 seq_ctr_bytes->data[2] = (packet->key_source.addr32 >> 8) & 0xFF;
1151 seq_ctr_bytes->data[3] = packet->key_source.addr32 & 0xFF;
1152 /* Acquire the sequence counter if configured in preferences */
1153 if (thread_auto_acq_seq_ctr && !thread_seq_ctr_acqd) {
1154 memcpy(thread_seq_ctr_bytes, seq_ctr_bytes->data, 4);
1155 thread_seq_ctr_acqd = true;
1158 if (seq_ctr_bytes != NULL) {
1159 create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, NULL, key);
1160 /* Create an alternate key based on the wraparound case */
1161 seq_ctr_bytes->data[3] ^= 0x80;
1162 create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, NULL, alt_key);
1163 g_byte_array_free(seq_ctr_bytes, true);
1164 return 2;
1167 return 0;
1170 static unsigned
1171 count_bits_in_byte(uint8_t byte)
1173 static const uint8_t lut[16] = {0, /* 0b0000 */
1174 1, /* 0b0001 */
1175 1, /* 0b0010 */
1176 2, /* 0b0011 */
1177 1, /* 0b0100 */
1178 2, /* 0b0101 */
1179 2, /* 0b0110 */
1180 3, /* 0b0111 */
1181 1, /* 0b1000 */
1182 2, /* 0b1001 */
1183 2, /* 0b1010 */
1184 3, /* 0b1011 */
1185 2, /* 0b1100 */
1186 3, /* 0b1101 */
1187 3, /* 0b1110 */
1188 4 /* 0b1111 */};
1189 return lut[byte >> 4] + lut[byte & 0xf];
1192 static unsigned
1193 get_chancount(tvbuff_t *tvb)
1195 unsigned offset;
1196 uint8_t tlv_type;
1197 uint16_t tlv_len;
1198 tlv_len_len_e tlv_len_len;
1199 unsigned chancount = THREAD_MC_INVALID_CHAN_COUNT;
1201 offset = 0;
1203 /* Thread Network Data TLVs */
1204 while (tvb_offset_exists(tvb, offset)) {
1206 /* Get the type and length ahead of time to pass to next function so we can highlight
1207 proper amount of bytes */
1208 tlv_type = tvb_get_uint8(tvb, offset);
1209 tlv_len = (uint16_t)tvb_get_uint8(tvb, offset + 1);
1211 /* TODO: need to make sure this applies to all MeshCoP TLVs */
1212 if (THREAD_TLV_LENGTH_ESC == tlv_len) {
1213 /* 16-bit length field */
1214 tlv_len = tvb_get_ntohs(tvb, offset + 2);
1215 tlv_len_len = TLV_LEN_LEN16;
1216 } else {
1217 tlv_len_len = TLV_LEN_LEN8;
1220 /* Skip over Type and Length */
1221 offset += 1 + tlv_len_len;
1223 switch(tlv_type) {
1225 case THREAD_MC_TLV_CHANNEL_MASK:
1227 int i, j;
1228 uint8_t entries = 0;
1229 int32_t check_len = tlv_len;
1230 int check_offset = offset + 1; /* Channel page first */
1231 uint16_t masklen;
1233 /* Check consistency of entries */
1234 while (check_len > 0) {
1236 masklen = tvb_get_uint8(tvb, check_offset);
1237 if (masklen == 0) {
1238 break; /* Get out or we might spin forever */
1240 masklen += 2; /* Add in page and length */
1241 check_offset += masklen;
1242 check_len -= masklen;
1243 entries++;
1246 if (check_len != 0) {
1247 /* Not an integer number of entries */
1248 /* offset += tlv_len; */
1249 return chancount;
1250 } else {
1251 chancount = 0;
1252 for (i = 0; i < entries; i++) {
1253 /* Skip over channel page */
1254 offset++;
1255 masklen = tvb_get_uint8(tvb, offset);
1256 offset++;
1257 /* Count the number of channels in the channel mask */
1258 for (j = 0; j < masklen; j++) {
1259 chancount += count_bits_in_byte(tvb_get_uint8(tvb, offset));
1260 offset++;
1265 break;
1267 default:
1268 /* Skip over any other TLVs */
1269 offset += tlv_len;
1272 return chancount;
1275 static int
1276 dissect_thread_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1278 proto_item *proto_root;
1279 proto_tree *thread_address_tree;
1280 proto_tree *tlv_tree;
1281 tvbuff_t *sub_tvb;
1282 unsigned offset = 0;
1283 proto_item *ti;
1284 uint8_t tlv_type, tlv_len;
1286 /* Create the protocol tree. */
1287 proto_root = proto_tree_add_item(tree, proto_thread_address, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1288 thread_address_tree = proto_item_add_subtree(proto_root, ett_thread_address);
1290 /* Thread Network Data TLVs */
1291 while (tvb_offset_exists(tvb, offset)) {
1293 /* Get the length ahead of time to pass to next function so we can highlight
1294 proper amount of bytes */
1295 tlv_len = tvb_get_uint8(tvb, offset + 1);
1297 ti = proto_tree_add_item(thread_address_tree, hf_thread_address_tlv, tvb, offset, tlv_len+2, ENC_NA);
1298 tlv_tree = proto_item_add_subtree(ti, ett_thread_address_tlv);
1300 /* Type */
1301 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1302 tlv_type = tvb_get_uint8(tvb, offset);
1303 offset++;
1305 /* Add value name to value root label */
1306 proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_address_tlv_vals, "Unknown (%d)"));
1308 /* Length */
1309 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1310 offset++;
1312 switch(tlv_type) {
1313 case THREAD_ADDRESS_TLV_TARGET_EID:
1315 /* Check length is consistent */
1316 if (tlv_len != 16) {
1317 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1318 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1319 } else {
1320 /* Target EID */
1321 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_target_eid, tvb, offset, tlv_len, ENC_NA);
1323 offset += tlv_len;
1325 break;
1327 case THREAD_ADDRESS_TLV_EXT_MAC_ADDR:
1329 /* Check length is consistent */
1330 if (tlv_len != 8) {
1331 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1332 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1333 } else {
1334 /* Extended MAC address */
1335 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_ext_mac_addr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1337 offset += tlv_len;
1339 break;
1341 case THREAD_ADDRESS_TLV_RLOC16:
1343 /* Check length is consistent */
1344 if (tlv_len != 2) {
1345 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1346 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1347 } else {
1348 /* Mesh Locator */
1349 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_rloc16, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1351 offset += tlv_len;
1353 break;
1355 case THREAD_ADDRESS_TLV_ML_EID:
1357 /* Check length is consistent */
1358 if (tlv_len != 8) {
1359 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1360 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1361 } else {
1362 /* ML IID */
1363 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_ml_eid, tvb, offset, tlv_len, ENC_NA);
1365 offset += tlv_len;
1367 break;
1369 case THREAD_ADDRESS_TLV_STATUS:
1371 /* Check length is consistent */
1372 if (tlv_len != 1) {
1373 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1374 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1375 } else {
1376 /* Status */
1377 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_status, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1379 offset += tlv_len;
1381 break;
1383 case THREAD_ADDRESS_TLV_LAST_TRANSACTION_TIME:
1385 /* Check length is consistent */
1386 if (tlv_len != 4) {
1387 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1388 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1389 } else {
1390 /* Last transaction time */
1391 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_last_transaction_time, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1393 offset += tlv_len;
1395 break;
1397 case THREAD_ADDRESS_TLV_ROUTER_MASK:
1399 /* Check length is consistent */
1400 if (tlv_len != 9) {
1401 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1402 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1403 offset += tlv_len;
1404 } else {
1405 /* Router Mask */
1406 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_router_mask_id_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
1407 offset++;
1410 * | | | | | | | | | | |1|1|1|1|1|1|...|6|
1411 * |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|...|3|
1412 * ---------------------------------------
1413 * |1|0|1|1|1|0|0|0|1|1|0|0|0|1|0|1|...
1415 * is sent as 0xb8, 0xc5
1416 * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
1419 /* Just show the string of octets - best representation for a bit mask */
1420 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_router_mask_assigned, tvb, offset, 8, ENC_NA);
1421 offset += 8;
1424 break;
1426 case THREAD_ADDRESS_TLV_ND_OPTION:
1427 /* Just show the data */
1428 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_nd_option, tvb, offset, tlv_len, ENC_NA);
1429 offset += tlv_len;
1430 break;
1432 case THREAD_ADDRESS_TLV_ND_DATA:
1433 /* Just show the data. Note there is no icmpv6 options dissector so would have to copy it */
1434 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_nd_data, tvb, offset, tlv_len, ENC_NA);
1435 offset += tlv_len;
1436 break;
1438 case THREAD_ADDRESS_TLV_THREAD_NETWORK_DATA:
1439 if (tlv_len > 0) {
1440 sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
1441 call_dissector(thread_address_nwd_handle, sub_tvb, pinfo, tlv_tree);
1443 offset += tlv_len;
1444 break;
1446 case THREAD_ADDRESS_TLV_TIMEOUT:
1447 if (tlv_len > 4) {
1448 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1449 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1451 else {
1452 /* Time out*/
1453 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_timeout, tvb, offset, tlv_len, ENC_NA);
1455 offset += tlv_len;
1456 break;
1457 case THREAD_ADDRESS_TLV_THREAD_NETWORK_NAME:
1458 if (tlv_len > 16) {
1459 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1460 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1462 else {
1463 /* Network Name */
1464 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8 );
1466 offset += tlv_len;
1467 break;
1468 case THREAD_ADDRESS_TLV_IPV6_ADDRESS:
1469 if ((tlv_len % 16) != 0) {
1470 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1471 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1472 offset += tlv_len;
1474 else {
1475 //Need to only take 16 bytes for the IPv6 address
1476 for (int i = 0; i < (tlv_len / 16); i++)
1478 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, 16, ENC_NA);
1479 offset += 16;
1482 offset += tlv_len;
1483 break;
1484 default:
1485 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1486 offset += tlv_len;
1489 return tvb_captured_length(tvb);
1492 static int
1493 dissect_thread_nm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1495 proto_item *proto_root;
1496 proto_tree *thread_nm_tree;
1497 proto_tree *tlv_tree;
1498 tvbuff_t *sub_tvb;
1499 unsigned offset = 0;
1500 proto_item *ti;
1501 uint8_t tlv_type, tlv_len;
1503 /* Create the protocol tree. */
1504 proto_root = proto_tree_add_item(tree, proto_thread_nm, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1505 thread_nm_tree = proto_item_add_subtree(proto_root, ett_thread_nm);
1507 /* Thread Network Data TLVs */
1508 while (tvb_offset_exists(tvb, offset)) {
1510 /* Get the length ahead of time to pass to next function so we can highlight
1511 proper amount of bytes */
1512 tlv_len = tvb_get_uint8(tvb, offset + 1);
1514 /* Create the tree */
1515 ti = proto_tree_add_item(thread_nm_tree, hf_thread_nm_tlv, tvb, offset, tlv_len+2, ENC_NA);
1516 tlv_tree = proto_item_add_subtree(ti, ett_thread_nm_tlv);
1518 /* Type */
1519 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1520 tlv_type = tvb_get_uint8(tvb, offset);
1521 offset++;
1523 /* Add value name to value root label */
1524 proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_nm_tlv_vals, "Unknown (%d)"));
1526 /* Length */
1527 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1528 offset++;
1531 switch(tlv_type) {
1532 case THREAD_NM_TLV_TARGET_EID:
1534 /* Check length is consistent */
1535 if (tlv_len != 16) {
1536 expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1537 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1538 } else {
1539 /* Target EID */
1540 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_target_eid, tvb, offset, tlv_len, ENC_NA);
1542 offset += tlv_len;
1544 break;
1546 case THREAD_NM_TLV_EXT_MAC_ADDR:
1548 /* Check length is consistent */
1549 if (tlv_len != 8) {
1550 expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1551 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1552 } else {
1553 /* Extended MAC address */
1554 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_ext_mac_addr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1556 offset += tlv_len;
1558 break;
1560 case THREAD_NM_TLV_RLOC16:
1562 /* Check length is consistent */
1563 if (tlv_len != 2) {
1564 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1565 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1566 } else {
1567 /* Mesh Locator */
1568 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_rloc16, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1570 offset += tlv_len;
1572 break;
1574 case THREAD_NM_TLV_ML_EID:
1576 /* Check length is consistent */
1577 if (tlv_len != 8) {
1578 expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1579 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1580 } else {
1581 /* ML IID */
1582 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_ml_eid, tvb, offset, tlv_len, ENC_NA);
1584 offset += tlv_len;
1586 break;
1588 case THREAD_NM_TLV_STATUS:
1590 /* Check length is consistent */
1591 if (tlv_len != 1) {
1592 expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1593 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1594 } else {
1595 /* Status */
1596 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_status, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1598 offset += tlv_len;
1600 break;
1602 case THREAD_NM_TLV_LAST_TRANSACTION_TIME:
1604 /* Check length is consistent */
1605 if (tlv_len != 4) {
1606 expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1607 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1608 } else {
1609 /* Last transaction time */
1610 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_last_transaction_time, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1612 offset += tlv_len;
1614 break;
1616 case THREAD_NM_TLV_ROUTER_MASK:
1618 /* Check length is consistent */
1619 if (tlv_len != 9) {
1620 expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1621 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1622 offset += tlv_len;
1623 } else {
1624 /* Router Mask */
1625 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_router_mask_id_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
1626 offset++;
1629 * | | | | | | | | | | |1|1|1|1|1|1|...|6|
1630 * |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|...|3|
1631 * ---------------------------------------
1632 * |1|0|1|1|1|0|0|0|1|1|0|0|0|1|0|1|...
1634 * is sent as 0xb8, 0xc5
1635 * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
1638 /* Just show the string of octets - best representation for a bit mask */
1639 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_router_mask_assigned, tvb, offset, 8, ENC_NA);
1640 offset += 8;
1643 break;
1645 case THREAD_NM_TLV_ND_OPTION:
1646 /* Just show the data */
1647 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_nd_option, tvb, offset, tlv_len, ENC_NA);
1648 offset += tlv_len;
1649 break;
1651 case THREAD_NM_TLV_ND_DATA:
1652 /* Just show the data. Note there is no icmpv6 options dissector so would have to copy it */
1653 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_nd_data, tvb, offset, tlv_len, ENC_NA);
1654 offset += tlv_len;
1655 break;
1657 case THREAD_NM_TLV_THREAD_NETWORK_DATA:
1658 if (tlv_len > 0) {
1659 sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
1660 call_dissector(thread_address_nwd_handle, sub_tvb, pinfo, tlv_tree);
1662 offset += tlv_len;
1663 break;
1665 case THREAD_NM_TLV_TIMEOUT:
1666 if (tlv_len > 4) {
1667 expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1668 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1670 else {
1671 /* Time out*/
1672 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_timeout, tvb, offset, tlv_len, ENC_NA);
1674 offset += tlv_len;
1677 break;
1679 case THREAD_NM_TLV_THREAD_NETWORK_NAME:
1680 if (tlv_len > 16) {
1681 expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1682 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1684 else {
1685 /* Network Name */
1686 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8);
1688 offset += tlv_len;
1690 break;
1692 case THREAD_NM_TLV_IPV6_ADDRESS:
1693 if ((tlv_len % 16) != 0) {
1694 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1695 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1696 offset += tlv_len;
1698 else {
1699 //Need to only take 16 bytes for the IPv6 address
1700 for (int i = 0; i < (tlv_len / 16); i++)
1702 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, 16, ENC_NA);
1703 offset += 16;
1706 break;
1708 case THREAD_NM_TLV_COMMISSIONER_SESSION_ID:
1710 /* Check length is consistent */
1711 if (tlv_len != 2) {
1712 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1714 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1715 } else {
1716 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_sess_id, tvb, offset, tlv_len, ENC_NA);
1718 offset += tlv_len;
1720 break;
1722 default:
1723 proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1724 offset += tlv_len;
1727 return tvb_captured_length(tvb);
1729 static int
1730 dissect_thread_bl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1732 proto_item *proto_root;
1733 proto_tree *thread_bl_tree;
1734 proto_tree *tlv_tree;
1735 tvbuff_t *sub_tvb;
1736 unsigned offset = 0;
1737 proto_item *ti;
1738 uint8_t tlv_type, tlv_len;
1740 /* Create the protocol tree. */
1741 proto_root = proto_tree_add_item(tree, proto_thread_bl, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1742 thread_bl_tree = proto_item_add_subtree(proto_root, ett_thread_bl);
1744 /* Thread Network Data TLVs */
1745 while (tvb_offset_exists(tvb, offset)) {
1747 /* Get the length ahead of time to pass to next function so we can highlight
1748 proper amount of bytes */
1749 tlv_len = tvb_get_uint8(tvb, offset + 1);
1751 ti = proto_tree_add_item(thread_bl_tree, hf_thread_bl_tlv, tvb, offset, tlv_len+2, ENC_NA);
1752 tlv_tree = proto_item_add_subtree(ti, ett_thread_bl_tlv);
1754 /* Type */
1755 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1756 tlv_type = tvb_get_uint8(tvb, offset);
1757 offset++;
1759 /* Add value name to value root label */
1760 proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_bl_tlv_vals, "Unknown (%d)"));
1762 /* Length */
1763 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1764 offset++;
1765 switch(tlv_type) {
1766 case THREAD_NM_TLV_TARGET_EID:
1768 /* Check length is consistent */
1769 if (tlv_len != 16) {
1770 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1771 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1772 } else {
1773 /* Target EID */
1774 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_target_eid, tvb, offset, tlv_len, ENC_NA);
1776 offset += tlv_len;
1778 break;
1780 case THREAD_NM_TLV_EXT_MAC_ADDR:
1782 /* Check length is consistent */
1783 if (tlv_len != 8) {
1784 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1785 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1786 } else {
1787 /* Extended MAC address */
1788 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_ext_mac_addr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1790 offset += tlv_len;
1792 break;
1794 case THREAD_NM_TLV_RLOC16:
1796 /* Check length is consistent */
1797 if (tlv_len != 2) {
1798 expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1799 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1800 } else {
1801 /* Mesh Locator */
1802 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_rloc16, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1804 offset += tlv_len;
1806 break;
1808 case THREAD_NM_TLV_ML_EID:
1810 /* Check length is consistent */
1811 if (tlv_len != 8) {
1812 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1813 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1814 } else {
1815 /* ML IID */
1816 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_ml_eid, tvb, offset, tlv_len, ENC_NA);
1818 offset += tlv_len;
1820 break;
1822 case THREAD_NM_TLV_STATUS:
1824 /* Check length is consistent */
1825 if (tlv_len != 1) {
1826 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1827 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1828 } else {
1829 /* Status */
1830 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_status, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1832 offset += tlv_len;
1834 break;
1836 case THREAD_NM_TLV_LAST_TRANSACTION_TIME:
1838 /* Check length is consistent */
1839 if (tlv_len != 4) {
1840 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1841 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1842 } else {
1843 /* Last transaction time */
1844 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_last_transaction_time, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1846 offset += tlv_len;
1848 break;
1850 case THREAD_NM_TLV_ROUTER_MASK:
1852 /* Check length is consistent */
1853 if (tlv_len != 9) {
1854 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1855 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1856 offset += tlv_len;
1857 } else {
1858 /* Router Mask */
1859 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_router_mask_id_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
1860 offset++;
1863 * | | | | | | | | | | |1|1|1|1|1|1|...|6|
1864 * |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|...|3|
1865 * ---------------------------------------
1866 * |1|0|1|1|1|0|0|0|1|1|0|0|0|1|0|1|...
1868 * is sent as 0xb8, 0xc5
1869 * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
1872 /* Just show the string of octets - best representation for a bit mask */
1873 proto_tree_add_item(tlv_tree, hf_thread_address_tlv_router_mask_assigned, tvb, offset, 8, ENC_NA);
1874 offset += 8;
1877 break;
1879 case THREAD_NM_TLV_ND_OPTION:
1880 /* Just show the data */
1881 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_nd_option, tvb, offset, tlv_len, ENC_NA);
1882 offset += tlv_len;
1883 break;
1885 case THREAD_NM_TLV_ND_DATA:
1886 /* Just show the data. Note there is no icmpv6 options dissector so would have to copy it */
1887 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_nd_data, tvb, offset, tlv_len, ENC_NA);
1888 offset += tlv_len;
1889 break;
1891 case THREAD_NM_TLV_THREAD_NETWORK_DATA:
1892 if (tlv_len > 0) {
1893 sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
1894 call_dissector(thread_address_nwd_handle, sub_tvb, pinfo, tlv_tree);
1896 offset += tlv_len;
1897 break;
1899 case THREAD_NM_TLV_TIMEOUT:
1900 if (tlv_len > 4) {
1901 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1902 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1904 else {
1905 /* Time out*/
1906 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_timeout, tvb, offset, tlv_len, ENC_NA);
1908 offset += tlv_len;
1911 break;
1913 case THREAD_NM_TLV_THREAD_NETWORK_NAME:
1914 if (tlv_len > 16) {
1915 expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1916 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1918 else {
1919 /* Network Name */
1920 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8);
1922 offset += tlv_len;
1924 break;
1926 case THREAD_NM_TLV_IPV6_ADDRESS:
1927 if ((tlv_len % 16) != 0) {
1928 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1929 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1930 offset += tlv_len;
1932 else {
1933 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, tlv_len, ENC_NA);
1934 for(int i = 0; i < (tlv_len/16) ; i ++)
1936 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, 16, ENC_NA);
1937 offset += 16;
1940 offset += tlv_len;
1941 break;
1943 default:
1944 proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1945 offset += tlv_len;
1948 return tvb_captured_length(tvb);
1951 static int
1952 dissect_thread_dg(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
1954 proto_item *proto_root;
1955 proto_tree *thread_dg_tree;
1956 proto_tree *tlv_tree;
1957 unsigned offset = 0;
1958 proto_item *ti;
1959 uint8_t tlv_type;
1960 uint16_t tlv_len;
1961 tlv_len_len_e tlv_len_len;
1963 /* Create the protocol tree. */
1964 proto_root = proto_tree_add_item(tree, proto_thread_dg, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1965 thread_dg_tree = proto_item_add_subtree(proto_root, ett_thread_dg);
1967 /* Thread Network Data TLVs */
1968 while (tvb_offset_exists(tvb, offset)) {
1970 /* Get the type and length ahead of time to pass to next function so we can highlight
1971 proper amount of bytes */
1972 tlv_type = tvb_get_uint8(tvb, offset);
1973 tlv_len = (uint16_t)tvb_get_uint8(tvb, offset + 1);
1975 /* TODO: need to make sure this applies to all Diagnostic TLVs */
1976 if (THREAD_TLV_LENGTH_ESC == tlv_len) {
1977 /* 16-bit length field */
1978 tlv_len = tvb_get_ntohs(tvb, offset + 2);
1979 tlv_len_len = TLV_LEN_LEN16;
1980 } else {
1981 tlv_len_len = TLV_LEN_LEN8;
1984 /* Create the tree */
1985 ti = proto_tree_add_item(thread_dg_tree, hf_thread_dg_tlv, tvb, offset, 1 + tlv_len_len + tlv_len, ENC_NA);
1986 tlv_tree = proto_item_add_subtree(ti, ett_thread_dg_tlv);
1988 /* Type */
1989 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1990 offset++;
1992 /* Add value name to value root label */
1993 proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_dg_tlv_vals, "Unknown (%d)"));
1995 /* Length */
1996 switch (tlv_len_len) {
1997 case TLV_LEN_LEN8:
1998 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_length8, tvb, offset, 1, ENC_BIG_ENDIAN);
1999 break;
2000 case TLV_LEN_LEN16:
2001 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_length16, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
2002 break;
2003 default:
2004 break;
2006 offset += tlv_len_len;
2008 switch(tlv_type) {
2009 case THREAD_DG_TLV_TYPE_LIST:
2011 int i;
2013 for (i = 0; i < tlv_len; i++) {
2014 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2015 offset++;
2018 break;
2020 case THREAD_DG_TLV_EXT_MAC_ADDR:
2021 case THREAD_DG_TLV_ADDRESS16:
2022 case THREAD_DG_TLV_MODE:
2023 case THREAD_DG_TLV_TIMEOUT:
2024 case THREAD_DG_TLV_CONNECTIVITY:
2025 case THREAD_DG_TLV_ROUTE64:
2026 case THREAD_DG_TLV_LEADER_DATA:
2027 case THREAD_DG_TLV_NETWORK_DATA:
2028 case THREAD_DG_TLV_IPV6_ADDR_LIST:
2029 /* Counters */
2030 case THREAD_DG_TLV_MAC_COUNTERS:
2031 case THREAD_DG_TLV_BATTERY_LEVEL:
2032 case THREAD_DG_TLV_VOLTAGE:
2033 case THREAD_DG_TLV_CHILD_TABLE:
2034 case THREAD_DG_TLV_CHANNEL_PAGES:
2035 case THREAD_DG_TLV_MAX_CHILD_TIMEOUT:
2036 case THREAD_DG_TLV_LDEVID_SUBJECT_PUBLIC_KEY_INFO:
2037 case THREAD_DG_TLV_IDEVID_CERTIFICATE:
2038 case THREAD_DG_TLV_EUI_64:
2039 case THREAD_DG_TLV_VERSION:
2040 case THREAD_DG_TLV_VENDOR_NAME:
2041 case THREAD_DG_TLV_VENDOR_MODEL:
2042 case THREAD_DG_TLV_VENDOR_SW_VERSION:
2043 case THREAD_DG_TLV_THREAD_STACK_VERSION:
2044 case THREAD_DG_TLV_CHILD:
2045 case THREAD_DG_TLV_CHILD_IPV6_ADDRESS_LIST:
2046 case THREAD_DG_TLV_ROUTER_NEIGHBOR:
2047 case THREAD_DG_TLV_ANSWER:
2048 case THREAD_DG_TLV_QUERY_ID:
2049 case THREAD_DG_TLV_MLE_COUNTERS:
2050 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_general, tvb, offset, tlv_len, ENC_NA);
2051 offset += tlv_len;
2052 break;
2054 default:
2055 proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2056 offset += tlv_len;
2059 return tvb_captured_length(tvb);
2062 static int
2063 dissect_thread_mc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2065 proto_item *proto_root;
2066 proto_tree *thread_mc_tree;
2067 proto_tree *tlv_tree;
2068 unsigned offset = 0;
2069 proto_item *ti;
2070 proto_item *pi;
2071 uint8_t tlv_type;
2072 uint16_t tlv_len;
2073 tlv_len_len_e tlv_len_len;
2074 unsigned chancount;
2077 /* Create the protocol tree. */
2078 proto_root = proto_tree_add_item(tree, proto_thread_mc, tvb, 0, tvb_reported_length(tvb), ENC_NA);
2079 thread_mc_tree = proto_item_add_subtree(proto_root, ett_thread_mc);
2081 /* Get channel count a priori so we can process energy list better */
2082 chancount = get_chancount(tvb);
2084 /* Thread Network Data TLVs */
2085 while (tvb_offset_exists(tvb, offset)) {
2087 /* Get the type and length ahead of time to pass to next function so we can highlight
2088 proper amount of bytes */
2089 tlv_type = tvb_get_uint8(tvb, offset);
2090 tlv_len = (uint16_t)tvb_get_uint8(tvb, offset + 1);
2092 /* TODO: need to make sure this applies to all MeshCoP TLVs */
2093 if (THREAD_TLV_LENGTH_ESC == tlv_len) {
2094 /* 16-bit length field */
2095 tlv_len = tvb_get_ntohs(tvb, offset + 2);
2096 tlv_len_len = TLV_LEN_LEN16;
2097 } else {
2098 tlv_len_len = TLV_LEN_LEN8;
2101 /* Create the tree */
2102 ti = proto_tree_add_item(thread_mc_tree, hf_thread_mc_tlv, tvb, offset, 1 + tlv_len_len + tlv_len, ENC_NA);
2103 tlv_tree = proto_item_add_subtree(ti, ett_thread_mc_tlv);
2105 /* Type */
2106 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2107 offset++;
2109 /* Add value name to value root label */
2110 proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_mc_tlv_vals, "Unknown (%d)"));
2112 /* Length */
2113 switch (tlv_len_len) {
2114 case TLV_LEN_LEN8:
2115 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_length8, tvb, offset, 1, ENC_BIG_ENDIAN);
2116 break;
2117 case TLV_LEN_LEN16:
2118 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_length16, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
2119 break;
2120 default:
2121 break;
2123 offset += tlv_len_len;
2125 switch(tlv_type) {
2126 case THREAD_MC_TLV_CHANNEL:
2128 /* Check length is consistent */
2129 if (tlv_len != 3) {
2130 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2131 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2132 } else {
2133 /* Channel page */
2134 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_channel_page, tvb, offset, 1, ENC_BIG_ENDIAN);
2135 /* Channel */
2136 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_channel, tvb, offset+1, 2, ENC_BIG_ENDIAN);
2138 offset += tlv_len;
2140 break;
2142 case THREAD_MC_TLV_PANID:
2144 /* Check length is consistent */
2145 if (tlv_len != 2) {
2146 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2147 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2148 } else {
2149 /* PAN ID */
2150 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_pan_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2152 offset += tlv_len;
2154 break;
2156 case THREAD_MC_TLV_XPANID:
2158 /* Check length is consistent */
2159 if (tlv_len != 8) {
2160 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2161 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2162 } else {
2163 /* PAN ID */
2164 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_xpan_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2166 offset += tlv_len;
2168 break;
2170 case THREAD_MC_TLV_NETWORK_NAME:
2172 /* Check length is consistent */
2173 if (tlv_len > 16) {
2174 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2175 //proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2176 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8);
2177 } else {
2178 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8);
2180 offset += tlv_len;
2182 break;
2184 case THREAD_MC_TLV_PSKC:
2186 /* Check length is consistent */
2187 if (tlv_len != 16) {
2188 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2189 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2190 } else {
2191 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_pskc, tvb, offset, tlv_len, ENC_NA);
2193 offset += tlv_len;
2195 break;
2197 case THREAD_MC_TLV_NETWORK_MASTER_KEY:
2199 /* Check length is consistent */
2200 if (tlv_len != 16) {
2201 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2202 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2203 } else {
2204 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_master_key, tvb, offset, tlv_len, ENC_NA);
2206 offset += tlv_len;
2208 break;
2210 case THREAD_MC_TLV_NETWORK_KEY_SEQ_CTR:
2212 /* Check length is consistent */
2213 if (tlv_len != 4) {
2214 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2215 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2216 } else {
2217 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_key_seq_ctr, tvb, offset, tlv_len, ENC_NA);
2219 offset += tlv_len;
2221 break;
2223 case THREAD_MC_TLV_NETWORK_ML_PREFIX:
2225 /* Check length is consistent */
2226 if (tlv_len != 8) {
2227 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2228 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2229 } else {
2230 ws_in6_addr prefix;
2232 memset(&prefix, 0, sizeof(prefix));
2233 tvb_memcpy(tvb, (uint8_t *)&prefix.bytes, offset, tlv_len);
2234 pi = proto_tree_add_ipv6(tlv_tree, hf_thread_mc_tlv_ml_prefix, tvb, offset, tlv_len, &prefix);
2235 proto_item_append_text(pi, "/%d", tlv_len * 8);
2237 offset += tlv_len;
2239 break;
2241 case THREAD_MC_TLV_STEERING_DATA:
2243 /* Check length is consistent */
2244 if (tlv_len > 16) {
2245 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2246 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2247 } else {
2248 /* Display it simply */
2249 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_steering_data, tvb, offset, tlv_len, ENC_NA);
2251 offset += tlv_len;
2253 break;
2255 case THREAD_MC_TLV_BORDER_AGENT_LOCATOR:
2257 /* Check length is consistent */
2258 if (tlv_len != 2) {
2259 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2260 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2261 } else {
2262 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ba_locator, tvb, offset, tlv_len, ENC_NA);
2264 offset += tlv_len;
2266 break;
2268 case THREAD_MC_TLV_COMMISSIONER_ID:
2270 /* Check length is consistent */
2271 if (tlv_len > 64) {
2272 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2273 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2274 } else {
2275 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_id, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
2277 offset += tlv_len;
2279 break;
2281 case THREAD_MC_TLV_COMMISSIONER_SESSION_ID:
2283 /* Check length is consistent */
2284 if (tlv_len != 2) {
2285 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2286 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2287 } else {
2288 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_sess_id, tvb, offset, tlv_len, ENC_NA);
2290 offset += tlv_len;
2292 break;
2294 case THREAD_MC_TLV_SECURITY_POLICY:
2296 /* Check length is consistent */
2297 //Thread 1.1 has length 3
2298 //Thread 1.2 has length 4
2299 //else throw error
2300 if (tlv_len == 3) {
2301 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rot, tvb, offset, 2, ENC_BIG_ENDIAN);
2302 offset += 2;
2303 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_o, tvb, offset, 1, ENC_BIG_ENDIAN);
2304 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2305 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_r, tvb, offset, 1, ENC_BIG_ENDIAN);
2306 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2307 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_b, tvb, offset, 1, ENC_BIG_ENDIAN);
2308 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rsv1, tvb, offset, 1, ENC_BIG_ENDIAN);
2309 offset++;
2310 } else if (tlv_len == 4) {
2311 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rot, tvb, offset, 2, ENC_BIG_ENDIAN);
2312 offset += 2;
2313 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_o, tvb, offset, 1, ENC_BIG_ENDIAN);
2314 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2315 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_r, tvb, offset, 1, ENC_BIG_ENDIAN);
2316 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2317 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_b, tvb, offset, 1, ENC_BIG_ENDIAN);
2318 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_ccm, tvb, offset, 1, ENC_BIG_ENDIAN);
2319 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_ae, tvb, offset, 1, ENC_BIG_ENDIAN);
2320 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_nmp, tvb, offset, 1, ENC_BIG_ENDIAN);
2321 offset++;
2322 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_l, tvb, offset, 1, ENC_BIG_ENDIAN);
2323 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_ncr, tvb, offset, 1, ENC_BIG_ENDIAN);
2324 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rsv, tvb, offset, 1, ENC_BIG_ENDIAN);
2325 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_vr, tvb, offset, 1, ENC_BIG_ENDIAN);
2326 offset++;
2328 } else{
2329 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2330 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2331 offset += tlv_len;
2334 break;
2336 case THREAD_MC_TLV_GET:
2338 int i;
2340 for (i = 0; i < tlv_len; i++) {
2341 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2342 offset++;
2345 break;
2347 case THREAD_MC_TLV_ACTIVE_TSTAMP:
2348 case THREAD_MC_TLV_PENDING_TSTAMP:
2350 nstime_t timestamp;
2352 if (tlv_len != 8) {
2353 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2354 //proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2355 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_pending_tstamp, tvb, offset, tlv_len, ENC_NA);
2356 } else {
2357 /* Fill in the nstime_t structure */
2358 timestamp.secs = (time_t)tvb_get_ntoh48(tvb, offset);
2359 timestamp.nsecs = (int)lround((double)(tvb_get_ntohs(tvb, offset + 6) >> 1) * THREAD_MC_32768_TO_NSEC_FACTOR);
2360 if (tlv_type == THREAD_MC_TLV_ACTIVE_TSTAMP) {
2361 proto_tree_add_time(tlv_tree, hf_thread_mc_tlv_active_tstamp, tvb, offset, 8, &timestamp);
2362 } else {
2363 proto_tree_add_time(tlv_tree, hf_thread_mc_tlv_pending_tstamp, tvb, offset, 8, &timestamp);
2366 offset += tlv_len;
2368 break;
2370 case THREAD_MC_TLV_STATE:
2372 /* Check length is consistent */
2373 if (tlv_len != 1) {
2374 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2375 //proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2376 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_state, tvb, offset, tlv_len, ENC_NA);
2377 } else {
2378 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_state, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2380 offset += tlv_len;
2382 break;
2384 case THREAD_MC_TLV_JOINER_DTLS_ENCAP:
2386 tvbuff_t *sub_tvb;
2388 if (tlv_len > 0) {
2389 sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
2390 call_dissector(thread_dtls_handle, sub_tvb, pinfo, tree);
2392 offset += tlv_len;
2394 break;
2396 case THREAD_MC_TLV_COMMISSIONER_UDP_PORT:
2397 case THREAD_MC_TLV_JOINER_UDP_PORT:
2399 if (tlv_len != 2) {
2400 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2401 //proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2402 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_port, tvb, offset, tlv_len, ENC_NA);
2403 } else {
2404 /* UDP Port */
2405 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_port, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2407 offset += tlv_len;
2409 break;
2411 case THREAD_MC_TLV_JOINER_IID:
2413 if (tlv_len != 8) {
2414 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2415 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2416 } else {
2417 /* IID */
2418 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_iid, tvb, offset, tlv_len, ENC_NA);
2420 offset += tlv_len;
2422 break;
2424 case THREAD_MC_TLV_JOINER_ROUTER_LOCATOR:
2426 if (tlv_len != 2) {
2427 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2428 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2429 } else {
2430 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_jr_locator, tvb, offset, tlv_len, ENC_NA);
2432 offset += tlv_len;
2434 break;
2436 case THREAD_MC_TLV_JOINER_KEK:
2438 if (tlv_len != 16) {
2439 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2440 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2441 } else {
2442 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_kek, tvb, offset, tlv_len, ENC_NA);
2444 offset += tlv_len;
2446 break;
2448 case THREAD_MC_TLV_PROVISIONING_URL:
2450 /* Check length is consistent */
2451 if (tlv_len > 64) {
2452 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2453 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2454 } else {
2455 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_provisioning_url, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
2457 offset += tlv_len;
2459 break;
2461 case THREAD_MC_TLV_VENDOR_NAME:
2463 /* Check length is consistent */
2464 if (tlv_len > 32) {
2465 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2466 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2467 } else {
2468 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_name, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
2470 offset += tlv_len;
2472 break;
2474 case THREAD_MC_TLV_VENDOR_MODEL:
2476 /* Check length is consistent: TODO not specified in spec. */
2477 if (tlv_len > 32) {
2478 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2479 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2480 } else {
2481 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_model, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
2483 offset += tlv_len;
2485 break;
2487 case THREAD_MC_TLV_VENDOR_SW_VERSION:
2489 /* Check length is consistent */
2490 if (tlv_len > 16) {
2491 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2492 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2493 } else {
2494 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_sw_ver, tvb, offset, tlv_len, ENC_NA|ENC_UTF_8);
2496 offset += tlv_len;
2498 break;
2500 case THREAD_MC_TLV_VENDOR_DATA:
2502 /* Check length is consistent */
2503 if (tlv_len > 64) {
2504 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2505 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2506 } else {
2507 /* Display it simply */
2508 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_data, tvb, offset, tlv_len, ENC_ASCII);
2510 offset += tlv_len;
2512 break;
2514 case THREAD_MC_TLV_VENDOR_STACK_VERSION:
2516 /* Check length is consistent */
2517 if (tlv_len != 6) {
2518 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2519 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2520 offset += tlv_len;
2521 } else {
2522 uint8_t build_u8;
2523 uint16_t build;
2525 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
2526 offset += 3;
2527 build_u8 = tvb_get_uint8(tvb, offset);
2528 offset++;
2529 build = (uint16_t)build_u8 << 4;
2530 build_u8 = tvb_get_uint8(tvb, offset);
2531 build |= (uint16_t)build_u8 >> 4;
2532 pi = proto_tree_add_uint(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_build, tvb, 0, 0, build);
2533 proto_item_set_generated(pi);
2534 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_rev, tvb, offset, 1, ENC_BIG_ENDIAN);
2535 offset++;
2536 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_min, tvb, offset, 1, ENC_BIG_ENDIAN);
2537 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_maj, tvb, offset, 1, ENC_BIG_ENDIAN);
2538 offset++;
2541 break;
2543 case THREAD_MC_TLV_UDP_ENCAPSULATION:
2545 tvbuff_t *sub_tvb;
2546 uint16_t src_port;
2547 uint16_t dst_port;
2549 src_port = tvb_get_ntohs(tvb, offset);
2550 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_encap_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2551 offset += 2;
2552 dst_port = tvb_get_ntohs(tvb, offset);
2553 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_encap_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2554 offset += 2;
2556 if (tlv_len >= 4)
2558 /* Allocate a buffer for the fake UDP datagram and create the fake header. */
2559 udp_hdr_t* udp_hdr = (udp_hdr_t *)wmem_alloc(pinfo->pool, sizeof(udp_hdr_t) + (tlv_len - 4));
2561 /* Create pseudo UDP header */
2562 udp_hdr->src_port = g_htons(src_port);
2563 udp_hdr->dst_port = g_htons(dst_port);
2564 udp_hdr->length = g_htons(tlv_len + 4); /* Includes UDP header length */
2565 udp_hdr->checksum = 0;
2566 /* Copy UDP payload in */
2567 tvb_memcpy(tvb, udp_hdr + 1, offset, tlv_len - 4);
2568 /* Create child tvb */
2569 sub_tvb = tvb_new_child_real_data(tvb, (uint8_t *)udp_hdr, tlv_len + 4, tvb_reported_length(tvb) + 4);
2570 call_dissector(thread_udp_handle, sub_tvb, pinfo, tree);
2572 offset += (tlv_len-4);
2574 break;
2576 case THREAD_MC_TLV_IPV6_ADDRESS:
2578 /* Check length is consistent */
2579 if (tlv_len != 16) {
2580 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2581 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2582 } else {
2583 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, tlv_len, ENC_NA);
2585 offset += tlv_len;
2587 break;
2589 /* case THREAD_MC_TLV_PENDING_TSTAMP: Handled in THREAD_MC_TLV_ACTIVE_TSTAMP case */
2591 case THREAD_MC_TLV_DELAY_TIMER:
2593 if (tlv_len != 4) {
2594 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2595 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2596 } else {
2597 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_delay_timer, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2599 offset += tlv_len;
2601 break;
2603 case THREAD_MC_TLV_CHANNEL_MASK:
2605 proto_tree *cm_tree;
2606 int i;
2607 uint8_t entries = 0;
2608 int32_t check_len = tlv_len;
2609 int check_offset = offset + 1; /* Channel page first */
2610 uint16_t masklen;
2612 /* Check consistency of entries */
2613 while (check_len > 0) {
2615 masklen = tvb_get_uint8(tvb, check_offset);
2616 if (masklen == 0) {
2617 break; /* Get out or we might spin forever */
2619 masklen += 2; /* Add in page and length */
2620 check_offset += masklen;
2621 check_len -= masklen;
2622 entries++;
2625 if (check_len != 0) {
2626 /* Not an integer number of entries */
2627 expert_add_info(pinfo, proto_root, &ei_thread_mc_tlv_length_failed);
2628 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2629 offset += tlv_len;
2630 } else {
2631 for (i = 0; i < entries; i++) {
2632 pi = proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_chan_mask, tvb, offset, 1, ENC_NA);
2633 cm_tree = proto_item_add_subtree(pi, ett_thread_mc_chan_mask);
2634 proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_page, tvb, offset, 1, ENC_BIG_ENDIAN);
2635 offset++;
2636 masklen = tvb_get_uint8(tvb, offset);
2637 proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_len, tvb, offset, 1, ENC_BIG_ENDIAN);
2638 offset++;
2639 proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_mask, tvb, offset, masklen, ENC_NA);
2640 offset += masklen;
2644 break;
2646 case THREAD_MC_TLV_COUNT:
2648 if (tlv_len != 1) {
2649 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2650 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2651 } else {
2652 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_count, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2654 offset += tlv_len;
2656 break;
2658 case THREAD_MC_TLV_PERIOD:
2660 if (tlv_len != 2) {
2661 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2662 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2663 } else {
2664 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_period, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2666 offset += tlv_len;
2668 break;
2670 case THREAD_MC_TLV_SCAN_DURATION:
2672 if (tlv_len != 2) {
2673 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2674 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2675 } else {
2676 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_scan_duration, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2678 offset += tlv_len;
2680 break;
2682 case THREAD_MC_TLV_ENERGY_LIST:
2684 proto_tree *it_tree;
2685 int i;
2687 if ((chancount != THREAD_MC_INVALID_CHAN_COUNT) && (chancount != 0) && ((tlv_len % chancount) == 0)) {
2688 /* Go through the number of el_counts of scan */
2689 for (i = 0; i < (int)(tlv_len / (uint16_t)chancount); i++) {
2690 pi = proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_el_count, tvb, offset, 1, ENC_NA);
2691 proto_item_append_text(pi, " %d", i + 1);
2692 it_tree = proto_item_add_subtree(pi, ett_thread_mc_el_count);
2693 proto_tree_add_item(it_tree, hf_thread_mc_tlv_energy_list, tvb, offset, chancount, ENC_NA);
2694 offset += chancount;
2696 } else {
2697 /* This might not work but try and display as string */
2698 /* Something wrong with channel count so just show it as a simple string */
2699 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_energy_list, tvb, offset, tlv_len, ENC_NA);
2701 offset += tlv_len;
2703 break;
2705 case THREAD_MC_TLV_DOMAIN_NAME:
2707 /* Check length is consistent */
2708 if (tlv_len > 16) {
2709 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2710 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2711 } else {
2712 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_domain_name, tvb, offset, tlv_len, ENC_NA);
2714 offset += tlv_len;
2716 break;
2718 case THREAD_MC_TLV_DOMAIN_PREFIX:
2719 //To be defined in future in draft
2720 break;
2722 case THREAD_MC_TLV_AE_STEERING_DATA:
2724 /* Check length is consistent */
2725 if (tlv_len > 16) {
2726 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2727 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2728 } else {
2729 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ae_steering_data, tvb, offset, tlv_len, ENC_NA);
2731 offset += tlv_len;
2733 break;
2735 case THREAD_MC_TLV_NMKP_STEERING_DATA:
2737 /* Check length is consistent */
2738 if (tlv_len > 16) {
2739 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2740 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2741 } else {
2742 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_nmkp_steering_data, tvb, offset, tlv_len, ENC_NA);
2744 offset += tlv_len;
2746 break;
2748 case THREAD_MC_TLV_COMMISSIONER_TOKEN:
2749 break;
2751 case THREAD_MC_TLV_COMMISSIONER_SIGNATURE:
2752 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_signature, tvb, offset, tlv_len, ENC_NA);
2753 offset += tlv_len;
2754 break;
2756 case THREAD_MC_TLV_AE_UDP_PORT:
2758 /* Check length is consistent */
2759 if (tlv_len != 2) {
2760 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2761 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2762 } else {
2763 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ae_udp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2765 offset += tlv_len;
2767 break;
2769 case THREAD_MC_TLV_NMKP_UDP_PORT:
2771 /* Check length is consistent */
2772 if (tlv_len != 2) {
2773 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2774 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2775 } else {
2776 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_nmkp_udp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2778 offset += tlv_len;
2780 break;
2782 case THREAD_MC_TLV_TRI_HOSTNAME:
2783 break;
2785 case THREAD_MC_TLV_REGISTRAR_IPV6_ADDRESS:
2787 /* Check length is consistent */
2788 if (tlv_len != 16) {
2789 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2790 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2791 } else {
2792 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_registrar_ipv6_addr, tvb, offset, tlv_len, ENC_NA);
2794 offset += tlv_len;
2796 break;
2798 case THREAD_MC_TLV_REGISTRAR_HOSTNAME:
2799 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_registrar_hostname, tvb, offset, tlv_len, ENC_NA);
2800 offset += tlv_len;
2801 break;
2803 case THREAD_MC_TLV_COMMISSIONER_PEN_SIGNATURE:
2804 break;
2806 case THREAD_MC_TLV_COMMISSIONER_PEN_TOKEN:
2807 break;
2809 case THREAD_MC_TLV_DISCOVERY_REQUEST:
2811 /* Check length is consistent */
2812 if (tlv_len != 2) {
2813 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2814 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2815 } else {
2816 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_req_ver, tvb, offset, 1, ENC_BIG_ENDIAN);
2817 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_req_j, tvb, offset, 1, ENC_BIG_ENDIAN);
2819 offset += tlv_len;
2821 break;
2823 case THREAD_MC_TLV_DISCOVERY_RESPONSE:
2825 /* Check length is consistent */
2826 if (tlv_len != 2) {
2827 expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2828 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2829 } else {
2830 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_rsp_ver, tvb, offset, 1, ENC_BIG_ENDIAN);
2831 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_rsp_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2832 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_rsp_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2834 offset += tlv_len;
2836 break;
2838 default:
2839 proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2840 offset += tlv_len;
2843 return tvb_captured_length(tvb);
2846 static int
2847 // NOLINTNEXTLINE(misc-no-recursion)
2848 dissect_thread_nwd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2850 proto_item *proto_root;
2851 proto_tree *thread_nwd_tree;
2852 proto_tree *tlv_tree;
2853 tvbuff_t *sub_tvb;
2854 unsigned offset = 0, tlv_offset;
2855 proto_item *ti;
2856 uint8_t tlv_type, tlv_len;
2857 int g_server_decode = 1; /* used to check if the full decoding of Server TLV has to be done or not */
2859 /* Create the protocol tree. */
2860 proto_root = proto_tree_add_item(tree, proto_thread_nwd, tvb, 0, tvb_reported_length(tvb), ENC_NA);
2861 thread_nwd_tree = proto_item_add_subtree(proto_root, ett_thread_nwd);
2863 /* Thread Network Data TLVs */
2864 increment_dissection_depth(pinfo);
2865 while (tvb_offset_exists(tvb, offset)) {
2867 /* Get the length ahead of time to pass to next function so we can highlight
2868 proper amount of bytes */
2869 tlv_len = tvb_get_uint8(tvb, offset + 1);
2871 ti = proto_tree_add_item(thread_nwd_tree, hf_thread_nwd_tlv, tvb, offset, tlv_len+2, ENC_NA);
2872 tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_tlv);
2874 /* Type */
2875 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2876 tlv_type = tvb_get_uint8(tvb, offset) >> 1;
2878 /* Stable */
2879 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_stable, tvb, offset, 1, ENC_BIG_ENDIAN);
2880 offset++;
2882 /* Add value name to value root label */
2883 proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_nwd_tlv_vals, "Unknown (%d)"));
2885 /* Length */
2886 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2887 offset++;
2889 switch(tlv_type) {
2890 case THREAD_NWD_TLV_HAS_ROUTE:
2892 /* Has Route TLV can be top level TLV or sub-TLV */
2894 /* Check length is consistent */
2895 if ((tlv_len % THREAD_NWD_TLV_HAS_ROUTE_SIZE) != 0)
2897 expert_add_info(pinfo, proto_root, &ei_thread_nwd_len_size_mismatch);
2898 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2899 offset += tlv_len;
2900 } else {
2901 proto_tree *has_route_tree;
2902 unsigned i;
2903 unsigned count = tlv_len / THREAD_NWD_TLV_HAS_ROUTE_SIZE;
2905 /* Add subtrees */
2906 for (i = 0; i < count; i++) {
2907 ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_has_route, tvb, offset, 1, ENC_NA);
2908 has_route_tree = proto_item_add_subtree(ti, ett_thread_nwd_has_route);
2909 proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_br_16, tvb, offset, 2, ENC_BIG_ENDIAN);
2910 offset += 2;
2911 proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_pref, tvb, offset, 1, ENC_BIG_ENDIAN);
2912 proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_np, tvb, offset, 1, ENC_BIG_ENDIAN);
2913 proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2914 offset += 1;
2918 break;
2920 case THREAD_NWD_TLV_PREFIX:
2922 uint8_t prefix_len;
2923 uint8_t prefix_byte_len;
2924 ws_in6_addr prefix;
2925 address prefix_addr;
2927 /* Domain ID */
2928 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_prefix_domain_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2929 offset++;
2930 tlv_offset = 1;
2932 /* Prefix Length */
2933 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_prefix_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2934 prefix_len = tvb_get_uint8(tvb, offset);
2935 prefix_byte_len = (prefix_len + 7) / 8;
2936 offset++;
2937 tlv_offset++;
2939 /* Prefix */
2940 memset(&prefix.bytes, 0, sizeof(prefix));
2941 if (prefix_byte_len <= sizeof(prefix))
2942 tvb_memcpy(tvb, (uint8_t *)&prefix.bytes, offset, prefix_byte_len);
2943 proto_tree_add_ipv6(tlv_tree, hf_thread_nwd_tlv_prefix, tvb, offset, prefix_byte_len, &prefix);
2944 set_address(&prefix_addr, AT_IPv6, 16, prefix.bytes);
2945 proto_item_append_text(ti, " = %s/%d", address_to_str(pinfo->pool, &prefix_addr), prefix_len);
2946 offset += prefix_byte_len;
2947 tlv_offset += prefix_byte_len;
2949 if (tlv_offset < tlv_len) {
2950 proto_tree *sub_tlv_tree;
2951 unsigned remaining = tlv_len - tlv_offset;
2953 ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_sub_tlvs, tvb, offset, 1, ENC_NA);
2954 sub_tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_prefix_sub_tlvs);
2955 /* Call this dissector for sub-TLVs */
2956 sub_tvb = tvb_new_subset_length(tvb, offset, remaining); /* remove prefix length (1) and prefix (prefix_byte_len) */
2957 dissect_thread_nwd(sub_tvb, pinfo, sub_tlv_tree, data);
2958 offset += remaining;
2961 break;
2963 case THREAD_NWD_TLV_BORDER_ROUTER:
2965 /* Border Router TLV can only be sub-TLV */
2967 /* Check length is consistent */
2968 if ((tlv_len % 4) != 0)
2970 expert_add_info(pinfo, proto_root, &ei_thread_nwd_len_size_mismatch);
2971 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2972 offset += tlv_len;
2973 } else {
2974 proto_tree *border_router_tree;
2975 unsigned i;
2976 unsigned count = tlv_len / 4;
2978 /* Add subtrees */
2979 for (i = 0; i < count; i++) {
2980 ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_border_router, tvb, offset, 1, ENC_NA);
2981 border_router_tree = proto_item_add_subtree(ti, ett_thread_nwd_border_router);
2983 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_16, tvb, offset, 2, ENC_BIG_ENDIAN);
2984 offset += 2;
2985 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_pref, tvb, offset, 1, ENC_BIG_ENDIAN);
2986 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_p, tvb, offset, 1, ENC_BIG_ENDIAN);
2987 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_s, tvb, offset, 1, ENC_BIG_ENDIAN);
2988 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_d, tvb, offset, 1, ENC_BIG_ENDIAN);
2989 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2990 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_r, tvb, offset, 1, ENC_BIG_ENDIAN);
2991 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_o, tvb, offset, 1, ENC_BIG_ENDIAN);
2992 offset++;
2993 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2994 proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_dp, tvb, offset, 1, ENC_BIG_ENDIAN);
2995 offset++;
2999 break;
3001 case THREAD_NWD_TLV_6LOWPAN_ID:
3003 static int * const nwd_6lowpan_flags[] = {
3004 &hf_thread_nwd_tlv_6lowpan_id_6co_flag_reserved,
3005 &hf_thread_nwd_tlv_6lowpan_id_6co_flag_c,
3006 &hf_thread_nwd_tlv_6lowpan_id_6co_flag_cid,
3007 NULL
3010 /* 6lowpan-ND */
3011 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);
3012 offset++;
3014 /* Context Length */
3015 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_6lowpan_id_6co_context_length, tvb, offset, 1, ENC_BIG_ENDIAN);
3016 offset++;
3018 break;
3020 case THREAD_NWD_TLV_COMMISSIONING_DATA:
3022 if (tlv_len > 0) {
3023 sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
3024 call_dissector(thread_mc_handle, sub_tvb, pinfo, tlv_tree);
3026 offset += tlv_len;
3028 break;
3030 case THREAD_NWD_TLV_SERVICE:
3032 uint8_t flags;
3033 uint8_t s_data_len;
3035 /* Flags and S_id */
3036 flags = tvb_get_uint8(tvb, offset);
3037 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_t, tvb, offset, 1, ENC_BIG_ENDIAN);
3038 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3039 offset++;
3040 tlv_offset = 1;
3042 /* Enterprise number */
3043 if ((flags & THREAD_NWD_TLV_SERVICE_T) == 0) {
3044 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_ent_num, tvb, offset, 4, ENC_BIG_ENDIAN);
3045 offset += 4;
3046 tlv_offset += 4;
3049 /* S_data */
3050 s_data_len = tvb_get_uint8(tvb, offset);
3051 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_len, tvb, offset, 1, ENC_BIG_ENDIAN);
3052 offset++;
3053 tlv_offset++;
3054 uint8_t thread_service_data = tvb_get_uint8(tvb, offset);
3055 // Thread 1.3 Service TLV code
3056 if((s_data_len == 2) && (thread_service_data == 0x5c))
3058 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
3059 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_srp_dataset_identifier, tvb, offset, 1, ENC_NA);
3060 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_anycast_seqno, tvb, offset + 1, 1, ENC_NA);
3061 offset += 2;
3062 tlv_offset += 2;
3063 g_server_decode = 2;
3064 } else if(((s_data_len == 1) && (thread_service_data == 0x5d)) || ((s_data_len == 19) && (thread_service_data == 0x5d)))
3066 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
3067 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_srp_dataset_identifier, tvb, offset, 1, ENC_NA);
3068 offset += 1;
3069 tlv_offset += 1;
3070 if(s_data_len == 1)
3072 g_server_decode = 3;
3074 else if(s_data_len == 19)
3076 g_server_decode = 2;
3077 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_unicast_ipv6_address, tvb, offset, 16, ENC_NA);
3078 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_unicast_port_number, tvb, offset + 16, 2, ENC_NA);
3079 offset += 18;
3080 tlv_offset += 18;
3083 else
3085 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
3086 offset += s_data_len;
3087 tlv_offset += s_data_len;
3088 //Flag to be 1 (BIG_ENDIAN so check the MSB) and thread_service_data = 1 then Server Sub TLV needs to be decoded with s_server_data fields
3089 if(((flags & THREAD_NWD_TLV_SERVICE_T) == THREAD_NWD_TLV_SERVICE_T) &&
3090 (thread_service_data == THREAD_SERVICE_DATA_BBR)) {
3091 g_server_decode = 1;
3093 else {
3094 g_server_decode = 0;
3098 // proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
3099 // offset += s_data_len;
3100 // tlv_offset += s_data_len;
3101 // //Flag to be 1 (BIG_ENDIAN so check the MSB) and thread_service_data = 1 then Server Sub TLV needs to be decoded with s_server_data fields
3102 // if(((flags & THREAD_NWD_TLV_SERVICE_T) == THREAD_NWD_TLV_SERVICE_T) &&
3103 // (thread_service_data == THREAD_SERVICE_DATA_BBR)) {
3104 // g_server_decode = 1;
3105 // }
3106 // else {
3107 // g_server_decode = 0;
3108 // }
3109 // Thread 1.3 Service TLV code
3111 /* sub-TLVs */
3113 if (tlv_offset < tlv_len) {
3114 proto_tree *sub_tlv_tree;
3115 unsigned remaining = tlv_len - tlv_offset;
3117 ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_sub_tlvs, tvb, offset, 1, ENC_NA);
3118 sub_tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_prefix_sub_tlvs);
3119 /* Call this dissector for sub-TLVs. Should only be server TLVs */
3120 sub_tvb = tvb_new_subset_length(tvb, offset, remaining); /* remove prefix length (1) and prefix (prefix_byte_len) */
3121 dissect_thread_nwd(sub_tvb, pinfo, sub_tlv_tree, data);
3122 offset += remaining;
3125 break;
3127 case THREAD_NWD_TLV_SERVER:
3129 if(g_server_decode == 1) {
3130 //2 bytes of server 16
3131 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
3132 offset += 2;
3133 /* tlv_offset = 2; */
3134 //7 bytes of server data
3135 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_seqno, tvb, offset, 1, ENC_NA);
3136 offset += 1;
3137 /* tlv_offset += 1; */
3138 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_rrdelay, tvb, offset, 2, ENC_NA);
3139 offset += 2;
3140 /* tlv_offset += 2; */
3141 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_mlrtimeout, tvb, offset, 4, ENC_NA);
3142 offset += 4;
3144 else if(g_server_decode == 0) {
3145 //2 bytes of server 16
3146 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
3147 offset += 2;
3148 tlv_offset = 2;
3150 if (tlv_offset < tlv_len)
3152 unsigned remaining = tlv_len - tlv_offset;
3153 //remaining bytes - server data
3154 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_data, tvb, offset, remaining, ENC_NA);
3155 offset += remaining;
3159 // Thread 1.3 Service TLV code
3160 else if(g_server_decode == 2) {
3161 //2 bytes of server 16
3162 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
3163 offset += 2;
3164 tlv_offset = 2;
3165 if (tlv_offset < tlv_len)
3167 unsigned remaining = tlv_len - tlv_offset;
3168 //remaining bytes - server data
3169 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_data, tvb, offset, remaining, ENC_NA);
3170 offset += remaining;
3173 else if(g_server_decode == 3) {
3174 //2 bytes of server 16
3175 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
3176 offset += 2;
3177 tlv_offset = 2;
3178 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_unicast_ipv6_address, tvb, offset, 16, ENC_NA);
3179 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_unicast_port_number, tvb, offset + 16, 2, ENC_NA);
3180 offset += 18;
3181 tlv_offset += 18;
3183 if (tlv_offset < tlv_len)
3185 unsigned remaining = tlv_len - tlv_offset;
3186 //remaining bytes - server data
3187 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_data, tvb, offset, remaining, ENC_NA);
3188 offset += remaining;
3191 // Thread 1.3 Service TLV code
3193 break;
3195 default:
3196 proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
3197 offset += tlv_len;
3200 decrement_dissection_depth(pinfo);
3201 return tvb_captured_length(tvb);
3204 static int
3205 dissect_thread_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3207 coap_info *coinfo;
3208 const char *uri;
3209 char **tokens;
3211 /* Obtain the CoAP info */
3212 coinfo = (coap_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_coap, 0);
3214 /* Reject the packet if not CoAP */
3215 if (!coinfo) return 0;
3217 uri = wmem_strbuf_get_str(coinfo->uri_str_strbuf);
3219 tokens = wmem_strsplit(pinfo->pool, uri, "/", 3);
3220 if (g_strv_length(tokens) == 3) {
3221 /* No need to create a subset as we are dissecting the tvb as it is. */
3222 dissector_try_string_with_data(thread_coap_namespace, tokens[1], tvb, pinfo, tree, true, NULL);
3225 return tvb_captured_length(tvb);
3228 static int dissect_thread_bcn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3230 ieee802154_packet *packet = (ieee802154_packet *)data;
3231 proto_item *ti, *beacon_root;
3232 proto_tree *beacon_tree;
3233 unsigned offset = 0;
3234 const uint8_t *ssid;
3235 uint8_t tlv_type, tlv_len;
3236 proto_tree *tlv_tree = NULL;
3238 /* Reject the packet if data is NULL */
3239 if (!packet) return 0;
3241 /* Add ourself to the protocol column. */
3242 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Thread");
3243 /* Create the tree for this beacon. */
3244 beacon_root = proto_tree_add_item(tree, proto_thread_bcn, tvb, 0, -1, ENC_NA);
3245 beacon_tree = proto_item_add_subtree(beacon_root, ett_thread_bcn);
3247 /* Update the info column. */
3248 col_clear(pinfo->cinfo, COL_INFO);
3249 col_append_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src16);
3251 /* Get and display the protocol id, must be 0x03 on all Thread beacons. */
3252 proto_tree_add_item(beacon_tree, hf_thread_bcn_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
3253 offset += 1;
3255 /* Get and display the beacon flags */
3256 proto_tree_add_item(beacon_tree, hf_thread_bcn_joining, tvb, offset, 1, ENC_BIG_ENDIAN);
3257 proto_tree_add_item(beacon_tree, hf_thread_bcn_native, tvb, offset, 1, ENC_BIG_ENDIAN);
3258 proto_tree_add_item(beacon_tree, hf_thread_bcn_version, tvb, offset, 1, ENC_BIG_ENDIAN);
3259 offset += 1;
3261 /* Get and display the network ID. */
3262 proto_tree_add_item_ret_string(beacon_tree, hf_thread_bcn_network_id, tvb, offset, 16, ENC_ASCII|ENC_NA, pinfo->pool, &ssid);
3263 col_append_fstr(pinfo->cinfo, COL_INFO, ", Network ID: %s", ssid);
3264 offset += 16;
3266 /* See if we're at the end */
3267 if (offset >= tvb_captured_length(tvb)) {
3268 return tvb_captured_length(tvb);
3271 /* XPANID */
3272 proto_tree_add_item(beacon_tree, hf_thread_bcn_epid, tvb, offset, 8, ENC_BIG_ENDIAN);
3273 offset += 8;
3275 /* See if we're at the end */
3276 if (offset >= tvb_captured_length(tvb)) {
3277 return tvb_captured_length(tvb);
3280 /* Steering data TLV present */
3282 /* Get the length ahead of time to pass to next function so we can highlight
3283 proper amount of bytes */
3284 tlv_len = tvb_get_uint8(tvb, offset+1);
3286 /* Type */
3287 ti = proto_tree_add_item(beacon_tree, hf_thread_bcn_tlv, tvb, offset, tlv_len+2, ENC_NA);
3288 tlv_tree = proto_item_add_subtree(ti, ett_thread_bcn_tlv);
3289 proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3291 tlv_type = tvb_get_uint8(tvb, offset);
3292 offset++;
3294 /* Add value name to value root label */
3295 proto_item_append_text(ti, " (%s)", val_to_str(tlv_type, thread_bcn_tlv_vals, "Unknown (%d)"));
3297 /* Length */
3298 proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
3299 offset++;
3301 if (tlv_len) { /* Belt 'n' braces check */
3302 switch (tlv_type) {
3303 case THREAD_BCN_TLV_STEERING_DATA:
3304 proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_steering_data, tvb, offset, tlv_len, ENC_NA);
3305 /* offset += tlv_len; */
3306 break;
3307 default:
3308 proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
3309 /* offset += tlv_len; */
3310 break;
3313 return tvb_captured_length(tvb);
3316 static bool
3317 dissect_thread_bcn_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3319 ieee802154_packet *packet = (ieee802154_packet *)data;
3321 /* Thread beacon frames can be 16 or 64-bit source */
3322 if (!packet) return false;
3323 if (!((packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
3324 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT))) return false;
3326 if (tvb_captured_length(tvb) > 0) {
3327 /* Thread beacons begin with a protocol identifier. */
3328 if (tvb_get_uint8(tvb, 0) != THREAD_BCN_PROTOCOL_ID) return false;
3329 dissect_thread_bcn(tvb, pinfo, tree, packet);
3330 return true;
3332 return false;
3335 void
3336 proto_register_thread_nm(void)
3338 static hf_register_info hf[] = {
3340 /* Generic TLV */
3341 { &hf_thread_nm_tlv,
3342 { "TLV",
3343 "thread_nm.tlv",
3344 FT_NONE, BASE_NONE, NULL, 0x0,
3345 "Type-Length-Value",
3346 HFILL
3349 { &hf_thread_nm_tlv_type,
3350 { "Type",
3351 "thread_nm.tlv.type",
3352 FT_UINT8, BASE_DEC, VALS(thread_nm_tlv_vals), 0x0,
3353 "Type of value",
3354 HFILL
3357 { &hf_thread_nm_tlv_length,
3358 { "Length",
3359 "thread_nm.tlv.len",
3360 FT_UINT8, BASE_DEC, NULL, 0x0,
3361 "Length of value",
3362 HFILL
3365 { &hf_thread_nm_tlv_unknown,
3366 { "Unknown",
3367 "thread_nm.tlv.unknown",
3368 FT_BYTES, BASE_NONE, NULL, 0x0,
3369 "Unknown TLV, raw value",
3370 HFILL }
3372 #if 0
3373 { &hf_thread_nm_tlv_sub_tlvs,
3374 { "Sub-TLV(s)",
3375 "thread_nm.tlv.sub_tlvs",
3376 FT_NONE, BASE_NONE, NULL, 0x0,
3377 NULL,
3378 HFILL
3381 #endif
3382 /* Type-Specific TLV Fields */
3383 { &hf_thread_nm_tlv_target_eid,
3384 { "Target EID",
3385 "thread_nm.tlv.target_eid",
3386 FT_IPv6, BASE_NONE, NULL, 0x0,
3387 NULL,
3388 HFILL
3391 { &hf_thread_nm_tlv_ext_mac_addr,
3392 { "Extended MAC Address",
3393 "thread_nm.tlv.ext_mac_addr",
3394 FT_EUI64, BASE_NONE, NULL, 0x0,
3395 NULL,
3396 HFILL
3399 { &hf_thread_nm_tlv_rloc16,
3400 { "RLOC16",
3401 "thread_nm.tlv.rloc16",
3402 FT_UINT16, BASE_HEX, NULL, 0x0,
3403 NULL,
3404 HFILL
3407 { &hf_thread_nm_tlv_ml_eid,
3408 { "ML-EID",
3409 "thread_nm.tlv.ml_eid",
3410 FT_BYTES, BASE_NONE, NULL, 0x0,
3411 NULL,
3412 HFILL
3415 { &hf_thread_nm_tlv_status,
3416 { "Status",
3417 "thread_nm.tlv.status",
3418 FT_UINT8, BASE_DEC, VALS(thread_nm_tlv_status_vals), 0x0,
3419 NULL,
3420 HFILL
3423 { &hf_thread_nm_tlv_last_transaction_time,
3424 { "Last Transaction Time",
3425 "thread_nm.tlv.last_transaction_time",
3426 FT_UINT32, BASE_DEC, NULL, 0x0,
3427 NULL,
3428 HFILL
3431 { &hf_thread_nm_tlv_router_mask_id_seq,
3432 { "ID Sequence",
3433 "thread_nm.tlv.router_mask_id_seq",
3434 FT_UINT8, BASE_DEC, NULL, 0x0,
3435 NULL,
3436 HFILL
3439 { &hf_thread_nm_tlv_router_mask_assigned,
3440 { "Assigned Router ID Mask",
3441 "thread_nm.tlv.router_mask_assigned",
3442 FT_BYTES, BASE_NONE, NULL, 0x0,
3443 NULL,
3444 HFILL
3447 { &hf_thread_nm_tlv_nd_option,
3448 { "ND Option",
3449 "thread_nm.tlv.nd_option",
3450 FT_BYTES, BASE_NONE, NULL, 0x0,
3451 NULL,
3452 HFILL
3455 { &hf_thread_nm_tlv_nd_data,
3456 { "ND Data",
3457 "thread_nm.tlv.nd_data",
3458 FT_BYTES, BASE_NONE, NULL, 0x0,
3459 NULL,
3460 HFILL
3463 { &hf_thread_nm_tlv_timeout,
3464 { "Timeout",
3465 "thread_nm.tlv.timeout",
3466 FT_UINT32, BASE_DEC, NULL, 0x0,
3467 NULL,
3468 HFILL
3473 static int *ett[] = {
3474 &ett_thread_nm,
3475 &ett_thread_nm_tlv,
3476 /* These need to be registered somewhere.. */
3477 &ett_thread,
3478 &ett_thread_ie_fields
3481 static ei_register_info ei[] = {
3482 #if 0
3483 { &ei_thread_nm_tlv_length_failed,{ "thread_nm.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL } },
3484 #endif
3485 { &ei_thread_nm_len_size_mismatch,{ "thread_nm.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL } },
3488 expert_module_t* expert_thread_nm;
3490 proto_thread_nm = proto_register_protocol("Thread Network Management", "Thread Network Management", "thread_nm");
3491 proto_register_field_array(proto_thread_nm, hf, array_length(hf));
3492 proto_register_subtree_array(ett, array_length(ett));
3493 expert_thread_nm = expert_register_protocol(proto_thread_nm);
3494 expert_register_field_array(expert_thread_nm, ei, array_length(ei));
3496 thread_nm_handle = register_dissector("thread_nm", dissect_thread_nm, proto_thread_nm);
3499 void
3500 proto_register_thread_bl(void)
3502 static hf_register_info hf[] = {
3504 /* Generic TLV */
3505 { &hf_thread_bl_tlv,
3506 { "TLV",
3507 "thread_bl.tlv",
3508 FT_NONE, BASE_NONE, NULL, 0x0,
3509 "Type-Length-Value",
3510 HFILL
3514 { &hf_thread_bl_tlv_type,
3515 { "Type",
3516 "thread_bl.tlv.type",
3517 FT_UINT8, BASE_DEC, VALS(thread_bl_tlv_vals), 0x0,
3518 "Type of value",
3519 HFILL
3523 { &hf_thread_bl_tlv_length,
3524 { "Length",
3525 "thread_bl.tlv.len",
3526 FT_UINT8, BASE_DEC, NULL, 0x0,
3527 "Length of value",
3528 HFILL
3532 { &hf_thread_bl_tlv_unknown,
3533 { "Unknown",
3534 "thread_bl.tlv.unknown",
3535 FT_BYTES, BASE_NONE, NULL, 0x0,
3536 "Unknown TLV, raw value",
3537 HFILL
3540 #if 0
3541 { &hf_thread_bl_tlv_sub_tlvs,
3542 { "Sub-TLV(s)",
3543 "thread_bl.tlv.sub_tlvs",
3544 FT_NONE, BASE_NONE, NULL, 0x0,
3545 NULL,
3546 HFILL
3549 #endif
3550 /* Type-Specific TLV Fields */
3551 { &hf_thread_bl_tlv_target_eid,
3552 { "Target EID",
3553 "thread_bl.tlv.target_eid",
3554 FT_IPv6, BASE_NONE, NULL, 0x0,
3555 NULL,
3556 HFILL
3560 { &hf_thread_bl_tlv_ext_mac_addr,
3561 { "Extended MAC Address",
3562 "thread_bl.tlv.ext_mac_addr",
3563 FT_EUI64, BASE_NONE, NULL, 0x0,
3564 NULL,
3565 HFILL }
3568 { &hf_thread_bl_tlv_rloc16,
3569 { "RLOC16",
3570 "thread_bl.tlv.rloc16",
3571 FT_UINT16, BASE_HEX, NULL, 0x0,
3572 NULL,
3573 HFILL }
3576 { &hf_thread_bl_tlv_ml_eid,
3577 { "ML-EID",
3578 "thread_bl.tlv.ml_eid",
3579 FT_BYTES, BASE_NONE, NULL, 0x0,
3580 NULL,
3581 HFILL }
3584 { &hf_thread_bl_tlv_status,
3585 { "Status",
3586 "thread_bl.tlv.status",
3587 FT_UINT8, BASE_DEC, VALS(thread_bl_tlv_status_vals), 0x0,
3588 NULL,
3589 HFILL }
3591 #if 0
3592 { &hf_thread_bl_tlv_attached_time,
3593 { "Attached Time",
3594 "thread_bl.tlv.attached_time",
3595 FT_UINT32, BASE_DEC, NULL, 0x0,
3596 NULL,
3597 HFILL }
3599 #endif
3600 { &hf_thread_bl_tlv_last_transaction_time,
3601 { "Last Transaction Time",
3602 "thread_bl.tlv.last_transaction_time",
3603 FT_UINT32, BASE_DEC, NULL, 0x0,
3604 NULL,
3605 HFILL }
3608 { &hf_thread_bl_tlv_router_mask_id_seq,
3609 { "ID Sequence",
3610 "thread_bl.tlv.router_mask_id_seq",
3611 FT_UINT8, BASE_DEC, NULL, 0x0,
3612 NULL,
3613 HFILL }
3616 { &hf_thread_bl_tlv_router_mask_assigned,
3617 { "Assigned Router ID Mask",
3618 "thread_bl.tlv.router_mask_assigned",
3619 FT_BYTES, BASE_NONE, NULL, 0x0,
3620 NULL,
3621 HFILL }
3624 { &hf_thread_bl_tlv_nd_option,
3625 { "ND Option",
3626 "thread_bl.tlv.nd_option",
3627 FT_BYTES, BASE_NONE, NULL, 0x0,
3628 NULL,
3629 HFILL }
3632 { &hf_thread_bl_tlv_nd_data,
3633 { "ND Data",
3634 "thread_bl.tlv.nd_data",
3635 FT_BYTES, BASE_NONE, NULL, 0x0,
3636 NULL,
3637 HFILL }
3639 { &hf_thread_bl_tlv_timeout,
3640 { "Timeout",
3641 "thread_bl.tlv.timeout",
3642 FT_UINT32, BASE_DEC, NULL, 0x0,
3643 NULL,
3644 HFILL }
3651 static int *ett[] = {
3652 &ett_thread_bl,
3653 &ett_thread_bl_tlv,
3656 static ei_register_info ei[] = {
3657 #if 0
3658 { &ei_thread_bl_tlv_length_failed,{ "thread_bl.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL } },
3659 #endif
3660 { &ei_thread_bl_len_size_mismatch,{ "thread_bl.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL } },
3663 expert_module_t* expert_thread_bl;
3665 proto_thread_bl = proto_register_protocol("Thread Backbone Link", "Thread Backbone Link", "thread_bl");
3666 proto_register_field_array(proto_thread_bl, hf, array_length(hf));
3667 proto_register_subtree_array(ett, array_length(ett));
3668 expert_thread_bl = expert_register_protocol(proto_thread_bl);
3669 expert_register_field_array(expert_thread_bl, ei, array_length(ei));
3671 thread_bl_handle = register_dissector("thread_bl", dissect_thread_bl, proto_thread_bl);
3674 void
3675 proto_register_thread_address(void)
3677 static hf_register_info hf[] = {
3679 /* Generic TLV */
3680 { &hf_thread_address_tlv,
3681 { "TLV",
3682 "thread_address.tlv",
3683 FT_NONE, BASE_NONE, NULL, 0x0,
3684 "Type-Length-Value",
3685 HFILL }
3688 { &hf_thread_address_tlv_type,
3689 { "Type",
3690 "thread_address.tlv.type",
3691 FT_UINT8, BASE_DEC, VALS(thread_address_tlv_vals), 0x0,
3692 "Type of value",
3693 HFILL }
3696 { &hf_thread_address_tlv_length,
3697 { "Length",
3698 "thread_address.tlv.len",
3699 FT_UINT8, BASE_DEC, NULL, 0x0,
3700 "Length of value",
3701 HFILL }
3704 { &hf_thread_address_tlv_unknown,
3705 { "Unknown",
3706 "thread_address.tlv.unknown",
3707 FT_BYTES, BASE_NONE, NULL, 0x0,
3708 "Unknown TLV, raw value",
3709 HFILL }
3711 #if 0
3712 { &hf_thread_address_tlv_sub_tlvs,
3713 { "Sub-TLV(s)",
3714 "thread_address.tlv.sub_tlvs",
3715 FT_NONE, BASE_NONE, NULL, 0x0,
3716 NULL,
3717 HFILL }
3719 #endif
3720 /* Type-Specific TLV Fields */
3721 { &hf_thread_address_tlv_target_eid,
3722 { "Target EID",
3723 "thread_address.tlv.target_eid",
3724 FT_IPv6, BASE_NONE, NULL, 0x0,
3725 NULL,
3726 HFILL }
3729 { &hf_thread_address_tlv_ext_mac_addr,
3730 { "Extended MAC Address",
3731 "thread_address.tlv.ext_mac_addr",
3732 FT_EUI64, BASE_NONE, NULL, 0x0,
3733 NULL,
3734 HFILL }
3737 { &hf_thread_address_tlv_rloc16,
3738 { "RLOC16",
3739 "thread_address.tlv.rloc16",
3740 FT_UINT16, BASE_HEX, NULL, 0x0,
3741 NULL,
3742 HFILL }
3745 { &hf_thread_address_tlv_ml_eid,
3746 { "ML-EID",
3747 "thread_address.tlv.ml_eid",
3748 FT_BYTES, BASE_NONE, NULL, 0x0,
3749 NULL,
3750 HFILL }
3753 { &hf_thread_address_tlv_status,
3754 { "Status",
3755 "thread_address.tlv.status",
3756 FT_UINT8, BASE_DEC, VALS(thread_address_tlv_status_vals), 0x0,
3757 NULL,
3758 HFILL }
3760 #if 0
3761 { &hf_thread_address_tlv_attached_time,
3762 { "Attached Time",
3763 "thread_address.tlv.attached_time",
3764 FT_UINT32, BASE_DEC, NULL, 0x0,
3765 NULL,
3766 HFILL }
3768 #endif
3769 { &hf_thread_address_tlv_last_transaction_time,
3770 { "Last Transaction Time",
3771 "thread_address.tlv.last_transaction_time",
3772 FT_UINT32, BASE_DEC, NULL, 0x0,
3773 NULL,
3774 HFILL }
3777 { &hf_thread_address_tlv_router_mask_id_seq,
3778 { "ID Sequence",
3779 "thread_address.tlv.router_mask_id_seq",
3780 FT_UINT8, BASE_DEC, NULL, 0x0,
3781 NULL,
3782 HFILL }
3785 { &hf_thread_address_tlv_router_mask_assigned,
3786 { "Assigned Router ID Mask",
3787 "thread_address.tlv.router_mask_assigned",
3788 FT_BYTES, BASE_NONE, NULL, 0x0,
3789 NULL,
3790 HFILL }
3793 { &hf_thread_address_tlv_nd_option,
3794 { "ND Option",
3795 "thread_address.tlv.nd_option",
3796 FT_BYTES, BASE_NONE, NULL, 0x0,
3797 NULL,
3798 HFILL }
3801 { &hf_thread_address_tlv_nd_data,
3802 { "ND Data",
3803 "thread_address.tlv.nd_data",
3804 FT_BYTES, BASE_NONE, NULL, 0x0,
3805 NULL,
3806 HFILL }
3809 { &hf_thread_address_tlv_timeout,
3810 { "Timeout",
3811 "thread_address.tlv.timeout",
3812 FT_UINT32, BASE_DEC, NULL, 0x0,
3813 NULL,
3814 HFILL }
3818 static int *ett[] = {
3819 &ett_thread_address,
3820 &ett_thread_address_tlv,
3823 static ei_register_info ei[] = {
3824 #if 0
3825 { &ei_thread_address_tlv_length_failed, { "thread_address.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
3826 #endif
3827 { &ei_thread_address_len_size_mismatch, { "thread_address.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
3830 expert_module_t* expert_thread_address;
3832 proto_thread_address = proto_register_protocol("Thread Address", "Thread Address", "thread_address");
3833 proto_register_field_array(proto_thread_address, hf, array_length(hf));
3834 proto_register_subtree_array(ett, array_length(ett));
3835 expert_thread_address = expert_register_protocol(proto_thread_address);
3836 expert_register_field_array(expert_thread_address, ei, array_length(ei));
3838 thread_address_handle = register_dissector("thread_address", dissect_thread_address, proto_thread_address);
3841 void
3842 proto_register_thread_dg(void)
3844 static hf_register_info hf[] = {
3846 /* Generic TLV */
3847 { &hf_thread_dg_tlv,
3848 { "TLV",
3849 "thread_diagnostic.tlv",
3850 FT_NONE, BASE_NONE, NULL, 0x0,
3851 "Type-Length-Value",
3852 HFILL }
3855 { &hf_thread_dg_tlv_type,
3856 { "Type",
3857 "thread_diagnostic.tlv.type",
3858 FT_UINT8, BASE_DEC, VALS(thread_dg_tlv_vals), 0x0,
3859 "Type of value",
3860 HFILL }
3863 { &hf_thread_dg_tlv_length8,
3864 { "Length",
3865 "thread_diagnostic.tlv.len8",
3866 FT_UINT8, BASE_DEC, NULL, 0x0,
3867 "Length of value (8-bit)",
3868 HFILL }
3871 { &hf_thread_dg_tlv_length16,
3872 { "Length",
3873 "thread_diagnostic.tlv.len16",
3874 FT_UINT16, BASE_DEC, NULL, 0x0,
3875 "Length of value (16-bit)",
3876 HFILL }
3879 { &hf_thread_dg_tlv_general,
3880 { "General",
3881 "thread_diagnostic.tlv.general",
3882 FT_BYTES, BASE_NONE, NULL, 0x0,
3883 "General TLV, raw value",
3884 HFILL }
3887 { &hf_thread_dg_tlv_unknown,
3888 { "Unknown",
3889 "thread_diagnostic.tlv.unknown",
3890 FT_BYTES, BASE_NONE, NULL, 0x0,
3891 "Unknown TLV, raw value",
3892 HFILL }
3896 static int *ett[] = {
3897 &ett_thread_dg,
3898 &ett_thread_dg_tlv,
3901 #if 0
3902 static ei_register_info ei[] = {
3903 { &ei_thread_dg_tlv_length_failed, { "thread_diagnostic.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
3904 { &ei_thread_dg_len_size_mismatch, { "thread_diagnostic.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
3907 expert_module_t* expert_thread_dg;
3908 #endif
3910 proto_thread_dg = proto_register_protocol("Thread Diagnostics", "Thread Diagnostics", "thread_diagnostic");
3911 proto_register_field_array(proto_thread_dg, hf, array_length(hf));
3912 proto_register_subtree_array(ett, array_length(ett));
3913 #if 0
3914 expert_thread_dg = expert_register_protocol(proto_thread_dg);
3915 expert_register_field_array(expert_thread_dg, ei, array_length(ei));
3916 #endif
3918 thread_dg_handle = register_dissector("thread_diagnostic", dissect_thread_dg, proto_thread_dg);
3921 void
3922 proto_register_thread_mc(void)
3924 static hf_register_info hf[] = {
3926 /* Generic TLV */
3927 { &hf_thread_mc_tlv,
3928 { "TLV",
3929 "thread_meshcop.tlv",
3930 FT_NONE, BASE_NONE, NULL, 0x0,
3931 "Type-Length-Value",
3932 HFILL }
3935 { &hf_thread_mc_tlv_type,
3936 { "Type",
3937 "thread_meshcop.tlv.type",
3938 FT_UINT8, BASE_DEC, VALS(thread_mc_tlv_vals), 0x0,
3939 "Type of value",
3940 HFILL }
3943 { &hf_thread_mc_tlv_length8,
3944 { "Length",
3945 "thread_meshcop.tlv.len8",
3946 FT_UINT8, BASE_DEC, NULL, 0x0,
3947 "Length of value (8-bit)",
3948 HFILL }
3951 { &hf_thread_mc_tlv_length16,
3952 { "Length",
3953 "thread_meshcop.tlv.len16",
3954 FT_UINT16, BASE_DEC, NULL, 0x0,
3955 "Length of value (16-bit)",
3956 HFILL }
3959 { &hf_thread_mc_tlv_unknown,
3960 { "Unknown",
3961 "thread_meshcop.tlv.unknown",
3962 FT_BYTES, BASE_NONE, NULL, 0x0,
3963 "Unknown TLV, raw value",
3964 HFILL }
3966 #if 0
3967 { &hf_thread_mc_tlv_sub_tlvs,
3968 { "Sub-TLV(s)",
3969 "thread_meshcop.tlv.sub_tlvs",
3970 FT_NONE, BASE_NONE, NULL, 0x0,
3971 NULL,
3972 HFILL }
3974 #endif
3975 /* Type-Specific TLV Fields */
3976 { &hf_thread_mc_tlv_channel_page,
3977 { "Channel Page",
3978 "thread_meshcop.tlv.channel_page",
3979 FT_UINT8, BASE_DEC, NULL, 0x0,
3980 NULL,
3981 HFILL }
3984 { &hf_thread_mc_tlv_channel,
3985 { "Channel",
3986 "thread_meshcop.tlv.channel",
3987 FT_UINT16, BASE_DEC, NULL, 0x0,
3988 NULL,
3989 HFILL }
3992 { &hf_thread_mc_tlv_pan_id,
3993 { "PAN ID",
3994 "thread_meshcop.tlv.pan_id",
3995 FT_UINT16, BASE_HEX, NULL, 0x0,
3996 NULL,
3997 HFILL }
4000 { &hf_thread_mc_tlv_xpan_id,
4001 { "Extended PAN ID",
4002 "thread_meshcop.tlv.xpan_id",
4003 FT_UINT64, BASE_HEX, NULL, 0x0,
4004 NULL,
4005 HFILL }
4008 { &hf_thread_mc_tlv_net_name,
4009 { "Network Name",
4010 "thread_meshcop.tlv.net_name",
4011 FT_STRING, BASE_NONE, NULL, 0x0,
4012 NULL,
4013 HFILL }
4016 { &hf_thread_mc_tlv_pskc,
4017 { "PSKc",
4018 "thread_meshcop.tlv.pskc",
4019 FT_BYTES, BASE_NONE, NULL, 0x0,
4020 NULL,
4021 HFILL }
4024 { &hf_thread_mc_tlv_master_key,
4025 { "Master Key",
4026 "thread_meshcop.tlv.master_key",
4027 FT_BYTES, BASE_NONE, NULL, 0x0,
4028 NULL,
4029 HFILL }
4032 { &hf_thread_mc_tlv_net_key_seq_ctr,
4033 { "Network Key Sequence Counter",
4034 "thread_meshcop.tlv.net_key_seq_ctr",
4035 FT_BYTES, BASE_NONE, NULL, 0x0,
4036 NULL,
4037 HFILL }
4040 { &hf_thread_mc_tlv_ml_prefix,
4041 { "Mesh Local Prefix",
4042 "thread_meshcop.tlv.ml_prefix",
4043 FT_IPv6, BASE_NONE, NULL, 0x0,
4044 NULL,
4045 HFILL }
4048 { &hf_thread_mc_tlv_steering_data,
4049 { "Steering Data",
4050 "thread_meshcop.tlv.steering_data",
4051 FT_BYTES, BASE_NONE, NULL, 0x0,
4052 NULL,
4053 HFILL }
4056 { &hf_thread_mc_tlv_ba_locator,
4057 { "Border Agent Locator",
4058 "thread_meshcop.tlv.ba_locator",
4059 FT_BYTES, BASE_NONE, NULL, 0x0,
4060 NULL,
4061 HFILL }
4064 { &hf_thread_mc_tlv_commissioner_id,
4065 { "Commissioner ID",
4066 "thread_meshcop.tlv.commissioner_id",
4067 FT_STRING, BASE_NONE, NULL, 0x0,
4068 NULL,
4069 HFILL }
4072 { &hf_thread_mc_tlv_commissioner_sess_id,
4073 { "Commissioner Session ID",
4074 "thread_meshcop.tlv.commissioner_sess_id",
4075 FT_BYTES, BASE_NONE, NULL, 0x0,
4076 NULL,
4077 HFILL }
4080 { &hf_thread_mc_tlv_sec_policy_rot,
4081 { "Rotation Time",
4082 "thread_meshcop.tlv.sec_policy_rot",
4083 FT_UINT16, BASE_DEC, NULL, 0x0,
4084 NULL,
4085 HFILL }
4088 { &hf_thread_mc_tlv_sec_policy_o,
4089 { "Out-of-band Commissioning",
4090 "thread_meshcop.tlv.sec_policy_o",
4091 FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_O_MASK,
4092 NULL,
4093 HFILL }
4096 { &hf_thread_mc_tlv_sec_policy_n,
4097 { "Native Commissioning",
4098 "thread_meshcop.tlv.sec_policy_n",
4099 FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_N_MASK,
4100 NULL,
4101 HFILL }
4104 { &hf_thread_mc_tlv_sec_policy_r,
4105 { "Thread 1.x Routers",
4106 "thread_meshcop.tlv.sec_policy_r",
4107 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_R_MASK,
4108 NULL,
4109 HFILL }
4112 { &hf_thread_mc_tlv_sec_policy_c,
4113 { "PSKc-based Commissioning",
4114 "thread_meshcop.tlv.sec_policy_c",
4115 FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_C_MASK,
4116 NULL,
4117 HFILL }
4120 { &hf_thread_mc_tlv_sec_policy_b,
4121 { "Thread 1.x Beacons",
4122 "thread_meshcop.tlv.sec_policy_b",
4123 FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_B_MASK,
4124 NULL,
4125 HFILL }
4128 { &hf_thread_mc_tlv_sec_policy_ccm,
4129 { "Commercial Commissioning Mode Bit disabled",
4130 "thread_meshcop.tlv.sec_policy_ccm",
4131 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_CCM_MASK,
4132 NULL,
4133 HFILL }
4136 { &hf_thread_mc_tlv_sec_policy_ae,
4137 { "Autonomous Enrollment disabled",
4138 "thread_meshcop.tlv.sec_policy_ae",
4139 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_AE_MASK,
4140 NULL,
4141 HFILL }
4144 { &hf_thread_mc_tlv_sec_policy_nmp,
4145 { "Network Master-key Provisioning disabled",
4146 "thread_meshcop.tlv.sec_policy_nmp",
4147 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_NMP_MASK,
4148 NULL,
4149 HFILL }
4152 { &hf_thread_mc_tlv_sec_policy_l,
4153 { "ToBLE Link Enabled",
4154 "thread_meshcop.tlv.sec_policy_l",
4155 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_L_MASK,
4156 NULL,
4157 HFILL }
4160 { &hf_thread_mc_tlv_sec_policy_ncr,
4161 { "Non-CCM Routers disabled",
4162 "thread_meshcop.tlv.sec_policy_ncr",
4163 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_NCR_MASK,
4164 NULL,
4165 HFILL }
4168 { &hf_thread_mc_tlv_sec_policy_rsv,
4169 { "Reserved Bits",
4170 "thread_meshcop.tlv.sec_policy_rsv",
4171 FT_UINT8, BASE_DEC, NULL, THREAD_MC_SEC_POLICY_MASK_RSV_MASK,
4172 NULL,
4173 HFILL }
4176 { &hf_thread_mc_tlv_sec_policy_rsv1,
4177 { "Reserved Bits",
4178 "thread_meshcop.tlv.sec_policy_rsv",
4179 FT_UINT8, BASE_DEC, NULL, THREAD_MC_SEC_POLICY_MASK_RSV1_MASK,
4180 NULL,
4181 HFILL }
4184 { &hf_thread_mc_tlv_sec_policy_vr,
4185 { "Version-threshold for Routing",
4186 "thread_meshcop.tlv.sec_policy_vr",
4187 FT_UINT8, BASE_DEC, NULL, THREAD_MC_SEC_POLICY_MASK_VR_MASK,
4188 NULL,
4189 HFILL }
4192 { &hf_thread_mc_tlv_state,
4193 { "State",
4194 "thread_meshcop.tlv.state",
4195 FT_INT8, BASE_DEC, VALS(thread_mc_state_vals), 0x0,
4196 NULL,
4197 HFILL }
4200 { &hf_thread_mc_tlv_active_tstamp,
4201 { "Active Timestamp",
4202 "thread_meshcop.tlv.active_tstamp",
4203 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
4204 NULL,
4205 HFILL }
4208 { &hf_thread_mc_tlv_pending_tstamp,
4209 { "Pending Timestamp",
4210 "thread_meshcop.tlv.pending_tstamp",
4211 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
4212 NULL,
4213 HFILL }
4216 { &hf_thread_mc_tlv_udp_port,
4217 { "UDP Port",
4218 "thread_meshcop.tlv.udp_port",
4219 FT_UINT16, BASE_DEC, NULL, 0x0,
4220 NULL,
4221 HFILL }
4224 { &hf_thread_mc_tlv_iid,
4225 { "Interface Identifier",
4226 "thread_meshcop.tlv.iid",
4227 FT_BYTES, BASE_NONE, NULL, 0x0,
4228 NULL,
4229 HFILL }
4232 { &hf_thread_mc_tlv_jr_locator,
4233 { "Joiner Router Locator",
4234 "thread_meshcop.tlv.jr_locator",
4235 FT_BYTES, BASE_NONE, NULL, 0x0,
4236 NULL,
4237 HFILL }
4240 { &hf_thread_mc_tlv_kek,
4241 { "Key Encryption Key (KEK)",
4242 "thread_meshcop.tlv.kek",
4243 FT_BYTES, BASE_NONE, NULL, 0x0,
4244 NULL,
4245 HFILL }
4248 { &hf_thread_mc_tlv_provisioning_url,
4249 { "Provisioning URL",
4250 "thread_meshcop.tlv.provisioning_url",
4251 FT_STRING, BASE_NONE, NULL, 0x0,
4252 NULL,
4253 HFILL }
4256 { &hf_thread_mc_tlv_vendor_name,
4257 { "Vendor Name",
4258 "thread_meshcop.tlv.vendor_name",
4259 FT_STRING, BASE_NONE, NULL, 0x0,
4260 NULL,
4261 HFILL }
4264 { &hf_thread_mc_tlv_vendor_model,
4265 { "Vendor Model",
4266 "thread_meshcop.tlv.vendor_model",
4267 FT_STRING, BASE_NONE, NULL, 0x0,
4268 NULL,
4269 HFILL }
4272 { &hf_thread_mc_tlv_vendor_sw_ver,
4273 { "Vendor Software Version",
4274 "thread_meshcop.tlv.vendor_sw_ver",
4275 FT_STRING, BASE_NONE, NULL, 0x0,
4276 NULL,
4277 HFILL }
4280 { &hf_thread_mc_tlv_vendor_data,
4281 { "Vendor Data",
4282 "thread_meshcop.tlv.vendor_data",
4283 FT_STRING, BASE_NONE, NULL, 0x0,
4284 NULL,
4285 HFILL }
4288 { &hf_thread_mc_tlv_vendor_stack_ver_oui,
4289 { "OUI",
4290 "thread_meshcop.tlv.vendor_stack_ver_oui",
4291 FT_UINT24, BASE_OUI, NULL, 0x0,
4292 NULL,
4293 HFILL }
4296 { &hf_thread_mc_tlv_vendor_stack_ver_build,
4297 { "Build",
4298 "thread_meshcop.tlv.vendor_stack_ver_build",
4299 FT_UINT16, BASE_DEC, NULL, 0x0,
4300 NULL,
4301 HFILL }
4304 { &hf_thread_mc_tlv_vendor_stack_ver_rev,
4305 { "Revision",
4306 "thread_meshcop.tlv.vendor_stack_ver_rev",
4307 FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_REV_MASK,
4308 NULL,
4309 HFILL }
4312 { &hf_thread_mc_tlv_vendor_stack_ver_min,
4313 { "Minor",
4314 "thread_meshcop.tlv.vendor_stack_ver_min",
4315 FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_MIN_MASK,
4316 NULL,
4317 HFILL }
4320 { &hf_thread_mc_tlv_vendor_stack_ver_maj,
4321 { "Major",
4322 "thread_meshcop.tlv.vendor_stack_ver_maj",
4323 FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_MAJ_MASK,
4324 NULL,
4325 HFILL }
4328 { &hf_thread_mc_tlv_udp_encap_src_port,
4329 { "Source UDP Port",
4330 "thread_meshcop.tlv.udp_encap_src_port",
4331 FT_UINT16, BASE_DEC, NULL, 0x0,
4332 NULL,
4333 HFILL }
4336 { &hf_thread_mc_tlv_udp_encap_dst_port,
4337 { "Destination UDP Port",
4338 "thread_meshcop.tlv.udp_encap_dst_port",
4339 FT_UINT16, BASE_DEC, NULL, 0x0,
4340 NULL,
4341 HFILL }
4344 { &hf_thread_mc_tlv_ipv6_addr,
4345 { "IPv6 Address",
4346 "thread_meshcop.tlv.ipv6_addr",
4347 FT_IPv6, BASE_NONE, NULL, 0x0,
4348 NULL,
4349 HFILL }
4352 { &hf_thread_mc_tlv_delay_timer,
4353 { "Delay Timer",
4354 "thread_meshcop.tlv.delay_timer",
4355 FT_UINT32, BASE_DEC, NULL, 0x0,
4356 NULL,
4357 HFILL }
4360 { &hf_thread_mc_tlv_chan_mask,
4361 { "Channel Mask",
4362 "thread_meshcop.tlv.chan_mask",
4363 FT_NONE, BASE_NONE, NULL, 0x0,
4364 NULL,
4365 HFILL }
4368 { &hf_thread_mc_tlv_chan_mask_page,
4369 { "Channel Page",
4370 "thread_meshcop.tlv.chan_mask_page",
4371 FT_UINT8, BASE_DEC, NULL, 0,
4372 NULL,
4373 HFILL }
4376 { &hf_thread_mc_tlv_chan_mask_len,
4377 { "Mask Length",
4378 "thread_meshcop.tlv.chan_mask_len",
4379 FT_UINT8, BASE_DEC, NULL, 0,
4380 NULL,
4381 HFILL }
4384 { &hf_thread_mc_tlv_chan_mask_mask,
4385 { "Mask",
4386 "thread_meshcop.tlv.chan_mask_mask",
4387 FT_BYTES, BASE_NONE, NULL, 0x0,
4388 NULL,
4389 HFILL }
4392 { &hf_thread_mc_tlv_el_count,
4393 { "Count",
4394 "thread_meshcop.tlv.el_count",
4395 FT_NONE, BASE_NONE, NULL, 0x0,
4396 NULL,
4397 HFILL }
4400 { &hf_thread_mc_tlv_count,
4401 { "Count",
4402 "thread_meshcop.tlv.count",
4403 FT_UINT8, BASE_DEC, NULL, 0,
4404 NULL,
4405 HFILL }
4408 { &hf_thread_mc_tlv_period,
4409 { "Period",
4410 "thread_meshcop.tlv.period",
4411 FT_UINT16, BASE_DEC, NULL, 0,
4412 NULL,
4413 HFILL }
4416 { &hf_thread_mc_tlv_scan_duration,
4417 { "Scan Duration",
4418 "thread_meshcop.tlv.scan_duration",
4419 FT_UINT16, BASE_DEC, NULL, 0,
4420 NULL,
4421 HFILL }
4424 { &hf_thread_mc_tlv_energy_list,
4425 { "Energy List",
4426 "thread_meshcop.tlv.energy_list",
4427 FT_BYTES, BASE_NONE, NULL, 0x0,
4428 NULL,
4429 HFILL }
4432 { &hf_thread_mc_tlv_domain_name,
4433 { "Domain Name",
4434 "thread_meshcop.tlv.domain_name",
4435 FT_BYTES, BASE_NONE, NULL, 0x0,
4436 NULL,
4437 HFILL }
4440 { &hf_thread_mc_tlv_ae_steering_data,
4441 { "AE Steering Data",
4442 "thread_meshcop.tlv.ae_steering_data",
4443 FT_BYTES, BASE_NONE, NULL, 0x0,
4444 NULL,
4445 HFILL }
4448 { &hf_thread_mc_tlv_nmkp_steering_data,
4449 { "NMKP Steering Data",
4450 "thread_meshcop.tlv.nmkp_steering_data",
4451 FT_BYTES, BASE_NONE, NULL, 0x0,
4452 NULL,
4453 HFILL }
4456 { &hf_thread_mc_tlv_commissioner_signature,
4457 { "Commissioner Signature",
4458 "thread_meshcop.tlv.nmkp_commissioner_signature",
4459 FT_BYTES, BASE_NONE, NULL, 0x0,
4460 NULL,
4461 HFILL }
4465 { &hf_thread_mc_tlv_ae_udp_port,
4466 { "AE UDP Port",
4467 "thread_meshcop.tlv.ae_udp_port",
4468 FT_UINT16, BASE_DEC, NULL, 0x0,
4469 NULL,
4470 HFILL }
4473 { &hf_thread_mc_tlv_nmkp_udp_port,
4474 { "NMKP UDP Port",
4475 "thread_meshcop.tlv.nmkp_udp_port",
4476 FT_UINT16, BASE_DEC, NULL, 0x0,
4477 NULL,
4478 HFILL }
4481 { &hf_thread_mc_tlv_registrar_ipv6_addr,
4482 { "Registrar IPv6 Address",
4483 "thread_meshcop.tlv.registrar_ipv6_addr",
4484 FT_IPv6, BASE_NONE, NULL, 0x0,
4485 NULL,
4486 HFILL }
4489 { &hf_thread_mc_tlv_registrar_hostname,
4490 { "Registrar IPv6 Hostname",
4491 "thread_meshcop.tlv.registrar_hostname",
4492 FT_BYTES, BASE_NONE, NULL, 0x0,
4493 NULL,
4494 HFILL }
4497 { &hf_thread_mc_tlv_discovery_req_ver,
4498 { "Version",
4499 "thread_meshcop.tlv.discovery_req_ver",
4500 FT_UINT8, BASE_DEC, NULL, THREAD_MC_DISCOVERY_REQ_MASK_VER_MASK,
4501 NULL,
4502 HFILL }
4505 { &hf_thread_mc_tlv_discovery_req_j,
4506 { "Joiner Flag",
4507 "thread_meshcop.tlv.discovery_req_j",
4508 FT_BOOLEAN, 8, TFS(&thread_mc_tlv_join_intent), THREAD_MC_DISCOVERY_REQ_MASK_J_MASK,
4509 NULL,
4510 HFILL }
4513 { &hf_thread_mc_tlv_discovery_rsp_ver,
4514 { "Version",
4515 "thread_meshcop.tlv.discovery_rsp_ver",
4516 FT_UINT8, BASE_DEC, NULL, THREAD_MC_DISCOVERY_RSP_MASK_VER_MASK,
4517 NULL,
4518 HFILL }
4521 { &hf_thread_mc_tlv_discovery_rsp_n,
4522 { "Native Commissioning",
4523 "thread_meshcop.tlv.discovery_rsp_n",
4524 FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_DISCOVERY_RSP_MASK_N_MASK,
4525 NULL,
4526 HFILL }
4529 { &hf_thread_mc_tlv_discovery_rsp_c,
4530 { "Commercial Commissioning",
4531 "thread_meshcop.tlv.discovery_rsp_c",
4532 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), THREAD_MC_DISCOVERY_RSP_MASK_C_MASK,
4533 NULL,
4534 HFILL }
4538 static int *ett[] = {
4539 &ett_thread_mc,
4540 &ett_thread_mc_tlv,
4541 &ett_thread_mc_chan_mask,
4542 &ett_thread_mc_el_count
4545 static ei_register_info ei[] = {
4546 { &ei_thread_mc_tlv_length_failed, { "thread_meshcop.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
4547 { &ei_thread_mc_len_size_mismatch, { "thread_meshcop.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
4548 { &ei_thread_mc_len_too_long, { "thread_meshcop.len_too_long", PI_UNDECODED, PI_WARN, "TLV Length too long", EXPFILL }}
4551 expert_module_t* expert_thread_mc;
4553 proto_thread_mc = proto_register_protocol("Thread MeshCoP", "Thread MeshCoP", "thread_meshcop");
4554 proto_register_field_array(proto_thread_mc, hf, array_length(hf));
4555 proto_register_subtree_array(ett, array_length(ett));
4556 expert_thread_mc = expert_register_protocol(proto_thread_mc);
4557 expert_register_field_array(expert_thread_mc, ei, array_length(ei));
4559 thread_mc_handle = register_dissector("thread_meshcop", dissect_thread_mc, proto_thread_mc);
4562 void
4563 proto_register_thread_nwd(void)
4565 static hf_register_info hf[] = {
4567 /* Generic TLV */
4568 { &hf_thread_nwd_tlv,
4569 { "TLV",
4570 "thread_nwd.tlv",
4571 FT_NONE, BASE_NONE, NULL, 0x0,
4572 "Type-Length-Value",
4573 HFILL }
4576 { &hf_thread_nwd_tlv_type,
4577 { "Type",
4578 "thread_nwd.tlv.type",
4579 FT_UINT8, BASE_DEC, VALS(thread_nwd_tlv_vals), THREAD_NWD_TLV_TYPE_M,
4580 "Type of value",
4581 HFILL }
4584 { &hf_thread_nwd_tlv_stable,
4585 { "Stable",
4586 "thread_nwd.tlv.stable",
4587 FT_BOOLEAN, 8, NULL, THREAD_NWD_TLV_STABLE_M,
4588 "Stability or transience of network data",
4589 HFILL }
4592 { &hf_thread_nwd_tlv_length,
4593 { "Length",
4594 "thread_nwd.tlv.len",
4595 FT_UINT8, BASE_DEC, NULL, 0x0,
4596 "Length of value",
4597 HFILL }
4600 { &hf_thread_nwd_tlv_unknown,
4601 { "Unknown",
4602 "thread_nwd.tlv.unknown",
4603 FT_BYTES, BASE_NONE, NULL, 0x0,
4604 "Unknown TLV, raw value",
4605 HFILL }
4608 { &hf_thread_nwd_tlv_sub_tlvs,
4609 { "Sub-TLV(s)",
4610 "thread_nwd.tlv.sub_tlvs",
4611 FT_NONE, BASE_NONE, NULL, 0x0,
4612 NULL,
4613 HFILL }
4616 /* Type-Specific TLV Fields */
4617 { &hf_thread_nwd_tlv_has_route,
4618 { "Has Route",
4619 "thread_nwd.tlv.has_route",
4620 FT_NONE, BASE_NONE, NULL, 0x0,
4621 NULL,
4622 HFILL }
4625 { &hf_thread_nwd_tlv_has_route_br_16,
4626 { "Border Router 16",
4627 "thread_nwd.tlv.has_route.br_16",
4628 FT_UINT16, BASE_HEX, NULL, 0x0,
4629 "Has Route Border Router 16-bit address",
4630 HFILL }
4633 { &hf_thread_nwd_tlv_has_route_pref,
4634 { "Preference",
4635 "thread_nwd.tlv.has_route.pref",
4636 FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_HAS_ROUTE_PREF,
4637 "Has Route preference",
4638 HFILL }
4641 { &hf_thread_nwd_tlv_has_route_np,
4642 { "NP",
4643 "thread_nwd.tlv.has_route.np",
4644 FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_HAS_ROUTE_NP,
4645 "Has Route NP",
4646 HFILL }
4649 { &hf_thread_nwd_tlv_has_route_reserved,
4650 { "Reserved",
4651 "thread_nwd.tlv.has_route.reserved",
4652 FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_HAS_ROUTE_RESERVED,
4653 "Has Route Reserved",
4654 HFILL }
4657 { &hf_thread_nwd_tlv_prefix_domain_id,
4658 { "Domain ID",
4659 "thread_nwd.tlv.prefix.domain_id",
4660 FT_UINT8, BASE_DEC, NULL, 0x0,
4661 "Prefix Domain ID",
4662 HFILL }
4665 { &hf_thread_nwd_tlv_prefix_length,
4666 { "Prefix Length",
4667 "thread_nwd.tlv.prefix.length",
4668 FT_UINT8, BASE_DEC, NULL, 0x0,
4669 "Length of Prefix",
4670 HFILL }
4673 { &hf_thread_nwd_tlv_prefix,
4674 { "Prefix",
4675 "thread_nwd.tlv.prefix",
4676 FT_IPv6, BASE_NONE, NULL, 0x0,
4677 "IPv6 prefix",
4678 HFILL }
4681 { &hf_thread_nwd_tlv_border_router,
4682 { "Border Router",
4683 "thread_nwd.tlv.border_router",
4684 FT_NONE, BASE_NONE, NULL, 0x0,
4685 NULL,
4686 HFILL }
4689 { &hf_thread_nwd_tlv_border_router_16,
4690 { "Border Router 16",
4691 "thread_nwd.tlv.border_router.16",
4692 FT_UINT16, BASE_HEX, NULL, 0x0,
4693 "Border Router 16-bit address",
4694 HFILL }
4697 { &hf_thread_nwd_tlv_border_router_pref,
4698 { "Preference",
4699 "thread_nwd.tlv.border_router.pref",
4700 FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_BORDER_ROUTER_PREF,
4701 "Value of P_preference",
4702 HFILL }
4705 { &hf_thread_nwd_tlv_border_router_p,
4706 { "P Flag",
4707 "thread_nwd.tlv.border_router.flag.p",
4708 FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_p), THREAD_NWD_TLV_BORDER_ROUTER_P,
4709 "Value of P_preferred",
4710 HFILL }
4713 { &hf_thread_nwd_tlv_border_router_s,
4714 { "SLAAC",
4715 "thread_nwd.tlv.border_router.flag.s",
4716 FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_NWD_TLV_BORDER_ROUTER_S,
4717 "Value of P_slaac",
4718 HFILL }
4721 { &hf_thread_nwd_tlv_border_router_d,
4722 { "DHCPv6",
4723 "thread_nwd.tlv.border_router.flag.d",
4724 FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_NWD_TLV_BORDER_ROUTER_D,
4725 "Value of P_dhcp",
4726 HFILL }
4729 { &hf_thread_nwd_tlv_border_router_c,
4730 { "C Flag",
4731 "thread_nwd.tlv.border_router.flag.c",
4732 FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_c), THREAD_NWD_TLV_BORDER_ROUTER_C,
4733 "Value of P_configure",
4734 HFILL }
4737 { &hf_thread_nwd_tlv_border_router_r,
4738 { "Default route",
4739 "thread_nwd.tlv.border_router.flag.r",
4740 FT_BOOLEAN, 8, TFS(&tfs_yes_no), THREAD_NWD_TLV_BORDER_ROUTER_R,
4741 "Value of P_default",
4742 HFILL }
4745 { &hf_thread_nwd_tlv_border_router_o,
4746 { "O Flag",
4747 "thread_nwd.tlv.border_router.flag.o",
4748 FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_o), THREAD_NWD_TLV_BORDER_ROUTER_O,
4749 "Value of P_on_mesh",
4750 HFILL }
4753 { &hf_thread_nwd_tlv_border_router_n,
4754 { "DNS",
4755 "thread_nwd.tlv.border_router.flag.n",
4756 FT_BOOLEAN, 8, TFS(&tfs_available_not_available), THREAD_NWD_TLV_BORDER_ROUTER_N,
4757 "Value of P_nd_dns",
4758 HFILL }
4761 { &hf_thread_nwd_tlv_border_router_dp,
4762 { "DP Flag",
4763 "thread_nwd.tlv.border_router.flag.dp",
4764 FT_BOOLEAN, 8, TFS(&tfs_available_not_available), THREAD_NWD_TLV_BORDER_ROUTER_DP,
4765 "Value of P_dp",
4766 HFILL }
4769 { &hf_thread_nwd_tlv_6lowpan_id_6co_flag,
4770 { "Flag",
4771 "thread_nwd.tlv.6co.flag",
4772 FT_UINT8, BASE_HEX, NULL, 0x00,
4773 NULL,
4774 HFILL }
4777 { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_c,
4778 { "Compression Flag",
4779 "thread_nwd.tlv.6co.flag.c",
4780 FT_BOOLEAN, 8, TFS(&tfs_set_notset), ND_OPT_6CO_FLAG_C,
4781 "This flag indicates if the context is valid for use in compression",
4782 HFILL }
4785 { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_cid,
4786 { "CID",
4787 "thread_nwd.tlv.6co.flag.cid",
4788 FT_UINT8, BASE_DEC, NULL, ND_OPT_6CO_FLAG_CID,
4789 "Context Identifier for this prefix information",
4790 HFILL }
4793 { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_reserved,
4794 { "Reserved",
4795 "thread_nwd.tlv.6co.flag.reserved",
4796 FT_UINT8, BASE_DEC, NULL, ND_OPT_6CO_FLAG_RESERVED,
4797 "Must be zero",
4798 HFILL }
4801 { &hf_thread_nwd_tlv_6lowpan_id_6co_context_length,
4802 { "Context Length",
4803 "thread_nwd.tlv.6co.context_length",
4804 FT_UINT8, BASE_DEC, NULL, 0x00,
4805 "The number of leading bits in the Context Prefix field that are valid",
4806 HFILL }
4808 #if 0
4809 { &hf_thread_nwd_tlv_comm_data,
4810 { "Commissioning Data",
4811 "thread_nwd.tlv.comm_data",
4812 FT_BYTES, BASE_NONE, NULL, 0x0,
4813 "Contains Thread Commissioning data",
4814 HFILL }
4816 #endif
4817 { &hf_thread_nwd_tlv_service_t,
4818 { "T flag",
4819 "thread_nwd.tlv.service.t",
4820 FT_UINT8, BASE_HEX, NULL, THREAD_NWD_TLV_SERVICE_T,
4821 NULL,
4822 HFILL }
4825 { &hf_thread_nwd_tlv_service_s_id,
4826 { "Service Type ID",
4827 "thread_nwd.tlv.service.s_id",
4828 FT_UINT8, BASE_HEX, NULL, THREAD_NWD_TLV_SERVICE_S_ID,
4829 NULL,
4830 HFILL }
4833 { &hf_thread_nwd_tlv_service_s_ent_num,
4834 { "Enterprise Number",
4835 "thread_nwd.tlv.service.s_ent_num",
4836 FT_UINT32, BASE_DEC, NULL, 0,
4837 NULL,
4838 HFILL }
4841 { &hf_thread_nwd_tlv_service_s_data_len,
4842 { "Service Data Length",
4843 "thread_nwd.tlv.service.s_data_len",
4844 FT_UINT8, BASE_DEC, NULL, 0,
4845 NULL,
4846 HFILL }
4849 { &hf_thread_nwd_tlv_service_s_data,
4850 { "Service Data",
4851 "thread_nwd.tlv.service.s_data",
4852 FT_BYTES, BASE_NONE, NULL, 0x0,
4853 "Service data in raw bytes",
4854 HFILL }
4857 { &hf_thread_nwd_tlv_service_s_data_seqno,
4858 { "Service Data - BBR Sequence Number",
4859 "thread_nwd.tlv.service.s_data.seqno",
4860 FT_UINT8, BASE_DEC, NULL, 0x0,
4861 "Service data in raw bytes",
4862 HFILL }
4865 { &hf_thread_nwd_tlv_service_s_data_rrdelay,
4866 { "Service Data - Reregistration Delay(s)",
4867 "thread_nwd.tlv.service.s_data.rrdelay",
4868 FT_UINT16, BASE_DEC, NULL, 0x0,
4869 "Service data in raw bytes",
4870 HFILL }
4873 { &hf_thread_nwd_tlv_service_s_data_mlrtimeout,
4874 { "Service Data - MLR Timeout(s)",
4875 "thread_nwd.tlv.service.s_data.mlrtimeout",
4876 FT_UINT32, BASE_DEC, NULL, 0x0,
4877 "Service data in raw bytes",
4878 HFILL }
4881 { &hf_thread_nwd_tlv_server_16,
4882 { "Server 16",
4883 "thread_nwd.tlv.server.16",
4884 FT_UINT16, BASE_HEX, NULL, 0x0,
4885 "Server 16-bit address",
4886 HFILL }
4889 { &hf_thread_nwd_tlv_server_data,
4890 { "Server Data",
4891 "thread_nwd.tlv.server.data",
4892 FT_BYTES, BASE_NONE, NULL, 0x0,
4893 "Server data in raw bytes",
4894 HFILL }
4897 // Thread 1.3 Service TLV code
4899 { &hf_thread_nwd_tlv_service_srp_dataset_identifier,
4900 { "Service Data SRP Dataset Identifier",
4901 "thread_nwd.tlv.service.srp_dataset_identifier",
4902 FT_UINT8, BASE_HEX, NULL, 0x0,
4903 NULL,
4904 HFILL }
4907 { &hf_thread_nwd_tlv_service_anycast_seqno,
4908 { "Service Data Anycast Sequence Number",
4909 "thread_nwd.tlv.service.anycast_seqno",
4910 FT_UINT8, BASE_DEC, NULL, 0x0,
4911 "Sequence Number of Anycast Dataset",
4912 HFILL }
4915 { &hf_thread_nwd_tlv_service_unicast_ipv6_address,
4916 { "Service Data Unicast Server IPV6 Address",
4917 "thread_nwd.tlv.service.unicast_server_ipv6_address",
4918 FT_IPv6, BASE_NONE, NULL, 0x0,
4919 "IPV6 Address of Unicast SRP Server",
4920 HFILL }
4923 { &hf_thread_nwd_tlv_service_unicast_port_number,
4924 { "Service Data Unicast Port Number",
4925 "thread_nwd.tlv.service.unicast_port_no",
4926 FT_UINT16, BASE_DEC, NULL, 0x0,
4927 "Port Number of Unicast SRP Server",
4928 HFILL }
4933 static int *ett[] = {
4934 &ett_thread_nwd,
4935 &ett_thread_nwd_tlv,
4936 &ett_thread_nwd_has_route,
4937 &ett_thread_nwd_6co_flag,
4938 &ett_thread_nwd_border_router,
4939 &ett_thread_nwd_prefix_sub_tlvs
4942 static ei_register_info ei[] = {
4943 #if 0
4944 { &ei_thread_nwd_tlv_length_failed, { "thread_nwd.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
4945 #endif
4946 { &ei_thread_nwd_len_size_mismatch, { "thread_nwd.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
4949 expert_module_t* expert_thread_nwd;
4951 proto_thread_nwd = proto_register_protocol("Thread Network Data", "Thread NWD", "thread_nwd");
4952 proto_register_field_array(proto_thread_nwd, hf, array_length(hf));
4953 proto_register_subtree_array(ett, array_length(ett));
4954 expert_thread_nwd = expert_register_protocol(proto_thread_nwd);
4955 expert_register_field_array(expert_thread_nwd, ei, array_length(ei));
4957 thread_address_nwd_handle = register_dissector("thread_nwd", dissect_thread_nwd, proto_thread_nwd);
4960 void proto_register_thread_bcn(void)
4962 static hf_register_info hf[] = {
4964 { &hf_thread_bcn_protocol,
4965 { "Protocol ID", "thread_bcn.protocol", FT_UINT8, BASE_DEC, NULL, 0x0,
4966 NULL, HFILL }},
4968 { &hf_thread_bcn_joining,
4969 { "Joining", "thread_bcn.joining", FT_BOOLEAN, 8, NULL, THREAD_BCN_JOINING,
4970 NULL, HFILL }},
4972 { &hf_thread_bcn_native,
4973 { "Native", "thread_bcn.native", FT_BOOLEAN, 8, NULL, THREAD_BCN_NATIVE,
4974 NULL, HFILL }},
4976 { &hf_thread_bcn_version,
4977 { "Version", "thread_bcn.version", FT_UINT8, BASE_DEC, NULL, THREAD_BCN_PROTOCOL_VERSION,
4978 NULL, HFILL }},
4980 { &hf_thread_bcn_network_id,
4981 { "Network Name", "thread_bcn.network_name", FT_STRING, BASE_NONE, NULL, 0x0,
4982 "A string that uniquely identifies this network.", HFILL }},
4984 { &hf_thread_bcn_epid,
4985 { "Extended PAN ID", "thread_bcn.epid", FT_EUI64, BASE_NONE, NULL, 0x0,
4986 NULL, HFILL }},
4988 { &hf_thread_bcn_tlv,
4989 { "TLV", "thread_bcn.tlv", FT_NONE, BASE_NONE, NULL, 0x0,
4990 "Type-Length-Value", HFILL }},
4992 { &hf_thread_bcn_tlv_type,
4993 { "Type", "thread_bcn.tlv.type", FT_UINT8, BASE_DEC, VALS(thread_bcn_tlv_vals), 0x0,
4994 "Type of Value", HFILL }},
4996 { &hf_thread_bcn_tlv_length,
4997 { "Length", "thread_bcn.tlv.len", FT_UINT8, BASE_DEC, NULL, 0x0,
4998 "Length of Value", HFILL }},
5000 { &hf_thread_bcn_tlv_steering_data,
5001 { "Steering Data", "thread_bcn.tlv.steering_data", FT_BYTES, BASE_NONE, NULL, 0x0,
5002 "Steering data for joining devices", HFILL }},
5004 { &hf_thread_bcn_tlv_unknown,
5005 { "Unknown", "thread_bcn.tlv.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
5006 "Unknown TLV, raw value", HFILL }}
5009 /* NWK Layer subtrees */
5010 static int *ett[] = {
5011 &ett_thread_bcn,
5012 &ett_thread_bcn_tlv
5015 /* Register the protocol with Wireshark. */
5016 proto_thread_bcn = proto_register_protocol("Thread Beacon", "Thread Beacon", "thread_bcn");
5017 proto_register_field_array(proto_thread_bcn, hf, array_length(hf));
5018 proto_register_subtree_array(ett, array_length(ett));
5020 /* Register the dissectors with Wireshark. */
5021 register_dissector("thread_bcn", dissect_thread_bcn, proto_thread_bcn);
5024 static void
5025 proto_init_thread(void)
5027 /* Reset the sequence counter variables */
5028 thread_seq_ctr_acqd = false;
5029 memset(thread_seq_ctr_bytes, 0, 4);
5032 void
5033 proto_register_thread(void)
5035 module_t *thread_module;
5037 proto_thread = proto_register_protocol("Thread", "Thread", "thread");
5039 thread_module = prefs_register_protocol(proto_thread, NULL);
5040 prefs_register_obsolete_preference(thread_module, "thr_coap_decode");
5041 prefs_register_string_preference(thread_module, "thr_seq_ctr",
5042 "Thread sequence counter",
5043 "32-bit sequence counter for hash",
5044 (const char **)&thread_seq_ctr_str);
5046 prefs_register_bool_preference(thread_module, "thr_use_pan_id_in_key",
5047 "Use PAN ID as first two octets of master key",
5048 "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]...",
5049 &thread_use_pan_id_in_key);
5051 prefs_register_bool_preference(thread_module, "thr_auto_acq_thr_seq_ctr",
5052 "Automatically acquire Thread sequence counter",
5053 "Set if the Thread sequence counter should be automatically acquired from Key ID mode 2 MLE messages.",
5054 &thread_auto_acq_seq_ctr);
5056 /*static hf_register_info hf[] = {
5057 { &hf_ieee802154_thread_ie,
5058 { "IE header", "thread_ie", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5060 { &hf_ieee802154_thread_ie_length,
5061 { "Length", "thread_ie.length", FT_UINT16, BASE_DEC, NULL,
5062 THREAD_IE_LENGTH_MASK, NULL, HFILL }}
5065 static int *ett[] = {
5066 &ett_thread_header_ie,
5067 };*/
5069 register_init_routine(proto_init_thread);
5071 // proto_register_field_array(proto_thread_ie, hf, array_length(hf));
5072 // proto_register_subtree_array(ett, array_length(ett));
5074 /* Register Dissector */
5075 register_dissector("thread_ie", dissect_thread_ie, proto_thread_ie);
5078 void
5079 proto_register_thread_coap(void)
5081 proto_thread_coap = proto_register_protocol("Thread CoAP", "Thread CoAP", "thread_coap");
5082 thread_coap_handle = register_dissector("thread_coap", dissect_thread_coap, proto_thread_coap);
5084 dissector_add_string("coap_tmf_media_type", "application/octet-stream", thread_coap_handle);
5085 thread_coap_namespace = register_dissector_table("thread.coap_namespace", "Thread CoAP namespace", proto_thread_coap, FT_STRING, STRING_CASE_SENSITIVE);
5088 void
5089 proto_reg_handoff_thread_mc(void)
5091 thread_dtls_handle = find_dissector_add_dependency("dtls", proto_thread_mc);
5092 thread_udp_handle = find_dissector_add_dependency("udp", proto_thread_mc);
5094 dissector_add_string("thread.coap_namespace", "c", thread_mc_handle);
5097 void
5098 proto_reg_handoff_thread_address(void)
5100 dissector_add_string("thread.coap_namespace", "a", thread_address_handle);
5101 dissector_add_string("thread.coap_namespace", "n", thread_address_handle);
5104 void
5105 proto_reg_handoff_thread_nm(void)
5107 dissector_add_string("thread.coap_namespace", "n", thread_nm_handle);
5110 void
5111 proto_reg_handoff_thread_bl(void)
5113 dissector_add_string("thread.coap_namespace", "b", thread_bl_handle);
5116 void
5117 proto_reg_handoff_thread_dg(void)
5119 dissector_add_string("thread.coap_namespace", "d", thread_dg_handle);
5122 void proto_reg_handoff_thread_bcn(void)
5124 /* Register our dissector with IEEE 802.15.4 */
5125 heur_dissector_add(IEEE802154_PROTOABBREV_WPAN_BEACON, dissect_thread_bcn_heur, "Thread Beacon", "thread_wlan_beacon", proto_thread_bcn, HEURISTIC_ENABLE);
5127 register_mle_key_hash_handler(KEY_HASH_THREAD, set_thread_mle_key);
5128 register_ieee802154_mac_key_hash_handler(KEY_HASH_THREAD, set_thread_mac_key);
5131 void
5132 proto_reg_handoff_thread(void)
5134 /* Thread Content-Format is opaque byte string, i.e. application/octet-stream */
5135 /* Enable decoding "Internet media type" as Thread over CoAP */
5136 dissector_add_for_decode_as("media_type", thread_coap_handle);
5137 /* Do NOT add the thread dissector to the generic media_type table for
5138 * "application/octet-stream", which is for "arbitrary binary data":
5139 * https://www.iana.org/assignments/media-types/application/octet-stream
5140 * Doing so hijacks *all* "application/octet-stream", including in HTTP, etc.
5141 * That is why there is a separate coap_tmf_media_type table and a
5142 * special CoAP-TMF dissector. (#14729).
5144 //dissector_add_string("media_type", "application/octet-stream", thread_coap_handle);
5146 proto_coap = proto_get_id_by_filter_name("coap");
5150 *Subdissector command for Thread Specific IEs (Information Elements)
5152 *@param tvb pointer to buffer containing raw packet.
5153 *@param pinfo pointer to packet information fields (unused).
5154 *@param tree pointer to command subtree.
5155 *@param data pointer to the length of the payload IE.
5157 static int
5158 dissect_thread_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data)
5161 proto_tree *subtree;
5162 //tvbuff_t *ie_tvb;
5163 uint16_t thread_ie;
5164 uint16_t id;
5165 uint16_t length;
5166 unsigned pie_length;
5167 unsigned offset = 0;
5169 static int * fields[] = {
5170 &hf_ieee802154_thread_ie_id,
5171 &hf_ieee802154_thread_ie_length,
5172 NULL
5175 pie_length = *(int *)data;
5177 do {
5178 thread_ie = tvb_get_letohs(tvb, offset);
5179 id = (thread_ie & THREAD_IE_ID_MASK) >> 6;
5180 length = thread_ie & THREAD_IE_LENGTH_MASK;
5182 /* Create a subtree for this command frame. */
5183 subtree = proto_tree_add_subtree(tree, tvb, offset, 2+length, ett_thread, NULL, "Thread IE");
5184 //proto_item_append_text(subtree, ", %s, Length: %d", val_to_str_const(id, ieee802154_zigbee_ie_names, "Unknown"), length);
5186 proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_thread_ie,
5187 ett_thread_ie_fields, fields, ENC_LITTLE_ENDIAN);
5188 offset += 2;
5190 switch (id) {
5191 /*case ZBEE_ZIGBEE_IE_REJOIN:
5192 dissect_ieee802154_zigbee_rejoin(tvb, pinfo, subtree, &offset);
5193 break;
5195 case ZBEE_ZIGBEE_IE_TX_POWER:
5196 dissect_ieee802154_zigbee_txpower(tvb, pinfo, subtree, &offset);
5197 break;
5199 case ZBEE_ZIGBEE_IE_BEACON_PAYLOAD:
5200 ie_tvb = tvb_new_subset_length(tvb, offset, ZBEE_NWK_BEACON_LENGTH);
5201 offset += dissect_zbee_beacon(ie_tvb, pinfo, subtree, NULL);
5202 dissect_ieee802154_superframe(tvb, pinfo, subtree, &offset);
5203 proto_tree_add_item(subtree, hf_ieee802154_zigbee_ie_source_addr, tvb, offset, 2, ENC_NA);
5204 offset += 2;
5205 break;*/
5207 default:
5208 if (length > 0) {
5209 //proto_tree_add_item(tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
5210 offset += length;
5212 break;
5214 } while (offset < pie_length);
5215 return tvb_captured_length(tvb);
5219 * Editor modelines - https://www.wireshark.org/tools/modelines.html
5221 * Local variables:
5222 * c-basic-offset: 4
5223 * tab-width: 8
5224 * indent-tabs-mode: nil
5225 * End:
5227 * vi: set shiftwidth=4 tabstop=8 expandtab:
5228 * :indentSize=4:tabSize=8:noTabs=true: