Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-thread.c
Line
Count
Source
1
/* packet-thread.c
2
 * Routines for Thread over CoAP and beacon packet dissection
3
 *
4
 * Robert Cragie <robert.cragie@arm.com>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
13
#include "config.h"
14
#include <stdlib.h>
15
#include <math.h>
16
#include <epan/packet.h>
17
#include <epan/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"
28
29
/* Use libgcrypt for cipher libraries. */
30
#include <wsutil/wsgcrypt.h>
31
32
/* Thread Vendor Sub IE Fields */
33
0
#define THREAD_IE_ID_MASK                      0xFFC0
34
0
#define THREAD_IE_LENGTH_MASK                  0x003F
35
36
/* Forward declarations */
37
void proto_register_thread_coap(void);
38
39
void proto_register_thread_address(void);
40
void proto_reg_handoff_thread_address(void);
41
42
void proto_register_thread_dg(void);
43
void proto_reg_handoff_thread_dg(void);
44
45
void proto_register_thread_mc(void);
46
void proto_reg_handoff_thread_mc(void);
47
48
void proto_register_thread_nwd(void);
49
50
void proto_register_thread_bcn(void);
51
void proto_reg_handoff_thread_bcn(void);
52
53
void proto_register_thread(void);
54
void proto_reg_handoff_thread(void);
55
56
void proto_register_thread_nm(void);
57
void proto_reg_handoff_thread_nm(void);
58
59
void proto_register_thread_bl(void);
60
void proto_reg_handoff_thread_bl(void);
61
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;
73
74
/* Header fields */
75
76
/* Thread address */
77
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; */
83
84
/* Target EID TLV fields */
85
static int hf_thread_address_tlv_target_eid;
86
87
/* Ext. MAC address TLV fields */
88
static int hf_thread_address_tlv_ext_mac_addr;
89
90
/* RLOC16 TLV fields */
91
static int hf_thread_address_tlv_rloc16;
92
93
/* Mesh Local IID TLV fields */
94
static int hf_thread_address_tlv_ml_eid;
95
96
/* Status TLV fields */
97
static int hf_thread_address_tlv_status;
98
99
/* Attached time TLV fields */
100
/* static int hf_thread_address_tlv_attached_time; */
101
102
/* Last transaction time TLV fields */
103
static int hf_thread_address_tlv_last_transaction_time;
104
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;
108
109
/* ND option fields */
110
static int hf_thread_address_tlv_nd_option;
111
112
/* ND data fields */
113
static int hf_thread_address_tlv_nd_data;
114
static int hf_thread_address_tlv_timeout;
115
116
/* Thread diagnostics */
117
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;
124
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
182
183
/* Thread MeshCoP */
184
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; */
191
192
/* Channel TLV fields */
193
static int hf_thread_mc_tlv_channel_page;
194
static int hf_thread_mc_tlv_channel;
195
196
/* PAN ID TLV fields */
197
static int hf_thread_mc_tlv_pan_id;
198
199
/* Extended PAN ID TLV fields */
200
static int hf_thread_mc_tlv_xpan_id;
201
202
/* Network Name TLV fields */
203
static int hf_thread_mc_tlv_net_name;
204
205
/* PSKc TLV fields */
206
static int hf_thread_mc_tlv_pskc;
207
208
/* Master Key TLV fields */
209
static int hf_thread_mc_tlv_master_key;
210
211
/* Network Key Sequence TLV fields */
212
static int hf_thread_mc_tlv_net_key_seq_ctr;
213
214
/* Mesh Local ULA TLV fields */
215
static int hf_thread_mc_tlv_ml_prefix;
216
217
/* Steering Data TLV fields */
218
static int hf_thread_mc_tlv_steering_data;
219
220
/* Border Agent Locator TLV fields */
221
static int hf_thread_mc_tlv_ba_locator;
222
223
/* Commissioner ID TLV fields */
224
static int hf_thread_mc_tlv_commissioner_id;
225
226
/* Commissioner ID TLV fields */
227
static int hf_thread_mc_tlv_commissioner_sess_id;
228
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;
244
245
246
/* State TLV fields */
247
static int hf_thread_mc_tlv_state;
248
249
/* Timestamp TLV fields */
250
static int hf_thread_mc_tlv_active_tstamp;
251
static int hf_thread_mc_tlv_pending_tstamp;
252
253
/* Delay Timer TLV fields */
254
static int hf_thread_mc_tlv_delay_timer;
255
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;
259
260
/* IPv6 Address fields */
261
static int hf_thread_mc_tlv_ipv6_addr;
262
263
/* UDP Port TLV fields */
264
static int hf_thread_mc_tlv_udp_port;
265
266
/* IID TLV fields */
267
static int hf_thread_mc_tlv_iid;
268
269
/* Joiner Router locator TLV fields */
270
static int hf_thread_mc_tlv_jr_locator;
271
272
/* KEK TLV fields */
273
static int hf_thread_mc_tlv_kek;
274
275
/* Provisioning URL TLV fields */
276
static int hf_thread_mc_tlv_provisioning_url;
277
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;
288
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;
294
295
/* Count TLV fields */
296
static int hf_thread_mc_tlv_count;
297
298
/* Period TLV fields */
299
static int hf_thread_mc_tlv_period;
300
301
/* Period TLV fields */
302
static int hf_thread_mc_tlv_scan_duration;
303
304
/* Energy List TLV fields */
305
static int hf_thread_mc_tlv_energy_list;
306
static int hf_thread_mc_tlv_el_count;
307
308
/* Domain Name TLV fields */
309
static int hf_thread_mc_tlv_domain_name;
310
311
/* AE Steering Data TLV fields */
312
static int hf_thread_mc_tlv_ae_steering_data;
313
314
/* NMKP Steering Data TLV fields */
315
static int hf_thread_mc_tlv_nmkp_steering_data;
316
317
/* Commissioner Signature TLV fields */
318
static int hf_thread_mc_tlv_commissioner_signature;
319
320
/* AE UDP Port TLV fields */
321
static int hf_thread_mc_tlv_ae_udp_port;
322
323
/* NMKP UDP Port TLV fields */
324
static int hf_thread_mc_tlv_nmkp_udp_port;
325
326
/* Registrar IPv6 Address fields */
327
static int hf_thread_mc_tlv_registrar_ipv6_addr;
328
329
/* Registrar Hostname fields */
330
static int hf_thread_mc_tlv_registrar_hostname;
331
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;
335
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;
340
341
/* Thread Network Data */
342
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;
349
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;
356
357
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;
362
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;
375
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;
382
383
/* Commissioning Data fields */
384
/* static int hf_thread_nwd_tlv_comm_data; */
385
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;
395
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;
401
402
/* Server fields */
403
static int hf_thread_nwd_tlv_server_16;
404
static int hf_thread_nwd_tlv_server_data;
405
406
/* Thread Beacon */
407
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;
419
420
/* Tree types */
421
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;
442
443
static int ett_thread;
444
/* static int ett_thread_header_ie; */
445
static int ett_thread_ie_fields;
446
447
448
449
/* Expert info. */
450
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;
462
463
464
static dissector_table_t thread_coap_namespace;
465
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;
476
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;
481
482
0
#define THREAD_SERVICE_DATA_BBR 0x1
483
484
2.65k
#define THREAD_TLV_LENGTH_ESC  0xFF
485
486
#define THREAD_URI_NAMESPACE_IDX 1
487
488
0
#define THREAD_MC_32768_TO_NSEC_FACTOR ((double)30517.578125)
489
#define THREAD_MC_TSTAMP_MASK_U_MASK 0x80
490
14
#define THREAD_MC_SEC_POLICY_MASK_O_MASK 0x80
491
14
#define THREAD_MC_SEC_POLICY_MASK_N_MASK 0x40
492
14
#define THREAD_MC_SEC_POLICY_MASK_R_MASK 0x20
493
14
#define THREAD_MC_SEC_POLICY_MASK_C_MASK 0x10
494
14
#define THREAD_MC_SEC_POLICY_MASK_B_MASK 0x08
495
14
#define THREAD_MC_SEC_POLICY_MASK_CCM_MASK 0x04
496
14
#define THREAD_MC_SEC_POLICY_MASK_AE_MASK 0x02
497
14
#define THREAD_MC_SEC_POLICY_MASK_NMP_MASK 0x01
498
14
#define THREAD_MC_SEC_POLICY_MASK_L_MASK 0x80
499
14
#define THREAD_MC_SEC_POLICY_MASK_NCR_MASK 0x40
500
14
#define THREAD_MC_SEC_POLICY_MASK_RSV_MASK 0x38
501
14
#define THREAD_MC_SEC_POLICY_MASK_RSV1_MASK 0x07
502
14
#define THREAD_MC_SEC_POLICY_MASK_VR_MASK 0x07
503
14
#define THREAD_MC_STACK_VER_REV_MASK 0x0F
504
14
#define THREAD_MC_STACK_VER_MIN_MASK 0xF0
505
14
#define THREAD_MC_STACK_VER_MAJ_MASK 0x0F
506
14
#define THREAD_MC_DISCOVERY_REQ_MASK_VER_MASK 0xF0
507
14
#define THREAD_MC_DISCOVERY_REQ_MASK_J_MASK 0x08
508
14
#define THREAD_MC_DISCOVERY_RSP_MASK_VER_MASK 0xF0
509
14
#define THREAD_MC_DISCOVERY_RSP_MASK_N_MASK 0x08
510
14
#define THREAD_MC_DISCOVERY_RSP_MASK_C_MASK 0x04
511
153
#define THREAD_MC_INVALID_CHAN_COUNT 0xFFFF
512
513
14
#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
428
#define THREAD_NWD_TLV_HAS_ROUTE_SIZE       3
517
518
14
#define THREAD_NWD_TLV_BORDER_ROUTER_PREF   0xC0
519
14
#define THREAD_NWD_TLV_HAS_ROUTE_NP         0x20
520
14
#define THREAD_NWD_TLV_HAS_ROUTE_RESERVED   0x1F
521
14
#define THREAD_NWD_TLV_BORDER_ROUTER_P      0x20
522
14
#define THREAD_NWD_TLV_BORDER_ROUTER_S      0x10
523
14
#define THREAD_NWD_TLV_BORDER_ROUTER_D      0x08
524
14
#define THREAD_NWD_TLV_BORDER_ROUTER_C      0x04
525
14
#define THREAD_NWD_TLV_BORDER_ROUTER_R      0x02
526
14
#define THREAD_NWD_TLV_BORDER_ROUTER_O      0x01
527
14
#define THREAD_NWD_TLV_BORDER_ROUTER_N      0x80
528
14
#define THREAD_NWD_TLV_BORDER_ROUTER_DP     0x40 //Thread 1.2 Draft5
529
530
73
#define THREAD_BCN_PROTOCOL_ID              0x03
531
14
#define THREAD_BCN_JOINING                  0x01
532
14
#define THREAD_BCN_NATIVE                   0x08
533
14
#define THREAD_BCN_PROTOCOL_VERSION         0xf0
534
#define THREAD_BCN_TLV_STEERING_DATA_S      0x80
535
1
#define THREAD_BCN_TLV_STEERING_DATA        8
536
537
14
#define ND_OPT_6CO_FLAG_C        0x10
538
14
#define ND_OPT_6CO_FLAG_CID      0x0F
539
14
#define ND_OPT_6CO_FLAG_RESERVED 0xE0
540
541
74
#define THREAD_NWD_TLV_SERVICE_T    0x80
542
14
#define THREAD_NWD_TLV_SERVICE_S_ID 0x0F
543
544
typedef enum {
545
    TLV_LEN_LEN8 = 1,
546
    TLV_LEN_LEN16 = 3
547
} tlv_len_len_e;
548
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;
555
556
/* TLV values */
557
558
0
#define THREAD_ADDRESS_TLV_TARGET_EID               0
559
0
#define THREAD_ADDRESS_TLV_EXT_MAC_ADDR             1
560
0
#define THREAD_ADDRESS_TLV_RLOC16                   2
561
0
#define THREAD_ADDRESS_TLV_ML_EID                   3
562
0
#define THREAD_ADDRESS_TLV_STATUS                   4
563
/* Gap */
564
0
#define THREAD_ADDRESS_TLV_LAST_TRANSACTION_TIME    6
565
0
#define THREAD_ADDRESS_TLV_ROUTER_MASK              7
566
0
#define THREAD_ADDRESS_TLV_ND_OPTION                8
567
0
#define THREAD_ADDRESS_TLV_ND_DATA                  9
568
0
#define THREAD_ADDRESS_TLV_THREAD_NETWORK_DATA      10
569
0
#define THREAD_ADDRESS_TLV_TIMEOUT                  11
570
0
#define THREAD_ADDRESS_TLV_THREAD_NETWORK_NAME      12
571
0
#define THREAD_ADDRESS_TLV_IPV6_ADDRESS             14
572
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 }
589
};
590
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 }
598
};
599
600
/* Network Layer (Address) mirrors */
601
0
#define THREAD_DG_TLV_EXT_MAC_ADDR          0 /* As THREAD_ADDRESS_TLV_EXT_MAC_ADDR */
602
/* MLE mirrors */
603
0
#define THREAD_DG_TLV_ADDRESS16             1 /* As MLE_TLV_ADDRESS16 */
604
0
#define THREAD_DG_TLV_MODE                  2 /* As MLE_TLV_MODE */
605
0
#define THREAD_DG_TLV_TIMEOUT               3 /* As MLE_TLV_TIMEOUT */
606
0
#define THREAD_DG_TLV_CONNECTIVITY          4 /* As MLE_TLV_CONNECTIVITY */
607
0
#define THREAD_DG_TLV_ROUTE64               5 /* As MLE_TLV_ROUTE64 */
608
0
#define THREAD_DG_TLV_LEADER_DATA           6 /* As MLE_TLV_LEADER_DATA */
609
0
#define THREAD_DG_TLV_NETWORK_DATA          7 /* As MLE_TLV_NETWORK_DATA */
610
/* Statistics */
611
0
#define THREAD_DG_TLV_IPV6_ADDR_LIST        8
612
0
#define THREAD_DG_TLV_MAC_COUNTERS          9
613
/* Others */
614
0
#define THREAD_DG_TLV_BATTERY_LEVEL         14
615
0
#define THREAD_DG_TLV_VOLTAGE               15
616
0
#define THREAD_DG_TLV_CHILD_TABLE           16
617
0
#define THREAD_DG_TLV_CHANNEL_PAGES         17
618
0
#define THREAD_DG_TLV_TYPE_LIST             18
619
0
#define THREAD_DG_TLV_MAX_CHILD_TIMEOUT     19
620
0
#define THREAD_DG_TLV_LDEVID_SUBJECT_PUBLIC_KEY_INFO 20
621
0
#define THREAD_DG_TLV_IDEVID_CERTIFICATE    21
622
/*  Reserved      22*/
623
0
#define THREAD_DG_TLV_EUI_64                23
624
0
#define THREAD_DG_TLV_VERSION               24
625
0
#define THREAD_DG_TLV_VENDOR_NAME           25
626
0
#define THREAD_DG_TLV_VENDOR_MODEL          26
627
0
#define THREAD_DG_TLV_VENDOR_SW_VERSION     27
628
0
#define THREAD_DG_TLV_THREAD_STACK_VERSION  28
629
0
#define THREAD_DG_TLV_CHILD                 29
630
0
#define THREAD_DG_TLV_CHILD_IPV6_ADDRESS_LIST        30
631
0
#define THREAD_DG_TLV_ROUTER_NEIGHBOR       31
632
0
#define THREAD_DG_TLV_ANSWER                32
633
0
#define THREAD_DG_TLV_QUERY_ID              33
634
0
#define THREAD_DG_TLV_MLE_COUNTERS          34
635
#define THREAD_DG_TLV_UNKNOWN               255
636
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 }
674
};
675
676
408
#define THREAD_MC_TLV_CHANNEL                      0 /* Modified for new features */
677
32
#define THREAD_MC_TLV_PANID                        1
678
31
#define THREAD_MC_TLV_XPANID                       2
679
26
#define THREAD_MC_TLV_NETWORK_NAME                 3
680
40
#define THREAD_MC_TLV_PSKC                         4
681
11
#define THREAD_MC_TLV_NETWORK_MASTER_KEY           5
682
8
#define THREAD_MC_TLV_NETWORK_KEY_SEQ_CTR          6
683
22
#define THREAD_MC_TLV_NETWORK_ML_PREFIX            7
684
24
#define THREAD_MC_TLV_STEERING_DATA                8
685
15
#define THREAD_MC_TLV_BORDER_AGENT_LOCATOR         9
686
10
#define THREAD_MC_TLV_COMMISSIONER_ID              10
687
19
#define THREAD_MC_TLV_COMMISSIONER_SESSION_ID      11
688
4
#define THREAD_MC_TLV_SECURITY_POLICY              12
689
9
#define THREAD_MC_TLV_GET                          13
690
17
#define THREAD_MC_TLV_ACTIVE_TSTAMP                14 /* Was "Commissioning Dataset Timestamp TLV" */
691
14
#define THREAD_MC_TLV_COMMISSIONER_UDP_PORT        15
692
19
#define THREAD_MC_TLV_STATE                        16
693
4
#define THREAD_MC_TLV_JOINER_DTLS_ENCAP            17
694
15
#define THREAD_MC_TLV_JOINER_UDP_PORT              18
695
6
#define THREAD_MC_TLV_JOINER_IID                   19
696
10
#define THREAD_MC_TLV_JOINER_ROUTER_LOCATOR        20
697
12
#define THREAD_MC_TLV_JOINER_KEK                   21
698
/* Gap */
699
87
#define THREAD_MC_TLV_PROVISIONING_URL             32
700
3
#define THREAD_MC_TLV_VENDOR_NAME                  33
701
11
#define THREAD_MC_TLV_VENDOR_MODEL                 34
702
8
#define THREAD_MC_TLV_VENDOR_SW_VERSION            35
703
6
#define THREAD_MC_TLV_VENDOR_DATA                  36
704
6
#define THREAD_MC_TLV_VENDOR_STACK_VERSION         37
705
/* Gap */
706
144
#define THREAD_MC_TLV_UDP_ENCAPSULATION            48
707
5
#define THREAD_MC_TLV_IPV6_ADDRESS                 49
708
/* Gap */
709
/* New features */
710
27
#define THREAD_MC_TLV_PENDING_TSTAMP               51
711
6
#define THREAD_MC_TLV_DELAY_TIMER                  52
712
29
#define THREAD_MC_TLV_CHANNEL_MASK                 53
713
5
#define THREAD_MC_TLV_COUNT                        54
714
6
#define THREAD_MC_TLV_PERIOD                       55
715
6
#define THREAD_MC_TLV_SCAN_DURATION                56
716
1
#define THREAD_MC_TLV_ENERGY_LIST                  57
717
6
#define THREAD_MC_TLV_DOMAIN_NAME                  59
718
48
#define THREAD_MC_TLV_DOMAIN_PREFIX                60
719
12
#define THREAD_MC_TLV_AE_STEERING_DATA             61
720
1
#define THREAD_MC_TLV_NMKP_STEERING_DATA           62
721
20
#define THREAD_MC_TLV_COMMISSIONER_TOKEN           63
722
5
#define THREAD_MC_TLV_COMMISSIONER_SIGNATURE       64
723
1
#define THREAD_MC_TLV_AE_UDP_PORT                  65
724
6
#define THREAD_MC_TLV_NMKP_UDP_PORT                66
725
68
#define THREAD_MC_TLV_TRI_HOSTNAME                 67
726
3
#define THREAD_MC_TLV_REGISTRAR_IPV6_ADDRESS       68
727
2
#define THREAD_MC_TLV_REGISTRAR_HOSTNAME           69
728
3
#define THREAD_MC_TLV_COMMISSIONER_PEN_SIGNATURE   70
729
138
#define THREAD_MC_TLV_COMMISSIONER_PEN_TOKEN       71
730
731
/* Gap */
732
/* New discovery mechanism */
733
2
#define THREAD_MC_TLV_DISCOVERY_REQUEST            128
734
1
#define THREAD_MC_TLV_DISCOVERY_RESPONSE           129
735
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}
792
};
793
794
static const value_string thread_mc_state_vals[] = {
795
{ -1, "Reject" },
796
{ 0, "Pending" },
797
{ 1, "Accept" },
798
{ 0, NULL}
799
};
800
801
static const true_false_string thread_mc_tlv_join_intent = {
802
    "Intending",
803
    "Not Intending"
804
};
805
806
231
#define THREAD_NWD_TLV_HAS_ROUTE                    0
807
51
#define THREAD_NWD_TLV_PREFIX                       1
808
14
#define THREAD_NWD_TLV_BORDER_ROUTER                2
809
12
#define THREAD_NWD_TLV_6LOWPAN_ID                   3
810
1
#define THREAD_NWD_TLV_COMMISSIONING_DATA           4
811
20
#define THREAD_NWD_TLV_SERVICE                      5
812
3
#define THREAD_NWD_TLV_SERVER                       6
813
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}
823
};
824
825
14
#define THREAD_NWD_TLV_TYPE_M       0xFE
826
14
#define THREAD_NWD_TLV_STABLE_M     0x01
827
828
static const true_false_string tfs_thread_nwd_tlv_border_router_p = {
829
    "Autoconfigured preferred",
830
    "Autoconfigured deprecated"
831
};
832
833
static const true_false_string tfs_thread_nwd_tlv_border_router_c = {
834
    "Additional config. data",
835
    "No additional config. data"
836
};
837
838
static const true_false_string tfs_thread_nwd_tlv_border_router_o = {
839
    "On mesh",
840
    "Not on mesh"
841
};
842
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; */
849
850
/* Target EID TLV fields */
851
static int hf_thread_nm_tlv_target_eid;
852
853
/* Ext. MAC address TLV fields */
854
static int hf_thread_nm_tlv_ext_mac_addr;
855
856
/* RLOC16 TLV fields */
857
static int hf_thread_nm_tlv_rloc16;
858
859
/* Mesh Local IID TLV fields */
860
static int hf_thread_nm_tlv_ml_eid;
861
862
/* Status TLV fields */
863
static int hf_thread_nm_tlv_status;
864
865
/* Last transaction time TLV fields */
866
static int hf_thread_nm_tlv_last_transaction_time;
867
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;
871
872
/* ND option fields */
873
static int hf_thread_nm_tlv_nd_option;
874
875
/* ND data fields */
876
static int hf_thread_nm_tlv_nd_data;
877
878
static int hf_thread_nm_tlv_timeout;
879
880
/* TLV values */
881
882
0
#define THREAD_NM_TLV_TARGET_EID               0
883
0
#define THREAD_NM_TLV_EXT_MAC_ADDR             1
884
0
#define THREAD_NM_TLV_RLOC16                   2
885
0
#define THREAD_NM_TLV_ML_EID                   3
886
0
#define THREAD_NM_TLV_STATUS                   4
887
/* Gap */
888
0
#define THREAD_NM_TLV_LAST_TRANSACTION_TIME    6
889
0
#define THREAD_NM_TLV_ROUTER_MASK              7
890
0
#define THREAD_NM_TLV_ND_OPTION                8
891
0
#define THREAD_NM_TLV_ND_DATA                  9
892
0
#define THREAD_NM_TLV_THREAD_NETWORK_DATA      10
893
0
#define THREAD_NM_TLV_TIMEOUT                  11
894
0
#define THREAD_NM_TLV_THREAD_NETWORK_NAME      12
895
0
#define THREAD_NM_TLV_IPV6_ADDRESS             14
896
0
#define THREAD_NM_TLV_COMMISSIONER_SESSION_ID  15
897
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 }
915
};
916
917
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 }
928
};
929
930
/* Network Management TLVs end*/
931
932
/*Backbone Link TLVs*/
933
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; */
939
940
/* Target EID TLV fields */
941
static int hf_thread_bl_tlv_target_eid;
942
943
/* Ext. MAC address TLV fields */
944
static int hf_thread_bl_tlv_ext_mac_addr;
945
946
/* RLOC16 TLV fields */
947
static int hf_thread_bl_tlv_rloc16;
948
949
/* Mesh Local IID TLV fields */
950
static int hf_thread_bl_tlv_ml_eid;
951
952
/* Status TLV fields */
953
static int hf_thread_bl_tlv_status;
954
955
/* Attached time TLV fields */
956
/* static int hf_thread_bl_tlv_attached_time; */
957
958
/* Last transaction time TLV fields */
959
static int hf_thread_bl_tlv_last_transaction_time;
960
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;
964
965
/* ND option fields */
966
static int hf_thread_bl_tlv_nd_option;
967
968
/* ND data fields */
969
static int hf_thread_bl_tlv_nd_data;
970
971
static int hf_thread_bl_tlv_timeout;
972
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
988
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 }
1005
};
1006
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 }
1014
};
1015
/* Backbone Link TLVs end*/
1016
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 }
1021
};
1022
1023
static int
1024
dissect_thread_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
1025
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;
1030
1031
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 };
1036
1037
static GByteArray *set_thread_seq_ctr_from_key_index(uint8_t key_index)
1038
0
{
1039
0
    GByteArray *seq_ctr_bytes = NULL;
1040
1041
0
    seq_ctr_bytes = g_byte_array_new();
1042
0
    if (thread_seq_ctr_acqd) {
1043
0
        seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
1044
0
        memcpy(seq_ctr_bytes->data, thread_seq_ctr_bytes, 4);
1045
0
    } else {
1046
0
        hex_str_to_bytes(thread_seq_ctr_str, seq_ctr_bytes, false);
1047
0
        if (seq_ctr_bytes->len != 4) {
1048
            /* Not read correctly - assume value is 0 */
1049
0
            seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
1050
0
            memset(seq_ctr_bytes->data, 0, 4);
1051
0
        }
1052
0
    }
1053
    /* Replace lower part with counter based on packet key index */
1054
0
    seq_ctr_bytes->data[3] = (seq_ctr_bytes->data[3] & 0x80) + ((key_index - 1) & 0x7F);
1055
1056
0
    return seq_ctr_bytes;
1057
0
}
1058
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)
1060
0
{
1061
0
    GByteArray *bytes;
1062
0
    char       buffer[10];
1063
0
    bool       res;
1064
0
    bool       key_valid;
1065
0
    bool       verbatim_key = true;
1066
1067
    /* Get the IEEE 802.15.4 decryption key. */
1068
0
    bytes = g_byte_array_new();
1069
0
    res = hex_str_to_bytes(key->pref_key, bytes, false);
1070
0
    key_valid = (res && bytes->len >= IEEE802154_CIPHER_SIZE);
1071
0
    if (key_valid) {
1072
0
        if (thread_use_pan_id_in_key) {
1073
            /* Substitute the bottom two keys bytes with PAN ID */
1074
0
            bytes->data[0] = (uint8_t)(src_pan & 0xFF);
1075
0
            bytes->data[1] = (uint8_t)(src_pan >> 8);
1076
0
        }
1077
0
        if (key->hash_type != KEY_HASH_NONE) {
1078
0
            char digest[32];
1079
1080
0
            if (key->hash_type == KEY_HASH_THREAD) {
1081
0
                memcpy(buffer, seq_ctr_bytes->data, 4);
1082
0
                memcpy(&buffer[4], "Thread", 6); /* len("Thread") */
1083
1084
0
                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
0
                    if (mac_key) {
1087
0
                        memcpy(mac_key, &digest[IEEE802154_CIPHER_SIZE], IEEE802154_CIPHER_SIZE);
1088
0
                    }
1089
                    /* Copy lower hashed bytes to the MLE key */
1090
0
                    if (mle_key) {
1091
0
                        memcpy(mle_key, digest, IEEE802154_CIPHER_SIZE);
1092
0
                    }
1093
0
                    verbatim_key = false;
1094
0
                }
1095
0
            }
1096
0
        }
1097
0
        if (verbatim_key) {
1098
            /* Just copy the keys verbatim */
1099
0
            if (mac_key) {
1100
0
                memcpy(mac_key, bytes->data, IEEE802154_CIPHER_SIZE);
1101
0
            }
1102
0
            if (mle_key) {
1103
0
                memcpy(mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
1104
0
            }
1105
0
        }
1106
0
    }
1107
0
    g_byte_array_free(bytes, true);
1108
0
}
1109
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)
1112
0
{
1113
0
    GByteArray *seq_ctr_bytes = NULL;
1114
1115
0
    if (packet->key_id_mode == KEY_ID_MODE_KEY_INDEX) {
1116
0
        seq_ctr_bytes = set_thread_seq_ctr_from_key_index(packet->key_index);
1117
0
    } else if ((packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) &&
1118
0
               (packet->key_index == IEEE802154_THR_WELL_KNOWN_KEY_INDEX) &&
1119
0
               (packet->key_source.addr32 == IEEE802154_THR_WELL_KNOWN_KEY_SRC))
1120
0
    {
1121
        /* This is the well-known Thread key. No need for an alternative key */
1122
0
        memcpy(key, thread_well_known_key, IEEE802154_CIPHER_SIZE);
1123
0
        return 1;
1124
0
    }
1125
0
    if (seq_ctr_bytes != NULL) {
1126
0
        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
0
        seq_ctr_bytes->data[3] ^= 0x80;
1129
0
        create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, alt_key, NULL);
1130
0
        g_byte_array_free(seq_ctr_bytes, true);
1131
0
        return 2;
1132
0
    }
