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