1133
1134
0
    return 0;
1135
0
}
1136
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)
1139
0
{
1140
0
    GByteArray *seq_ctr_bytes = NULL;
1141
0
    if (packet->key_id_mode == KEY_ID_MODE_KEY_INDEX) {
1142
0
        seq_ctr_bytes = set_thread_seq_ctr_from_key_index(packet->key_index);
1143
0
    }
1144
0
    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
0
        seq_ctr_bytes = g_byte_array_new();
1147
0
        seq_ctr_bytes = g_byte_array_set_size(seq_ctr_bytes, 4);
1148
0
        seq_ctr_bytes->data[0] = (packet->key_source.addr32 >> 24) & 0xFF;
1149
0
        seq_ctr_bytes->data[1] = (packet->key_source.addr32 >> 16) & 0xFF;
1150
0
        seq_ctr_bytes->data[2] = (packet->key_source.addr32 >> 8) & 0xFF;
1151
0
        seq_ctr_bytes->data[3] = packet->key_source.addr32 & 0xFF;
1152
        /* Acquire the sequence counter if configured in preferences */
1153
0
        if (thread_auto_acq_seq_ctr && !thread_seq_ctr_acqd) {
1154
0
            memcpy(thread_seq_ctr_bytes, seq_ctr_bytes->data, 4);
1155
0
            thread_seq_ctr_acqd = true;
1156
0
        }
1157
0
    }
1158
0
    if (seq_ctr_bytes != NULL) {
1159
0
        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
0
        seq_ctr_bytes->data[3] ^= 0x80;
1162
0
        create_thread_temp_keys(seq_ctr_bytes, packet->src_pan, uat_key, NULL, alt_key);
1163
0
        g_byte_array_free(seq_ctr_bytes, true);
1164
0
        return 2;
1165
0
    }
1166
1167
0
    return 0;
1168
0
}
1169
1170
static unsigned
1171
count_bits_in_byte(uint8_t byte)
1172
5
{
1173
5
    static const uint8_t lut[16] = {0, /* 0b0000 */
1174
5
                                   1, /* 0b0001 */
1175
5
                                   1, /* 0b0010 */
1176
5
                                   2, /* 0b0011 */
1177
5
                                   1, /* 0b0100 */
1178
5
                                   2, /* 0b0101 */
1179
5
                                   2, /* 0b0110 */
1180
5
                                   3, /* 0b0111 */
1181
5
                                   1, /* 0b1000 */
1182
5
                                   2, /* 0b1001 */
1183
5
                                   2, /* 0b1010 */
1184
5
                                   3, /* 0b1011 */
1185
5
                                   2, /* 0b1100 */
1186
5
                                   3, /* 0b1101 */
1187
5
                                   3, /* 0b1110 */
1188
5
                                   4  /* 0b1111 */};
1189
5
    return lut[byte >> 4] + lut[byte & 0xf];
1190
5
}
1191
1192
static unsigned
1193
get_chancount(tvbuff_t *tvb)
1194
152
{
1195
152
    unsigned      offset;
1196
152
    uint8_t       tlv_type;
1197
152
    uint16_t      tlv_len;
1198
152
    tlv_len_len_e tlv_len_len;
1199
152
    unsigned      chancount = THREAD_MC_INVALID_CHAN_COUNT;
1200
1201
152
    offset = 0;
1202
1203
    /* Thread Network Data TLVs */
1204
1.26k
    while (tvb_offset_exists(tvb, offset)) {
1205
1206
        /* Get the type and length ahead of time to pass to next function so we can highlight
1207
           proper amount of bytes */
1208
1.12k
        tlv_type = tvb_get_uint8(tvb, offset);
1209
1.12k
        tlv_len = (uint16_t)tvb_get_uint8(tvb, offset + 1);
1210
1211
        /* TODO: need to make sure this applies to all MeshCoP TLVs */
1212
1.12k
        if (THREAD_TLV_LENGTH_ESC == tlv_len) {
1213
            /* 16-bit length field */
1214
15
            tlv_len = tvb_get_ntohs(tvb, offset + 2);
1215
15
            tlv_len_len = TLV_LEN_LEN16;
1216
1.10k
        } else {
1217
1.10k
            tlv_len_len = TLV_LEN_LEN8;
1218
1.10k
        }
1219
1220
        /* Skip over Type and Length */
1221
1.12k
        offset += 1 + tlv_len_len;
1222
1223
1.12k
        switch(tlv_type) {
1224
1225
15
            case THREAD_MC_TLV_CHANNEL_MASK:
1226
15
                {
1227
15
                    int i, j;
1228
15
                    uint8_t entries = 0;
1229
15
                    int32_t check_len = tlv_len;
1230
15
                    int check_offset = offset + 1; /* Channel page first */
1231
15
                    uint16_t masklen;
1232
1233
                    /* Check consistency of entries */
1234
38
                    while (check_len > 0) {
1235
1236
24
                        masklen = tvb_get_uint8(tvb, check_offset);
1237
24
                        if (masklen == 0) {
1238
1
                            break; /* Get out or we might spin forever */
1239
1
                        }
1240
23
                        masklen += 2; /* Add in page and length */
1241
23
                        check_offset += masklen;
1242
23
                        check_len -= masklen;
1243
23
                        entries++;
1244
23
                    }
1245
1246
15
                    if (check_len != 0) {
1247
                        /* Not an integer number of entries */
1248
                        /* offset += tlv_len; */
1249
10
                        return chancount;
1250
10
                    } else {
1251
5
                        chancount = 0;
1252
7
                        for (i = 0; i < entries; i++) {
1253
                            /* Skip over channel page */
1254
2
                            offset++;
1255
2
                            masklen = tvb_get_uint8(tvb, offset);
1256
2
                            offset++;
1257
                            /* Count the number of channels in the channel mask */
1258
8
                            for (j = 0; j < masklen; j++) {
1259
6
                                chancount += count_bits_in_byte(tvb_get_uint8(tvb, offset));
1260
6
                                offset++;
1261
6
                            }
1262
2
                        }
1263
5
                    }
1264
15
                }
1265
5
                break;
1266
1267
1.10k
            default:
1268
                /* Skip over any other TLVs */
1269
1.10k
                offset += tlv_len;
1270
1.12k
        }
1271
1.12k
    }
1272
139
    return chancount;
1273
152
}
1274
1275
static int
1276
dissect_thread_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1277
0
{
1278
0
    proto_item  *proto_root;
1279
0
    proto_tree  *thread_address_tree;
1280
0
    proto_tree  *tlv_tree;
1281
0
    tvbuff_t    *sub_tvb;
1282
0
    unsigned    offset = 0;
1283
0
    proto_item  *ti;
1284
0
    uint8_t     tlv_type, tlv_len;
1285
1286
    /* Create the protocol tree. */
1287
0
    proto_root = proto_tree_add_item(tree, proto_thread_address, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1288
0
    thread_address_tree = proto_item_add_subtree(proto_root, ett_thread_address);
1289
1290
    /* Thread Network Data TLVs */
1291
0
    while (tvb_offset_exists(tvb, offset)) {
1292
1293
        /* Get the length ahead of time to pass to next function so we can highlight
1294
           proper amount of bytes */
1295
0
        tlv_len = tvb_get_uint8(tvb, offset + 1);
1296
1297
0
        ti = proto_tree_add_item(thread_address_tree, hf_thread_address_tlv, tvb, offset, tlv_len+2, ENC_NA);
1298
0
        tlv_tree = proto_item_add_subtree(ti, ett_thread_address_tlv);
1299
1300
        /* Type */
1301
0
        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1302
0
        tlv_type = tvb_get_uint8(tvb, offset);
1303
0
        offset++;
1304
1305
        /* Add value name to value root label */
1306
0
        proto_item_append_text(ti, " (%s)", val_to_str(pinfo->pool, tlv_type, thread_address_tlv_vals, "Unknown (%d)"));
1307
1308
        /* Length */
1309
0
        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1310
0
        offset++;
1311
1312
0
        switch(tlv_type) {
1313
0
            case THREAD_ADDRESS_TLV_TARGET_EID:
1314
0
                {
1315
                    /* Check length is consistent */
1316
0
                    if (tlv_len != 16) {
1317
0
                        expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1318
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1319
0
                    } else {
1320
                        /* Target EID */
1321
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_target_eid, tvb, offset, tlv_len, ENC_NA);
1322
0
                    }
1323
0
                    offset += tlv_len;
1324
0
                }
1325
0
                break;
1326
1327
0
            case THREAD_ADDRESS_TLV_EXT_MAC_ADDR:
1328
0
                {
1329
                    /* Check length is consistent */
1330
0
                    if (tlv_len != 8) {
1331
0
                        expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1332
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1333
0
                    } else {
1334
                        /* Extended MAC address */
1335
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_ext_mac_addr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1336
0
                    }
1337
0
                    offset += tlv_len;
1338
0
                }
1339
0
                break;
1340
1341
0
            case THREAD_ADDRESS_TLV_RLOC16:
1342
0
                {
1343
                    /* Check length is consistent */
1344
0
                    if (tlv_len != 2) {
1345
0
                        expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1346
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1347
0
                    } else {
1348
                        /* Mesh Locator */
1349
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_rloc16, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1350
0
                    }
1351
0
                    offset += tlv_len;
1352
0
                }
1353
0
                break;
1354
1355
0
            case THREAD_ADDRESS_TLV_ML_EID:
1356
0
                {
1357
                    /* Check length is consistent */
1358
0
                    if (tlv_len != 8) {
1359
0
                        expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1360
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1361
0
                    } else {
1362
                        /* ML IID */
1363
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_ml_eid, tvb, offset, tlv_len, ENC_NA);
1364
0
                    }
1365
0
                    offset += tlv_len;
1366
0
                }
1367
0
                break;
1368
1369
0
            case THREAD_ADDRESS_TLV_STATUS:
1370
0
                {
1371
                    /* Check length is consistent */
1372
0
                    if (tlv_len != 1) {
1373
0
                        expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1374
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1375
0
                    } else {
1376
                        /* Status */
1377
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_status, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1378
0
                    }
1379
0
                    offset += tlv_len;
1380
0
                }
1381
0
                break;
1382
1383
0
            case THREAD_ADDRESS_TLV_LAST_TRANSACTION_TIME:
1384
0
                {
1385
                    /* Check length is consistent */
1386
0
                    if (tlv_len != 4) {
1387
0
                        expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1388
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1389
0
                    } else {
1390
                        /* Last transaction time */
1391
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_last_transaction_time, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1392
0
                    }
1393
0
                    offset += tlv_len;
1394
0
                }
1395
0
                break;
1396
1397
0
            case THREAD_ADDRESS_TLV_ROUTER_MASK:
1398
0
                {
1399
                    /* Check length is consistent */
1400
0
                    if (tlv_len != 9) {
1401
0
                        expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1402
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1403
0
                        offset += tlv_len;
1404
0
                    } else {
1405
                        /* Router Mask */
1406
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_router_mask_id_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
1407
0
                        offset++;
1408
1409
                        /*
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|...
1414
                         *
1415
                         * is sent as 0xb8, 0xc5
1416
                         * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
1417
                         */
1418
1419
                        /* Just show the string of octets - best representation for a bit mask */
1420
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_router_mask_assigned, tvb, offset, 8, ENC_NA);
1421
0
                        offset += 8;
1422
0
                    }
1423
0
                }
1424
0
                break;
1425
1426
0
            case THREAD_ADDRESS_TLV_ND_OPTION:
1427
                /* Just show the data */
1428
0
                proto_tree_add_item(tlv_tree, hf_thread_address_tlv_nd_option, tvb, offset, tlv_len, ENC_NA);
1429
0
                offset += tlv_len;
1430
0
                break;
1431
1432
0
            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
0
                proto_tree_add_item(tlv_tree, hf_thread_address_tlv_nd_data, tvb, offset, tlv_len, ENC_NA);
1435
0
                offset += tlv_len;
1436
0
                break;
1437
1438
0
            case THREAD_ADDRESS_TLV_THREAD_NETWORK_DATA:
1439
0
                if (tlv_len > 0) {
1440
0
                    sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
1441
0
                    call_dissector(thread_address_nwd_handle, sub_tvb, pinfo, tlv_tree);
1442
0
                }
1443
0
                offset += tlv_len;
1444
0
                break;
1445
1446
0
            case THREAD_ADDRESS_TLV_TIMEOUT:
1447
0
                if (tlv_len > 4) {
1448
0
                    expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1449
0
                    proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1450
0
                }
1451
0
                else {
1452
                    /* Time out*/
1453
0
                    proto_tree_add_item(tlv_tree, hf_thread_address_tlv_timeout, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1454
0
                }
1455
0
                offset += tlv_len;
1456
0
                break;
1457
0
            case THREAD_ADDRESS_TLV_THREAD_NETWORK_NAME:
1458
0
                if (tlv_len > 16) {
1459
0
                    expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1460
0
                    proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1461
0
                }
1462
0
                else {
1463
                    /* Network Name */
1464
0
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8  );
1465
0
                }
1466
0
                offset += tlv_len;
1467
0
                break;
1468
0
            case THREAD_ADDRESS_TLV_IPV6_ADDRESS:
1469
0
                if ((tlv_len % 16) != 0) {
1470
0
                    expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1471
0
                    proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1472
0
                    offset += tlv_len;
1473
0
                }
1474
0
                else {
1475
                    //Need to only take 16 bytes for the IPv6 address
1476
0
                    for (int i = 0; i < (tlv_len / 16); i++)
1477
0
                    {
1478
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, 16, ENC_NA);
1479
0
                        offset += 16;
1480
0
                    }
1481
0
                }
1482
0
                offset += tlv_len;
1483
0
                break;
1484
0
            default:
1485
0
                proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1486
0
                offset += tlv_len;
1487
0
        }
1488
0
    }
1489
0
    return tvb_captured_length(tvb);
1490
0
}
1491
1492
static int
1493
dissect_thread_nm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1494
0
{
1495
0
    proto_item  *proto_root;
1496
0
    proto_tree  *thread_nm_tree;
1497
0
    proto_tree  *tlv_tree;
1498
0
    tvbuff_t    *sub_tvb;
1499
0
    unsigned    offset = 0;
1500
0
    proto_item  *ti;
1501
0
    uint8_t     tlv_type, tlv_len;
1502
1503
    /* Create the protocol tree. */
1504
0
    proto_root = proto_tree_add_item(tree, proto_thread_nm, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1505
0
    thread_nm_tree = proto_item_add_subtree(proto_root, ett_thread_nm);
1506
1507
    /* Thread Network Data TLVs */
1508
0
    while (tvb_offset_exists(tvb, offset)) {
1509
1510
        /* Get the length ahead of time to pass to next function so we can highlight
1511
           proper amount of bytes */
1512
0
        tlv_len = tvb_get_uint8(tvb, offset + 1);
1513
1514
        /* Create the tree */
1515
0
        ti = proto_tree_add_item(thread_nm_tree, hf_thread_nm_tlv, tvb, offset, tlv_len+2, ENC_NA);
1516
0
        tlv_tree = proto_item_add_subtree(ti, ett_thread_nm_tlv);
1517
1518
        /* Type */
1519
0
        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1520
0
        tlv_type = tvb_get_uint8(tvb, offset);
1521
0
        offset++;
1522
1523
        /* Add value name to value root label */
1524
0
        proto_item_append_text(ti, " (%s)", val_to_str(pinfo->pool, tlv_type, thread_nm_tlv_vals, "Unknown (%d)"));
1525
1526
        /* Length */
1527
0
                proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1528
0
        offset++;
1529
1530
1531
0
        switch(tlv_type) {
1532
0
                case THREAD_NM_TLV_TARGET_EID:
1533
0
                {
1534
                    /* Check length is consistent */
1535
0
                    if (tlv_len != 16) {
1536
0
                        expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1537
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1538
0
                    } else {
1539
                        /* Target EID */
1540
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_target_eid, tvb, offset, tlv_len, ENC_NA);
1541
0
                    }
1542
0
                    offset += tlv_len;
1543
0
                }
1544
0
                break;
1545
1546
0
            case THREAD_NM_TLV_EXT_MAC_ADDR:
1547
0
                {
1548
                    /* Check length is consistent */
1549
0
                    if (tlv_len != 8) {
1550
0
                        expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1551
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1552
0
                    } else {
1553
                        /* Extended MAC address */
1554
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_ext_mac_addr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1555
0
                    }
1556
0
                    offset += tlv_len;
1557
0
                }
1558
0
                break;
1559
1560
0
            case THREAD_NM_TLV_RLOC16:
1561
0
                {
1562
                    /* Check length is consistent */
1563
0
                    if (tlv_len != 2) {
1564
0
                        expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1565
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1566
0
                    } else {
1567
                        /* Mesh Locator */
1568
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_rloc16, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1569
0
                    }
1570
0
                    offset += tlv_len;
1571
0
                }
1572
0
                break;
1573
1574
0
            case THREAD_NM_TLV_ML_EID:
1575
0
                {
1576
                    /* Check length is consistent */
1577
0
                    if (tlv_len != 8) {
1578
0
                        expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1579
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1580
0
                    } else {
1581
                        /* ML IID */
1582
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_ml_eid, tvb, offset, tlv_len, ENC_NA);
1583
0
                    }
1584
0
                    offset += tlv_len;
1585
0
                }
1586
0
                break;
1587
1588
0
            case THREAD_NM_TLV_STATUS:
1589
0
                {
1590
                    /* Check length is consistent */
1591
0
                    if (tlv_len != 1) {
1592
0
                        expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1593
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1594
0
                    } else {
1595
                        /* Status */
1596
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_status, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1597
0
                    }
1598
0
                    offset += tlv_len;
1599
0
                }
1600
0
                break;
1601
1602
0
            case THREAD_NM_TLV_LAST_TRANSACTION_TIME:
1603
0
                {
1604
                    /* Check length is consistent */
1605
0
                    if (tlv_len != 4) {
1606
0
                        expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1607
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1608
0
                    } else {
1609
                        /* Last transaction time */
1610
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_last_transaction_time, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1611
0
                    }
1612
0
                    offset += tlv_len;
1613
0
                }
1614
0
                break;
1615
1616
0
            case THREAD_NM_TLV_ROUTER_MASK:
1617
0
                {
1618
                    /* Check length is consistent */
1619
0
                    if (tlv_len != 9) {
1620
0
                        expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1621
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1622
0
                        offset += tlv_len;
1623
0
                    } else {
1624
                        /* Router Mask */
1625
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_router_mask_id_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
1626
0
                        offset++;
1627
1628
                        /*
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|...
1633
                         *
1634
                         * is sent as 0xb8, 0xc5
1635
                         * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
1636
                         */
1637
1638
                        /* Just show the string of octets - best representation for a bit mask */
1639
0
                        proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_router_mask_assigned, tvb, offset, 8, ENC_NA);
1640
0
                        offset += 8;
1641
0
                    }
1642
0
                }
1643
0
                break;
1644
1645
0
            case THREAD_NM_TLV_ND_OPTION:
1646
                /* Just show the data */
1647
0
                proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_nd_option, tvb, offset, tlv_len, ENC_NA);
1648
0
                offset += tlv_len;
1649
0
                break;
1650
1651
0
            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
0
                proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_nd_data, tvb, offset, tlv_len, ENC_NA);
1654
0
                offset += tlv_len;
1655
0
                break;
1656
1657
0
           case THREAD_NM_TLV_THREAD_NETWORK_DATA:
1658
0
                if (tlv_len > 0) {
1659
0
                    sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
1660
0
                    call_dissector(thread_address_nwd_handle, sub_tvb, pinfo, tlv_tree);
1661
0
                }
1662
0
                offset += tlv_len;
1663
0
                break;
1664
1665
0
           case THREAD_NM_TLV_TIMEOUT:
1666
0
                if (tlv_len > 4) {
1667
0
                    expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1668
0
                    proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1669
0
                }
1670
0
                else {
1671
                    /* Time out*/
1672
0
                    proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_timeout, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1673
0
                }
1674
0
                offset += tlv_len;
1675
1676
1677
0
                break;
1678
1679
0
           case THREAD_NM_TLV_THREAD_NETWORK_NAME:
1680
0
                if (tlv_len > 16) {
1681
0
                    expert_add_info(pinfo, proto_root, &ei_thread_nm_len_size_mismatch);
1682
0
                    proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1683
0
                }
1684
0
                else {
1685
                    /* Network Name */
1686
0
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8);
1687
0
                }
1688
0
                offset += tlv_len;
1689
1690
0
                break;
1691
1692
0
           case THREAD_NM_TLV_IPV6_ADDRESS:
1693
0
                if ((tlv_len % 16) != 0) {
1694
0
                    expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1695
0
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1696
0
                    offset += tlv_len;
1697
0
                }
1698
0
                else {
1699
                    //Need to only take 16 bytes for the IPv6 address
1700
0
                    for (int i = 0; i < (tlv_len / 16); i++)
1701
0
                    {
1702
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, 16, ENC_NA);
1703
0
                        offset += 16;
1704
0
                    }
1705
0
                }
1706
0
                break;
1707
1708
0
           case THREAD_NM_TLV_COMMISSIONER_SESSION_ID:
1709
0
                {
1710
                    /* Check length is consistent */
1711
0
                    if (tlv_len != 2) {
1712
0
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1713
1714
0
            proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1715
0
                    } else {
1716
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_sess_id, tvb, offset, tlv_len, ENC_NA);
1717
0
                    }
1718
0
                    offset += tlv_len;
1719
0
                }
1720
0
                break;
1721
1722
0
            default:
1723
0
                proto_tree_add_item(tlv_tree, hf_thread_nm_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1724
0
                offset += tlv_len;
1725
0
        }
1726
0
    }
1727
0
    return tvb_captured_length(tvb);
1728
0
}
1729
static int
1730
dissect_thread_bl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1731
0
{
1732
0
    proto_item  *proto_root;
1733
0
    proto_tree  *thread_bl_tree;
1734
0
    proto_tree  *tlv_tree;
1735
0
    tvbuff_t    *sub_tvb;
1736
0
    unsigned    offset = 0;
1737
0
    proto_item  *ti;
1738
0
    uint8_t     tlv_type, tlv_len;
1739
1740
    /* Create the protocol tree. */
1741
0
    proto_root = proto_tree_add_item(tree, proto_thread_bl, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1742
0
    thread_bl_tree = proto_item_add_subtree(proto_root, ett_thread_bl);
1743
1744
    /* Thread Network Data TLVs */
1745
0
    while (tvb_offset_exists(tvb, offset)) {
1746
1747
        /* Get the length ahead of time to pass to next function so we can highlight
1748
           proper amount of bytes */
1749
0
        tlv_len = tvb_get_uint8(tvb, offset + 1);
1750
1751
0
       ti = proto_tree_add_item(thread_bl_tree, hf_thread_bl_tlv, tvb, offset, tlv_len+2, ENC_NA);
1752
0
        tlv_tree = proto_item_add_subtree(ti, ett_thread_bl_tlv);
1753
1754
        /* Type */
1755
0
        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1756
0
        tlv_type = tvb_get_uint8(tvb, offset);
1757
0
        offset++;
1758
1759
        /* Add value name to value root label */
1760
0
        proto_item_append_text(ti, " (%s)", val_to_str(pinfo->pool, tlv_type, thread_bl_tlv_vals, "Unknown (%d)"));
1761
1762
        /* Length */
1763
0
        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1764
0
        offset++;
1765
0
        switch(tlv_type) {
1766
0
           case THREAD_NM_TLV_TARGET_EID:
1767
0
                {
1768
                    /* Check length is consistent */
1769
0
                    if (tlv_len != 16) {
1770
0
                       expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1771
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1772
0
                   } else {
1773
                        /* Target EID */
1774
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_target_eid, tvb, offset, tlv_len, ENC_NA);
1775
0
                    }
1776
0
                    offset += tlv_len;
1777
0
                }
1778
0
                break;
1779
1780
0
            case THREAD_NM_TLV_EXT_MAC_ADDR:
1781
0
                {
1782
                    /* Check length is consistent */
1783
0
                    if (tlv_len != 8) {
1784
0
                        expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1785
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1786
0
                    } else {
1787
                        /* Extended MAC address */
1788
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_ext_mac_addr, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1789
0
                    }
1790
0
                    offset += tlv_len;
1791
0
                }
1792
0
                break;
1793
1794
0
            case THREAD_NM_TLV_RLOC16:
1795
0
                {
1796
                    /* Check length is consistent */
1797
0
                    if (tlv_len != 2) {
1798
0
                        expert_add_info(pinfo, proto_root, &ei_thread_address_len_size_mismatch);
1799
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1800
0
                    } else {
1801
                        /* Mesh Locator */
1802
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_rloc16, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1803
0
                    }
1804
0
                    offset += tlv_len;
1805
0
                }
1806
0
                break;
1807
1808
0
            case THREAD_NM_TLV_ML_EID:
1809
0
                {
1810
                    /* Check length is consistent */
1811
0
                    if (tlv_len != 8) {
1812
0
                        expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1813
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1814
0
                    } else {
1815
                        /* ML IID */
1816
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_ml_eid, tvb, offset, tlv_len, ENC_NA);
1817
0
                    }
1818
0
                    offset += tlv_len;
1819
0
                }
1820
0
                break;
1821
1822
0
            case THREAD_NM_TLV_STATUS:
1823
0
                {
1824
                    /* Check length is consistent */
1825
0
                    if (tlv_len != 1) {
1826
0
                        expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1827
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1828
0
                    } else {
1829
                        /* Status */
1830
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_status, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1831
0
                    }
1832
0
                    offset += tlv_len;
1833
0
                }
1834
0
                break;
1835
1836
0
            case THREAD_NM_TLV_LAST_TRANSACTION_TIME:
1837
0
                {
1838
                    /* Check length is consistent */
1839
0
                    if (tlv_len != 4) {
1840
0
                        expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1841
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1842
0
                    } else {
1843
                        /* Last transaction time */
1844
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_last_transaction_time, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1845
0
                    }
1846
0
                    offset += tlv_len;
1847
0
                }
1848
0
                break;
1849
1850
0
            case THREAD_NM_TLV_ROUTER_MASK:
1851
0
                {
1852
                    /* Check length is consistent */
1853
0
                    if (tlv_len != 9) {
1854
0
                        expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1855
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1856
0
                        offset += tlv_len;
1857
0
                    } else {
1858
                        /* Router Mask */
1859
0
                        proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_router_mask_id_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
1860
0
                        offset++;
1861
1862
                        /*
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|...
1867
                         *
1868
                         * is sent as 0xb8, 0xc5
1869
                         * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
1870
                         */
1871
1872
                        /* Just show the string of octets - best representation for a bit mask */
1873
0
                        proto_tree_add_item(tlv_tree, hf_thread_address_tlv_router_mask_assigned, tvb, offset, 8, ENC_NA);
1874
0
                        offset += 8;
1875
0
                    }
1876
0
                }
1877
0
                break;
1878
1879
0
            case THREAD_NM_TLV_ND_OPTION:
1880
                /* Just show the data */
1881
0
                proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_nd_option, tvb, offset, tlv_len, ENC_NA);
1882
0
                offset += tlv_len;
1883
0
                break;
1884
1885
0
            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
0
                proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_nd_data, tvb, offset, tlv_len, ENC_NA);
1888
0
                offset += tlv_len;
1889
0
                break;
1890
1891
0
            case THREAD_NM_TLV_THREAD_NETWORK_DATA:
1892
0
                if (tlv_len > 0) {
1893
0
                    sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
1894
0
                    call_dissector(thread_address_nwd_handle, sub_tvb, pinfo, tlv_tree);
1895
0
                }
1896
0
                offset += tlv_len;
1897
0
                break;
1898
1899
0
            case THREAD_NM_TLV_TIMEOUT:
1900
0
                if (tlv_len > 4) {
1901
0
                    expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1902
0
                    proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1903
0
                }
1904
0
                else {
1905
                    /* Time out*/
1906
0
                    proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_timeout, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1907
0
                }
1908
0
                offset += tlv_len;
1909
1910
1911
0
                break;
1912
1913
0
            case THREAD_NM_TLV_THREAD_NETWORK_NAME:
1914
0
                if (tlv_len > 16) {
1915
0
                    expert_add_info(pinfo, proto_root, &ei_thread_bl_len_size_mismatch);
1916
0
                    proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1917
0
                }
1918
0
                else {
1919
                    /* Network Name */
1920
0
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8);
1921
0
                }
1922
0
                offset += tlv_len;
1923
1924
0
                break;
1925
1926
0
            case THREAD_NM_TLV_IPV6_ADDRESS:
1927
0
                if ((tlv_len % 16) != 0) {
1928
0
                    expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
1929
0
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1930
0
                    offset += tlv_len;
1931
0
                }
1932
0
                else {
1933
0
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, tlv_len, ENC_NA);
1934
0
                     for(int i = 0; i < (tlv_len/16) ; i ++)
1935
0
                    {
1936
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, 16, ENC_NA);
1937
0
                        offset += 16;
1938
0
                    }
1939
0
                }
1940
0
                offset += tlv_len;
1941
0
                break;
1942
1943
0
            default:
1944
0
                proto_tree_add_item(tlv_tree, hf_thread_bl_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
1945
0
                offset += tlv_len;
1946
0
        }
1947
0
    }
1948
0
    return tvb_captured_length(tvb);
1949
0
}
1950
1951
static int
1952
dissect_thread_dg(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
1953
0
{
1954
0
    proto_item    *proto_root;
1955
0
    proto_tree    *thread_dg_tree;
1956
0
    proto_tree    *tlv_tree;
1957
0
    unsigned      offset = 0;
1958
0
    proto_item    *ti;
1959
0
    uint8_t       tlv_type;
1960
0
    uint16_t      tlv_len;
1961
0
    tlv_len_len_e tlv_len_len;
1962
1963
    /* Create the protocol tree. */
1964
0
    proto_root = proto_tree_add_item(tree, proto_thread_dg, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1965
0
    thread_dg_tree = proto_item_add_subtree(proto_root, ett_thread_dg);
1966
1967
    /* Thread Network Data TLVs */
1968
0
    while (tvb_offset_exists(tvb, offset)) {
1969
1970
        /* Get the type and length ahead of time to pass to next function so we can highlight
1971
           proper amount of bytes */
1972
0
        tlv_type = tvb_get_uint8(tvb, offset);
1973
0
        tlv_len = (uint16_t)tvb_get_uint8(tvb, offset + 1);
1974
1975
        /* TODO: need to make sure this applies to all Diagnostic TLVs */
1976
0
        if (THREAD_TLV_LENGTH_ESC == tlv_len) {
1977
            /* 16-bit length field */
1978
0
            tlv_len = tvb_get_ntohs(tvb, offset + 2);
1979
0
            tlv_len_len = TLV_LEN_LEN16;
1980
0
        } else {
1981
0
            tlv_len_len = TLV_LEN_LEN8;
1982
0
        }
1983
1984
        /* Create the tree */
1985
0
        ti = proto_tree_add_item(thread_dg_tree, hf_thread_dg_tlv, tvb, offset, 1 + tlv_len_len + tlv_len, ENC_NA);
1986
0
        tlv_tree = proto_item_add_subtree(ti, ett_thread_dg_tlv);
1987
1988
        /* Type */
1989
0
        proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1990
0
        offset++;
1991
1992
        /* Add value name to value root label */
1993
0
        proto_item_append_text(ti, " (%s)", val_to_str(pinfo->pool, tlv_type, thread_dg_tlv_vals, "Unknown (%d)"));
1994
1995
        /* Length */
1996
0
        switch (tlv_len_len) {
1997
0
            case TLV_LEN_LEN8:
1998
0
                proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_length8, tvb, offset, 1, ENC_BIG_ENDIAN);
1999
0
                break;
2000
0
            case TLV_LEN_LEN16:
2001
0
                proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_length16, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
2002
0
                break;
2003
0
            default:
2004
0
                break;
2005
0
        }
2006
0
        offset += tlv_len_len;
2007
2008
0
        switch(tlv_type) {
2009
0
            case THREAD_DG_TLV_TYPE_LIST:
2010
0
                {
2011
0
                    int i;
2012
2013
0
                    for (i = 0; i < tlv_len; i++) {
2014
0
                        proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2015
0
                        offset++;
2016
0
                    }
2017
0
                }
2018
0
                break;
2019
2020
0
            case THREAD_DG_TLV_EXT_MAC_ADDR:
2021
0
            case THREAD_DG_TLV_ADDRESS16:
2022
0
            case THREAD_DG_TLV_MODE:
2023
0
            case THREAD_DG_TLV_TIMEOUT:
2024
0
            case THREAD_DG_TLV_CONNECTIVITY:
2025
0
            case THREAD_DG_TLV_ROUTE64:
2026
0
            case THREAD_DG_TLV_LEADER_DATA:
2027
0
            case THREAD_DG_TLV_NETWORK_DATA:
2028
0
            case THREAD_DG_TLV_IPV6_ADDR_LIST:
2029
            /* Counters */
2030
0
            case THREAD_DG_TLV_MAC_COUNTERS:
2031
0
            case THREAD_DG_TLV_BATTERY_LEVEL:
2032
0
            case THREAD_DG_TLV_VOLTAGE:
2033
0
            case THREAD_DG_TLV_CHILD_TABLE:
2034
0
            case THREAD_DG_TLV_CHANNEL_PAGES:
2035
0
            case THREAD_DG_TLV_MAX_CHILD_TIMEOUT:
2036
0
            case THREAD_DG_TLV_LDEVID_SUBJECT_PUBLIC_KEY_INFO:
2037
0
            case THREAD_DG_TLV_IDEVID_CERTIFICATE:
2038
0
            case THREAD_DG_TLV_EUI_64:
2039
0
            case THREAD_DG_TLV_VERSION:
2040
0
            case THREAD_DG_TLV_VENDOR_NAME:
2041
0
            case THREAD_DG_TLV_VENDOR_MODEL:
2042
0
            case THREAD_DG_TLV_VENDOR_SW_VERSION:
2043
0
            case THREAD_DG_TLV_THREAD_STACK_VERSION:
2044
0
            case THREAD_DG_TLV_CHILD:
2045
0
            case THREAD_DG_TLV_CHILD_IPV6_ADDRESS_LIST:
2046
0
            case THREAD_DG_TLV_ROUTER_NEIGHBOR:
2047
0
            case THREAD_DG_TLV_ANSWER:
2048
0
            case THREAD_DG_TLV_QUERY_ID:
2049
0
            case THREAD_DG_TLV_MLE_COUNTERS:
2050
0
                proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_general, tvb, offset, tlv_len, ENC_NA);
2051
0
                offset += tlv_len;
2052
0
                break;
2053
2054
0
            default:
2055
0
                proto_tree_add_item(tlv_tree, hf_thread_dg_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2056
0
                offset += tlv_len;
2057
0
        }
2058
0
    }
2059
0
    return tvb_captured_length(tvb);
2060
0
}
2061
2062
static int
2063
dissect_thread_mc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2064
152
{
2065
152
    proto_item    *proto_root;
2066
152
    proto_tree    *thread_mc_tree;
2067
152
    proto_tree    *tlv_tree;
2068
152
    unsigned      offset = 0;
2069
152
    proto_item    *ti;
2070
152
    proto_item    *pi;
2071
152
    uint8_t       tlv_type;
2072
152
    uint16_t      tlv_len;
2073
152
    tlv_len_len_e tlv_len_len;
2074
152
    unsigned      chancount;
2075
2076
2077
    /* Create the protocol tree. */
2078
152
    proto_root = proto_tree_add_item(tree, proto_thread_mc, tvb, 0, tvb_reported_length(tvb), ENC_NA);
2079
152
    thread_mc_tree = proto_item_add_subtree(proto_root, ett_thread_mc);
2080
2081
    /* Get channel count a priori so we can process energy list better */
2082
152
    chancount = get_chancount(tvb);
2083
2084
    /* Thread Network Data TLVs */
2085
1.54k
    while (tvb_offset_exists(tvb, offset)) {
2086
2087
        /* Get the type and length ahead of time to pass to next function so we can highlight
2088
           proper amount of bytes */
2089
1.53k
        tlv_type = tvb_get_uint8(tvb, offset);
2090
1.53k
        tlv_len = (uint16_t)tvb_get_uint8(tvb, offset + 1);
2091
2092
        /* TODO: need to make sure this applies to all MeshCoP TLVs */
2093
1.53k
        if (THREAD_TLV_LENGTH_ESC == tlv_len) {
2094
            /* 16-bit length field */
2095
15
            tlv_len = tvb_get_ntohs(tvb, offset + 2);
2096
15
            tlv_len_len = TLV_LEN_LEN16;
2097
1.51k
        } else {
2098
1.51k
            tlv_len_len = TLV_LEN_LEN8;
2099
1.51k
        }
2100
2101
        /* Create the tree */
2102
1.53k
        ti = proto_tree_add_item(thread_mc_tree, hf_thread_mc_tlv, tvb, offset, 1 + tlv_len_len + tlv_len, ENC_NA);
2103
1.53k
        tlv_tree = proto_item_add_subtree(ti, ett_thread_mc_tlv);
2104
2105
        /* Type */
2106
1.53k
        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2107
1.53k
        offset++;
2108
2109
        /* Add value name to value root label */
2110
1.53k
        proto_item_append_text(ti, " (%s)", val_to_str(pinfo->pool, tlv_type, thread_mc_tlv_vals, "Unknown (%d)"));
2111
2112
        /* Length */
2113
1.53k
        switch (tlv_len_len) {
2114
1.51k
            case TLV_LEN_LEN8:
2115
1.51k
                proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_length8, tvb, offset, 1, ENC_BIG_ENDIAN);
2116
1.51k
                break;
2117
15
            case TLV_LEN_LEN16:
2118
15
                proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_length16, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
2119
15
                break;
2120
0
            default:
2121
0
                break;
2122
1.53k
        }
2123
1.52k
        offset += tlv_len_len;
2124
2125
1.52k
        switch(tlv_type) {
2126
408
            case THREAD_MC_TLV_CHANNEL:
2127
408
                {
2128
                    /* Check length is consistent */
2129
408
                    if (tlv_len != 3) {
2130
407
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2131
407
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2132
407
                    } else {
2133
                        /* Channel page */
2134
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_channel_page, tvb, offset, 1, ENC_BIG_ENDIAN);
2135
                        /* Channel */
2136
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_channel, tvb, offset+1, 2, ENC_BIG_ENDIAN);
2137
1
                    }
2138
408
                    offset += tlv_len;
2139
408
                }
2140
408
                break;
2141
2142
32
            case THREAD_MC_TLV_PANID:
2143
32
                {
2144
                    /* Check length is consistent */
2145
32
                    if (tlv_len != 2) {
2146
29
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2147
29
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2148
29
                    } else {
2149
                        /* PAN ID */
2150
3
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_pan_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2151
3
                    }
2152
32
                    offset += tlv_len;
2153
32
                }
2154
32
                break;
2155
2156
31
            case THREAD_MC_TLV_XPANID:
2157
31
                {
2158
                    /* Check length is consistent */
2159
31
                    if (tlv_len != 8) {
2160
31
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2161
31
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2162
31
                    } else {
2163
                        /* PAN ID */
2164
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_xpan_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2165
0
                    }
2166
31
                    offset += tlv_len;
2167
31
                }
2168
31
                break;
2169
2170
26
            case THREAD_MC_TLV_NETWORK_NAME:
2171
26
                {
2172
                    /* Check length is consistent */
2173
26
                    if (tlv_len > 16) {
2174
13
                        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
13
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8);
2177
13
                    } else {
2178
13
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_name, tvb, offset, tlv_len, ENC_ASCII | ENC_UTF_8);
2179
13
                    }
2180
26
                    offset += tlv_len;
2181
26
                }
2182
26
                break;
2183
2184
40
            case THREAD_MC_TLV_PSKC:
2185
40
                {
2186
                    /* Check length is consistent */
2187
40
                    if (tlv_len != 16) {
2188
40
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2189
40
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2190
40
                    } else {
2191
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_pskc, tvb, offset, tlv_len, ENC_NA);
2192
0
                    }
2193
40
                    offset += tlv_len;
2194
40
                }
2195
40
                break;
2196
2197
11
            case THREAD_MC_TLV_NETWORK_MASTER_KEY:
2198
11
                {
2199
                    /* Check length is consistent */
2200
11
                    if (tlv_len != 16) {
2201
11
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2202
11
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2203
11
                    } else {
2204
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_master_key, tvb, offset, tlv_len, ENC_NA);
2205
0
                    }
2206
11
                    offset += tlv_len;
2207
11
                }
2208
11
                break;
2209
2210
8
            case THREAD_MC_TLV_NETWORK_KEY_SEQ_CTR:
2211
8
                {
2212
                    /* Check length is consistent */
2213
8
                    if (tlv_len != 4) {
2214
8
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2215
8
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2216
8
                    } else {
2217
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_net_key_seq_ctr, tvb, offset, tlv_len, ENC_NA);
2218
0
                    }
2219
8
                    offset += tlv_len;
2220
8
                }
2221
8
                break;
2222
2223
22
            case THREAD_MC_TLV_NETWORK_ML_PREFIX:
2224
22
                {
2225
                    /* Check length is consistent */
2226
22
                    if (tlv_len != 8) {
2227
22
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2228
22
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2229
22
                    } else {
2230
0
                        ws_in6_addr prefix;
2231
2232
0
                        memset(&prefix, 0, sizeof(prefix));
2233
0
                        tvb_memcpy(tvb, (uint8_t *)&prefix.bytes, offset, tlv_len);
2234
0
                        pi = proto_tree_add_ipv6(tlv_tree, hf_thread_mc_tlv_ml_prefix, tvb, offset, tlv_len, &prefix);
2235
0
                        proto_item_append_text(pi, "/%d", tlv_len * 8);
2236
0
                    }
2237
22
                    offset += tlv_len;
2238
22
                }
2239
22
                break;
2240
2241
24
            case THREAD_MC_TLV_STEERING_DATA:
2242
24
                {
2243
                    /* Check length is consistent */
2244
24
                    if (tlv_len > 16) {
2245
2
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2246
2
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2247
22
                    } else {
2248
                        /* Display it simply */
2249
22
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_steering_data, tvb, offset, tlv_len, ENC_NA);
2250
22
                    }
2251
24
                    offset += tlv_len;
2252
24
                }
2253
24
                break;
2254
2255
15
            case THREAD_MC_TLV_BORDER_AGENT_LOCATOR:
2256
15
                {
2257
                    /* Check length is consistent */
2258
15
                    if (tlv_len != 2) {
2259
14
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2260
14
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2261
14
                    } else {
2262
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ba_locator, tvb, offset, tlv_len, ENC_NA);
2263
1
                    }
2264
15
                    offset += tlv_len;
2265
15
                }
2266
15
                break;
2267
2268
10
            case THREAD_MC_TLV_COMMISSIONER_ID:
2269
10
                {
2270
                    /* Check length is consistent */
2271
10
                    if (tlv_len > 64) {
2272
1
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2273
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2274
9
                    } else {
2275
9
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_id, tvb, offset, tlv_len, ENC_UTF_8);
2276
9
                    }
2277
10
                    offset += tlv_len;
2278
10
                }
2279
10
                break;
2280
2281
19
            case THREAD_MC_TLV_COMMISSIONER_SESSION_ID:
2282
19
                {
2283
                    /* Check length is consistent */
2284
19
                    if (tlv_len != 2) {
2285
19
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2286
19
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2287
19
                    } else {
2288
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_sess_id, tvb, offset, tlv_len, ENC_NA);
2289
0
                    }
2290
19
                    offset += tlv_len;
2291
19
                }
2292
19
                break;
2293
2294
4
            case THREAD_MC_TLV_SECURITY_POLICY:
2295
4
                {
2296
                    /* Check length is consistent */
2297
                    //Thread 1.1 has length 3
2298
                    //Thread 1.2 has length 4
2299
                    //else throw error
2300
4
                    if (tlv_len == 3) {
2301
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rot, tvb, offset, 2, ENC_BIG_ENDIAN);
2302
0
                        offset += 2;
2303
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_o, tvb, offset, 1, ENC_BIG_ENDIAN);
2304
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2305
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_r, tvb, offset, 1, ENC_BIG_ENDIAN);
2306
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2307
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_b, tvb, offset, 1, ENC_BIG_ENDIAN);
2308
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rsv1, tvb, offset, 1, ENC_BIG_ENDIAN);
2309
0
                        offset++;
2310
4
                    } else if (tlv_len == 4) {
2311
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rot, tvb, offset, 2, ENC_BIG_ENDIAN);
2312
0
                        offset += 2;
2313
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_o, tvb, offset, 1, ENC_BIG_ENDIAN);
2314
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2315
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_r, tvb, offset, 1, ENC_BIG_ENDIAN);
2316
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2317
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_b, tvb, offset, 1, ENC_BIG_ENDIAN);
2318
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_ccm, tvb, offset, 1, ENC_BIG_ENDIAN);
2319
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_ae, tvb, offset, 1, ENC_BIG_ENDIAN);
2320
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_nmp, tvb, offset, 1, ENC_BIG_ENDIAN);
2321
0
                        offset++;
2322
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_l, tvb, offset, 1, ENC_BIG_ENDIAN);
2323
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_ncr, tvb, offset, 1, ENC_BIG_ENDIAN);
2324
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_rsv, tvb, offset, 1, ENC_BIG_ENDIAN);
2325
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_sec_policy_vr, tvb, offset, 1, ENC_BIG_ENDIAN);
2326
0
                        offset++;
2327
2328
4
                    } else{
2329
4
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2330
4
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2331
4
                        offset += tlv_len;
2332
4
                    }
2333
4
                }
2334
4
                break;
2335
2336
9
            case THREAD_MC_TLV_GET:
2337
9
                {
2338
9
                    int i;
2339
2340
239
                    for (i = 0; i < tlv_len; i++) {
2341
230
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2342
230
                        offset++;
2343
230
                    }
2344
9
                }
2345
9
                break;
2346
2347
17
            case THREAD_MC_TLV_ACTIVE_TSTAMP:
2348
27
            case THREAD_MC_TLV_PENDING_TSTAMP:
2349
27
                {
2350
27
                    nstime_t timestamp;
2351
2352
27
                    if (tlv_len != 8) {
2353
27
                        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
27
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_pending_tstamp, tvb, offset, tlv_len, ENC_TIME_SECS_NSECS);
2356
27
                    } else {
2357
                        /* Fill in the nstime_t structure */
2358
0
                        timestamp.secs = (time_t)tvb_get_ntoh48(tvb, offset);
2359
0
                        timestamp.nsecs = (int)lround((double)(tvb_get_ntohs(tvb, offset + 6) >> 1) * THREAD_MC_32768_TO_NSEC_FACTOR);
2360
0
                        if (tlv_type == THREAD_MC_TLV_ACTIVE_TSTAMP) {
2361
0
                            proto_tree_add_time(tlv_tree, hf_thread_mc_tlv_active_tstamp, tvb, offset, 8, &timestamp);
2362
0
                        } else {
2363
0
                            proto_tree_add_time(tlv_tree, hf_thread_mc_tlv_pending_tstamp, tvb, offset, 8, &timestamp);
2364
0
                        }
2365
0
                    }
2366
27
                    offset += tlv_len;
2367
27
                }
2368
27
                break;
2369
2370
19
            case THREAD_MC_TLV_STATE:
2371
19
                {
2372
                    /* Check length is consistent */
2373
19
                    if (tlv_len != 1) {
2374
19
                        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
19
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_state, tvb, offset, tlv_len, ENC_NA);
2377
19
                    } else {
2378
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_state, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2379
0
                    }
2380
19
                    offset += tlv_len;
2381
19
                }
2382
19
                break;
2383
2384
4
            case THREAD_MC_TLV_JOINER_DTLS_ENCAP:
2385
4
                {
2386
4
                    tvbuff_t *sub_tvb;
2387
2388
4
                    if (tlv_len > 0) {
2389
4
                        sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
2390
4
                        call_dissector(thread_dtls_handle, sub_tvb, pinfo, tree);
2391
4
                    }
2392
4
                    offset += tlv_len;
2393
4
                }
2394
4
                break;
2395
2396
14
            case THREAD_MC_TLV_COMMISSIONER_UDP_PORT:
2397
15
            case THREAD_MC_TLV_JOINER_UDP_PORT:
2398
15
                {
2399
15
                    if (tlv_len != 2) {
2400
15
                        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
15
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_port, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2403
15
                    } else {
2404
                        /* UDP Port */
2405
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_port, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2406
0
                    }
2407
15
                    offset += tlv_len;
2408
15
                }
2409
15
                break;
2410
2411
6
            case THREAD_MC_TLV_JOINER_IID:
2412
6
                {
2413
6
                    if (tlv_len != 8) {
2414
6
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2415
6
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2416
6
                    } else {
2417
                        /* IID */
2418
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_iid, tvb, offset, tlv_len, ENC_NA);
2419
0
                    }
2420
6
                    offset += tlv_len;
2421
6
                }
2422
6
                break;
2423
2424
10
            case THREAD_MC_TLV_JOINER_ROUTER_LOCATOR:
2425
10
                {
2426
10
                    if (tlv_len != 2) {
2427
10
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2428
10
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2429
10
                    } else {
2430
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_jr_locator, tvb, offset, tlv_len, ENC_NA);
2431
0
                    }
2432
10
                    offset += tlv_len;
2433
10
                }
2434
10
                break;
2435
2436
12
            case THREAD_MC_TLV_JOINER_KEK:
2437
12
                {
2438
12
                    if (tlv_len != 16) {
2439
12
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2440
12
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2441
12
                    } else {
2442
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_kek, tvb, offset, tlv_len, ENC_NA);
2443
0
                    }
2444
12
                    offset += tlv_len;
2445
12
                }
2446
12
                break;
2447
2448
87
            case THREAD_MC_TLV_PROVISIONING_URL:
2449
87
                {
2450
                    /* Check length is consistent */
2451
87
                    if (tlv_len > 64) {
2452
1
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2453
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2454
86
                    } else {
2455
86
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_provisioning_url, tvb, offset, tlv_len, ENC_UTF_8);
2456
86
                    }
2457
87
                    offset += tlv_len;
2458
87
                }
2459
87
                break;
2460
2461
3
            case THREAD_MC_TLV_VENDOR_NAME:
2462
3
                {
2463
                    /* Check length is consistent */
2464
3
                    if (tlv_len > 32) {
2465
1
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2466
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2467
2
                    } else {
2468
2
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_name, tvb, offset, tlv_len, ENC_UTF_8);
2469
2
                    }
2470
3
                    offset += tlv_len;
2471
3
                }
2472
3
                break;
2473
2474
11
            case THREAD_MC_TLV_VENDOR_MODEL:
2475
11
                {
2476
                    /* Check length is consistent: TODO not specified in spec. */
2477
11
                    if (tlv_len > 32) {
2478
10
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2479
10
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2480
10
                    } else {
2481
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_model, tvb, offset, tlv_len, ENC_UTF_8);
2482
1
                    }
2483
11
                    offset += tlv_len;
2484
11
                }
2485
11
                break;
2486
2487
8
            case THREAD_MC_TLV_VENDOR_SW_VERSION:
2488
8
                {
2489
                    /* Check length is consistent */
2490
8
                    if (tlv_len > 16) {
2491
7
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2492
7
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2493
7
                    } else {
2494
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_sw_ver, tvb, offset, tlv_len, ENC_UTF_8);
2495
1
                    }
2496
8
                    offset += tlv_len;
2497
8
                }
2498
8
                break;
2499
2500
6
            case THREAD_MC_TLV_VENDOR_DATA:
2501
6
                {
2502
                    /* Check length is consistent */
2503
6
                    if (tlv_len > 64) {
2504
1
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_too_long);
2505
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2506
5
                    } else {
2507
                        /* Display it simply */
2508
5
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_data, tvb, offset, tlv_len, ENC_ASCII);
2509
5
                    }
2510
6
                    offset += tlv_len;
2511
6
                }
2512
6
                break;
2513
2514
6
            case THREAD_MC_TLV_VENDOR_STACK_VERSION:
2515
6
                {
2516
                    /* Check length is consistent */
2517
6
                    if (tlv_len != 6) {
2518
6
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2519
6
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2520
6
                        offset += tlv_len;
2521
6
                    } else {
2522
0
                        uint8_t build_u8;
2523
0
                        uint16_t build;
2524
2525
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
2526
0
                        offset += 3;
2527
0
                        build_u8 = tvb_get_uint8(tvb, offset);
2528
0
                        offset++;
2529
0
                        build = (uint16_t)build_u8 << 4;
2530
0
                        build_u8 = tvb_get_uint8(tvb, offset);
2531
0
                        build |= (uint16_t)build_u8 >> 4;
2532
0
                        pi = proto_tree_add_uint(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_build, tvb, 0, 0, build);
2533
0
                        proto_item_set_generated(pi);
2534
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_rev, tvb, offset, 1, ENC_BIG_ENDIAN);
2535
0
                        offset++;
2536
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_min, tvb, offset, 1, ENC_BIG_ENDIAN);
2537
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_vendor_stack_ver_maj, tvb, offset, 1, ENC_BIG_ENDIAN);
2538
0
                        offset++;
2539
0
                    }
2540
6
                }
2541
6
                break;
2542
2543
144
            case THREAD_MC_TLV_UDP_ENCAPSULATION:
2544
144
                {
2545
144
                    tvbuff_t *sub_tvb;
2546
144
                    uint16_t src_port;
2547
144
                    uint16_t dst_port;
2548
2549
144
                    src_port = tvb_get_ntohs(tvb, offset);
2550
144
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_encap_src_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2551
144
                    offset += 2;
2552
144
                    dst_port = tvb_get_ntohs(tvb, offset);
2553
144
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_udp_encap_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2554
144
                    offset += 2;
2555
2556
144
                    if (tlv_len >= 4)
2557
131
                    {
2558
                        /* Allocate a buffer for the fake UDP datagram and create the fake header. */
2559
131
                        udp_hdr_t* udp_hdr = (udp_hdr_t *)wmem_alloc(pinfo->pool, sizeof(udp_hdr_t) + (tlv_len - 4));
2560
2561
                        /* Create pseudo UDP header */
2562
131
                        udp_hdr->src_port = g_htons(src_port);
2563
131
                        udp_hdr->dst_port = g_htons(dst_port);
2564
131
                        udp_hdr->length = g_htons(tlv_len + 4); /* Includes UDP header length */
2565
131
                        udp_hdr->checksum = 0;
2566
                        /* Copy UDP payload in */
2567
131
                        tvb_memcpy(tvb, udp_hdr + 1, offset, tlv_len - 4);
2568
                        /* Create child tvb */
2569
131
                        sub_tvb = tvb_new_child_real_data(tvb, (uint8_t *)udp_hdr, tlv_len + 4, tvb_reported_length(tvb) + 4);
2570
131
                        call_dissector(thread_udp_handle, sub_tvb, pinfo, tree);
2571
131
                    }
2572
144
                    offset += (tlv_len-4);
2573
144
                }
2574
144
                break;
2575
2576
5
            case THREAD_MC_TLV_IPV6_ADDRESS:
2577
5
                {
2578
                    /* Check length is consistent */
2579
5
                    if (tlv_len != 16) {
2580
4
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2581
4
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2582
4
                    } else {
2583
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ipv6_addr, tvb, offset, tlv_len, ENC_NA);
2584
1
                    }
2585
5
                    offset += tlv_len;
2586
5
                }
2587
5
                break;
2588
2589
            /* case THREAD_MC_TLV_PENDING_TSTAMP: Handled in THREAD_MC_TLV_ACTIVE_TSTAMP case */
2590
2591
6
            case THREAD_MC_TLV_DELAY_TIMER:
2592
6
                {
2593
6
                    if (tlv_len != 4) {
2594
6
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2595
6
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2596
6
                    } else {
2597
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_delay_timer, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2598
0
                    }
2599
6
                    offset += tlv_len;
2600
6
                }
2601
6
                break;
2602
2603
14
            case THREAD_MC_TLV_CHANNEL_MASK:
2604
14
                {
2605
14
                    proto_tree *cm_tree;
2606
14
                    int i;
2607
14
                    uint8_t entries = 0;
2608
14
                    int32_t check_len = tlv_len;
2609
14
                    int check_offset = offset + 1; /* Channel page first */
2610
14
                    uint16_t masklen;
2611
2612
                    /* Check consistency of entries */
2613
32
                    while (check_len > 0) {
2614
2615
19
                        masklen = tvb_get_uint8(tvb, check_offset);
2616
19
                        if (masklen == 0) {
2617
1
                            break; /* Get out or we might spin forever */
2618
1
                        }
2619
18
                        masklen += 2; /* Add in page and length */
2620
18
                        check_offset += masklen;
2621
18
                        check_len -= masklen;
2622
18
                        entries++;
2623
18
                    }
2624
2625
14
                    if (check_len != 0) {
2626
                        /* Not an integer number of entries */
2627
12
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_tlv_length_failed);
2628
12
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2629
12
                        offset += tlv_len;
2630
12
                    } else {
2631
2
                        for (i = 0; i < entries; i++) {
2632
0
                            pi = proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_chan_mask, tvb, offset, 1, ENC_NA);
2633
0
                            cm_tree = proto_item_add_subtree(pi, ett_thread_mc_chan_mask);
2634
0
                            proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_page, tvb, offset, 1, ENC_BIG_ENDIAN);
2635
0
                            offset++;
2636
0
                            masklen = tvb_get_uint8(tvb, offset);
2637
0
                            proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_len, tvb, offset, 1, ENC_BIG_ENDIAN);
2638
0
                            offset++;
2639
0
                            proto_tree_add_item(cm_tree, hf_thread_mc_tlv_chan_mask_mask, tvb, offset, masklen, ENC_NA);
2640
0
                            offset += masklen;
2641
0
                        }
2642
2
                    }
2643
14
                }
2644
14
                break;
2645
2646
5
            case THREAD_MC_TLV_COUNT:
2647
5
                {
2648
5
                    if (tlv_len != 1) {
2649
5
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2650
5
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2651
5
                    } else {
2652
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_count, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2653
0
                    }
2654
5
                    offset += tlv_len;
2655
5
                }
2656
5
                break;
2657
2658
6
            case THREAD_MC_TLV_PERIOD:
2659
6
                {
2660
6
                    if (tlv_len != 2) {
2661
6
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2662
6
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2663
6
                    } else {
2664
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_period, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2665
0
                    }
2666
6
                    offset += tlv_len;
2667
6
                }
2668
6
                break;
2669
2670
6
            case THREAD_MC_TLV_SCAN_DURATION:
2671
6
                {
2672
6
                    if (tlv_len != 2) {
2673
6
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2674
6
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2675
6
                    } else {
2676
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_scan_duration, tvb, offset, tlv_len, ENC_BIG_ENDIAN);
2677
0
                    }
2678
6
                    offset += tlv_len;
2679
6
                }
2680
6
                break;
2681
2682
1
            case THREAD_MC_TLV_ENERGY_LIST:
2683
1
                {
2684
1
                    proto_tree *it_tree;
2685
1
                    int i;
2686
2687
1
                    if ((chancount != THREAD_MC_INVALID_CHAN_COUNT) && (chancount != 0) && ((tlv_len % chancount) == 0)) {
2688
                        /* Go through the number of el_counts of scan */
2689
0
                        for (i = 0; i < (int)(tlv_len / (uint16_t)chancount); i++) {
2690
0
                            pi = proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_el_count, tvb, offset, 1, ENC_NA);
2691
0
                            proto_item_append_text(pi, " %d", i + 1);
2692
0
                            it_tree = proto_item_add_subtree(pi, ett_thread_mc_el_count);
2693
0
                            proto_tree_add_item(it_tree, hf_thread_mc_tlv_energy_list, tvb, offset, chancount, ENC_NA);
2694
0
                            offset += chancount;
2695
0
                        }
2696
1
                    } 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
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_energy_list, tvb, offset, tlv_len, ENC_NA);
2700
1
                    }
2701
1
                    offset += tlv_len;
2702
1
                }
2703
1
                break;
2704
2705
6
            case THREAD_MC_TLV_DOMAIN_NAME:
2706
6
                {
2707
                    /* Check length is consistent */
2708
6
                    if (tlv_len > 16) {
2709
5
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2710
5
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2711
5
                    } else {
2712
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_domain_name, tvb, offset, tlv_len, ENC_NA);
2713
1
                    }
2714
6
                    offset += tlv_len;
2715
6
                }
2716
6
                break;
2717
2718
48
            case THREAD_MC_TLV_DOMAIN_PREFIX:
2719
                //To be defined in future in draft
2720
48
                break;
2721
2722
12
            case THREAD_MC_TLV_AE_STEERING_DATA:
2723
12
                {
2724
                    /* Check length is consistent */
2725
12
                    if (tlv_len > 16) {
2726
10
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2727
10
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2728
10
                    } else {
2729
2
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ae_steering_data, tvb, offset, tlv_len, ENC_NA);
2730
2
                    }
2731
12
                    offset += tlv_len;
2732
12
                }
2733
12
                break;
2734
2735
1
            case THREAD_MC_TLV_NMKP_STEERING_DATA:
2736
1
                {
2737
                    /* Check length is consistent */
2738
1
                    if (tlv_len > 16) {
2739
1
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2740
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2741
1
                    } else {
2742
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_nmkp_steering_data, tvb, offset, tlv_len, ENC_NA);
2743
0
                    }
2744
1
                    offset += tlv_len;
2745
1
                }
2746
1
                break;
2747
2748
20
            case THREAD_MC_TLV_COMMISSIONER_TOKEN:
2749
20
                break;
2750
2751
5
            case THREAD_MC_TLV_COMMISSIONER_SIGNATURE:
2752
5
                    proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_commissioner_signature, tvb, offset, tlv_len, ENC_NA);
2753
5
                    offset += tlv_len;
2754
5
                break;
2755
2756
1
            case THREAD_MC_TLV_AE_UDP_PORT:
2757
1
                {
2758
                    /* Check length is consistent */
2759
1
                    if (tlv_len != 2) {
2760
1
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2761
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2762
1
                    } else {
2763
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_ae_udp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2764
0
                    }
2765
1
                    offset += tlv_len;
2766
1
                }
2767
1
                break;
2768
2769
6
            case THREAD_MC_TLV_NMKP_UDP_PORT:
2770
6
                {
2771
                    /* Check length is consistent */
2772
6
                    if (tlv_len != 2) {
2773
6
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2774
6
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2775
6
                    } else {
2776
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_nmkp_udp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
2777
0
                    }
2778
6
                    offset += tlv_len;
2779
6
                }
2780
6
                break;
2781
2782
68
            case THREAD_MC_TLV_TRI_HOSTNAME:
2783
68
                break;
2784
2785
3
            case THREAD_MC_TLV_REGISTRAR_IPV6_ADDRESS:
2786
3
                {
2787
                    /* Check length is consistent */
2788
3
                    if (tlv_len != 16) {
2789
3
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2790
3
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2791
3
                    } else {
2792
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_registrar_ipv6_addr, tvb, offset, tlv_len, ENC_NA);
2793
0
                    }
2794
3
                    offset += tlv_len;
2795
3
                }
2796
3
                break;
2797
2798
2
            case THREAD_MC_TLV_REGISTRAR_HOSTNAME:
2799
2
                proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_registrar_hostname, tvb, offset, tlv_len, ENC_NA);
2800
2
                offset += tlv_len;
2801
2
                break;
2802
2803
3
            case THREAD_MC_TLV_COMMISSIONER_PEN_SIGNATURE:
2804
3
                break;
2805
2806
138
            case THREAD_MC_TLV_COMMISSIONER_PEN_TOKEN:
2807
138
                break;
2808
2809
2
            case THREAD_MC_TLV_DISCOVERY_REQUEST:
2810
2
                {
2811
                    /* Check length is consistent */
2812
2
                    if (tlv_len != 2) {
2813
2
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2814
2
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2815
2
                    } else {
2816
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_req_ver, tvb, offset, 1, ENC_BIG_ENDIAN);
2817
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_req_j, tvb, offset, 1, ENC_BIG_ENDIAN);
2818
0
                    }
2819
2
                    offset += tlv_len;
2820
2
                }
2821
2
                break;
2822
2823
1
            case THREAD_MC_TLV_DISCOVERY_RESPONSE:
2824
1
                {
2825
                    /* Check length is consistent */
2826
1
                    if (tlv_len != 2) {
2827
1
                        expert_add_info(pinfo, proto_root, &ei_thread_mc_len_size_mismatch);
2828
1
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2829
1
                    } else {
2830
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_rsp_ver, tvb, offset, 1, ENC_BIG_ENDIAN);
2831
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_rsp_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2832
0
                        proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_discovery_rsp_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2833
0
                    }
2834
1
                    offset += tlv_len;
2835
1
                }
2836
1
                break;
2837
2838
149
            default:
2839
149
                proto_tree_add_item(tlv_tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2840
149
                offset += tlv_len;
2841
1.52k
        }
2842
1.52k
    }
2843
9
    return tvb_captured_length(tvb);
2844
152
}
2845
2846
static int
2847
// NOLINTNEXTLINE(misc-no-recursion)
2848
dissect_thread_nwd_with_server_decode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int server_decode)
2849
46
{
2850
46
    proto_item  *proto_root;
2851
46
    proto_tree  *thread_nwd_tree;
2852
46
    proto_tree  *tlv_tree;
2853
46
    tvbuff_t    *sub_tvb;
2854
46
    unsigned    offset = 0, tlv_offset;
2855
46
    proto_item  *ti;
2856
46
    uint8_t     tlv_type, tlv_len;
2857
2858
    /* Create the protocol tree. */
2859
46
    proto_root = proto_tree_add_item(tree, proto_thread_nwd, tvb, 0, tvb_reported_length(tvb), ENC_NA);
2860
46
    thread_nwd_tree = proto_item_add_subtree(proto_root, ett_thread_nwd);
2861
2862
    /* Thread Network Data TLVs */
2863
46
    increment_dissection_depth(pinfo);
2864
417
    while (tvb_offset_exists(tvb, offset)) {
2865
2866
        /* Get the length ahead of time to pass to next function so we can highlight
2867
           proper amount of bytes */
2868
399
        tlv_len = tvb_get_uint8(tvb, offset + 1);
2869
2870
399
        ti = proto_tree_add_item(thread_nwd_tree, hf_thread_nwd_tlv, tvb, offset, tlv_len+2, ENC_NA);
2871
399
        tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_tlv);
2872
2873
        /* Type */
2874
399
        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2875
399
        tlv_type = tvb_get_uint8(tvb, offset) >> 1;
2876
2877
        /* Stable */
2878
399
        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_stable, tvb, offset, 1, ENC_BIG_ENDIAN);
2879
399
        offset++;
2880
2881
        /* Add value name to value root label */
2882
399
        proto_item_append_text(ti, " (%s)", val_to_str(pinfo->pool, tlv_type, thread_nwd_tlv_vals, "Unknown (%d)"));
2883
2884
        /* Length */
2885
399
        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2886
399
        offset++;
2887
2888
399
        switch(tlv_type) {
2889
231
            case THREAD_NWD_TLV_HAS_ROUTE:
2890
231
                {
2891
                    /* Has Route TLV can be top level TLV or sub-TLV */
2892
2893
                    /* Check length is consistent */
2894
231
                    if ((tlv_len % THREAD_NWD_TLV_HAS_ROUTE_SIZE) != 0)
2895
34
                    {
2896
34
                        expert_add_info(pinfo, proto_root, &ei_thread_nwd_len_size_mismatch);
2897
34
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2898
34
                        offset += tlv_len;
2899
197
                    } else {
2900
197
                        proto_tree *has_route_tree;
2901
197
                        unsigned i;
2902
197
                        unsigned count = tlv_len / THREAD_NWD_TLV_HAS_ROUTE_SIZE;
2903
2904
                        /* Add subtrees */
2905
309
                        for (i = 0; i < count; i++) {
2906
112
                            ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_has_route, tvb, offset, 1, ENC_NA);
2907
112
                            has_route_tree = proto_item_add_subtree(ti, ett_thread_nwd_has_route);
2908
112
                            proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_br_16, tvb, offset, 2, ENC_BIG_ENDIAN);
2909
112
                            offset += 2;
2910
112
                            proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_pref, tvb, offset, 1, ENC_BIG_ENDIAN);
2911
112
                            proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_np, tvb, offset, 1, ENC_BIG_ENDIAN);
2912
112
                            proto_tree_add_item(has_route_tree, hf_thread_nwd_tlv_has_route_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2913
112
                            offset += 1;
2914
112
                        }
2915
197
                    }
2916
231
                }
2917
231
                break;
2918
2919
51
            case THREAD_NWD_TLV_PREFIX:
2920
51
                {
2921
51
                    uint8_t prefix_len;
2922
51
                    uint8_t prefix_byte_len;
2923
51
                    ws_in6_addr prefix;
2924
51
                    address prefix_addr;
2925
2926
                    /* Domain ID */
2927
51
                    proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_prefix_domain_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2928
51
                    offset++;
2929
51
                    tlv_offset = 1;
2930
2931
                    /* Prefix Length */
2932
51
                    proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_prefix_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2933
51
                    prefix_len = tvb_get_uint8(tvb, offset);
2934
51
                    prefix_byte_len = (prefix_len + 7) / 8;
2935
51
                    offset++;
2936
51
                    tlv_offset++;
2937
2938
                    /* Prefix */
2939
51
                    memset(&prefix.bytes, 0, sizeof(prefix));
2940
51
                    if (prefix_byte_len <= sizeof(prefix))
2941
50
                        tvb_memcpy(tvb, (uint8_t *)&prefix.bytes, offset, prefix_byte_len);
2942
51
                    proto_tree_add_ipv6(tlv_tree, hf_thread_nwd_tlv_prefix, tvb, offset, prefix_byte_len, &prefix);
2943
51
                    set_address(&prefix_addr, AT_IPv6, 16, prefix.bytes);
2944
51
                    proto_item_append_text(ti, " = %s/%d", address_to_str(pinfo->pool, &prefix_addr), prefix_len);
2945
51
                    offset += prefix_byte_len;
2946
51
                    tlv_offset += prefix_byte_len;
2947
2948
51
                    if (tlv_offset < tlv_len) {
2949
10
                        proto_tree *sub_tlv_tree;
2950
10
                        unsigned remaining = tlv_len - tlv_offset;
2951
2952
10
                        ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_sub_tlvs, tvb, offset, 1, ENC_NA);
2953
10
                        sub_tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_prefix_sub_tlvs);
2954
                        /* Call this dissector for sub-TLVs */
2955
10
                        sub_tvb = tvb_new_subset_length(tvb, offset, remaining); /* remove prefix length (1) and prefix (prefix_byte_len) */
2956
10
                        dissect_thread_nwd_with_server_decode(sub_tvb, pinfo, sub_tlv_tree, server_decode);
2957
10
                        offset += remaining;
2958
10
                    }
2959
51
                }
2960
51
                break;
2961
2962
14
            case THREAD_NWD_TLV_BORDER_ROUTER:
2963
14
                {
2964
                    /* Border Router TLV can only be sub-TLV */
2965
2966
                    /* Check length is consistent */
2967
14
                    if ((tlv_len % 4) != 0)
2968
8
                    {
2969
8
                        expert_add_info(pinfo, proto_root, &ei_thread_nwd_len_size_mismatch);
2970
8
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
2971
8
                        offset += tlv_len;
2972
8
                    } else {
2973
6
                        proto_tree *border_router_tree;
2974
6
                        unsigned i;
2975
6
                        unsigned count = tlv_len / 4;
2976
2977
                        /* Add subtrees */
2978
23
                        for (i = 0; i < count; i++) {
2979
17
                            ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_border_router, tvb, offset, 1, ENC_NA);
2980
17
                            border_router_tree = proto_item_add_subtree(ti, ett_thread_nwd_border_router);
2981
2982
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_16, tvb, offset, 2, ENC_BIG_ENDIAN);
2983
17
                            offset += 2;
2984
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_pref, tvb, offset, 1, ENC_BIG_ENDIAN);
2985
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_p, tvb, offset, 1, ENC_BIG_ENDIAN);
2986
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_s, tvb, offset, 1, ENC_BIG_ENDIAN);
2987
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_d, tvb, offset, 1, ENC_BIG_ENDIAN);
2988
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_c, tvb, offset, 1, ENC_BIG_ENDIAN);
2989
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_r, tvb, offset, 1, ENC_BIG_ENDIAN);
2990
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_o, tvb, offset, 1, ENC_BIG_ENDIAN);
2991
17
                            offset++;
2992
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_n, tvb, offset, 1, ENC_BIG_ENDIAN);
2993
17
                            proto_tree_add_item(border_router_tree, hf_thread_nwd_tlv_border_router_dp, tvb, offset, 1, ENC_BIG_ENDIAN);
2994
17
                            offset++;
2995
17
                        }
2996
6
                    }
2997
14
                }
2998
14
                break;
2999
3000
12
            case THREAD_NWD_TLV_6LOWPAN_ID:
3001
12
                {
3002
12
                    static int * const nwd_6lowpan_flags[] = {
3003
12
                        &hf_thread_nwd_tlv_6lowpan_id_6co_flag_reserved,
3004
12
                        &hf_thread_nwd_tlv_6lowpan_id_6co_flag_c,
3005
12
                        &hf_thread_nwd_tlv_6lowpan_id_6co_flag_cid,
3006
12
                        NULL
3007
12
                    };
3008
3009
                    /* 6lowpan-ND */
3010
12
                    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);
3011
12
                    offset++;
3012
3013
                    /* Context Length */
3014
12
                    proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_6lowpan_id_6co_context_length, tvb, offset, 1, ENC_BIG_ENDIAN);
3015
12
                    offset++;
3016
12
                }
3017
12
                break;
3018
3019
1
            case THREAD_NWD_TLV_COMMISSIONING_DATA:
3020
1
                {
3021
1
                    if (tlv_len > 0) {
3022
1
                        sub_tvb = tvb_new_subset_length(tvb, offset, tlv_len);
3023
1
                        call_dissector(thread_mc_handle, sub_tvb, pinfo, tlv_tree);
3024
1
                    }
3025
1
                    offset += tlv_len;
3026
1
                }
3027
1
                break;
3028
3029
20
            case THREAD_NWD_TLV_SERVICE:
3030
20
                {
3031
20
                    uint8_t flags;
3032
20
                    uint8_t s_data_len;
3033
3034
                    /* Flags and S_id */
3035
20
                    flags = tvb_get_uint8(tvb, offset);
3036
20
                    proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_t, tvb, offset, 1, ENC_BIG_ENDIAN);
3037
20
                    proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3038
20
                    offset++;
3039
20
                    tlv_offset = 1;
3040
3041
                    /* Enterprise number */
3042
20
                    if ((flags & THREAD_NWD_TLV_SERVICE_T) == 0) {
3043
19
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_ent_num, tvb, offset, 4, ENC_BIG_ENDIAN);
3044
19
                        offset += 4;
3045
19
                        tlv_offset += 4;
3046
19
                    }
3047
3048
                    /* S_data */
3049
20
                    s_data_len = tvb_get_uint8(tvb, offset);
3050
20
                    proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_len, tvb, offset, 1, ENC_BIG_ENDIAN);
3051
20
                    offset++;
3052
20
                    tlv_offset++;
3053
20
                    uint8_t thread_service_data = tvb_get_uint8(tvb, offset);
3054
                    // Thread 1.3 Service TLV code
3055
20
                    if((s_data_len == 2) && (thread_service_data == 0x5c))
3056
0
                    {
3057
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
3058
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_srp_dataset_identifier, tvb, offset, 1, ENC_NA);
3059
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_anycast_seqno, tvb, offset + 1, 1, ENC_NA);
3060
0
                        offset += 2;
3061
0
                        tlv_offset += 2;
3062
0
                        server_decode = 2;
3063
20
                    } else if(((s_data_len == 1) && (thread_service_data == 0x5d)) || ((s_data_len == 19) && (thread_service_data == 0x5d)))
3064
0
                    {
3065
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
3066
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_srp_dataset_identifier, tvb, offset, 1, ENC_NA);
3067
0
                        offset += 1;
3068
0
                        tlv_offset += 1;
3069
0
                        if(s_data_len == 1)
3070
0
                        {
3071
0
                            server_decode = 3;
3072
0
                        }
3073
0
                        else if(s_data_len == 19)
3074
0
                        {
3075
0
                            server_decode = 2;
3076
0
                            proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_unicast_ipv6_address, tvb, offset, 16, ENC_NA);
3077
0
                            proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_unicast_port_number, tvb, offset  + 16, 2, ENC_BIG_ENDIAN);
3078
0
                            offset += 18;
3079
0
                            tlv_offset += 18;
3080
0
                        }
3081
0
                    }
3082
20
                    else
3083
20
                    {
3084
20
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
3085
20
                        offset += s_data_len;
3086
20
                        tlv_offset += s_data_len;
3087
                        //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
3088
20
                       if(((flags & THREAD_NWD_TLV_SERVICE_T) == THREAD_NWD_TLV_SERVICE_T) &&
3089
0
                                      (thread_service_data == THREAD_SERVICE_DATA_BBR)) {
3090
0
                            server_decode = 1;
3091
0
                        }
3092
20
                        else {
3093
20
                            server_decode = 0;
3094
20
                        }
3095
20
                    }
3096
3097
                    // proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data, tvb, offset, s_data_len, ENC_NA);
3098
                    // offset += s_data_len;
3099
                    // tlv_offset += s_data_len;
3100
                    // //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
3101
                    // if(((flags & THREAD_NWD_TLV_SERVICE_T) == THREAD_NWD_TLV_SERVICE_T) &&
3102
                    //                   (thread_service_data == THREAD_SERVICE_DATA_BBR)) {
3103
                    //     server_decode = 1;
3104
                    // }
3105
                    // else {
3106
                    //     server_decode = 0;
3107
                    // }
3108
                    // Thread 1.3 Service TLV code
3109
3110
                    /* sub-TLVs */
3111
3112
20
                    if (tlv_offset < tlv_len) {
3113
2
                        proto_tree *sub_tlv_tree;
3114
2
                        unsigned remaining = tlv_len - tlv_offset;
3115
3116
2
                        ti = proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_sub_tlvs, tvb, offset, 1, ENC_NA);
3117
2
                        sub_tlv_tree = proto_item_add_subtree(ti, ett_thread_nwd_prefix_sub_tlvs);
3118
                        /* Call this dissector for sub-TLVs. Should only be server TLVs */
3119
2
                        sub_tvb = tvb_new_subset_length(tvb, offset, remaining); /* remove prefix length (1) and prefix (prefix_byte_len) */
3120
2
                        dissect_thread_nwd_with_server_decode(sub_tvb, pinfo, sub_tlv_tree, server_decode);
3121
2
                        offset += remaining;
3122
2
                    }
3123
20
                }
3124
20
                break;
3125
3126
3
            case THREAD_NWD_TLV_SERVER:
3127
3
                {
3128
3
                    if(server_decode == 1) {
3129
                        //2 bytes of server 16
3130
2
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
3131
2
                        offset += 2;
3132
                        /* tlv_offset = 2; */
3133
                        //7 bytes of server data
3134
2
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_seqno, tvb, offset, 1, ENC_NA);
3135
2
                        offset += 1;
3136
                        /* tlv_offset += 1; */
3137
2
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_rrdelay, tvb, offset, 2, ENC_BIG_ENDIAN);
3138
2
                        offset += 2;
3139
                        /* tlv_offset += 2; */
3140
2
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_s_data_mlrtimeout, tvb, offset, 4, ENC_BIG_ENDIAN);
3141
2
                        offset += 4;
3142
2
                    }
3143
1
                    else if(server_decode == 0) {
3144
                        //2 bytes of server 16
3145
1
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
3146
1
                        offset += 2;
3147
1
                        tlv_offset = 2;
3148
3149
1
                        if (tlv_offset < tlv_len)
3150
1
                        {
3151
1
                            unsigned remaining = tlv_len - tlv_offset;
3152
                            //remaining bytes - server data
3153
1
                            proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_data, tvb, offset, remaining, ENC_NA);
3154
1
                            offset += remaining;
3155
1
                        }
3156
3157
1
                    }
3158
                    // Thread 1.3 Service TLV code
3159
0
                    else if(server_decode == 2) {
3160
                        //2 bytes of server 16
3161
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
3162
0
                        offset += 2;
3163
0
                        tlv_offset = 2;
3164
0
                        if (tlv_offset < tlv_len)
3165
0
                        {
3166
0
                            unsigned remaining = tlv_len - tlv_offset;
3167
                            //remaining bytes - server data
3168
0
                            proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_data, tvb, offset, remaining, ENC_NA);
3169
0
                            offset += remaining;
3170
0
                        }
3171
0
                    }
3172
0
                    else if(server_decode == 3) {
3173
                        //2 bytes of server 16
3174
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_16, tvb, offset, 2, ENC_BIG_ENDIAN);
3175
0
                        offset += 2;
3176
0
                        tlv_offset = 2;
3177
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_unicast_ipv6_address, tvb, offset, 16, ENC_NA);
3178
0
                        proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_service_unicast_port_number, tvb, offset  + 16, 2, ENC_BIG_ENDIAN);
3179
0
                        offset += 18;
3180
0
                        tlv_offset += 18;
3181
3182
0
                        if (tlv_offset < tlv_len)
3183
0
                        {
3184
0
                            unsigned remaining = tlv_len - tlv_offset;
3185
                            //remaining bytes - server data
3186
0
                            proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_server_data, tvb, offset, remaining, ENC_NA);
3187
0
                            offset += remaining;
3188
0
                        }
3189
0
                    }
3190
                    // Thread 1.3 Service TLV code
3191
3
                }
3192
3
                break;
3193
3194
66
            default:
3195
66
                proto_tree_add_item(tlv_tree, hf_thread_nwd_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
3196
66
                offset += tlv_len;
3197
399
        }
3198
399
    }
3199
18
    decrement_dissection_depth(pinfo);
3200
18
    return tvb_captured_length(tvb);
3201
46
}
3202
3203
static int
3204
// NOLINTNEXTLINE(misc-no-recursion)
3205
dissect_thread_nwd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3206
34
{
3207
34
    return dissect_thread_nwd_with_server_decode(tvb, pinfo, tree, 1);
3208
34
}
3209
3210
static int
3211
dissect_thread_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3212
0
{
3213
0
    coap_info           *coinfo;
3214
0
    const char          *uri;
3215
0
    char                **tokens;
3216
3217
    /* Obtain the CoAP info */
3218
0
    coinfo = (coap_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_coap, 0);
3219
3220
    /* Reject the packet if not CoAP */
3221
0
    if (!coinfo) return 0;
3222
3223
0
    uri = wmem_strbuf_get_str(coinfo->uri_path_strbuf);
3224
3225
0
    tokens = wmem_strsplit(pinfo->pool, uri, "/", 3);
3226
0
    if (g_strv_length(tokens) == 3) {
3227
        /* No need to create a subset as we are dissecting the tvb as it is. */
3228
0
        dissector_try_string_with_data(thread_coap_namespace, tokens[1], tvb, pinfo, tree, true, NULL);
3229
0
    }
3230
3231
0
    return tvb_captured_length(tvb);
3232
0
}
3233
3234
static int dissect_thread_bcn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3235
10
{
3236
10
    ieee802154_packet   *packet = (ieee802154_packet *)data;
3237
10
    proto_item  *ti, *beacon_root;
3238
10
    proto_tree  *beacon_tree;
3239
10
    unsigned    offset = 0;
3240
10
    const uint8_t *ssid;
3241
10
    uint8_t     tlv_type, tlv_len;
3242
10
    proto_tree  *tlv_tree = NULL;
3243
3244
    /* Reject the packet if data is NULL */
3245
10
    if (!packet) return 0;
3246
3247
    /* Add ourself to the protocol column. */
3248
10
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Thread");
3249
    /* Create the tree for this beacon. */
3250
10
    beacon_root = proto_tree_add_item(tree, proto_thread_bcn, tvb, 0, -1, ENC_NA);
3251
10
    beacon_tree = proto_item_add_subtree(beacon_root, ett_thread_bcn);
3252
3253
    /* Update the info column. */
3254
10
    col_clear(pinfo->cinfo, COL_INFO);
3255
10
    col_append_fstr(pinfo->cinfo, COL_INFO, "Beacon, Src: 0x%04x", packet->src16);
3256
3257
    /* Get and display the protocol id, must be 0x03 on all Thread beacons. */
3258
10
    proto_tree_add_item(beacon_tree, hf_thread_bcn_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
3259
10
    offset += 1;
3260
3261
    /* Get and display the beacon flags */
3262
10
    proto_tree_add_item(beacon_tree, hf_thread_bcn_joining, tvb, offset, 1, ENC_BIG_ENDIAN);
3263
10
    proto_tree_add_item(beacon_tree, hf_thread_bcn_native, tvb, offset, 1, ENC_BIG_ENDIAN);
3264
10
    proto_tree_add_item(beacon_tree, hf_thread_bcn_version, tvb, offset, 1, ENC_BIG_ENDIAN);
3265
10
    offset += 1;
3266
3267
    /* Get and display the network ID. */
3268
10
    proto_tree_add_item_ret_string(beacon_tree, hf_thread_bcn_network_id, tvb, offset, 16, ENC_ASCII|ENC_NA, pinfo->pool, &ssid);
3269
10
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Network ID: %s", ssid);
3270
10
    offset += 16;
3271
3272
    /* See if we're at the end */
3273
10
    if (offset >= tvb_captured_length(tvb)) {
3274
0
        return tvb_captured_length(tvb);
3275
0
    }
3276
3277
    /* XPANID */
3278
10
    proto_tree_add_item(beacon_tree, hf_thread_bcn_epid, tvb, offset, 8, ENC_BIG_ENDIAN);
3279
10
    offset += 8;
3280
3281
    /* See if we're at the end */
3282
10
    if (offset >= tvb_captured_length(tvb)) {
3283
1
        return tvb_captured_length(tvb);
3284
1
    }
3285
3286
    /* Steering data TLV present */
3287
3288
    /* Get the length ahead of time to pass to next function so we can highlight
3289
       proper amount of bytes */
3290
9
    tlv_len = tvb_get_uint8(tvb, offset+1);
3291
3292
    /* Type */
3293
9
    ti = proto_tree_add_item(beacon_tree, hf_thread_bcn_tlv, tvb, offset, tlv_len+2, ENC_NA);
3294
9
    tlv_tree = proto_item_add_subtree(ti, ett_thread_bcn_tlv);
3295
9
    proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3296
3297
9
    tlv_type = tvb_get_uint8(tvb, offset);
3298
9
    offset++;
3299
3300
    /* Add value name to value root label */
3301
9
    proto_item_append_text(ti, " (%s)", val_to_str(pinfo->pool, tlv_type, thread_bcn_tlv_vals, "Unknown (%d)"));
3302
3303
    /* Length */
3304
9
    proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_length, tvb, offset, 1, ENC_BIG_ENDIAN);
3305
9
    offset++;
3306
3307
9
    if (tlv_len) { /* Belt 'n' braces check */
3308
5
        switch (tlv_type) {
3309
1
            case THREAD_BCN_TLV_STEERING_DATA:
3310
1
                proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_steering_data, tvb, offset, tlv_len, ENC_NA);
3311
                /* offset += tlv_len; */
3312
1
                break;
3313
4
            default:
3314
4
                proto_tree_add_item(tlv_tree, hf_thread_bcn_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
3315
                /* offset += tlv_len; */
3316
4
                break;
3317
5
        }
3318
5
    }
3319
4
    return tvb_captured_length(tvb);
3320
9
}
3321
3322
static bool
3323
dissect_thread_bcn_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3324
159
{
3325
159
    ieee802154_packet   *packet = (ieee802154_packet *)data;
3326
3327
    /* Thread beacon frames can be 16 or 64-bit source */
3328
159
    if (!packet) return false;
3329
159
    if (!((packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
3330
138
          (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT))) return false;
3331
3332
73
    if (tvb_captured_length(tvb) > 0) {
3333
        /* Thread beacons begin with a protocol identifier. */
3334
73
        if (tvb_get_uint8(tvb, 0) != THREAD_BCN_PROTOCOL_ID) return false;
3335
10
        dissect_thread_bcn(tvb, pinfo, tree, packet);
3336
10
        return true;
3337
73
    }
3338
0
    return false;
3339
73
}
3340
3341
void
3342
proto_register_thread_nm(void)
3343
14
{
3344
14
        static hf_register_info hf[] = {
3345
3346
            /* Generic TLV */
3347
14
            { &hf_thread_nm_tlv,
3348
14
                {   "TLV",
3349
14
                    "thread_nm.tlv",
3350
14
                    FT_NONE, BASE_NONE, NULL, 0x0,
3351
14
                    "Type-Length-Value",
3352
14
                    HFILL
3353
14
                }
3354
14
            },
3355
14
            { &hf_thread_nm_tlv_type,
3356
14
                {   "Type",
3357
14
                    "thread_nm.tlv.type",
3358
14
                    FT_UINT8, BASE_DEC, VALS(thread_nm_tlv_vals), 0x0,
3359
14
                    "Type of value",
3360
14
                    HFILL
3361
14
                }
3362
14
            },
3363
14
            { &hf_thread_nm_tlv_length,
3364
14
                {   "Length",
3365
14
                    "thread_nm.tlv.len",
3366
14
                    FT_UINT8, BASE_DEC, NULL, 0x0,
3367
14
                    "Length of value",
3368
14
                    HFILL
3369
14
                }
3370
14
            },
3371
14
            { &hf_thread_nm_tlv_unknown,
3372
14
                {   "Unknown",
3373
14
                    "thread_nm.tlv.unknown",
3374
14
                    FT_BYTES, BASE_NONE, NULL, 0x0,
3375
14
                    "Unknown TLV, raw value",
3376
14
                HFILL }
3377
14
            },
3378
    #if 0
3379
            { &hf_thread_nm_tlv_sub_tlvs,
3380
                {   "Sub-TLV(s)",
3381
                    "thread_nm.tlv.sub_tlvs",
3382
                    FT_NONE, BASE_NONE, NULL, 0x0,
3383
                    NULL,
3384
                    HFILL
3385
                }
3386
            },
3387
    #endif
3388
                /* Type-Specific TLV Fields */
3389
14
            { &hf_thread_nm_tlv_target_eid,
3390
14
                {   "Target EID",
3391
14
                    "thread_nm.tlv.target_eid",
3392
14
                    FT_IPv6, BASE_NONE, NULL, 0x0,
3393
14
                    NULL,
3394
14
                    HFILL
3395
14
                }
3396
14
            },
3397
14
            { &hf_thread_nm_tlv_ext_mac_addr,
3398
14
                {   "Extended MAC Address",
3399
14
                    "thread_nm.tlv.ext_mac_addr",
3400
14
                    FT_EUI64, BASE_NONE, NULL, 0x0,
3401
14
                    NULL,
3402
14
                    HFILL
3403
14
                }
3404
14
            },
3405
14
            { &hf_thread_nm_tlv_rloc16,
3406
14
                {   "RLOC16",
3407
14
                    "thread_nm.tlv.rloc16",
3408
14
                    FT_UINT16, BASE_HEX, NULL, 0x0,
3409
14
                    NULL,
3410
14
                    HFILL
3411
14
                }
3412
14
            },
3413
14
            { &hf_thread_nm_tlv_ml_eid,
3414
14
                {   "ML-EID",
3415
14
                    "thread_nm.tlv.ml_eid",
3416
14
                    FT_BYTES, BASE_NONE, NULL, 0x0,
3417
14
                    NULL,
3418
14
                    HFILL
3419
14
                }
3420
14
            },
3421
14
            { &hf_thread_nm_tlv_status,
3422
14
                {   "Status",
3423
14
                    "thread_nm.tlv.status",
3424
14
                    FT_UINT8, BASE_DEC, VALS(thread_nm_tlv_status_vals), 0x0,
3425
14
                    NULL,
3426
14
                    HFILL
3427
14
                }
3428
14
            },
3429
14
            { &hf_thread_nm_tlv_last_transaction_time,
3430
14
                {   "Last Transaction Time",
3431
14
                    "thread_nm.tlv.last_transaction_time",
3432
14
                    FT_UINT32, BASE_DEC, NULL, 0x0,
3433
14
                    NULL,
3434
14
                    HFILL
3435
14
                }
3436
14
            },
3437
14
            { &hf_thread_nm_tlv_router_mask_id_seq,
3438
14
                {   "ID Sequence",
3439
14
                    "thread_nm.tlv.router_mask_id_seq",
3440
14
                    FT_UINT8, BASE_DEC, NULL, 0x0,
3441
14
                    NULL,
3442
14
                    HFILL
3443
14
                }
3444
14
            },
3445
14
            { &hf_thread_nm_tlv_router_mask_assigned,
3446
14
                {   "Assigned Router ID Mask",
3447
14
                    "thread_nm.tlv.router_mask_assigned",
3448
14
                    FT_BYTES, BASE_NONE, NULL, 0x0,
3449
14
                    NULL,
3450
14
                    HFILL
3451
14
                 }
3452
14
            },
3453
14
            { &hf_thread_nm_tlv_nd_option,
3454
14
                {   "ND Option",
3455
14
                    "thread_nm.tlv.nd_option",
3456
14
                    FT_BYTES, BASE_NONE, NULL, 0x0,
3457
14
                    NULL,
3458
14
                    HFILL
3459
14
                }
3460
14
            },
3461
14
            { &hf_thread_nm_tlv_nd_data,
3462
14
                {   "ND Data",
3463
14
                    "thread_nm.tlv.nd_data",
3464
14
                    FT_BYTES, BASE_NONE, NULL, 0x0,
3465
14
                    NULL,
3466
14
                    HFILL
3467
14
                }
3468
14
            },
3469
14
            { &hf_thread_nm_tlv_timeout,
3470
14
                {   "Timeout",
3471
14
                    "thread_nm.tlv.timeout",
3472
14
                    FT_UINT32, BASE_DEC, NULL, 0x0,
3473
14
                    NULL,
3474
14
                    HFILL
3475
14
                }
3476
14
            }
3477
14
        };
3478
3479
14
        static int *ett[] = {
3480
14
            &ett_thread_nm,
3481
14
            &ett_thread_nm_tlv,
3482
            /* These need to be registered somewhere.. */
3483
14
            &ett_thread,
3484
14
            &ett_thread_ie_fields
3485
14
        };
3486
3487
14
        static ei_register_info ei[] = {
3488
#if 0
3489
            { &ei_thread_nm_tlv_length_failed,{ "thread_nm.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL } },
3490
#endif
3491
14
        { &ei_thread_nm_len_size_mismatch,{ "thread_nm.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL } },
3492
14
        };
3493
3494
14
        expert_module_t* expert_thread_nm;
3495
3496
14
        proto_thread_nm = proto_register_protocol("Thread Network Management", "Thread Network Management", "thread_nm");
3497
14
        proto_register_field_array(proto_thread_nm, hf, array_length(hf));
3498
14
        proto_register_subtree_array(ett, array_length(ett));
3499
14
        expert_thread_nm = expert_register_protocol(proto_thread_nm);
3500
14
        expert_register_field_array(expert_thread_nm, ei, array_length(ei));
3501
3502
14
        thread_nm_handle = register_dissector("thread_nm", dissect_thread_nm, proto_thread_nm);
3503
14
}
3504
3505
void
3506
proto_register_thread_bl(void)
3507
14
{
3508
14
        static hf_register_info hf[] = {
3509
3510
            /* Generic TLV */
3511
14
            { &hf_thread_bl_tlv,
3512
14
                {   "TLV",
3513
14
                    "thread_bl.tlv",
3514
14
                    FT_NONE, BASE_NONE, NULL, 0x0,
3515
14
                    "Type-Length-Value",
3516
14
                    HFILL
3517
14
                }
3518
14
            },
3519
3520
14
            { &hf_thread_bl_tlv_type,
3521
14
                {   "Type",
3522
14
                    "thread_bl.tlv.type",
3523
14
                    FT_UINT8, BASE_DEC, VALS(thread_bl_tlv_vals), 0x0,
3524
14
                    "Type of value",
3525
14
                    HFILL
3526
14
                }
3527
14
            },
3528
3529
14
            { &hf_thread_bl_tlv_length,
3530
14
                {   "Length",
3531
14
                    "thread_bl.tlv.len",
3532
14
                    FT_UINT8, BASE_DEC, NULL, 0x0,
3533
14
                    "Length of value",
3534
14
                    HFILL
3535
14
                }
3536
14
            },
3537
3538
14
            { &hf_thread_bl_tlv_unknown,
3539
14
                {   "Unknown",
3540
14
                    "thread_bl.tlv.unknown",
3541
14
                    FT_BYTES, BASE_NONE, NULL, 0x0,
3542
14
                    "Unknown TLV, raw value",
3543
14
                    HFILL
3544
14
                }
3545
14
            },
3546
    #if 0
3547
            { &hf_thread_bl_tlv_sub_tlvs,
3548
                {  "Sub-TLV(s)",
3549
                    "thread_bl.tlv.sub_tlvs",
3550
                    FT_NONE, BASE_NONE, NULL, 0x0,
3551
                    NULL,
3552
                    HFILL
3553
                }
3554
            },
3555
    #endif
3556
                /* Type-Specific TLV Fields */
3557
14
            { &hf_thread_bl_tlv_target_eid,
3558
14
                {   "Target EID",
3559
14
                    "thread_bl.tlv.target_eid",
3560
14
                    FT_IPv6, BASE_NONE, NULL, 0x0,
3561
14
                    NULL,
3562
14
                    HFILL
3563
14
                }
3564
14
            },
3565
3566
14
            { &hf_thread_bl_tlv_ext_mac_addr,
3567
14
            { "Extended MAC Address",
3568
14
                "thread_bl.tlv.ext_mac_addr",
3569
14
                FT_EUI64, BASE_NONE, NULL, 0x0,
3570
14
                NULL,
3571
14
                HFILL }
3572
14
            },
3573
3574
14
            { &hf_thread_bl_tlv_rloc16,
3575
14
            { "RLOC16",
3576
14
                "thread_bl.tlv.rloc16",
3577
14
                FT_UINT16, BASE_HEX, NULL, 0x0,
3578
14
                NULL,
3579
14
                HFILL }
3580
14
            },
3581
3582
14
            { &hf_thread_bl_tlv_ml_eid,
3583
14
            { "ML-EID",
3584
14
                "thread_bl.tlv.ml_eid",
3585
14
                FT_BYTES, BASE_NONE, NULL, 0x0,
3586
14
                NULL,
3587
14
                HFILL }
3588
14
            },
3589
3590
14
            { &hf_thread_bl_tlv_status,
3591
14
            { "Status",
3592
14
                "thread_bl.tlv.status",
3593
14
                FT_UINT8, BASE_DEC, VALS(thread_bl_tlv_status_vals), 0x0,
3594
14
                NULL,
3595
14
                HFILL }
3596
14
            },
3597
    #if 0
3598
            { &hf_thread_bl_tlv_attached_time,
3599
            { "Attached Time",
3600
                "thread_bl.tlv.attached_time",
3601
                FT_UINT32, BASE_DEC, NULL, 0x0,
3602
                NULL,
3603
                HFILL }
3604
            },
3605
    #endif
3606
14
            { &hf_thread_bl_tlv_last_transaction_time,
3607
14
            { "Last Transaction Time",
3608
14
                "thread_bl.tlv.last_transaction_time",
3609
14
                FT_UINT32, BASE_DEC, NULL, 0x0,
3610
14
                NULL,
3611
14
                HFILL }
3612
14
            },
3613
3614
14
            { &hf_thread_bl_tlv_router_mask_id_seq,
3615
14
            { "ID Sequence",
3616
14
                "thread_bl.tlv.router_mask_id_seq",
3617
14
                FT_UINT8, BASE_DEC, NULL, 0x0,
3618
14
                NULL,
3619
14
                HFILL }
3620
14
            },
3621
3622
14
            { &hf_thread_bl_tlv_router_mask_assigned,
3623
14
            { "Assigned Router ID Mask",
3624
14
                "thread_bl.tlv.router_mask_assigned",
3625
14
                FT_BYTES, BASE_NONE, NULL, 0x0,
3626
14
                NULL,
3627
14
                HFILL }
3628
14
            },
3629
3630
14
            { &hf_thread_bl_tlv_nd_option,
3631
14
            { "ND Option",
3632
14
                "thread_bl.tlv.nd_option",
3633
14
                FT_BYTES, BASE_NONE, NULL, 0x0,
3634
14
                NULL,
3635
14
                HFILL }
3636
14
            },
3637
3638
14
            { &hf_thread_bl_tlv_nd_data,
3639
14
            { "ND Data",
3640
14
                "thread_bl.tlv.nd_data",
3641
14
                FT_BYTES, BASE_NONE, NULL, 0x0,
3642
14
                NULL,
3643
14
                HFILL }
3644
14
            },
3645
14
            { &hf_thread_bl_tlv_timeout,
3646
14
            { "Timeout",
3647
14
                "thread_bl.tlv.timeout",
3648
14
                FT_UINT32, BASE_DEC, NULL, 0x0,
3649
14
                NULL,
3650
14
                HFILL }
3651
14
            }
3652
3653
3654
3655
14
        };
3656
3657
14
        static int *ett[] = {
3658
14
            &ett_thread_bl,
3659
14
            &ett_thread_bl_tlv,
3660
14
        };
3661
3662
14
        static ei_register_info ei[] = {
3663
#if 0
3664
            { &ei_thread_bl_tlv_length_failed,{ "thread_bl.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL } },
3665
#endif
3666
14
        { &ei_thread_bl_len_size_mismatch,{ "thread_bl.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL } },
3667
14
        };
3668
3669
14
        expert_module_t* expert_thread_bl;
3670
3671
14
        proto_thread_bl = proto_register_protocol("Thread Backbone Link", "Thread Backbone Link", "thread_bl");
3672
14
        proto_register_field_array(proto_thread_bl, hf, array_length(hf));
3673
14
        proto_register_subtree_array(ett, array_length(ett));
3674
14
        expert_thread_bl = expert_register_protocol(proto_thread_bl);
3675
14
        expert_register_field_array(expert_thread_bl, ei, array_length(ei));
3676
3677
14
        thread_bl_handle = register_dissector("thread_bl", dissect_thread_bl, proto_thread_bl);
3678
14
}
3679
3680
void
3681
proto_register_thread_address(void)
3682
14
{
3683
14
    static hf_register_info hf[] = {
3684
3685
        /* Generic TLV */
3686
14
        { &hf_thread_address_tlv,
3687
14
            { "TLV",
3688
14
            "thread_address.tlv",
3689
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3690
14
            "Type-Length-Value",
3691
14
            HFILL }
3692
14
        },
3693
3694
14
        { &hf_thread_address_tlv_type,
3695
14
            { "Type",
3696
14
            "thread_address.tlv.type",
3697
14
            FT_UINT8, BASE_DEC, VALS(thread_address_tlv_vals), 0x0,
3698
14
            "Type of value",
3699
14
            HFILL }
3700
14
        },
3701
3702
14
        { &hf_thread_address_tlv_length,
3703
14
            { "Length",
3704
14
            "thread_address.tlv.len",
3705
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
3706
14
            "Length of value",
3707
14
            HFILL }
3708
14
        },
3709
3710
14
        { &hf_thread_address_tlv_unknown,
3711
14
            { "Unknown",
3712
14
            "thread_address.tlv.unknown",
3713
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3714
14
            "Unknown TLV, raw value",
3715
14
            HFILL }
3716
14
        },
3717
#if 0
3718
        { &hf_thread_address_tlv_sub_tlvs,
3719
            { "Sub-TLV(s)",
3720
            "thread_address.tlv.sub_tlvs",
3721
            FT_NONE, BASE_NONE, NULL, 0x0,
3722
            NULL,
3723
            HFILL }
3724
        },
3725
#endif
3726
        /* Type-Specific TLV Fields */
3727
14
        { &hf_thread_address_tlv_target_eid,
3728
14
            { "Target EID",
3729
14
            "thread_address.tlv.target_eid",
3730
14
            FT_IPv6, BASE_NONE, NULL, 0x0,
3731
14
            NULL,
3732
14
            HFILL }
3733
14
        },
3734
3735
14
        { &hf_thread_address_tlv_ext_mac_addr,
3736
14
            { "Extended MAC Address",
3737
14
            "thread_address.tlv.ext_mac_addr",
3738
14
            FT_EUI64, BASE_NONE, NULL, 0x0,
3739
14
            NULL,
3740
14
            HFILL }
3741
14
        },
3742
3743
14
        { &hf_thread_address_tlv_rloc16,
3744
14
            { "RLOC16",
3745
14
            "thread_address.tlv.rloc16",
3746
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
3747
14
            NULL,
3748
14
            HFILL }
3749
14
        },
3750
3751
14
        { &hf_thread_address_tlv_ml_eid,
3752
14
            { "ML-EID",
3753
14
            "thread_address.tlv.ml_eid",
3754
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3755
14
            NULL,
3756
14
            HFILL }
3757
14
        },
3758
3759
14
        { &hf_thread_address_tlv_status,
3760
14
            { "Status",
3761
14
            "thread_address.tlv.status",
3762
14
            FT_UINT8, BASE_DEC, VALS(thread_address_tlv_status_vals), 0x0,
3763
14
            NULL,
3764
14
            HFILL }
3765
14
        },
3766
#if 0
3767
        { &hf_thread_address_tlv_attached_time,
3768
            { "Attached Time",
3769
            "thread_address.tlv.attached_time",
3770
            FT_UINT32, BASE_DEC, NULL, 0x0,
3771
            NULL,
3772
            HFILL }
3773
        },
3774
#endif
3775
14
        { &hf_thread_address_tlv_last_transaction_time,
3776
14
            { "Last Transaction Time",
3777
14
            "thread_address.tlv.last_transaction_time",
3778
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3779
14
            NULL,
3780
14
            HFILL }
3781
14
        },
3782
3783
14
        { &hf_thread_address_tlv_router_mask_id_seq,
3784
14
            { "ID Sequence",
3785
14
            "thread_address.tlv.router_mask_id_seq",
3786
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
3787
14
            NULL,
3788
14
            HFILL }
3789
14
        },
3790
3791
14
        { &hf_thread_address_tlv_router_mask_assigned,
3792
14
            { "Assigned Router ID Mask",
3793
14
            "thread_address.tlv.router_mask_assigned",
3794
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3795
14
            NULL,
3796
14
            HFILL }
3797
14
        },
3798
3799
14
        { &hf_thread_address_tlv_nd_option,
3800
14
            { "ND Option",
3801
14
            "thread_address.tlv.nd_option",
3802
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3803
14
            NULL,
3804
14
            HFILL }
3805
14
        },
3806
3807
14
        { &hf_thread_address_tlv_nd_data,
3808
14
            { "ND Data",
3809
14
            "thread_address.tlv.nd_data",
3810
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3811
14
            NULL,
3812
14
            HFILL }
3813
14
        },
3814
3815
14
        { &hf_thread_address_tlv_timeout,
3816
14
            { "Timeout",
3817
14
            "thread_address.tlv.timeout",
3818
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
3819
14
            NULL,
3820
14
            HFILL }
3821
14
        }
3822
14
    };
3823
3824
14
    static int *ett[] = {
3825
14
        &ett_thread_address,
3826
14
        &ett_thread_address_tlv,
3827
14
    };
3828
3829
14
    static ei_register_info ei[] = {
3830
#if 0
3831
        { &ei_thread_address_tlv_length_failed, { "thread_address.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
3832
#endif
3833
14
        { &ei_thread_address_len_size_mismatch, { "thread_address.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
3834
14
    };
3835
3836
14
    expert_module_t* expert_thread_address;
3837
3838
14
    proto_thread_address = proto_register_protocol("Thread Address", "Thread Address", "thread_address");
3839
14
    proto_register_field_array(proto_thread_address, hf, array_length(hf));
3840
14
    proto_register_subtree_array(ett, array_length(ett));
3841
14
    expert_thread_address = expert_register_protocol(proto_thread_address);
3842
14
    expert_register_field_array(expert_thread_address, ei, array_length(ei));
3843
3844
14
    thread_address_handle = register_dissector("thread_address", dissect_thread_address, proto_thread_address);
3845
14
}
3846
3847
void
3848
proto_register_thread_dg(void)
3849
14
{
3850
14
    static hf_register_info hf[] = {
3851
3852
        /* Generic TLV */
3853
14
        { &hf_thread_dg_tlv,
3854
14
            { "TLV",
3855
14
            "thread_diagnostic.tlv",
3856
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3857
14
            "Type-Length-Value",
3858
14
            HFILL }
3859
14
        },
3860
3861
14
        { &hf_thread_dg_tlv_type,
3862
14
            { "Type",
3863
14
            "thread_diagnostic.tlv.type",
3864
14
            FT_UINT8, BASE_DEC, VALS(thread_dg_tlv_vals), 0x0,
3865
14
            "Type of value",
3866
14
            HFILL }
3867
14
        },
3868
3869
14
        { &hf_thread_dg_tlv_length8,
3870
14
            { "Length",
3871
14
            "thread_diagnostic.tlv.len8",
3872
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
3873
14
            "Length of value (8-bit)",
3874
14
            HFILL }
3875
14
        },
3876
3877
14
        { &hf_thread_dg_tlv_length16,
3878
14
            { "Length",
3879
14
            "thread_diagnostic.tlv.len16",
3880
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3881
14
            "Length of value (16-bit)",
3882
14
            HFILL }
3883
14
        },
3884
3885
14
        { &hf_thread_dg_tlv_general,
3886
14
            { "General",
3887
14
            "thread_diagnostic.tlv.general",
3888
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3889
14
            "General TLV, raw value",
3890
14
            HFILL }
3891
14
        },
3892
3893
14
        { &hf_thread_dg_tlv_unknown,
3894
14
            { "Unknown",
3895
14
            "thread_diagnostic.tlv.unknown",
3896
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3897
14
            "Unknown TLV, raw value",
3898
14
            HFILL }
3899
14
        }
3900
14
    };
3901
3902
14
    static int *ett[] = {
3903
14
        &ett_thread_dg,
3904
14
        &ett_thread_dg_tlv,
3905
14
    };
3906
3907
#if 0
3908
    static ei_register_info ei[] = {
3909
        { &ei_thread_dg_tlv_length_failed, { "thread_diagnostic.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
3910
        { &ei_thread_dg_len_size_mismatch, { "thread_diagnostic.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
3911
    };
3912
3913
    expert_module_t* expert_thread_dg;
3914
#endif
3915
3916
14
    proto_thread_dg = proto_register_protocol("Thread Diagnostics", "Thread Diagnostics", "thread_diagnostic");
3917
14
    proto_register_field_array(proto_thread_dg, hf, array_length(hf));
3918
14
    proto_register_subtree_array(ett, array_length(ett));
3919
#if 0
3920
    expert_thread_dg = expert_register_protocol(proto_thread_dg);
3921
    expert_register_field_array(expert_thread_dg, ei, array_length(ei));
3922
#endif
3923
3924
14
    thread_dg_handle = register_dissector("thread_diagnostic", dissect_thread_dg, proto_thread_dg);
3925
14
}
3926
3927
void
3928
proto_register_thread_mc(void)
3929
14
{
3930
14
    static hf_register_info hf[] = {
3931
3932
        /* Generic TLV */
3933
14
        { &hf_thread_mc_tlv,
3934
14
            { "TLV",
3935
14
            "thread_meshcop.tlv",
3936
14
            FT_NONE, BASE_NONE, NULL, 0x0,
3937
14
            "Type-Length-Value",
3938
14
            HFILL }
3939
14
        },
3940
3941
14
        { &hf_thread_mc_tlv_type,
3942
14
            { "Type",
3943
14
            "thread_meshcop.tlv.type",
3944
14
            FT_UINT8, BASE_DEC, VALS(thread_mc_tlv_vals), 0x0,
3945
14
            "Type of value",
3946
14
            HFILL }
3947
14
        },
3948
3949
14
        { &hf_thread_mc_tlv_length8,
3950
14
            { "Length",
3951
14
            "thread_meshcop.tlv.len8",
3952
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
3953
14
            "Length of value (8-bit)",
3954
14
            HFILL }
3955
14
        },
3956
3957
14
        { &hf_thread_mc_tlv_length16,
3958
14
            { "Length",
3959
14
            "thread_meshcop.tlv.len16",
3960
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3961
14
            "Length of value (16-bit)",
3962
14
            HFILL }
3963
14
        },
3964
3965
14
        { &hf_thread_mc_tlv_unknown,
3966
14
            { "Unknown",
3967
14
            "thread_meshcop.tlv.unknown",
3968
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
3969
14
            "Unknown TLV, raw value",
3970
14
            HFILL }
3971
14
        },
3972
#if 0
3973
        { &hf_thread_mc_tlv_sub_tlvs,
3974
            { "Sub-TLV(s)",
3975
            "thread_meshcop.tlv.sub_tlvs",
3976
            FT_NONE, BASE_NONE, NULL, 0x0,
3977
            NULL,
3978
            HFILL }
3979
        },
3980
#endif
3981
        /* Type-Specific TLV Fields */
3982
14
        { &hf_thread_mc_tlv_channel_page,
3983
14
            { "Channel Page",
3984
14
            "thread_meshcop.tlv.channel_page",
3985
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
3986
14
            NULL,
3987
14
            HFILL }
3988
14
        },
3989
3990
14
        { &hf_thread_mc_tlv_channel,
3991
14
            { "Channel",
3992
14
            "thread_meshcop.tlv.channel",
3993
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
3994
14
            NULL,
3995
14
            HFILL }
3996
14
        },
3997
3998
14
        { &hf_thread_mc_tlv_pan_id,
3999
14
            { "PAN ID",
4000
14
            "thread_meshcop.tlv.pan_id",
4001
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
4002
14
            NULL,
4003
14
            HFILL }
4004
14
        },
4005
4006
14
        { &hf_thread_mc_tlv_xpan_id,
4007
14
            { "Extended PAN ID",
4008
14
            "thread_meshcop.tlv.xpan_id",
4009
14
            FT_UINT64, BASE_HEX, NULL, 0x0,
4010
14
            NULL,
4011
14
            HFILL }
4012
14
        },
4013
4014
14
        { &hf_thread_mc_tlv_net_name,
4015
14
            { "Network Name",
4016
14
            "thread_meshcop.tlv.net_name",
4017
14
            FT_STRING, BASE_NONE, NULL, 0x0,
4018
14
            NULL,
4019
14
            HFILL }
4020
14
        },
4021
4022
14
        { &hf_thread_mc_tlv_pskc,
4023
14
            { "PSKc",
4024
14
            "thread_meshcop.tlv.pskc",
4025
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4026
14
            NULL,
4027
14
            HFILL }
4028
14
        },
4029
4030
14
        { &hf_thread_mc_tlv_master_key,
4031
14
            { "Master Key",
4032
14
            "thread_meshcop.tlv.master_key",
4033
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4034
14
            NULL,
4035
14
            HFILL }
4036
14
        },
4037
4038
14
        { &hf_thread_mc_tlv_net_key_seq_ctr,
4039
14
            { "Network Key Sequence Counter",
4040
14
            "thread_meshcop.tlv.net_key_seq_ctr",
4041
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4042
14
            NULL,
4043
14
            HFILL }
4044
14
        },
4045
4046
14
        { &hf_thread_mc_tlv_ml_prefix,
4047
14
            { "Mesh Local Prefix",
4048
14
            "thread_meshcop.tlv.ml_prefix",
4049
14
            FT_IPv6, BASE_NONE, NULL, 0x0,
4050
14
            NULL,
4051
14
            HFILL }
4052
14
        },
4053
4054
14
        { &hf_thread_mc_tlv_steering_data,
4055
14
            { "Steering Data",
4056
14
            "thread_meshcop.tlv.steering_data",
4057
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4058
14
            NULL,
4059
14
            HFILL }
4060
14
        },
4061
4062
14
        { &hf_thread_mc_tlv_ba_locator,
4063
14
            { "Border Agent Locator",
4064
14
            "thread_meshcop.tlv.ba_locator",
4065
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4066
14
            NULL,
4067
14
            HFILL }
4068
14
        },
4069
4070
14
        { &hf_thread_mc_tlv_commissioner_id,
4071
14
            { "Commissioner ID",
4072
14
            "thread_meshcop.tlv.commissioner_id",
4073
14
            FT_STRING, BASE_NONE, NULL, 0x0,
4074
14
            NULL,
4075
14
            HFILL }
4076
14
        },
4077
4078
14
        { &hf_thread_mc_tlv_commissioner_sess_id,
4079
14
            { "Commissioner Session ID",
4080
14
            "thread_meshcop.tlv.commissioner_sess_id",
4081
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4082
14
            NULL,
4083
14
            HFILL }
4084
14
        },
4085
4086
14
        { &hf_thread_mc_tlv_sec_policy_rot,
4087
14
            { "Rotation Time",
4088
14
            "thread_meshcop.tlv.sec_policy_rot",
4089
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
4090
14
            NULL,
4091
14
            HFILL }
4092
14
        },
4093
4094
14
        { &hf_thread_mc_tlv_sec_policy_o,
4095
14
            { "Out-of-band Commissioning",
4096
14
            "thread_meshcop.tlv.sec_policy_o",
4097
14
            FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_O_MASK,
4098
14
            NULL,
4099
14
            HFILL }
4100
14
        },
4101
4102
14
        { &hf_thread_mc_tlv_sec_policy_n,
4103
14
            { "Native Commissioning",
4104
14
            "thread_meshcop.tlv.sec_policy_n",
4105
14
            FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_N_MASK,
4106
14
            NULL,
4107
14
            HFILL }
4108
14
        },
4109
4110
14
        { &hf_thread_mc_tlv_sec_policy_r,
4111
14
            { "Thread 1.x Routers",
4112
14
            "thread_meshcop.tlv.sec_policy_r",
4113
14
            FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_R_MASK,
4114
14
            NULL,
4115
14
            HFILL }
4116
14
        },
4117
4118
14
        { &hf_thread_mc_tlv_sec_policy_c,
4119
14
            { "PSKc-based Commissioning",
4120
14
            "thread_meshcop.tlv.sec_policy_c",
4121
14
            FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_C_MASK,
4122
14
            NULL,
4123
14
            HFILL }
4124
14
        },
4125
4126
14
        { &hf_thread_mc_tlv_sec_policy_b,
4127
14
            { "Thread 1.x Beacons",
4128
14
            "thread_meshcop.tlv.sec_policy_b",
4129
14
            FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_SEC_POLICY_MASK_B_MASK,
4130
14
            NULL,
4131
14
            HFILL }
4132
14
        },
4133
4134
14
         { &hf_thread_mc_tlv_sec_policy_ccm,
4135
14
            { "Commercial Commissioning Mode Bit disabled",
4136
14
            "thread_meshcop.tlv.sec_policy_ccm",
4137
14
            FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_CCM_MASK,
4138
14
            NULL,
4139
14
            HFILL }
4140
14
        },
4141
4142
14
        { &hf_thread_mc_tlv_sec_policy_ae,
4143
14
            { "Autonomous Enrollment disabled",
4144
14
            "thread_meshcop.tlv.sec_policy_ae",
4145
14
            FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_AE_MASK,
4146
14
            NULL,
4147
14
            HFILL }
4148
14
        },
4149
4150
14
        { &hf_thread_mc_tlv_sec_policy_nmp,
4151
14
            { "Network Master-key Provisioning disabled",
4152
14
            "thread_meshcop.tlv.sec_policy_nmp",
4153
14
            FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_NMP_MASK,
4154
14
            NULL,
4155
14
            HFILL }
4156
14
        },
4157
4158
14
        { &hf_thread_mc_tlv_sec_policy_l,
4159
14
            { "ToBLE Link Enabled",
4160
14
            "thread_meshcop.tlv.sec_policy_l",
4161
14
            FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_L_MASK,
4162
14
            NULL,
4163
14
            HFILL }
4164
14
        },
4165
4166
14
        { &hf_thread_mc_tlv_sec_policy_ncr,
4167
14
            { "Non-CCM Routers disabled",
4168
14
            "thread_meshcop.tlv.sec_policy_ncr",
4169
14
            FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), THREAD_MC_SEC_POLICY_MASK_NCR_MASK,
4170
14
            NULL,
4171
14
            HFILL }
4172
14
        },
4173
4174
14
        { &hf_thread_mc_tlv_sec_policy_rsv,
4175
14
            { "Reserved Bits",
4176
14
            "thread_meshcop.tlv.sec_policy_rsv",
4177
14
            FT_UINT8, BASE_DEC, NULL, THREAD_MC_SEC_POLICY_MASK_RSV_MASK,
4178
14
            NULL,
4179
14
            HFILL }
4180
14
        },
4181
4182
14
        { &hf_thread_mc_tlv_sec_policy_rsv1,
4183
14
            { "Reserved Bits",
4184
14
            "thread_meshcop.tlv.sec_policy_rsv",
4185
14
            FT_UINT8, BASE_DEC, NULL, THREAD_MC_SEC_POLICY_MASK_RSV1_MASK,
4186
14
            NULL,
4187
14
            HFILL }
4188
14
        },
4189
4190
14
        { &hf_thread_mc_tlv_sec_policy_vr,
4191
14
            { "Version-threshold for Routing",
4192
14
            "thread_meshcop.tlv.sec_policy_vr",
4193
14
            FT_UINT8, BASE_DEC, NULL, THREAD_MC_SEC_POLICY_MASK_VR_MASK,
4194
14
            NULL,
4195
14
            HFILL }
4196
14
        },
4197
4198
14
        { &hf_thread_mc_tlv_state,
4199
14
            { "State",
4200
14
            "thread_meshcop.tlv.state",
4201
14
            FT_INT8, BASE_DEC, VALS(thread_mc_state_vals), 0x0,
4202
14
            NULL,
4203
14
            HFILL }
4204
14
        },
4205
4206
14
        { &hf_thread_mc_tlv_active_tstamp,
4207
14
            { "Active Timestamp",
4208
14
            "thread_meshcop.tlv.active_tstamp",
4209
14
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
4210
14
            NULL,
4211
14
            HFILL }
4212
14
        },
4213
4214
14
        { &hf_thread_mc_tlv_pending_tstamp,
4215
14
            { "Pending Timestamp",
4216
14
            "thread_meshcop.tlv.pending_tstamp",
4217
14
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
4218
14
            NULL,
4219
14
            HFILL }
4220
14
        },
4221
4222
14
        { &hf_thread_mc_tlv_udp_port,
4223
14
            { "UDP Port",
4224
14
            "thread_meshcop.tlv.udp_port",
4225
14
            FT_UINT16, BASE_PT_UDP, NULL, 0x0,
4226
14
            NULL,
4227
14
            HFILL }
4228
14
        },
4229
4230
14
        { &hf_thread_mc_tlv_iid,
4231
14
            { "Interface Identifier",
4232
14
            "thread_meshcop.tlv.iid",
4233
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4234
14
            NULL,
4235
14
            HFILL }
4236
14
        },
4237
4238
14
        { &hf_thread_mc_tlv_jr_locator,
4239
14
            { "Joiner Router Locator",
4240
14
            "thread_meshcop.tlv.jr_locator",
4241
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4242
14
            NULL,
4243
14
            HFILL }
4244
14
        },
4245
4246
14
        { &hf_thread_mc_tlv_kek,
4247
14
            { "Key Encryption Key (KEK)",
4248
14
            "thread_meshcop.tlv.kek",
4249
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4250
14
            NULL,
4251
14
            HFILL }
4252
14
        },
4253
4254
14
        { &hf_thread_mc_tlv_provisioning_url,
4255
14
            { "Provisioning URL",
4256
14
            "thread_meshcop.tlv.provisioning_url",
4257
14
            FT_STRING, BASE_NONE, NULL, 0x0,
4258
14
            NULL,
4259
14
            HFILL }
4260
14
        },
4261
4262
14
        { &hf_thread_mc_tlv_vendor_name,
4263
14
            { "Vendor Name",
4264
14
            "thread_meshcop.tlv.vendor_name",
4265
14
            FT_STRING, BASE_NONE, NULL, 0x0,
4266
14
            NULL,
4267
14
            HFILL }
4268
14
        },
4269
4270
14
        { &hf_thread_mc_tlv_vendor_model,
4271
14
            { "Vendor Model",
4272
14
            "thread_meshcop.tlv.vendor_model",
4273
14
            FT_STRING, BASE_NONE, NULL, 0x0,
4274
14
            NULL,
4275
14
            HFILL }
4276
14
        },
4277
4278
14
        { &hf_thread_mc_tlv_vendor_sw_ver,
4279
14
            { "Vendor Software Version",
4280
14
            "thread_meshcop.tlv.vendor_sw_ver",
4281
14
            FT_STRING, BASE_NONE, NULL, 0x0,
4282
14
            NULL,
4283
14
            HFILL }
4284
14
        },
4285
4286
14
        { &hf_thread_mc_tlv_vendor_data,
4287
14
            { "Vendor Data",
4288
14
            "thread_meshcop.tlv.vendor_data",
4289
14
            FT_STRING, BASE_NONE, NULL, 0x0,
4290
14
            NULL,
4291
14
            HFILL }
4292
14
        },
4293
4294
14
        { &hf_thread_mc_tlv_vendor_stack_ver_oui,
4295
14
            { "OUI",
4296
14
            "thread_meshcop.tlv.vendor_stack_ver_oui",
4297
14
            FT_UINT24, BASE_OUI, NULL, 0x0,
4298
14
            NULL,
4299
14
            HFILL }
4300
14
        },
4301
4302
14
        { &hf_thread_mc_tlv_vendor_stack_ver_build,
4303
14
            { "Build",
4304
14
            "thread_meshcop.tlv.vendor_stack_ver_build",
4305
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
4306
14
            NULL,
4307
14
            HFILL }
4308
14
        },
4309
4310
14
        { &hf_thread_mc_tlv_vendor_stack_ver_rev,
4311
14
            { "Revision",
4312
14
            "thread_meshcop.tlv.vendor_stack_ver_rev",
4313
14
            FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_REV_MASK,
4314
14
            NULL,
4315
14
            HFILL }
4316
14
        },
4317
4318
14
        { &hf_thread_mc_tlv_vendor_stack_ver_min,
4319
14
            { "Minor",
4320
14
            "thread_meshcop.tlv.vendor_stack_ver_min",
4321
14
            FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_MIN_MASK,
4322
14
            NULL,
4323
14
            HFILL }
4324
14
        },
4325
4326
14
        { &hf_thread_mc_tlv_vendor_stack_ver_maj,
4327
14
            { "Major",
4328
14
            "thread_meshcop.tlv.vendor_stack_ver_maj",
4329
14
            FT_UINT8, BASE_DEC, NULL, THREAD_MC_STACK_VER_MAJ_MASK,
4330
14
            NULL,
4331
14
            HFILL }
4332
14
        },
4333
4334
14
        { &hf_thread_mc_tlv_udp_encap_src_port,
4335
14
            { "Source UDP Port",
4336
14
            "thread_meshcop.tlv.udp_encap_src_port",
4337
14
            FT_UINT16, BASE_PT_UDP, NULL, 0x0,
4338
14
            NULL,
4339
14
            HFILL }
4340
14
        },
4341
4342
14
        { &hf_thread_mc_tlv_udp_encap_dst_port,
4343
14
            { "Destination UDP Port",
4344
14
            "thread_meshcop.tlv.udp_encap_dst_port",
4345
14
            FT_UINT16, BASE_PT_UDP, NULL, 0x0,
4346
14
            NULL,
4347
14
            HFILL }
4348
14
        },
4349
4350
14
        { &hf_thread_mc_tlv_ipv6_addr,
4351
14
            { "IPv6 Address",
4352
14
            "thread_meshcop.tlv.ipv6_addr",
4353
14
            FT_IPv6, BASE_NONE, NULL, 0x0,
4354
14
            NULL,
4355
14
            HFILL }
4356
14
        },
4357
4358
14
        { &hf_thread_mc_tlv_delay_timer,
4359
14
            { "Delay Timer",
4360
14
            "thread_meshcop.tlv.delay_timer",
4361
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
4362
14
            NULL,
4363
14
            HFILL }
4364
14
        },
4365
4366
14
        { &hf_thread_mc_tlv_chan_mask,
4367
14
            { "Channel Mask",
4368
14
            "thread_meshcop.tlv.chan_mask",
4369
14
            FT_NONE, BASE_NONE, NULL, 0x0,
4370
14
            NULL,
4371
14
            HFILL }
4372
14
        },
4373
4374
14
        { &hf_thread_mc_tlv_chan_mask_page,
4375
14
            { "Channel Page",
4376
14
            "thread_meshcop.tlv.chan_mask_page",
4377
14
            FT_UINT8, BASE_DEC, NULL, 0,
4378
14
            NULL,
4379
14
            HFILL }
4380
14
        },
4381
4382
14
        { &hf_thread_mc_tlv_chan_mask_len,
4383
14
            { "Mask Length",
4384
14
            "thread_meshcop.tlv.chan_mask_len",
4385
14
            FT_UINT8, BASE_DEC, NULL, 0,
4386
14
            NULL,
4387
14
            HFILL }
4388
14
        },
4389
4390
14
        { &hf_thread_mc_tlv_chan_mask_mask,
4391
14
            { "Mask",
4392
14
            "thread_meshcop.tlv.chan_mask_mask",
4393
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4394
14
            NULL,
4395
14
            HFILL }
4396
14
        },
4397
4398
14
        { &hf_thread_mc_tlv_el_count,
4399
14
            { "Count",
4400
14
            "thread_meshcop.tlv.el_count",
4401
14
            FT_NONE, BASE_NONE, NULL, 0x0,
4402
14
            NULL,
4403
14
            HFILL }
4404
14
        },
4405
4406
14
        { &hf_thread_mc_tlv_count,
4407
14
            { "Count",
4408
14
            "thread_meshcop.tlv.count",
4409
14
            FT_UINT8, BASE_DEC, NULL, 0,
4410
14
            NULL,
4411
14
            HFILL }
4412
14
        },
4413
4414
14
        { &hf_thread_mc_tlv_period,
4415
14
            { "Period",
4416
14
            "thread_meshcop.tlv.period",
4417
14
            FT_UINT16, BASE_DEC, NULL, 0,
4418
14
            NULL,
4419
14
            HFILL }
4420
14
        },
4421
4422
14
        { &hf_thread_mc_tlv_scan_duration,
4423
14
            { "Scan Duration",
4424
14
            "thread_meshcop.tlv.scan_duration",
4425
14
            FT_UINT16, BASE_DEC, NULL, 0,
4426
14
            NULL,
4427
14
            HFILL }
4428
14
        },
4429
4430
14
        { &hf_thread_mc_tlv_energy_list,
4431
14
            { "Energy List",
4432
14
            "thread_meshcop.tlv.energy_list",
4433
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4434
14
            NULL,
4435
14
            HFILL }
4436
14
        },
4437
4438
14
         { &hf_thread_mc_tlv_domain_name,
4439
14
            { "Domain Name",
4440
14
            "thread_meshcop.tlv.domain_name",
4441
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4442
14
            NULL,
4443
14
            HFILL }
4444
14
        },
4445
4446
14
        { &hf_thread_mc_tlv_ae_steering_data,
4447
14
            { "AE Steering Data",
4448
14
            "thread_meshcop.tlv.ae_steering_data",
4449
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4450
14
            NULL,
4451
14
            HFILL }
4452
14
        },
4453
4454
14
        { &hf_thread_mc_tlv_nmkp_steering_data,
4455
14
            { "NMKP Steering Data",
4456
14
            "thread_meshcop.tlv.nmkp_steering_data",
4457
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4458
14
            NULL,
4459
14
            HFILL }
4460
14
        },
4461
4462
14
        { &hf_thread_mc_tlv_commissioner_signature,
4463
14
            { "Commissioner Signature",
4464
14
            "thread_meshcop.tlv.nmkp_commissioner_signature",
4465
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4466
14
            NULL,
4467
14
            HFILL }
4468
14
        },
4469
4470
4471
14
        { &hf_thread_mc_tlv_ae_udp_port,
4472
14
            { "AE UDP Port",
4473
14
            "thread_meshcop.tlv.ae_udp_port",
4474
14
            FT_UINT16, BASE_PT_UDP, NULL, 0x0,
4475
14
            NULL,
4476
14
            HFILL }
4477
14
        },
4478
4479
14
        { &hf_thread_mc_tlv_nmkp_udp_port,
4480
14
            { "NMKP UDP Port",
4481
14
            "thread_meshcop.tlv.nmkp_udp_port",
4482
14
            FT_UINT16, BASE_PT_UDP, NULL, 0x0,
4483
14
            NULL,
4484
14
            HFILL }
4485
14
        },
4486
4487
14
        { &hf_thread_mc_tlv_registrar_ipv6_addr,
4488
14
            { "Registrar IPv6 Address",
4489
14
            "thread_meshcop.tlv.registrar_ipv6_addr",
4490
14
            FT_IPv6, BASE_NONE, NULL, 0x0,
4491
14
            NULL,
4492
14
            HFILL }
4493
14
        },
4494
4495
14
        { &hf_thread_mc_tlv_registrar_hostname,
4496
14
            { "Registrar IPv6 Hostname",
4497
14
            "thread_meshcop.tlv.registrar_hostname",
4498
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4499
14
            NULL,
4500
14
            HFILL }
4501
14
        },
4502
4503
14
        { &hf_thread_mc_tlv_discovery_req_ver,
4504
14
            { "Version",
4505
14
            "thread_meshcop.tlv.discovery_req_ver",
4506
14
            FT_UINT8, BASE_DEC, NULL, THREAD_MC_DISCOVERY_REQ_MASK_VER_MASK,
4507
14
            NULL,
4508
14
            HFILL }
4509
14
        },
4510
4511
14
        { &hf_thread_mc_tlv_discovery_req_j,
4512
14
            { "Joiner Flag",
4513
14
            "thread_meshcop.tlv.discovery_req_j",
4514
14
            FT_BOOLEAN, 8, TFS(&thread_mc_tlv_join_intent), THREAD_MC_DISCOVERY_REQ_MASK_J_MASK,
4515
14
            NULL,
4516
14
            HFILL }
4517
14
        },
4518
4519
14
        { &hf_thread_mc_tlv_discovery_rsp_ver,
4520
14
            { "Version",
4521
14
            "thread_meshcop.tlv.discovery_rsp_ver",
4522
14
            FT_UINT8, BASE_DEC, NULL, THREAD_MC_DISCOVERY_RSP_MASK_VER_MASK,
4523
14
            NULL,
4524
14
            HFILL }
4525
14
        },
4526
4527
14
        { &hf_thread_mc_tlv_discovery_rsp_n,
4528
14
            { "Native Commissioning",
4529
14
            "thread_meshcop.tlv.discovery_rsp_n",
4530
14
            FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_MC_DISCOVERY_RSP_MASK_N_MASK,
4531
14
            NULL,
4532
14
            HFILL }
4533
14
        },
4534
4535
14
        { &hf_thread_mc_tlv_discovery_rsp_c,
4536
14
            { "Commercial Commissioning",
4537
14
            "thread_meshcop.tlv.discovery_rsp_c",
4538
14
            FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), THREAD_MC_DISCOVERY_RSP_MASK_C_MASK,
4539
14
            NULL,
4540
14
            HFILL }
4541
14
        }
4542
14
    };
4543
4544
14
    static int *ett[] = {
4545
14
        &ett_thread_mc,
4546
14
        &ett_thread_mc_tlv,
4547
14
        &ett_thread_mc_chan_mask,
4548
14
        &ett_thread_mc_el_count
4549
14
    };
4550
4551
14
    static ei_register_info ei[] = {
4552
14
        { &ei_thread_mc_tlv_length_failed, { "thread_meshcop.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
4553
14
        { &ei_thread_mc_len_size_mismatch, { "thread_meshcop.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
4554
14
        { &ei_thread_mc_len_too_long, { "thread_meshcop.len_too_long", PI_UNDECODED, PI_WARN, "TLV Length too long", EXPFILL }}
4555
14
    };
4556
4557
14
    expert_module_t* expert_thread_mc;
4558
4559
14
    proto_thread_mc = proto_register_protocol("Thread MeshCoP", "Thread MeshCoP", "thread_meshcop");
4560
14
    proto_register_field_array(proto_thread_mc, hf, array_length(hf));
4561
14
    proto_register_subtree_array(ett, array_length(ett));
4562
14
    expert_thread_mc = expert_register_protocol(proto_thread_mc);
4563
14
    expert_register_field_array(expert_thread_mc, ei, array_length(ei));
4564
4565
14
    thread_mc_handle = register_dissector("thread_meshcop", dissect_thread_mc, proto_thread_mc);
4566
14
}
4567
4568
void
4569
proto_register_thread_nwd(void)
4570
14
{
4571
14
    static hf_register_info hf[] = {
4572
4573
    /* Generic TLV */
4574
14
        { &hf_thread_nwd_tlv,
4575
14
            { "TLV",
4576
14
            "thread_nwd.tlv",
4577
14
            FT_NONE, BASE_NONE, NULL, 0x0,
4578
14
            "Type-Length-Value",
4579
14
            HFILL }
4580
14
        },
4581
4582
14
        { &hf_thread_nwd_tlv_type,
4583
14
            { "Type",
4584
14
            "thread_nwd.tlv.type",
4585
14
            FT_UINT8, BASE_DEC, VALS(thread_nwd_tlv_vals), THREAD_NWD_TLV_TYPE_M,
4586
14
            "Type of value",
4587
14
            HFILL }
4588
14
        },
4589
4590
14
        { &hf_thread_nwd_tlv_stable,
4591
14
            { "Stable",
4592
14
            "thread_nwd.tlv.stable",
4593
14
            FT_BOOLEAN, 8, NULL, THREAD_NWD_TLV_STABLE_M,
4594
14
            "Stability or transience of network data",
4595
14
            HFILL }
4596
14
        },
4597
4598
14
        { &hf_thread_nwd_tlv_length,
4599
14
            { "Length",
4600
14
            "thread_nwd.tlv.len",
4601
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
4602
14
            "Length of value",
4603
14
            HFILL }
4604
14
        },
4605
4606
14
        { &hf_thread_nwd_tlv_unknown,
4607
14
            { "Unknown",
4608
14
            "thread_nwd.tlv.unknown",
4609
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4610
14
            "Unknown TLV, raw value",
4611
14
            HFILL }
4612
14
        },
4613
4614
14
        { &hf_thread_nwd_tlv_sub_tlvs,
4615
14
            { "Sub-TLV(s)",
4616
14
            "thread_nwd.tlv.sub_tlvs",
4617
14
            FT_NONE, BASE_NONE, NULL, 0x0,
4618
14
            NULL,
4619
14
            HFILL }
4620
14
        },
4621
4622
        /* Type-Specific TLV Fields */
4623
14
        { &hf_thread_nwd_tlv_has_route,
4624
14
            { "Has Route",
4625
14
            "thread_nwd.tlv.has_route",
4626
14
            FT_NONE, BASE_NONE, NULL, 0x0,
4627
14
            NULL,
4628
14
            HFILL }
4629
14
        },
4630
4631
14
        { &hf_thread_nwd_tlv_has_route_br_16,
4632
14
            { "Border Router 16",
4633
14
            "thread_nwd.tlv.has_route.br_16",
4634
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
4635
14
            "Has Route Border Router 16-bit address",
4636
14
            HFILL }
4637
14
        },
4638
4639
14
        { &hf_thread_nwd_tlv_has_route_pref,
4640
14
            { "Preference",
4641
14
            "thread_nwd.tlv.has_route.pref",
4642
14
            FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_HAS_ROUTE_PREF,
4643
14
            "Has Route preference",
4644
14
            HFILL }
4645
14
        },
4646
4647
14
        { &hf_thread_nwd_tlv_has_route_np,
4648
14
            { "NP",
4649
14
            "thread_nwd.tlv.has_route.np",
4650
14
            FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_HAS_ROUTE_NP,
4651
14
            "Has Route NP",
4652
14
            HFILL }
4653
14
        },
4654
4655
14
        { &hf_thread_nwd_tlv_has_route_reserved,
4656
14
            { "Reserved",
4657
14
            "thread_nwd.tlv.has_route.reserved",
4658
14
            FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_HAS_ROUTE_RESERVED,
4659
14
            "Has Route Reserved",
4660
14
            HFILL }
4661
14
        },
4662
4663
14
        { &hf_thread_nwd_tlv_prefix_domain_id,
4664
14
            { "Domain ID",
4665
14
            "thread_nwd.tlv.prefix.domain_id",
4666
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
4667
14
            "Prefix Domain ID",
4668
14
            HFILL }
4669
14
        },
4670
4671
14
        { &hf_thread_nwd_tlv_prefix_length,
4672
14
            { "Prefix Length",
4673
14
            "thread_nwd.tlv.prefix.length",
4674
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
4675
14
            "Length of Prefix",
4676
14
            HFILL }
4677
14
        },
4678
4679
14
        { &hf_thread_nwd_tlv_prefix,
4680
14
            { "Prefix",
4681
14
            "thread_nwd.tlv.prefix",
4682
14
            FT_IPv6, BASE_NONE, NULL, 0x0,
4683
14
            "IPv6 prefix",
4684
14
            HFILL }
4685
14
        },
4686
4687
14
        { &hf_thread_nwd_tlv_border_router,
4688
14
            { "Border Router",
4689
14
            "thread_nwd.tlv.border_router",
4690
14
            FT_NONE, BASE_NONE, NULL, 0x0,
4691
14
            NULL,
4692
14
            HFILL }
4693
14
        },
4694
4695
14
        { &hf_thread_nwd_tlv_border_router_16,
4696
14
            { "Border Router 16",
4697
14
            "thread_nwd.tlv.border_router.16",
4698
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
4699
14
            "Border Router 16-bit address",
4700
14
            HFILL }
4701
14
        },
4702
4703
14
        { &hf_thread_nwd_tlv_border_router_pref,
4704
14
            { "Preference",
4705
14
            "thread_nwd.tlv.border_router.pref",
4706
14
            FT_UINT8, BASE_DEC, NULL, THREAD_NWD_TLV_BORDER_ROUTER_PREF,
4707
14
            "Value of P_preference",
4708
14
            HFILL }
4709
14
        },
4710
4711
14
        { &hf_thread_nwd_tlv_border_router_p,
4712
14
            { "P Flag",
4713
14
            "thread_nwd.tlv.border_router.flag.p",
4714
14
            FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_p), THREAD_NWD_TLV_BORDER_ROUTER_P,
4715
14
            "Value of P_preferred",
4716
14
            HFILL }
4717
14
        },
4718
4719
14
        { &hf_thread_nwd_tlv_border_router_s,
4720
14
            { "SLAAC",
4721
14
            "thread_nwd.tlv.border_router.flag.s",
4722
14
            FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_NWD_TLV_BORDER_ROUTER_S,
4723
14
            "Value of P_slaac",
4724
14
            HFILL }
4725
14
        },
4726
4727
14
        { &hf_thread_nwd_tlv_border_router_d,
4728
14
            { "DHCPv6",
4729
14
            "thread_nwd.tlv.border_router.flag.d",
4730
14
            FT_BOOLEAN, 8, TFS(&tfs_allowed_not_allowed), THREAD_NWD_TLV_BORDER_ROUTER_D,
4731
14
            "Value of P_dhcp",
4732
14
            HFILL }
4733
14
        },
4734
4735
14
        { &hf_thread_nwd_tlv_border_router_c,
4736
14
            { "C Flag",
4737
14
            "thread_nwd.tlv.border_router.flag.c",
4738
14
            FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_c), THREAD_NWD_TLV_BORDER_ROUTER_C,
4739
14
            "Value of P_configure",
4740
14
            HFILL }
4741
14
        },
4742
4743
14
        { &hf_thread_nwd_tlv_border_router_r,
4744
14
            { "Default route",
4745
14
            "thread_nwd.tlv.border_router.flag.r",
4746
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), THREAD_NWD_TLV_BORDER_ROUTER_R,
4747
14
            "Value of P_default",
4748
14
            HFILL }
4749
14
        },
4750
4751
14
        { &hf_thread_nwd_tlv_border_router_o,
4752
14
            { "O Flag",
4753
14
            "thread_nwd.tlv.border_router.flag.o",
4754
14
            FT_BOOLEAN, 8, TFS(&tfs_thread_nwd_tlv_border_router_o), THREAD_NWD_TLV_BORDER_ROUTER_O,
4755
14
            "Value of P_on_mesh",
4756
14
            HFILL }
4757
14
        },
4758
4759
14
        { &hf_thread_nwd_tlv_border_router_n,
4760
14
            { "DNS",
4761
14
            "thread_nwd.tlv.border_router.flag.n",
4762
14
            FT_BOOLEAN, 8, TFS(&tfs_available_not_available), THREAD_NWD_TLV_BORDER_ROUTER_N,
4763
14
            "Value of P_nd_dns",
4764
14
            HFILL }
4765
14
        },
4766
4767
14
        { &hf_thread_nwd_tlv_border_router_dp,
4768
14
            { "DP Flag",
4769
14
            "thread_nwd.tlv.border_router.flag.dp",
4770
14
            FT_BOOLEAN, 8, TFS(&tfs_available_not_available), THREAD_NWD_TLV_BORDER_ROUTER_DP,
4771
14
            "Value of P_dp",
4772
14
            HFILL }
4773
14
        },
4774
4775
14
        { &hf_thread_nwd_tlv_6lowpan_id_6co_flag,
4776
14
            { "Flag",
4777
14
            "thread_nwd.tlv.6co.flag",
4778
14
            FT_UINT8, BASE_HEX, NULL, 0x00,
4779
14
            NULL,
4780
14
            HFILL }
4781
14
        },
4782
4783
14
        { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_c,
4784
14
            { "Compression Flag",
4785
14
            "thread_nwd.tlv.6co.flag.c",
4786
14
            FT_BOOLEAN, 8, TFS(&tfs_set_notset), ND_OPT_6CO_FLAG_C,
4787
14
            "This flag indicates if the context is valid for use in compression",
4788
14
            HFILL }
4789
14
        },
4790
4791
14
        { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_cid,
4792
14
            { "CID",
4793
14
            "thread_nwd.tlv.6co.flag.cid",
4794
14
            FT_UINT8, BASE_DEC, NULL, ND_OPT_6CO_FLAG_CID,
4795
14
            "Context Identifier for this prefix information",
4796
14
            HFILL }
4797
14
        },
4798
4799
14
        { &hf_thread_nwd_tlv_6lowpan_id_6co_flag_reserved,
4800
14
            { "Reserved",
4801
14
            "thread_nwd.tlv.6co.flag.reserved",
4802
14
            FT_UINT8, BASE_DEC, NULL, ND_OPT_6CO_FLAG_RESERVED,
4803
14
            "Must be zero",
4804
14
            HFILL }
4805
14
        },
4806
4807
14
        { &hf_thread_nwd_tlv_6lowpan_id_6co_context_length,
4808
14
            { "Context Length",
4809
14
            "thread_nwd.tlv.6co.context_length",
4810
14
            FT_UINT8, BASE_DEC, NULL, 0x00,
4811
14
            "The number of leading bits in the Context Prefix field that are valid",
4812
14
            HFILL }
4813
14
        },
4814
#if 0
4815
        { &hf_thread_nwd_tlv_comm_data,
4816
            { "Commissioning Data",
4817
            "thread_nwd.tlv.comm_data",
4818
            FT_BYTES, BASE_NONE, NULL, 0x0,
4819
            "Contains Thread Commissioning data",
4820
            HFILL }
4821
        },
4822
#endif
4823
14
        { &hf_thread_nwd_tlv_service_t,
4824
14
            { "T flag",
4825
14
            "thread_nwd.tlv.service.t",
4826
14
            FT_UINT8, BASE_HEX, NULL, THREAD_NWD_TLV_SERVICE_T,
4827
14
            NULL,
4828
14
            HFILL }
4829
14
        },
4830
4831
14
        { &hf_thread_nwd_tlv_service_s_id,
4832
14
            { "Service Type ID",
4833
14
            "thread_nwd.tlv.service.s_id",
4834
14
            FT_UINT8, BASE_HEX, NULL, THREAD_NWD_TLV_SERVICE_S_ID,
4835
14
            NULL,
4836
14
            HFILL }
4837
14
        },
4838
4839
14
        { &hf_thread_nwd_tlv_service_s_ent_num,
4840
14
            { "Enterprise Number",
4841
14
            "thread_nwd.tlv.service.s_ent_num",
4842
14
            FT_UINT32, BASE_DEC, NULL, 0,
4843
14
            NULL,
4844
14
            HFILL }
4845
14
        },
4846
4847
14
        { &hf_thread_nwd_tlv_service_s_data_len,
4848
14
            { "Service Data Length",
4849
14
            "thread_nwd.tlv.service.s_data_len",
4850
14
            FT_UINT8, BASE_DEC, NULL, 0,
4851
14
            NULL,
4852
14
            HFILL }
4853
14
        },
4854
4855
14
        { &hf_thread_nwd_tlv_service_s_data,
4856
14
            { "Service Data",
4857
14
            "thread_nwd.tlv.service.s_data",
4858
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4859
14
            "Service data in raw bytes",
4860
14
            HFILL }
4861
14
        },
4862
4863
14
        { &hf_thread_nwd_tlv_service_s_data_seqno,
4864
14
        { "Service Data - BBR Sequence Number",
4865
14
            "thread_nwd.tlv.service.s_data.seqno",
4866
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
4867
14
            "Service data in raw bytes",
4868
14
            HFILL }
4869
14
        },
4870
4871
14
        { &hf_thread_nwd_tlv_service_s_data_rrdelay,
4872
14
        { "Service Data - Reregistration Delay(s)",
4873
14
            "thread_nwd.tlv.service.s_data.rrdelay",
4874
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
4875
14
            "Service data in raw bytes",
4876
14
            HFILL }
4877
14
        },
4878
4879
14
        { &hf_thread_nwd_tlv_service_s_data_mlrtimeout,
4880
14
        { "Service Data - MLR Timeout(s)",
4881
14
            "thread_nwd.tlv.service.s_data.mlrtimeout",
4882
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
4883
14
            "Service data in raw bytes",
4884
14
            HFILL }
4885
14
        },
4886
4887
14
        { &hf_thread_nwd_tlv_server_16,
4888
14
            { "Server 16",
4889
14
            "thread_nwd.tlv.server.16",
4890
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
4891
14
            "Server 16-bit address",
4892
14
            HFILL }
4893
14
        },
4894
4895
14
        { &hf_thread_nwd_tlv_server_data,
4896
14
            { "Server Data",
4897
14
            "thread_nwd.tlv.server.data",
4898
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4899
14
            "Server data in raw bytes",
4900
14
            HFILL }
4901
14
        },
4902
4903
        // Thread 1.3 Service TLV code
4904
4905
14
        { &hf_thread_nwd_tlv_service_srp_dataset_identifier,
4906
14
        { "Service Data SRP Dataset Identifier",
4907
14
            "thread_nwd.tlv.service.srp_dataset_identifier",
4908
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
4909
14
            NULL,
4910
14
            HFILL }
4911
14
        },
4912
4913
14
        { &hf_thread_nwd_tlv_service_anycast_seqno,
4914
14
        { "Service Data Anycast Sequence Number",
4915
14
           "thread_nwd.tlv.service.anycast_seqno",
4916
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
4917
14
            "Sequence Number of Anycast Dataset",
4918
14
            HFILL }
4919
14
        },
4920
4921
14
        { &hf_thread_nwd_tlv_service_unicast_ipv6_address,
4922
14
        { "Service Data Unicast Server IPV6 Address",
4923
14
            "thread_nwd.tlv.service.unicast_server_ipv6_address",
4924
14
            FT_IPv6, BASE_NONE, NULL, 0x0,
4925
14
            "IPV6 Address of Unicast SRP Server",
4926
14
            HFILL }
4927
14
        },
4928
4929
14
        { &hf_thread_nwd_tlv_service_unicast_port_number,
4930
14
        { "Service Data Unicast Port Number",
4931
14
            "thread_nwd.tlv.service.unicast_port_no",
4932
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
4933
14
            "Port Number of Unicast SRP Server",
4934
14
            HFILL }
4935
14
         }
4936
4937
14
    };
4938
4939
14
    static int *ett[] = {
4940
14
        &ett_thread_nwd,
4941
14
        &ett_thread_nwd_tlv,
4942
14
        &ett_thread_nwd_has_route,
4943
14
        &ett_thread_nwd_6co_flag,
4944
14
        &ett_thread_nwd_border_router,
4945
14
        &ett_thread_nwd_prefix_sub_tlvs
4946
14
    };
4947
4948
14
    static ei_register_info ei[] = {
4949
#if 0
4950
        { &ei_thread_nwd_tlv_length_failed, { "thread_nwd.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
4951
#endif
4952
14
        { &ei_thread_nwd_len_size_mismatch, { "thread_nwd.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
4953
14
    };
4954
4955
14
    expert_module_t* expert_thread_nwd;
4956
4957
14
    proto_thread_nwd = proto_register_protocol("Thread Network Data", "Thread NWD", "thread_nwd");
4958
14
    proto_register_field_array(proto_thread_nwd, hf, array_length(hf));
4959
14
    proto_register_subtree_array(ett, array_length(ett));
4960
14
    expert_thread_nwd = expert_register_protocol(proto_thread_nwd);
4961
14
    expert_register_field_array(expert_thread_nwd, ei, array_length(ei));
4962
4963
14
    thread_address_nwd_handle = register_dissector("thread_nwd", dissect_thread_nwd, proto_thread_nwd);
4964
14
}
4965
4966
void proto_register_thread_bcn(void)
4967
14
{
4968
14
    static hf_register_info hf[] = {
4969
4970
14
        { &hf_thread_bcn_protocol,
4971
14
        { "Protocol ID",          "thread_bcn.protocol", FT_UINT8, BASE_DEC, NULL, 0x0,
4972
14
          NULL, HFILL }},
4973
4974
14
        { &hf_thread_bcn_joining,
4975
14
        { "Joining",              "thread_bcn.joining", FT_BOOLEAN, 8, NULL, THREAD_BCN_JOINING,
4976
14
          NULL, HFILL }},
4977
4978
14
        { &hf_thread_bcn_native,
4979
14
        { "Native",               "thread_bcn.native", FT_BOOLEAN, 8, NULL, THREAD_BCN_NATIVE,
4980
14
          NULL, HFILL }},
4981
4982
14
        { &hf_thread_bcn_version,
4983
14
        { "Version",              "thread_bcn.version", FT_UINT8, BASE_DEC, NULL, THREAD_BCN_PROTOCOL_VERSION,
4984
14
          NULL, HFILL }},
4985
4986
14
        { &hf_thread_bcn_network_id,
4987
14
        { "Network Name",         "thread_bcn.network_name", FT_STRING, BASE_NONE, NULL, 0x0,
4988
14
          "A string that uniquely identifies this network.", HFILL }},
4989
4990
14
        { &hf_thread_bcn_epid,
4991
14
        { "Extended PAN ID",      "thread_bcn.epid", FT_EUI64, BASE_NONE, NULL, 0x0,
4992
14
          NULL, HFILL }},
4993
4994
14
        { &hf_thread_bcn_tlv,
4995
14
        { "TLV",                  "thread_bcn.tlv", FT_NONE, BASE_NONE, NULL, 0x0,
4996
14
          "Type-Length-Value", HFILL }},
4997
4998
14
        { &hf_thread_bcn_tlv_type,
4999
14
        { "Type",                 "thread_bcn.tlv.type", FT_UINT8, BASE_DEC, VALS(thread_bcn_tlv_vals), 0x0,
5000
14
          "Type of Value", HFILL }},
5001
5002
14
        { &hf_thread_bcn_tlv_length,
5003
14
        { "Length",               "thread_bcn.tlv.len", FT_UINT8, BASE_DEC, NULL, 0x0,
5004
14
          "Length of Value", HFILL }},
5005
5006
14
        { &hf_thread_bcn_tlv_steering_data,
5007
14
        { "Steering Data",         "thread_bcn.tlv.steering_data", FT_BYTES, BASE_NONE, NULL, 0x0,
5008
14
          "Steering data for joining devices", HFILL }},
5009
5010
14
        { &hf_thread_bcn_tlv_unknown,
5011
14
        { "Unknown",              "thread_bcn.tlv.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
5012
14
          "Unknown TLV, raw value", HFILL }}
5013
14
    };
5014
5015
    /*  NWK Layer subtrees */
5016
14
    static int *ett[] = {
5017
14
        &ett_thread_bcn,
5018
14
        &ett_thread_bcn_tlv
5019
14
    };
5020
5021
    /* Register the protocol with Wireshark. */
5022
14
    proto_thread_bcn = proto_register_protocol("Thread Beacon", "Thread Beacon", "thread_bcn");
5023
14
    proto_register_field_array(proto_thread_bcn, hf, array_length(hf));
5024
14
    proto_register_subtree_array(ett, array_length(ett));
5025
5026
    /* Register the dissectors with Wireshark. */
5027
14
    register_dissector("thread_bcn", dissect_thread_bcn, proto_thread_bcn);
5028
14
}
5029
5030
static void
5031
proto_init_thread(void)
5032
14
{
5033
    /* Reset the sequence counter variables */
5034
14
    thread_seq_ctr_acqd = false;
5035
14
    memset(thread_seq_ctr_bytes, 0, 4);
5036
14
}
5037
5038
void
5039
proto_register_thread(void)
5040
14
{
5041
14
    module_t *thread_module;
5042
5043
14
    proto_thread = proto_register_protocol("Thread", "Thread", "thread");
5044
5045
14
    thread_module = prefs_register_protocol(proto_thread, NULL);
5046
14
    prefs_register_obsolete_preference(thread_module, "thr_coap_decode");
5047
14
    prefs_register_string_preference(thread_module, "thr_seq_ctr",
5048
14
                                     "Thread sequence counter",
5049
14
                                     "32-bit sequence counter for hash",
5050
14
                                     (const char **)&thread_seq_ctr_str);
5051
5052
14
    prefs_register_bool_preference(thread_module, "thr_use_pan_id_in_key",
5053
14
                                   "Use PAN ID as first two octets of master key",
5054
14
                                   "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]...",
5055
14
                                   &thread_use_pan_id_in_key);
5056
5057
14
    prefs_register_bool_preference(thread_module, "thr_auto_acq_thr_seq_ctr",
5058
14
                                   "Automatically acquire Thread sequence counter",
5059
14
                                   "Set if the Thread sequence counter should be automatically acquired from Key ID mode 2 MLE messages.",
5060
14
                                   &thread_auto_acq_seq_ctr);
5061
5062
     /*static hf_register_info hf[] = {
5063
        { &hf_ieee802154_thread_ie,
5064
        { "IE header",                       "thread_ie", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5065
5066
        { &hf_ieee802154_thread_ie_length,
5067
        { "Length",                           "thread_ie.length", FT_UINT16, BASE_DEC, NULL,
5068
                THREAD_IE_LENGTH_MASK, NULL, HFILL }}
5069
     };
5070
5071
      static int *ett[] = {
5072
        &ett_thread_header_ie,
5073
     };*/
5074
5075
14
    register_init_routine(proto_init_thread);
5076
5077
    // proto_register_field_array(proto_thread_ie, hf, array_length(hf));
5078
   // proto_register_subtree_array(ett, array_length(ett));
5079
5080
    /* Register Dissector */
5081
14
    register_dissector("thread_ie", dissect_thread_ie, proto_thread_ie);
5082
14
}
5083
5084
void
5085
proto_register_thread_coap(void)
5086
14
{
5087
14
    proto_thread_coap = proto_register_protocol("Thread CoAP", "Thread CoAP", "thread_coap");
5088
14
    thread_coap_handle = register_dissector("thread_coap", dissect_thread_coap, proto_thread_coap);
5089
5090
14
    dissector_add_string("coap_tmf_media_type", "application/octet-stream", thread_coap_handle);
5091
14
    thread_coap_namespace = register_dissector_table("thread.coap_namespace", "Thread CoAP namespace", proto_thread_coap, FT_STRING, STRING_CASE_SENSITIVE);
5092
14
}
5093
5094
void
5095
proto_reg_handoff_thread_mc(void)
5096
14
{
5097
14
    thread_dtls_handle = find_dissector_add_dependency("dtls", proto_thread_mc);
5098
14
    thread_udp_handle = find_dissector_add_dependency("udp", proto_thread_mc);
5099
5100
14
    dissector_add_string("thread.coap_namespace", "c", thread_mc_handle);
5101
14
}
5102
5103
void
5104
proto_reg_handoff_thread_address(void)
5105
14
{
5106
14
    dissector_add_string("thread.coap_namespace", "a", thread_address_handle);
5107
14
    dissector_add_string("thread.coap_namespace", "n", thread_address_handle);
5108
14
}
5109
5110
void
5111
proto_reg_handoff_thread_nm(void)
5112
14
{
5113
14
    dissector_add_string("thread.coap_namespace", "n", thread_nm_handle);
5114
14
}
5115
5116
void
5117
proto_reg_handoff_thread_bl(void)
5118
14
{
5119
14
    dissector_add_string("thread.coap_namespace", "b", thread_bl_handle);
5120
14
}
5121
5122
void
5123
proto_reg_handoff_thread_dg(void)
5124
14
{
5125
14
    dissector_add_string("thread.coap_namespace", "d", thread_dg_handle);
5126
14
}
5127
5128
void proto_reg_handoff_thread_bcn(void)
5129
14
{
5130
    /* Register our dissector with IEEE 802.15.4 */
5131
14
    heur_dissector_add(IEEE802154_PROTOABBREV_WPAN_BEACON, dissect_thread_bcn_heur, "Thread Beacon", "thread_wlan_beacon", proto_thread_bcn, HEURISTIC_ENABLE);
5132
5133
14
    register_mle_key_hash_handler(KEY_HASH_THREAD, set_thread_mle_key);
5134
14
    register_ieee802154_mac_key_hash_handler(KEY_HASH_THREAD, set_thread_mac_key);
5135
14
}
5136
5137
void
5138
proto_reg_handoff_thread(void)
5139
14
{
5140
    /* Thread Content-Format is opaque byte string, i.e. application/octet-stream */
5141
    /* Enable decoding "Internet media type" as Thread over CoAP */
5142
14
    dissector_add_for_decode_as("media_type", thread_coap_handle);
5143
    /* Do NOT add the thread dissector to the generic media_type table for
5144
     * "application/octet-stream", which is for "arbitrary binary data":
5145
     * https://www.iana.org/assignments/media-types/application/octet-stream
5146
     * Doing so hijacks *all* "application/octet-stream", including in HTTP, etc.
5147
     * That is why there is a separate coap_tmf_media_type table and a
5148
     * special CoAP-TMF dissector. (#14729).
5149
     */
5150
    //dissector_add_string("media_type", "application/octet-stream", thread_coap_handle);
5151
5152
14
    proto_coap = proto_get_id_by_filter_name("coap");
5153
14
}
5154
5155
/**
5156
 *Subdissector command for Thread Specific IEs (Information Elements)
5157
 *
5158
 *@param tvb pointer to buffer containing raw packet.
5159
 *@param pinfo pointer to packet information fields (unused).
5160
 *@param tree pointer to command subtree.
5161
 *@param data pointer to the length of the payload IE.
5162
*/
5163
static int
5164
dissect_thread_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data)
5165
0
{
5166
5167
0
    proto_tree *subtree;
5168
    //tvbuff_t   *ie_tvb;
5169
0
    uint16_t    thread_ie;
5170
0
    uint16_t    id;
5171
0
    uint16_t    length;
5172
0
    unsigned    pie_length;
5173
0
    unsigned    offset = 0;
5174
5175
0
    static int * fields[] = {
5176
0
        &hf_ieee802154_thread_ie_id,
5177
0
        &hf_ieee802154_thread_ie_length,
5178
0
        NULL
5179
0
    };
5180
5181
0
    pie_length = *(int *)data;
5182
5183
0
    do {
5184
0
        thread_ie =  tvb_get_letohs(tvb, offset);
5185
0
        id        = (thread_ie & THREAD_IE_ID_MASK) >> 6;
5186
0
        length    =  thread_ie & THREAD_IE_LENGTH_MASK;
5187
5188
        /* Create a subtree for this command frame. */
5189
0
        subtree = proto_tree_add_subtree(tree, tvb, offset, 2+length, ett_thread, NULL, "Thread IE");
5190
        //proto_item_append_text(subtree, ", %s, Length: %d", val_to_str_const(id, ieee802154_zigbee_ie_names, "Unknown"), length);
5191
5192
0
        proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_thread_ie,
5193
0
                               ett_thread_ie_fields, fields, ENC_LITTLE_ENDIAN);
5194
0
        offset += 2;
5195
5196
0
        switch (id) {
5197
            /*case ZBEE_ZIGBEE_IE_REJOIN:
5198
                dissect_ieee802154_zigbee_rejoin(tvb, pinfo, subtree, &offset);
5199
                break;
5200
5201
            case ZBEE_ZIGBEE_IE_TX_POWER:
5202
                dissect_ieee802154_zigbee_txpower(tvb, pinfo, subtree, &offset);
5203
                break;
5204
5205
            case ZBEE_ZIGBEE_IE_BEACON_PAYLOAD:
5206
                ie_tvb = tvb_new_subset_length(tvb, offset, ZBEE_NWK_BEACON_LENGTH);
5207
                offset += dissect_zbee_beacon(ie_tvb, pinfo, subtree, NULL);
5208
                dissect_ieee802154_superframe(tvb, pinfo, subtree, &offset);
5209
                proto_tree_add_item(subtree, hf_ieee802154_zigbee_ie_source_addr, tvb, offset, 2, ENC_NA);
5210
                offset += 2;
5211
                break;*/
5212
5213
0
            default:
5214
0
                if (length > 0) {
5215
                    //proto_tree_add_item(tree, hf_thread_mc_tlv_unknown, tvb, offset, tlv_len, ENC_NA);
5216
0
                    offset += length;
5217
0
                }
5218
0
                break;
5219
0
        }
5220
0
    } while (offset < pie_length);
5221
0
    return tvb_captured_length(tvb);
5222
0
}
5223
5224
/*
5225
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
5226
 *
5227
 * Local variables:
5228
 * c-basic-offset: 4
5229
 * tab-width: 8
5230
 * indent-tabs-mode: nil
5231
 * End:
5232
 *
5233
 * vi: set shiftwidth=4 tabstop=8 expandtab:
5234
 * :indentSize=4:tabSize=8:noTabs=true:
5235
 */