1 /* packet-geonw.c 2 * Routines for GeoNetworking and BTP-A/B dissection 3 * Coyright 2018, C. Guerber <cguerber@yahoo.com> 4 * 5 * Wireshark - Network traffic analyzer 6 * By Gerald Combs <gerald@wireshark.org> 7 * Copyright 1998 Gerald Combs 8 * 9 * SPDX-License-Identifier: GPL-2.0-or-later 10 */ 11 12 /* 13 * The GeoNetworking protocol is a network layer protocol that provides packet 14 * routing in an ad hoc network. It makes use of geographical positions for 15 * packet transport. GeoNetworking supports the communication among individual 16 * ITS stations as well as the distribution of packets in geographical areas. 17 * (Extracted from ETSI EN 302 636-4-1) 18 * 19 * The Basic Transport Protocol (BTP) provides an end-to-end, connection-less 20 * transport service in the ITS ad hoc network. Its main purpose is the 21 * multiplexing of messages from different processes at the ITS facilities 22 * layer, e.g. CAM and DENM from the cooperative awareness basic service and 23 * the distributed environmental notification basic service, for the 24 * transmission of packets via the GeoNetworking protocol as well as the 25 * de-multiplexing at the destination. 26 * (Extracted from ETSI EN 302 636-5-1) 27 * 28 * Reference standards: 29 * ETSI EN 302 636-4-1 v1.2.0 (2013-10) 30 * Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking; 31 * Part 4: Geographical addressing and forwarding for point-to-point and 32 * point-to-multipoint communications; 33 * Sub-part 1: Media-Independent Functionality 34 * 35 * ETSI EN 302 636-5-1 v1.2.1 (2014-08) 36 * Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking; 37 * Part 5: Transport Protocols; 38 * Sub-part 1: Basic Transport Protocol 39 * 40 * ETSI EN 302 636-6-1 v1.2.1 (2014-05) 41 * Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking; 42 * Part 6: Internet Integration; 43 * Sub-part 1: Transmission of IPv6 Packets over GeoNetworking Protocols 44 * 45 * ETSI TS 103 248 v1.2.1 (2018-08) 46 * Intelligent Transport Systems (ITS); GeoNetworking; 47 * Port Numbers for the Basic Transport Protocol (BTP) 48 * 49 * ETSI TS 103 097 v1.1.1, v1.2.1 and v1.3.1 50 * Intelligent Transport Systems (ITS); Security; 51 * Security header and certificate formats 52 * 53 */ 54 55 #include <config.h> 56 #include <stdlib.h> 57 #include <stdio.h> 58 59 #include <epan/packet.h> 60 #include <epan/expert.h> 61 #include <epan/decode_as.h> 62 #include <epan/proto_data.h> 63 #include <epan/address_types.h> 64 #include <epan/addr_resolv.h> 65 #include <epan/to_str.h> 66 #include <epan/to_str.h> 67 #include <epan/conversation.h> 68 #include <epan/tap.h> 69 #include <epan/etypes.h> 70 71 #include <wsutil/utf8_entities.h> 72 73 #include "packet-e164.h" 74 #include "packet-ieee1609dot2.h" 75 #include "packet-geonw.h" 76 77 /* 78 * Prototypes 79 */ 80 void proto_reg_handoff_btpb(void); 81 void proto_register_btpb(void); 82 void proto_reg_handoff_btpa(void); 83 void proto_register_btpa(void); 84 void proto_reg_handoff_geonw(void); 85 void proto_register_geonw(void); 86 87 /* 88 * Constants 89 */ 90 #define HT_MASK 0xf0 91 #define HST_MASK 0x0f 92 93 // Definition of header types See section 8.7.4 table 9 94 #define HT_BEACON 0x10 95 #define HT_GEOUNICAST 0x20 96 #define HT_GEOANYCAST 0x30 97 #define HT_GEOBROADCAST 0x40 98 #define HT_TSB 0x50 99 #define HT_LS 0x60 100 101 // Area subtypes 102 #define HST_CIRCULAR 0x00 103 #define HST_RECTANGULAR 0x01 104 #define HST_ELLIPSOIDAL 0x02 105 106 // TSB subtype 107 #define HST_SINGLE_HOP 0x00 108 #define HST_MULTI_HOP 0x01 109 110 // LS subtypes 111 #define HST_REQUEST 0x00 112 #define HST_REPLY 0x01 113 114 // Types and subtype combined 115 #define HTST_BEACON (HT_BEACON) 116 #define HTST_GEOUNICAST (HT_GEOUNICAST) 117 #define HTST_GAC_CIRCLE (HT_GEOANYCAST|HST_CIRCULAR) 118 #define HTST_GAC_RECT (HT_GEOANYCAST|HST_RECTANGULAR) 119 #define HTST_GAC_ELLIPSE (HT_GEOANYCAST|HST_ELLIPSOIDAL) 120 #define HTST_GBC_CIRCLE (HT_GEOBROADCAST|HST_CIRCULAR) 121 #define HTST_GBC_RECT (HT_GEOBROADCAST|HST_RECTANGULAR) 122 #define HTST_GBC_ELLIPSE (HT_GEOBROADCAST|HST_ELLIPSOIDAL) 123 #define HTST_TSB_SINGLE (HT_TSB|HST_SINGLE_HOP) 124 #define HTST_TSB_MULT (HT_TSB|HST_MULTI_HOP) 125 #define HTST_LS_REQUEST (HT_LS|HST_REQUEST) 126 #define HTST_LS_REPLY (HT_LS|HST_REPLY) 127 128 #define HT_GET(ht) ((ht)&HT_MASK) 129 #define HST_GET(ht) ((ht)&HST_MASK) 130 #define IS_HT_KNOWN(ht) ((ht) <= 0x61) && (ht >= 0x10) && (HST_GET(ht) < 3) && ((HST_GET(ht) == 0) || ((HT_GET(ht) > 0x30) && ((HST_GET(ht) == 1) || ((HST_GET(ht) == 2) && (HT_GET(ht) < 0x43))))) 131 132 #define BH_LEN 4 133 #define BH_NH_COMMON_HDR 1 134 #define BH_NH_SECURED_PKT 2 135 136 #define CH_LEN 8 137 #define CH_NH_BTP_A 1 138 #define CH_NH_BTP_B 2 139 #define CH_NH_IPV6 3 140 141 #define GUC_LEN 48 142 #define TSB_LEN 28 143 #define GAC_LEN 44 144 #define GBC_LEN 44 145 #define BEACON_LEN 24 146 #define LS_REQUEST_LEN 36 147 #define LS_REPLY_LEN 48 148 149 #define TST_MAX 0xffffffff 150 151 /* 152 * Variables 153 */ 154 static wmem_map_t *geonw_hashtable = NULL; 155 156 static int proto_geonw = -1; 157 static int proto_btpa = -1; 158 static int proto_btpb = -1; 159 160 static int geonw_tap = -1; 161 static int btpa_tap = -1; 162 static int btpa_follow_tap = -1; 163 static int btpb_tap = -1; 164 static int btpb_follow_tap = -1; 165 166 static int hf_geonw_bh = -1; 167 static int hf_geonw_bh_version = -1; 168 static int hf_geonw_bh_next_header = -1; 169 static int hf_geonw_bh_reserved = -1; 170 static int hf_geonw_bh_life_time = -1; 171 static int hf_geonw_bh_lt_mult = -1; 172 static int hf_geonw_bh_lt_base = -1; 173 static int hf_geonw_bh_remain_hop_limit = -1; 174 175 static int hf_geonw_ch = -1; 176 static int hf_geonw_ch_next_header = -1; 177 static int hf_geonw_ch_reserved1 = -1; 178 static int hf_geonw_ch_header_type = -1; 179 //static int hf_geonw_ch_header_subtype = -1; 180 static int hf_geonw_ch_traffic_class = -1; 181 static int hf_geonw_ch_tc_scf = -1; 182 static int hf_geonw_ch_tc_offload = -1; 183 static int hf_geonw_ch_tc_id = -1; 184 static int hf_geonw_ch_flags = -1; 185 static int hf_geonw_ch_flags_mob = -1; 186 static int hf_geonw_ch_flags_reserved = -1; 187 static int hf_geonw_ch_payload_length = -1; 188 static int hf_geonw_ch_max_hop_limit = -1; 189 static int hf_geonw_ch_reserved2 = -1; 190 191 static int hf_geonw_seq_num = -1; 192 static int hf_geonw_reserved = -1; 193 static int hf_geonw_so_pv = -1; 194 static int hf_geonw_so_pv_addr = -1; 195 static int hf_geonw_so_pv_addr_manual = -1; 196 static int hf_geonw_so_pv_addr_type = -1; 197 static int hf_geonw_so_pv_addr_country = -1; 198 static int hf_geonw_so_pv_addr_mid = -1; 199 static int hf_geonw_so_pv_time = -1; 200 static int hf_geonw_so_pv_lat = -1; 201 static int hf_geonw_so_pv_lon = -1; 202 static int hf_geonw_so_pv_pai = -1; 203 static int hf_geonw_so_pv_speed = -1; 204 static int hf_geonw_so_pv_heading = -1; 205 static int hf_geonw_de_pv = -1; 206 static int hf_geonw_de_pv_addr = -1; 207 static int hf_geonw_de_pv_addr_manual = -1; 208 static int hf_geonw_de_pv_addr_type = -1; 209 static int hf_geonw_de_pv_addr_country = -1; 210 static int hf_geonw_de_pv_addr_mid = -1; 211 static int hf_geonw_de_pv_time = -1; 212 static int hf_geonw_de_pv_lat = -1; 213 static int hf_geonw_de_pv_lon = -1; 214 215 static int hf_geonw_gxc_latitude = -1; 216 static int hf_geonw_gxc_longitude = -1; 217 static int hf_geonw_gxc_radius = -1; 218 static int hf_geonw_gxc_distancea = -1; 219 static int hf_geonw_gxc_distanceb = -1; 220 static int hf_geonw_gxc_angle = -1; 221 static int hf_geonw_gxc_reserved = -1; 222 223 static int hf_geonw_shb_reserved = -1; 224 225 static int hf_geonw_lsrq_addr = -1; 226 static int hf_geonw_lsrq_addr_manual = -1; 227 static int hf_geonw_lsrq_addr_type = -1; 228 static int hf_geonw_lsrq_addr_country = -1; 229 static int hf_geonw_lsrq_addr_mid = -1; 230 231 static int hf_geonw_beacon = -1; 232 static int hf_geonw_guc = -1; 233 static int hf_geonw_gac = -1; 234 static int hf_geonw_gbc = -1; 235 static int hf_geonw_tsb = -1; 236 static int hf_geonw_ls = -1; 237 static int hf_geonw_analysis_flags = -1; 238 239 static int hf_btpa_dstport = -1; 240 static int hf_btpa_srcport = -1; 241 static int hf_btpa_port = -1; 242 static int hf_btpb_dstport = -1; 243 static int hf_btpb_dstport_info = -1; 244 245 static int hf_geonw_resp_in = -1; 246 static int hf_geonw_resp_to = -1; 247 static int hf_geonw_no_resp = -1; 248 static int hf_geonw_resptime = -1; 249 250 static int hf_geonw_dccmco = -1; 251 static int hf_geonw_dccmco_cbr_l_0_hop = -1; 252 static int hf_geonw_dccmco_cbr_l_1_hop = -1; 253 static int hf_geonw_dccmco_output_power = -1; 254 static int hf_geonw_dccmco_reserved = -1; 255 256 static gint ett_geonw = -1; 257 static gint ett_geonw_bh = -1; 258 static gint ett_geonw_bh_lt = -1; 259 static gint ett_geonw_ch = -1; 260 static gint ett_geonw_ch_tc = -1; 261 static gint ett_geonw_sh = -1; 262 static gint ett_geonw_so = -1; 263 static gint ett_geonw_so_add = -1; 264 static gint ett_geonw_de = -1; 265 static gint ett_geonw_de_add = -1; 266 static gint ett_geonw_lsrq_add = -1; 267 static gint ett_geonw_analysis = -1; 268 static gint ett_geonw_dccmco = -1; 269 static gint ett_btpa = -1; 270 static gint ett_btpb = -1; 271 272 static int geonw_address_type = -1; 273 274 static expert_field ei_geonw_nz_reserved = EI_INIT; 275 static expert_field ei_geonw_version_err = EI_INIT; 276 static expert_field ei_geonw_rhl_lncb = EI_INIT; 277 static expert_field ei_geonw_rhl_too_low = EI_INIT; 278 static expert_field ei_geonw_mhl_lt_rhl = EI_INIT; 279 static expert_field ei_geonw_scc_too_big = EI_INIT; 280 static expert_field ei_geonw_analysis_duplicate = EI_INIT; 281 static expert_field ei_geonw_resp_not_found = EI_INIT; 282 static expert_field ei_geonw_out_of_range = EI_INIT; 283 static expert_field ei_geonw_payload_len = EI_INIT; 284 285 static dissector_table_t geonw_subdissector_table; 286 static dissector_table_t ssp_subdissector_table; 287 static dissector_table_t btpa_subdissector_table; 288 static dissector_table_t btpb_subdissector_table; 289 290 static const value_string ch_header_type_names[] = { 291 { HTST_BEACON, "Beacon" }, 292 { HTST_GEOUNICAST, "Geo Unicast" }, 293 { HTST_GAC_CIRCLE, "Geo-scoped Anycast Circular area" }, 294 { HTST_GAC_RECT, "Geo-scoped Anycast Rectangular area" }, 295 { HTST_GAC_ELLIPSE, "Geo-scoped Anycast Ellipsoidal area" }, 296 { HTST_GBC_CIRCLE, "Geo-scoped Broadcast Circular area" }, 297 { HTST_GBC_RECT, "Geo-scoped Broadcast Rectangular area" }, 298 { HTST_GBC_ELLIPSE, "Geo-scoped Broadcast Ellipsoidal area" }, 299 { HTST_TSB_SINGLE, "Topologically-scoped broadcast Single-hop broadcast (SHB)" }, 300 { HTST_TSB_MULT, "Topologically-scoped broadcast Multi-hop broadcast (TSB)" }, 301 { HTST_LS_REQUEST, "Location Service Request" }, 302 { HTST_LS_REPLY, "Location Service Reply" }, 303 { 0x00, NULL} 304 }; 305 306 static dissector_handle_t ieee1609dot2_handle; 307 static dissector_handle_t geonw_handle; 308 static dissector_handle_t btpa_handle; 309 static dissector_handle_t btpb_handle; 310 static dissector_handle_t ipv6_handle; 311 312 static heur_dissector_list_t btpa_heur_subdissector_list; 313 static heur_dissector_list_t btpb_heur_subdissector_list; 314 315 /* 316 * Basic Transport Protocol A dissector 317 */ 318 static int 319 dissect_btpa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) 320 { 321 heur_dtbl_entry_t *hdtbl_entry; 322 int low_port, high_port; 323 int dst_port, src_port; 324 proto_item *hidden_item; 325 struct btpaheader *btpah; 326 327 btpah = wmem_new0(pinfo->pool, struct btpaheader); 328 329 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BTPA"); 330 /* Clear out stuff in the info column */ 331 col_clear(pinfo->cinfo,COL_INFO); 332 333 proto_item *ti = proto_tree_add_item(tree, proto_btpa, tvb, 0, 4, ENC_NA); 334 proto_tree *btpa_tree = proto_item_add_subtree(ti, ett_btpa); 335 336 proto_tree_add_item_ret_uint(btpa_tree, hf_btpa_dstport, tvb, 0, 2, ENC_BIG_ENDIAN, &dst_port); 337 proto_tree_add_item_ret_uint(btpa_tree, hf_btpa_srcport, tvb, 2, 2, ENC_BIG_ENDIAN, &src_port); 338 339 pinfo->srcport = src_port; 340 pinfo->destport = dst_port; 341 342 col_append_ports(pinfo->cinfo, COL_INFO, PT_NONE, pinfo->srcport, pinfo->destport); 343 344 // Add hidden port field 345 hidden_item = proto_tree_add_item(btpa_tree, hf_btpa_port, tvb, 0, 2, ENC_BIG_ENDIAN); 346 proto_item_set_hidden(hidden_item); 347 hidden_item = proto_tree_add_item(btpa_tree, hf_btpa_port, tvb, 2, 2, ENC_BIG_ENDIAN); 348 proto_item_set_hidden(hidden_item); 349 350 btpah->btp_psrc = src_port; 351 btpah->btp_pdst = dst_port; 352 copy_address_shallow(&btpah->gnw_src, &pinfo->src); 353 copy_address_shallow(&btpah->gnw_dst, &pinfo->dst); 354 tap_queue_packet(btpa_tap, pinfo, btpah); 355 356 tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, 4); 357 358 if (have_tap_listener(btpa_follow_tap)) 359 tap_queue_packet(btpa_follow_tap, pinfo, next_tvb); 360 361 if (src_port > dst_port) { 362 low_port = dst_port; 363 high_port = src_port; 364 } else { 365 low_port = src_port; 366 high_port = dst_port; 367 } 368 369 if (dissector_try_uint_new(btpa_subdissector_table, low_port, next_tvb, pinfo, tree, TRUE, NULL)) 370 return tvb_captured_length(tvb); 371 372 if (dissector_try_uint_new(btpa_subdissector_table, high_port, next_tvb, pinfo, tree, TRUE, NULL)) 373 return tvb_captured_length(tvb); 374 375 if (dissector_try_heuristic(btpa_heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) 376 return tvb_captured_length(tvb); 377 378 call_data_dissector(next_tvb, pinfo, tree); 379 return tvb_captured_length(tvb); 380 } 381 382 /* 383 * Basic Transport Protocol B dissector 384 */ 385 static int 386 dissect_btpb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) 387 { 388 heur_dtbl_entry_t *hdtbl_entry; 389 guint32 dst_port; 390 guint32 dst_info; 391 struct btpbheader *btpbh; 392 393 btpbh = wmem_new0(pinfo->pool, struct btpbheader); 394 395 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BTPB"); 396 /* Clear out stuff in the info column */ 397 col_clear(pinfo->cinfo,COL_INFO); 398 399 proto_item *ti = proto_tree_add_item(tree, proto_btpb, tvb, 0, 4, ENC_NA); 400 proto_tree *btpb_tree = proto_item_add_subtree(ti, ett_btpb); 401 402 proto_tree_add_item_ret_uint(btpb_tree, hf_btpb_dstport, tvb, 0, 2, ENC_BIG_ENDIAN, &dst_port); 403 proto_tree_add_item_ret_uint(btpb_tree, hf_btpb_dstport_info, tvb, 2, 2, ENC_BIG_ENDIAN, &dst_info); 404 405 pinfo->destport = dst_port; 406 407 col_append_fstr(pinfo->cinfo, COL_INFO, " " UTF8_RIGHTWARDS_ARROW " %u", dst_port); 408 409 btpbh->btp_pdst = dst_port; 410 btpbh->btp_idst = dst_info; 411 copy_address_shallow(&btpbh->gnw_src, &pinfo->src); 412 copy_address_shallow(&btpbh->gnw_dst, &pinfo->dst); 413 tap_queue_packet(btpb_tap, pinfo, btpbh); 414 415 tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, 4); 416 417 if (have_tap_listener(btpb_follow_tap)) 418 tap_queue_packet(btpb_follow_tap, pinfo, next_tvb); 419 420 if (dissector_try_uint_new(btpb_subdissector_table, dst_port, next_tvb, pinfo, tree, TRUE, NULL)) { 421 return tvb_captured_length(tvb); 422 } 423 if (dissector_try_heuristic(btpa_heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) { 424 return tvb_captured_length(tvb); 425 } 426 427 call_data_dissector(next_tvb, pinfo, tree); 428 return tvb_captured_length(tvb); 429 } 430 431 /* 432 * =========================================================================== 433 * GeoNetworking dissector 434 * =========================================================================== 435 */ 436 437 typedef struct _geonw_transaction_t { 438 guint32 rqst_frame; 439 guint32 resp_frame; 440 nstime_t rqst_time; 441 nstime_t resp_time; 442 } geonw_transaction_t; 443 444 typedef struct _geonw_conv_info_t { 445 wmem_stack_t *unmatched_pdus; 446 wmem_tree_t *matched_pdus; 447 } geonw_conv_info_t; 448 449 static const gchar * get_geonw_name(const guint8 *addr); 450 static const gchar* geonw_name_resolution_str(const address* addr); 451 static int geonw_name_resolution_len(void); 452 453 static geonw_transaction_t *transaction_start(packet_info * pinfo, proto_tree * tree); 454 static geonw_transaction_t *transaction_end(packet_info * pinfo, proto_tree * tree); 455 456 static gboolean geonw_analyze_seq = TRUE; 457 458 /* 459 * GeoNetworking Address Type 460 */ 461 462 /* Adapter from ethernet and ipv4 Address Type code */ 463 struct hashgeonw; 464 typedef struct hashgeonw hashgeonw_t; 465 466 struct hashgeonw { 467 guint status; 468 guint8 addr[8]; 469 char hexaddr[28]; 470 char resolved_name[MAXNAMELEN]; 471 472 // Node follow up used for duplication detection 473 guint32 timestamp; 474 guint32 sequence_number; 475 }; 476 477 478 static int 479 geonw_str_len(const address* addr _U_) 480 { 481 // (0/1)'.'(0..31)'.'(0..1023)'.'{eth} 482 return 28; 483 } 484 485 static int 486 _geonw_to_str(const guint8* addrdata, gchar *buf, int buf_len _U_) 487 { 488 address eth_addr; 489 490 // Initial or Manual 491 if (addrdata[0] & 0x80) 492 *buf++ = '1'; 493 else 494 *buf++ = '0'; 495 *buf++ = '.'; 496 // Station Type 497 guint32_to_str_buf((addrdata[0] & 0x7C) >> 2, buf, 26); 498 buf += (unsigned) strlen(buf); 499 *buf++ = '.'; 500 // Country Code 501 guint32_to_str_buf(((guint32)(addrdata[0] & 0x03) << 8) + addrdata[1], buf, 23); // > 23 502 buf += (unsigned) strlen(buf); 503 *buf++ = '.'; 504 // LL_ADDR 505 set_address(ð_addr, AT_ETHER, 6, &(addrdata[2])); 506 ether_to_str(ð_addr, buf, 18); 507 508 return 28; 509 } 510 511 static int 512 geonw_to_str(const address* addr, gchar *buf, int buf_len _U_) 513 { 514 return _geonw_to_str((const guint8 *)addr->data, buf, buf_len); 515 } 516 517 static const char* 518 geonw_col_filter_str(const address* addr _U_, gboolean is_src) 519 { 520 if (is_src) 521 return "geonw.src_pos.addr"; 522 523 return "geonw.dst_pos.addr"; 524 } 525 526 static int 527 geonw_len(void) 528 { 529 return 8; 530 } 531 532 static guint 533 geonw_addr_hash(gconstpointer key) 534 { 535 return wmem_strong_hash((const guint8 *)key, 8); 536 } 537 538 static gboolean 539 geonw_addr_cmp(gconstpointer a, gconstpointer b) 540 { 541 return (memcmp(a, b, 8) == 0); 542 } 543 544 /* 545 * These two value_string are used for address resolv: 546 */ 547 static const value_string itss_type_small_names[] = { 548 { 0, "unk" }, 549 { 1, "ped" }, 550 { 2, "cyc" }, 551 { 3, "mop" }, 552 { 4, "mot" }, 553 { 5, "pas" }, 554 { 6, "bus" }, 555 { 7, "ltr" }, 556 { 8, "htr" }, 557 { 9, "trl" }, 558 { 10, "spe" }, 559 { 11, "trm" }, 560 { 15, "rsu" }, 561 { 0, NULL} 562 }; 563 564 /* Resolve geonetworking address */ 565 static hashgeonw_t * 566 geonw_addr_resolve(hashgeonw_t *tp) { 567 const guint8 *addr = tp->addr; 568 guint16 val; 569 char *rname = tp->resolved_name; 570 address eth_addr; 571 guint8 l1, l2; 572 573 // Initial or Manual 574 if (addr[0] & 0x80) 575 *rname++ = 'm'; 576 else 577 *rname++ = 'i'; 578 *rname++ = '.'; 579 // Station Type 580 val = (addr[0] & 0x7C) >> 2; 581 const char *string = try_val_to_str(val, itss_type_small_names); 582 if (string == NULL) { 583 guint32_to_str_buf(val, rname, MAXNAMELEN-2); 584 l1 = (guint8) strlen(rname); 585 } 586 else { 587 l1 = (guint8) g_strlcpy(rname, string, MAXNAMELEN-2); 588 } 589 rname += l1; 590 *rname++ = '.'; 591 // Country Code 592 val = ((guint32)(addr[0] & 0x03) << 8) + addr[1]; 593 string = try_val_to_str(val, E164_ISO3166_country_code_short_value); 594 if (string == NULL) { 595 guint32_to_str_buf(val, rname, MAXNAMELEN-12); 596 l2 = (guint8) strlen(rname); 597 } 598 else { 599 l2 = (guint8) g_strlcpy(rname, string, MAXNAMELEN-l1-3); 600 } 601 rname += l2; 602 //l1 += l2; 603 *rname++ = '.'; 604 // LL_ADDR 605 set_address(ð_addr, AT_ETHER, 6, &(addr[2])); 606 ether_to_str(ð_addr, rname, 18); 607 // We could use ether_name_resolution_str: 608 // (void) g_strlcpy(rname, ether_name_resolution_str(ð_addr), MAXNAMELEN-l1-4); 609 610 tp->status = 1; 611 612 return tp; 613 } 614 615 static hashgeonw_t * 616 geonw_hash_new_entry(const guint8 *addr, gboolean resolve) 617 { 618 hashgeonw_t *tp; 619 620 tp = wmem_new(wmem_file_scope(), hashgeonw_t); 621 memcpy(tp->addr, addr, sizeof(tp->addr)); 622 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */ 623 _geonw_to_str(addr, tp->hexaddr, 28); 624 tp->resolved_name[0] = '\0'; 625 tp->status = 0; 626 tp->timestamp = 0; 627 tp->sequence_number = SN_MAX + 1; 628 629 if (resolve) 630 geonw_addr_resolve(tp); 631 632 wmem_map_insert(geonw_hashtable, tp->addr, tp); 633 634 return tp; 635 } /* geonw_hash_new_entry */ 636 637 static hashgeonw_t * 638 geonw_name_lookup(const guint8 *addr, gboolean resolve) 639 { 640 hashgeonw_t *tp; 641 642 tp = (hashgeonw_t *)wmem_map_lookup(geonw_hashtable, addr); 643 644 if (tp == NULL) { 645 tp = geonw_hash_new_entry(addr, resolve); 646 } else { 647 if (resolve && !tp->status) { 648 geonw_addr_resolve(tp); /* Found but needs to be resolved */ 649 } 650 } 651 652 return tp; 653 654 } /* geonw_name_lookup */ 655 656 const gchar * 657 get_geonw_name(const guint8 *addr) 658 { 659 hashgeonw_t *tp; 660 gboolean resolve = gbl_resolv_flags.network_name; 661 662 tp = geonw_name_lookup(addr, resolve); 663 664 return resolve ? tp->resolved_name : tp->hexaddr; 665 666 } /* get_geonw_name */ 667 668 const gchar* geonw_name_resolution_str(const address* addr) 669 { 670 return get_geonw_name((const guint8 *)addr->data); 671 } 672 673 int geonw_name_resolution_len(void) 674 { 675 return MAX_ADDR_STR_LEN; /* XXX - This can be lower */ 676 } 677 678 /* 679 * Conversations for GeoNetworking 680 */ 681 682 /* Adapted from ICMP echo request/reply code */ 683 684 /* GeoNw LS request/reply transaction statistics ... */ 685 static geonw_transaction_t *transaction_start(packet_info * pinfo, proto_tree * tree) 686 { 687 conversation_t *conversation; 688 geonw_conv_info_t *geonw_info; 689 geonw_transaction_t *geonw_trans; 690 wmem_tree_key_t geonw_key[3]; 691 proto_item *it; 692 693 /* Handle the conversation tracking */ 694 conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype), HT_LS, HT_LS, 0); 695 if (conversation == NULL) { 696 /* No, this is a new conversation. */ 697 conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype), HT_LS, HT_LS, 0); 698 } 699 geonw_info = (geonw_conv_info_t *)conversation_get_proto_data(conversation, proto_geonw); 700 if (geonw_info == NULL) { 701 geonw_info = wmem_new(wmem_file_scope(), geonw_conv_info_t); 702 geonw_info->unmatched_pdus = wmem_stack_new(wmem_file_scope()); 703 geonw_info->matched_pdus = wmem_tree_new(wmem_file_scope()); 704 conversation_add_proto_data(conversation, proto_geonw, geonw_info); 705 } 706 707 if (!PINFO_FD_VISITED(pinfo)) { 708 /* this is a new request, create a new transaction structure and map it to the 709 unmatched table 710 */ 711 geonw_trans = wmem_new(wmem_file_scope(), geonw_transaction_t); 712 geonw_trans->rqst_frame = pinfo->num; 713 geonw_trans->resp_frame = 0; 714 geonw_trans->rqst_time = pinfo->abs_ts; 715 nstime_set_zero(&geonw_trans->resp_time); 716 wmem_stack_push(geonw_info->unmatched_pdus, (void *) geonw_trans); 717 } else { 718 /* Already visited this frame */ 719 guint32 frame_num = pinfo->num; 720 721 geonw_key[0].length = 1; 722 geonw_key[0].key = &frame_num; 723 geonw_key[1].length = 0; 724 geonw_key[1].key = NULL; 725 726 geonw_trans = (geonw_transaction_t *)wmem_tree_lookup32_array(geonw_info->matched_pdus, geonw_key); 727 } 728 if (geonw_trans == NULL) { 729 if (PINFO_FD_VISITED(pinfo)) { 730 /* No response found - add field and expert info */ 731 it = proto_tree_add_item(tree, hf_geonw_no_resp, NULL, 0, 0, ENC_NA); 732 proto_item_set_generated(it); 733 734 col_append_fstr(pinfo->cinfo, COL_INFO, " (no response found!)"); 735 736 /* Expert info. */ 737 expert_add_info_format(pinfo, it, &ei_geonw_resp_not_found, "No response seen to LS Request"); 738 } 739 740 return NULL; 741 } 742 743 /* Print state tracking in the tree */ 744 if (geonw_trans->resp_frame) { 745 it = proto_tree_add_uint(tree, hf_geonw_resp_in, NULL, 0, 0, geonw_trans->resp_frame); 746 proto_item_set_generated(it); 747 748 col_append_frame_number(pinfo, COL_INFO, " (reply in %u)", geonw_trans->resp_frame); 749 } 750 751 return geonw_trans; 752 753 } /* transaction_start() */ 754 755 static geonw_transaction_t *transaction_end(packet_info * pinfo, proto_tree * tree) 756 { 757 conversation_t *conversation; 758 geonw_conv_info_t *geonw_info; 759 geonw_transaction_t *geonw_trans; 760 wmem_tree_key_t geonw_key[3]; 761 proto_item *it; 762 nstime_t ns; 763 double resp_time; 764 765 conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype), HT_LS, HT_LS, 0); 766 if (conversation == NULL) { 767 return NULL; 768 } 769 770 geonw_info = (geonw_conv_info_t *)conversation_get_proto_data(conversation, proto_geonw); 771 if (geonw_info == NULL) { 772 return NULL; 773 } 774 775 if (!PINFO_FD_VISITED(pinfo)) { 776 guint32 frame_num; 777 778 geonw_trans = (geonw_transaction_t *)wmem_stack_peek(geonw_info->unmatched_pdus); 779 if (geonw_trans == NULL) { 780 return NULL; 781 } 782 783 /* we have already seen this response, or an identical one */ 784 if (geonw_trans->resp_frame != 0) { 785 return NULL; 786 } 787 788 geonw_trans->resp_frame = pinfo->num; 789 790 /* we found a match. Add entries to the matched table for both request and reply frames 791 */ 792 geonw_key[0].length = 1; 793 geonw_key[0].key = &frame_num; 794 geonw_key[1].length = 0; 795 geonw_key[1].key = NULL; 796 797 frame_num = geonw_trans->rqst_frame; 798 wmem_tree_insert32_array(geonw_info->matched_pdus, geonw_key, (void *) geonw_trans); 799 800 frame_num = geonw_trans->resp_frame; 801 wmem_tree_insert32_array(geonw_info->matched_pdus, geonw_key, (void *) geonw_trans); 802 } else { 803 /* Already visited this frame */ 804 guint32 frame_num = pinfo->num; 805 806 geonw_key[0].length = 1; 807 geonw_key[0].key = &frame_num; 808 geonw_key[1].length = 0; 809 geonw_key[1].key = NULL; 810 811 geonw_trans = (geonw_transaction_t *)wmem_tree_lookup32_array(geonw_info->matched_pdus, geonw_key); 812 813 if (geonw_trans == NULL) { 814 return NULL; 815 } 816 } 817 818 819 it = proto_tree_add_uint(tree, hf_geonw_resp_to, NULL, 0, 0, geonw_trans->rqst_frame); 820 proto_item_set_generated(it); 821 822 nstime_delta(&ns, &pinfo->abs_ts, &geonw_trans->rqst_time); 823 geonw_trans->resp_time = ns; 824 resp_time = nstime_to_msec(&ns); 825 it = proto_tree_add_double_format_value(tree, hf_geonw_resptime, NULL, 0, 0, resp_time, "%.3f ms", resp_time); 826 proto_item_set_generated(it); 827 828 col_append_frame_number(pinfo, COL_INFO, " (request in %d)", geonw_trans->rqst_frame); 829 830 return geonw_trans; 831 832 } /* transaction_end() */ 833 834 // Adapted from TCP sequence number analysis 835 836 // Conversation data 837 struct geonw_analysis { 838 // Node follow up used for duplication detection 839 guint32 timestamp; 840 guint16 sequence_number; 841 }; 842 843 /* 844 * Secured geonetworking 845 */ 846 847 static int hf_geonw_sec = -1; 848 static int hf_sgeonw_version = -1; 849 static int hf_sgeonw_profile = -1; 850 static int hf_sgeonw_hdr = -1; 851 static int hf_sgeonw_pl = -1; 852 static int hf_sgeonw_trl = -1; 853 static int hf_sgeonw_var_len = -1; 854 static int hf_sgeonw_var_len_det = -1; 855 static int hf_sgeonw_var_len_val = -1; 856 static int hf_sgeonw_header_field = -1; 857 static int hf_sgeonw_header_field_type_v1 = -1; 858 static int hf_sgeonw_header_field_type_v2 = -1; 859 static int hf_sgeonw_opaque = -1; 860 861 static int hf_sgeonw_payload_field = -1; 862 static int hf_sgeonw_payload_field_type = -1; 863 864 static int hf_sgeonw_trailer_field = -1; 865 static int hf_sgeonw_trailer_field_type = -1; 866 867 static int hf_sgeonw_certificate = -1; 868 static int hf_sgeonw_encryption_parameter = -1; 869 static int hf_sgeonw_signature = -1; 870 static int hf_sgeonw_subject_info = -1; 871 static int hf_sgeonw_subject_attribute = -1; 872 873 static int hf_sgeonw_intx = -1; 874 static int hf_sgeonw_time64 = -1; 875 static int hf_sgeonw_conf = -1; 876 static int hf_sgeonw_time32 = -1; 877 static int hf_sgeonw_lat = -1; 878 static int hf_sgeonw_lon = -1; 879 static int hf_sgeonw_elev = -1; 880 static int hf_sgeonw_hashedid3 = -1; 881 static int hf_sgeonw_hashedid8 = -1; 882 static int hf_sgeonw_duration = -1; 883 static int hf_sgeonw_duration_unit = -1; 884 static int hf_sgeonw_duration_value = -1; 885 static int hf_sgeonw_encryption_parameter_nonce = -1; 886 887 static int hf_sgeonw_msg_id = -1; 888 static int hf_sgeonw_app_id = -1; 889 890 static int ett_geonw_sec = -1; 891 static int ett_sgeonw_hdr = -1; 892 static int ett_sgeonw_field = -1; 893 static int ett_sgeonw_var_len = -1; 894 static int ett_sgeonw_intx = -1; 895 static int ett_sgeonw_duration = -1; 896 static int ett_sgeonw_encryption_parameter = -1; 897 static int ett_sgeonw_signature = -1; 898 static int ett_sgeonw_subject_info = -1; 899 static int ett_sgeonw_subject_attribute = -1; 900 static int ett_sgeonw_ssp = -1; 901 902 static expert_field ei_sgeonw_len_unsupported = EI_INIT; 903 static expert_field ei_sgeonw_len_too_long = EI_INIT; 904 static expert_field ei_sgeonw_subj_info_too_long = EI_INIT; 905 static expert_field ei_sgeonw_ssp_too_long = EI_INIT; 906 static expert_field ei_sgeonw_bogus = EI_INIT; 907 908 typedef enum { 909 generation_time = 0, 910 generation_time_confidence = 1, 911 expiration = 2, 912 generation_location = 3, 913 request_unrecognized_certificate = 4, 914 message_type = 5, 915 signer_info = 128, 916 recipient_info = 129, 917 encryption_parameters = 130, 918 919 last_hdr_type = (2<<8)-1 920 } HeaderFieldType; 921 922 static const value_string header_field_type_v1_names[] = { 923 { generation_time, "Generation time" }, 924 { generation_time_confidence, "Generation time confidence" }, 925 { expiration, "Expiration" }, 926 { generation_location, "Generation location" }, 927 { request_unrecognized_certificate, "Request unrecognized certificate" }, 928 { message_type, "Message type" }, 929 { signer_info, "Signer info" }, 930 { recipient_info, "Recipient info" }, 931 { encryption_parameters, "Encryption parameters" }, 932 { 0x00, NULL} 933 }; 934 935 static const value_string header_field_type_v2_names[] = { 936 { generation_time, "Generation time" }, 937 { generation_time_confidence, "Generation time standard deviation" }, 938 { expiration, "Expiration" }, 939 { generation_location, "Generation location" }, 940 { request_unrecognized_certificate, "Request unrecognized certificate" }, 941 { message_type, "ITS Application ID" }, // Change in definition 942 { signer_info, "Signer info" }, 943 { recipient_info, "Encryption parameters" }, // Change in definition 944 { encryption_parameters, "Recipient info" }, // Change in definition 945 { 0x00, NULL} 946 }; 947 948 typedef enum { 949 unsecured = 0, 950 signed_pl = 1, 951 encrypted = 2, 952 signed_external = 3, 953 signed_and_encrypted = 4, 954 955 last_pl_type = (2<<8)-1 956 } PayloadType; 957 958 static const value_string payload_field_type_names[] = { 959 { unsecured, "Unsecured" }, 960 { signed_pl, "Signed" }, 961 { encrypted, "Encrypted" }, 962 { signed_external, "Signed external" }, 963 { signed_and_encrypted, "Signed and encrypted" }, 964 { 0, NULL }, 965 }; 966 967 typedef enum { 968 signature = 1, 969 970 last_trl_type = (2<<8)-1 971 } TrailerFieldType; 972 973 static const value_string trailer_field_type_names[] = { 974 { signature, "signature" }, 975 { 0, NULL }, 976 }; 977 978 static int hf_sgeonw_signer_info = -1; 979 static int hf_sgeonw_signer_info_type = -1; 980 981 typedef enum { 982 self = 0, 983 certificate_digest_with_ecdsap256 = 1, 984 certificate = 2, 985 certificate_chain = 3, 986 certificate_digest_with_other_algorithm = 4, 987 988 //reserved(240..255), 989 990 last_sif_type = (2<<8)-1 991 } SignerInfoType; 992 993 static const value_string signer_info_type_names[] = { 994 { self, "Self signed" }, 995 { certificate_digest_with_ecdsap256, "Certificate digest with ecdsap256" }, 996 { certificate, "Certificate" }, 997 { certificate_chain, "Certificate chain" }, 998 { certificate_digest_with_other_algorithm, "Certificate digest with other algorithm" }, 999 { 0, NULL }, 1000 }; 1001 1002 static int hf_sgeonw_public_key = -1; 1003 static int ett_sgeonw_public_key = -1; 1004 static int hf_sgeonw_public_key_algorithm = -1; 1005 static int hf_sgeonw_ecdsasignature_s = -1; 1006 1007 typedef enum { 1008 ecdsa_nistp256_with_sha256 = 0, 1009 ecies_nistp256 = 1, 1010 1011 // reserved(240..255), 1012 1013 last_pubkey_algo = (2<<8)-1 1014 } PublicKeyAlgorithm; 1015 1016 static const value_string public_key_algorithm_names[] = { 1017 { ecdsa_nistp256_with_sha256, "ECDSA nistp256 with SHA256" }, 1018 { ecies_nistp256, "ECIES nistp256" }, 1019 { 0, NULL }, 1020 }; 1021 1022 static const int etsits103097_table_2[] = { 1023 32, // ecdsa_nistp256_with_sha256(0) 1024 32 // ecies_nistp256(1) 1025 }; 1026 1027 static int hf_sgeonw_symmetric_algorithm = -1; 1028 1029 typedef enum { 1030 aes_128_ccm = 0, 1031 // reserved(240..255), 1032 last_sym_algo = (2<<8)-1 1033 } SymmetricAlgorithm; 1034 1035 static const value_string symmetric_algorithm_names[] = { 1036 { aes_128_ccm, "aes_128_ccm" }, 1037 { 0, NULL }, 1038 }; 1039 1040 static const int etsits103097_table_4[] = { 1041 16 // aes_128_ccm(0) 1042 }; 1043 1044 static int hf_sgeonw_region_type = -1; 1045 static int hf_sgeonw_radius = -1; 1046 1047 typedef enum { 1048 none = 0, 1049 circle = 1, 1050 rectangle = 2, 1051 polygon = 3, 1052 id = 4, 1053 1054 // reserved(240..255), 1055 1056 last_regiontype = (2<<8)-1 1057 } RegionType; 1058 1059 static const value_string region_type_names[] = { 1060 { none, "none" }, 1061 { circle, "circle" }, 1062 { rectangle, "rectangle" }, 1063 { polygon, "polygon" }, 1064 { id, "id" }, 1065 { 0, NULL }, 1066 }; 1067 1068 static int hf_sgeonw_region_dictionary = -1; 1069 static int hf_sgeonw_region_identifier = -1; 1070 static int hf_sgeonw_local_region = -1; 1071 1072 typedef enum { 1073 iso_3166_1 = 0, 1074 un_stats = 1, 1075 1076 last_regiondictionary = (2<<8)-1 1077 } RegionDictionary; 1078 1079 static const value_string region_dictionary_names[] = { 1080 { iso_3166_1, "Numeric country codes as in ISO 3166-1" }, 1081 { un_stats, "Defined by UN Statistics Division" }, 1082 { 0, NULL }, 1083 }; 1084 1085 static int hf_sgeonw_subject_type = -1; 1086 1087 typedef enum { 1088 enrollment_credential = 0, 1089 authorization_ticket = 1, 1090 authorization_authority = 2, 1091 enrollment_authority = 3, 1092 root_ca = 4, 1093 crl_signer = 5, 1094 1095 last_subjecttype = (2<<8)-1 1096 } SubjectType; 1097 1098 static const value_string subject_type_names[] = { 1099 { enrollment_credential, "enrollment_credential" }, 1100 { authorization_ticket, "authorization_ticket" }, 1101 { authorization_authority, "authorization_authority" }, 1102 { enrollment_authority, "enrollment_authority" }, 1103 { root_ca, "root_ca" }, 1104 { crl_signer, "crl_signer" }, 1105 1106 { 0, NULL }, 1107 }; 1108 1109 static int hf_sgeonw_subject_attribute_type_v1 = -1; 1110 static int hf_sgeonw_subject_attribute_type_v2 = -1; 1111 1112 typedef enum { 1113 verification_key = 0, 1114 encryption_key = 1, 1115 assurance_level = 2, 1116 reconstruction_value = 3, 1117 its_aid_list = 32, 1118 its_aid_ssp_list = 33, 1119 priority_its_aid_list = 34, 1120 priority_ssp_list = 35, 1121 1122 last_subjectattributetype = (2<<8)-1 1123 } SubjectAttributeType; 1124 1125 static const value_string subject_attribute_type_v1_names[] = { 1126 { verification_key, "verification_key" }, 1127 { encryption_key, "encryption_key" }, 1128 { assurance_level, "assurance_level" }, 1129 { reconstruction_value, "reconstruction_value" }, 1130 { its_aid_list, "its_aid_list" }, 1131 { its_aid_ssp_list, "its_aid_ssp_list" }, 1132 { priority_its_aid_list, "priority_its_aid_list" }, 1133 { priority_ssp_list, "priority_ssp_list" }, 1134 { 0, NULL }, 1135 }; 1136 1137 static const value_string subject_attribute_type_v2_names[] = { 1138 { verification_key, "verification_key" }, 1139 { encryption_key, "encryption_key" }, 1140 { assurance_level, "assurance_level" }, 1141 { reconstruction_value, "reconstruction_value" }, 1142 { its_aid_list, "its_aid_list" }, 1143 { its_aid_ssp_list, "its_aid_ssp_list" }, 1144 { 0, NULL }, 1145 }; 1146 1147 static int hf_sgeonw_validity_restriction_type = -1; 1148 1149 typedef enum { 1150 time_end = 0, 1151 time_start_and_end = 1, 1152 time_start_and_duration = 2, 1153 region = 3, 1154 1155 last_validityrestrictiontype = (2<<8)-1 1156 } ValidityRestrictionType; 1157 1158 static const value_string validity_restriction_type_names[] = { 1159 { time_end, "time_end" }, 1160 { time_start_and_end, "time_start_and_end" }, 1161 { time_start_and_duration, "time_start_and_duration" }, 1162 { region, "region" }, 1163 1164 { 0, NULL }, 1165 }; 1166 1167 static int hf_sgeonw_eccpoint = -1; 1168 static int ett_sgeonw_eccpoint = -1; 1169 static int hf_sgeonw_eccpoint_type = -1; 1170 static int hf_sgeonw_eccpoint_x = -1; 1171 static int hf_sgeonw_eccpoint_y = -1; 1172 1173 typedef enum { 1174 x_coordinate_only = 0, 1175 compressed_lsb_y_0 = 2, 1176 compressed_lsb_y_1 = 3, 1177 uncompressed = 4, 1178 1179 last_eccpointtype = (2<<8)-1 1180 } EccPointType; 1181 1182 static const value_string eccpoint_type_names[] = { 1183 { x_coordinate_only, "x_coordinate_only" }, 1184 { compressed_lsb_y_0, "compressed_lsb_y_0" }, 1185 { compressed_lsb_y_1, "compressed_lsb_y_1" }, 1186 { uncompressed, "uncompressed" }, 1187 1188 { 0, NULL }, 1189 }; 1190 1191 // Dissects a length and returns the value 1192 // The encoding of the length shall use at most 7 bits set to 1. We support only 3... 0xfffffff should be enough though to encode a length 1193 static guint32 1194 dissect_sec_var_len(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1195 { 1196 guint32 tmp_val; 1197 guint32 var_len; 1198 guint32 mask; 1199 gint start = *offset; 1200 proto_item *ti; 1201 proto_tree *subtree; 1202 1203 // Determine length 1204 var_len = tvb_get_guint8(tvb, *offset); 1205 *offset+=1; 1206 mask = 0x80; 1207 while(mask && (var_len & mask)) { 1208 tmp_val = tvb_get_guint8(tvb, *offset); 1209 *offset += 1; 1210 var_len = ((var_len & ~mask) << 8) + tmp_val; 1211 mask <<= 7; 1212 } 1213 ti = proto_tree_add_item(tree, hf_sgeonw_var_len, tvb, start, (*offset) - start, ENC_NA); // Length cannot be determined now 1214 subtree = proto_item_add_subtree(ti, ett_sgeonw_var_len); 1215 proto_tree_add_bits_item(subtree, hf_sgeonw_var_len_det, tvb, start << 3, (*offset) - start, ENC_NA); 1216 proto_tree_add_uint_bits_format_value(subtree, hf_sgeonw_var_len_val, tvb, (start << 3) + (*offset) - start, (((*offset) - start) << 3) - ((*offset) - start),var_len,ENC_BIG_ENDIAN,"%u",var_len); 1217 // EI Error if !mask (more than 32 bits) 1218 if (!mask) 1219 expert_add_info(pinfo, ti, &ei_sgeonw_len_unsupported); 1220 return var_len; 1221 } 1222 1223 // IntX 1224 static int 1225 dissect_sec_intx(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, int hf, guint32 *ret) 1226 { 1227 //guint8 var_len = 1; 1228 guint64 tmp_val; 1229 guint64 mask; 1230 gint start = *offset; 1231 proto_item *ti; 1232 proto_tree *subtree; 1233 1234 // Determine length 1235 tmp_val = tvb_get_guint8(tvb, *offset); 1236 *offset+=1; 1237 mask = 0x80; 1238 while(mask && (tmp_val & mask)) { 1239 tmp_val &= ~mask; 1240 tmp_val <<= 8; 1241 tmp_val += tvb_get_guint8(tvb, *offset); 1242 *offset += 1; 1243 mask <<= 7; 1244 //var_len++; 1245 } 1246 ti = proto_tree_add_item(tree, hf_sgeonw_intx, tvb, start, (*offset) - start, ENC_NA); 1247 subtree = proto_item_add_subtree(ti, ett_sgeonw_intx); 1248 proto_tree_add_bits_item(subtree, hf_sgeonw_var_len_det, tvb, start << 3, (*offset) - start, ENC_NA); 1249 if ((hf != hf_sgeonw_app_id) || ((*offset) - start) > 4) { 1250 proto_tree_add_uint64_bits_format_value(subtree, hf, tvb, (start << 3) + (*offset) - start, 1251 (((*offset) - start) << 3) - ((*offset) - start), tmp_val, ENC_BIG_ENDIAN, "%" G_GUINT64_FORMAT, tmp_val); 1252 } 1253 else { 1254 proto_tree_add_uint_bits_format_value(subtree, hf, tvb, (start << 3) + (*offset) - start, 1255 (((*offset) - start) << 3) - ((*offset) - start), (guint32)tmp_val, ENC_BIG_ENDIAN, "%s(%u)", val64_to_str_const(tmp_val, ieee1609dot2_Psid_vals, "Unknown") , (guint32)tmp_val); 1256 } 1257 // ETSI TS 103 097 V1.2.1: The encoding of the length shall use at most 7 bits set to 1. 1258 if (!mask) 1259 // EI Error if more than 7 1260 expert_add_info(pinfo, ti, &ei_sgeonw_len_too_long); 1261 if (ret) { 1262 DISSECTOR_ASSERT(!(tmp_val & 0xffffffff00000000)); 1263 *ret = (guint32) tmp_val; 1264 } 1265 1266 return (*offset) - start; 1267 } 1268 1269 static int 1270 dissect_sec_eccpoint(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, PublicKeyAlgorithm algorithm) 1271 { 1272 guint32 tmp_val; 1273 guint32 param_len; 1274 guint32 start = *offset; 1275 proto_item *ti; 1276 proto_tree *subtree; 1277 int field_size = etsits103097_table_2[algorithm]; 1278 1279 ti = proto_tree_add_item(tree, hf_sgeonw_eccpoint, tvb, *offset, 0, ENC_NA); 1280 subtree = proto_item_add_subtree(ti, ett_sgeonw_eccpoint); 1281 proto_tree_add_item_ret_uint(subtree, hf_sgeonw_eccpoint_type, tvb, *offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1282 // Opaque[field_size] 1283 proto_tree_add_item(subtree, hf_sgeonw_eccpoint_x, tvb, 1+(*offset), field_size, ENC_NA); 1284 *offset += field_size+1; 1285 switch(tmp_val) { 1286 case x_coordinate_only: 1287 case compressed_lsb_y_0: 1288 case compressed_lsb_y_1: 1289 break; 1290 case uncompressed: 1291 // Opaque[field_size] 1292 proto_tree_add_item(subtree, hf_sgeonw_eccpoint_y, tvb, *offset, field_size, ENC_NA); 1293 *offset += field_size; 1294 break; 1295 default: 1296 // Opaque<var> 1297 param_len = dissect_sec_var_len(tvb, offset, pinfo, subtree); 1298 proto_tree_add_item(subtree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1299 *offset += param_len; 1300 } 1301 proto_item_set_end(ti, tvb, *offset); 1302 return (*offset) - start; 1303 } 1304 1305 static int 1306 dissect_sec_publickey(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1307 { 1308 guint32 tmp_val; 1309 guint32 param_len; 1310 gint start = *offset; 1311 proto_item *part_item; 1312 proto_tree *part_tree; 1313 1314 part_item = proto_tree_add_item(tree, hf_sgeonw_public_key, tvb, *offset, 0, ENC_NA); // Length cannot be determined now 1315 part_tree = proto_item_add_subtree(part_item, ett_sgeonw_public_key); 1316 proto_tree_add_item_ret_uint(part_tree, hf_sgeonw_public_key_algorithm, tvb, *offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1317 *offset += 1; 1318 switch(tmp_val) { 1319 case ecdsa_nistp256_with_sha256: 1320 // EccPoint 1321 dissect_sec_eccpoint(tvb, offset, pinfo, part_tree, (PublicKeyAlgorithm) tmp_val); 1322 break; 1323 case ecies_nistp256: 1324 // SymAlgo + EccPoint 1325 proto_tree_add_item(part_tree, hf_sgeonw_symmetric_algorithm, tvb, *offset, 1, ENC_BIG_ENDIAN); 1326 *offset += 1; 1327 dissect_sec_eccpoint(tvb, offset, pinfo, part_tree, (PublicKeyAlgorithm) tmp_val); 1328 break; 1329 default: 1330 // Opaque 1331 param_len = dissect_sec_var_len(tvb, offset, pinfo, part_tree); 1332 proto_tree_add_item(part_tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1333 *offset += param_len; 1334 } 1335 proto_item_set_end(part_item, tvb, *offset); 1336 return (*offset) - start; 1337 } 1338 1339 static int 1340 dissect_sec_encryption_parameters(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1341 { 1342 guint32 tmp_val; 1343 guint32 param_len; 1344 guint32 start = *offset; 1345 proto_item *part_item; 1346 proto_tree *part_tree; 1347 1348 part_item = proto_tree_add_item(tree, hf_sgeonw_encryption_parameter, tvb, *offset, 0, ENC_NA); // Length cannot be determined now 1349 part_tree = proto_item_add_subtree(part_item, ett_sgeonw_encryption_parameter); 1350 proto_tree_add_item_ret_uint(part_tree, hf_sgeonw_symmetric_algorithm, tvb, *offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1351 *offset += 1; 1352 switch(tmp_val) { 1353 case ecdsa_nistp256_with_sha256: 1354 // Opaque[12] 1355 proto_tree_add_item(part_tree, hf_sgeonw_encryption_parameter_nonce, tvb, *offset, 12, ENC_NA); 1356 *offset += 12; 1357 break; 1358 default: 1359 // Opaque 1360 param_len = dissect_sec_var_len(tvb, offset, pinfo, part_tree); 1361 proto_tree_add_item(part_tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1362 *offset += param_len; 1363 } 1364 proto_item_set_end(part_item, tvb, *offset); 1365 return (*offset) - start; 1366 } 1367 1368 static int 1369 dissect_sec_ecdsasignature(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, PublicKeyAlgorithm algorithm) 1370 { 1371 guint32 start = *offset; 1372 int field_size = etsits103097_table_2[algorithm]; 1373 1374 dissect_sec_eccpoint(tvb, offset, pinfo, tree, algorithm); 1375 proto_tree_add_item(tree, hf_sgeonw_ecdsasignature_s, tvb, *offset, field_size, ENC_NA); 1376 *offset += field_size; 1377 return (*offset) - start; 1378 } 1379 1380 static int 1381 dissect_sec_signature(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1382 { 1383 gint start = *offset; 1384 guint32 param_len; 1385 guint32 tmp_val; 1386 proto_item *part_item; 1387 proto_tree *part_tree; 1388 1389 part_item = proto_tree_add_item(tree, hf_sgeonw_signature, tvb, *offset, 0, ENC_NA); // Length cannot be determined now 1390 part_tree = proto_item_add_subtree(part_item, ett_sgeonw_signature); 1391 proto_tree_add_item_ret_uint(part_tree, hf_sgeonw_public_key_algorithm, tvb, *offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1392 *offset += 1; 1393 switch(tmp_val) { 1394 case ecdsa_nistp256_with_sha256: 1395 // EcdsaSignature 1396 dissect_sec_ecdsasignature(tvb, offset, pinfo, part_tree, ecdsa_nistp256_with_sha256); 1397 break; 1398 default: 1399 // Opaque 1400 param_len = dissect_sec_var_len(tvb, offset, pinfo, part_tree); 1401 proto_tree_add_item(part_tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1402 *offset += param_len; 1403 } 1404 proto_item_set_end(part_item, tvb, *offset); 1405 return (*offset) - start; 1406 } 1407 1408 inline static int 1409 dissect_sec_2dlocation(tvbuff_t *tvb, gint *offset, proto_tree *tree) 1410 { 1411 proto_tree_add_item(tree, hf_sgeonw_lat, tvb, *offset, 4, ENC_BIG_ENDIAN); 1412 proto_tree_add_item(tree, hf_sgeonw_lon, tvb, 4+*offset, 4, ENC_BIG_ENDIAN); 1413 *offset += 8; 1414 1415 return 8; 1416 } 1417 1418 1419 static int 1420 dissect_sec_subject_info(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1421 { 1422 guint32 param_len; 1423 gint start = *offset; 1424 proto_item *ti; 1425 proto_item *part_item; 1426 proto_tree *part_tree; 1427 1428 part_item = proto_tree_add_item(tree, hf_sgeonw_subject_info, tvb, *offset, 0, ENC_NA); // Length cannot be determined now 1429 part_tree = proto_item_add_subtree(part_item, ett_sgeonw_subject_info); 1430 proto_tree_add_item(part_tree, hf_sgeonw_subject_type, tvb, *offset, 1, ENC_BIG_ENDIAN); 1431 *offset += 1; 1432 param_len = dissect_sec_var_len(tvb, offset, pinfo, part_tree); 1433 ti = proto_tree_add_item(part_tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1434 // Expert info: shall be at most 255 bytes long 1435 if (param_len > 255) 1436 expert_add_info(pinfo, ti, &ei_sgeonw_subj_info_too_long); 1437 *offset += param_len; 1438 proto_item_set_end(part_item, tvb, *offset); 1439 1440 return (*offset) - start; 1441 } 1442 1443 static int 1444 dissect_sec_itsaidssp(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1445 { 1446 gint start = *offset; 1447 guint32 param_len; 1448 guint32 appid; 1449 proto_item *ti; 1450 proto_tree *subtree; 1451 1452 dissect_sec_intx(tvb, offset, pinfo, tree, hf_sgeonw_app_id, &appid); 1453 param_len = dissect_sec_var_len(tvb, offset, pinfo, tree); 1454 ti = proto_tree_add_item(tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1455 // Expert info: shall be at most 31 bytes long 1456 if (param_len > 31) { 1457 expert_add_info(pinfo, ti, &ei_sgeonw_ssp_too_long); 1458 } 1459 else { 1460 subtree = proto_item_add_subtree(ti, ett_sgeonw_ssp); 1461 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, *offset, param_len); 1462 dissector_try_uint(ssp_subdissector_table, appid, next_tvb, pinfo, subtree); 1463 } 1464 *offset += param_len; 1465 1466 return (*offset) - start; 1467 } 1468 1469 static int hf_sgeonw_priority = -1; 1470 1471 static int 1472 dissect_sec_itsaidpriority(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1473 { 1474 gint start = *offset; 1475 1476 dissect_sec_intx(tvb, offset, pinfo, tree, hf_sgeonw_app_id, NULL); 1477 proto_tree_add_item(tree, hf_sgeonw_priority, tvb, *offset, 1, ENC_BIG_ENDIAN); 1478 *offset += 1; 1479 1480 return (*offset) - start; 1481 } 1482 1483 static int 1484 dissect_sec_itsaidpriorityssp(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1485 { 1486 gint start = *offset; 1487 guint32 param_len; 1488 proto_item *ti; 1489 1490 dissect_sec_intx(tvb, offset, pinfo, tree, hf_sgeonw_app_id, NULL); 1491 proto_tree_add_item(tree, hf_sgeonw_priority, tvb, *offset, 1, ENC_BIG_ENDIAN); 1492 *offset += 1; 1493 param_len = dissect_sec_var_len(tvb, offset, pinfo, tree); 1494 ti = proto_tree_add_item(tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1495 // Expert info: shall be at most 31 bytes long 1496 if (param_len > 31) 1497 expert_add_info(pinfo, ti, &ei_sgeonw_ssp_too_long); 1498 *offset += param_len; 1499 1500 return (*offset) - start; 1501 } 1502 1503 static int hf_sgeonw_subject_assurance = -1; 1504 static int ett_sgeonw_subject_assurance = -1; 1505 static int hf_sgeonw_subject_assurance_assurance = -1; 1506 static int hf_sgeonw_subject_assurance_reserved = -1; 1507 static int hf_sgeonw_subject_assurance_confidence = -1; 1508 1509 static int 1510 dissect_sec_subject_attributes(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, guint8 version) 1511 { 1512 gint start = *offset; 1513 guint32 tmp_val; 1514 guint32 param_len; 1515 proto_item *ti; 1516 proto_item *part_item; 1517 proto_tree *subtree; 1518 1519 part_item = proto_tree_add_item(tree, hf_sgeonw_subject_attribute, tvb, *offset, 0, ENC_NA); 1520 subtree = proto_item_add_subtree(part_item, ett_sgeonw_subject_attribute); 1521 ti = proto_tree_add_item_ret_uint(subtree, version == 1 ? hf_sgeonw_subject_attribute_type_v1 : hf_sgeonw_subject_attribute_type_v2, tvb, *offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1522 *offset += 1; 1523 switch (tmp_val) { 1524 case verification_key: 1525 case encryption_key: 1526 dissect_sec_publickey(tvb,offset,pinfo,subtree); 1527 break; 1528 case assurance_level: 1529 ti = proto_tree_add_item(subtree, hf_sgeonw_subject_assurance, tvb, *offset, 1, ENC_NA); 1530 subtree = proto_item_add_subtree(ti, ett_sgeonw_subject_assurance); 1531 proto_tree_add_item(subtree, hf_sgeonw_subject_assurance_assurance, tvb, *offset, 1, ENC_BIG_ENDIAN); 1532 proto_tree_add_item(subtree, hf_sgeonw_subject_assurance_reserved, tvb, *offset, 1, ENC_BIG_ENDIAN); 1533 proto_tree_add_item(subtree, hf_sgeonw_subject_assurance_confidence, tvb, *offset, 1, ENC_BIG_ENDIAN); 1534 *offset += 1; 1535 break; 1536 case reconstruction_value: 1537 dissect_sec_eccpoint(tvb,offset,pinfo,subtree,ecdsa_nistp256_with_sha256); // XXX Which algorithm? hack as only one algo defined 1538 break; 1539 case its_aid_list: 1540 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, subtree); 1541 while (tmp_val > 0) { 1542 param_len = dissect_sec_intx(tvb,offset,pinfo, subtree, hf_sgeonw_app_id, NULL); 1543 if(tmp_val < param_len) { 1544 expert_add_info(pinfo, ti, &ei_sgeonw_bogus); 1545 return *offset - start; 1546 } 1547 tmp_val -= param_len; 1548 } 1549 break; 1550 case its_aid_ssp_list: 1551 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, subtree); 1552 while (tmp_val > 0) { 1553 param_len = dissect_sec_itsaidssp(tvb, offset, pinfo, subtree); 1554 if(tmp_val < param_len) { 1555 expert_add_info(pinfo, ti, &ei_sgeonw_bogus); 1556 return *offset - start; 1557 } 1558 tmp_val -= param_len; 1559 } 1560 break; 1561 case priority_its_aid_list: 1562 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, subtree); 1563 while (tmp_val > 0) { 1564 param_len = dissect_sec_itsaidpriority(tvb, offset, pinfo, subtree); 1565 if(tmp_val < param_len) { 1566 expert_add_info(pinfo, ti, &ei_sgeonw_bogus); 1567 return *offset - start; 1568 } 1569 tmp_val -= param_len; 1570 } 1571 break; 1572 case priority_ssp_list: 1573 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, subtree); 1574 while (tmp_val > 0) { 1575 param_len = dissect_sec_itsaidpriorityssp(tvb, offset, pinfo, subtree); 1576 if(tmp_val < param_len) { 1577 expert_add_info(pinfo, ti, &ei_sgeonw_bogus); 1578 return *offset - start; 1579 } 1580 tmp_val -= param_len; 1581 } 1582 break; 1583 default: 1584 // Opaque 1585 param_len = dissect_sec_var_len(tvb, offset, pinfo, subtree); 1586 proto_tree_add_item(subtree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1587 *offset += param_len; 1588 } 1589 proto_item_set_end(part_item, tvb, *offset); 1590 1591 return (*offset) - start; 1592 } 1593 1594 static int 1595 dissect_sec_circularregion(tvbuff_t *tvb, gint *offset, proto_tree *tree) 1596 { 1597 dissect_sec_2dlocation(tvb, offset, tree); 1598 // uint16 1599 proto_tree_add_item(tree, hf_sgeonw_radius, tvb, *offset, 2, ENC_BIG_ENDIAN); 1600 *offset += 2; 1601 1602 return 10; 1603 } 1604 1605 static int 1606 dissect_sec_rectangularregion(tvbuff_t *tvb, gint *offset, proto_tree *tree) 1607 { 1608 dissect_sec_2dlocation(tvb, offset, tree); 1609 dissect_sec_2dlocation(tvb, offset, tree); 1610 1611 return 16; 1612 } 1613 1614 static int 1615 dissect_sec_polygonalregion(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1616 { 1617 gint start = *offset; 1618 guint32 param_len; 1619 guint32 tmp_val; 1620 1621 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, tree); 1622 while (tmp_val) { 1623 param_len = dissect_sec_2dlocation(tvb, offset, tree); 1624 if(tmp_val < param_len) 1625 return *offset - start; 1626 tmp_val -= param_len; 1627 } 1628 1629 return (*offset) - start; 1630 } 1631 1632 static int 1633 dissect_sec_identifiedregion(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1634 { 1635 gint start = *offset; 1636 1637 proto_tree_add_item(tree, hf_sgeonw_region_dictionary, tvb, *offset, 1, ENC_BIG_ENDIAN); 1638 proto_tree_add_item(tree, hf_sgeonw_region_identifier, tvb, *offset, 2, ENC_BIG_ENDIAN); 1639 *offset += 3; 1640 dissect_sec_intx(tvb, offset, pinfo, tree, hf_sgeonw_local_region, NULL); 1641 1642 return (*offset) - start; 1643 } 1644 1645 static int 1646 dissect_sec_geographicregion(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1647 { 1648 gint start = *offset; 1649 guint32 param_len; 1650 guint32 tmp_val; 1651 1652 proto_tree_add_item_ret_uint(tree, hf_sgeonw_region_type, tvb, *offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1653 *offset += 1; 1654 switch (tmp_val) { 1655 case none: 1656 break; 1657 case circle: 1658 dissect_sec_circularregion(tvb,offset,tree); 1659 break; 1660 case rectangle: 1661 dissect_sec_rectangularregion(tvb,offset,tree); 1662 break; 1663 case polygon: 1664 dissect_sec_polygonalregion(tvb, offset, pinfo, tree); 1665 break; 1666 case id: 1667 dissect_sec_identifiedregion(tvb, offset, pinfo, tree); 1668 break; 1669 default: 1670 // Opaque 1671 param_len = dissect_sec_var_len(tvb, offset, pinfo, tree); 1672 proto_tree_add_item(tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1673 *offset += param_len; 1674 } 1675 1676 return (*offset) - start; 1677 } 1678 1679 static const value_string sgeonw_duration_unit_names[] = { 1680 { 0, "Seconds" }, 1681 { 1, "Minutes" }, 1682 { 2, "Hours" }, 1683 { 3, "60 Hours block" }, 1684 { 4, "Years" }, 1685 { 0, NULL } 1686 }; 1687 1688 static int 1689 dissect_sec_validity_restrictions(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree) 1690 { 1691 gint start = *offset; 1692 guint32 tmp_val; 1693 guint32 param_len; 1694 proto_item *ti; 1695 proto_tree *subtree; 1696 1697 proto_tree_add_item_ret_uint(tree, hf_sgeonw_validity_restriction_type, tvb, *offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1698 *offset += 1; 1699 switch (tmp_val) { 1700 case time_end: 1701 // Time32 1702 proto_tree_add_item(tree, hf_sgeonw_time32, tvb, *offset, 4, ENC_BIG_ENDIAN); 1703 *offset += 4; 1704 break; 1705 case time_start_and_end: 1706 // Time32 1707 proto_tree_add_item(tree, hf_sgeonw_time32, tvb, *offset, 4, ENC_BIG_ENDIAN); 1708 *offset += 4; 1709 // Time32 1710 proto_tree_add_item(tree, hf_sgeonw_time32, tvb, *offset, 4, ENC_BIG_ENDIAN); 1711 *offset += 4; 1712 break; 1713 case time_start_and_duration: 1714 // Time32 1715 proto_tree_add_item(tree, hf_sgeonw_time32, tvb, *offset, 4, ENC_BIG_ENDIAN); 1716 *offset += 4; 1717 // Duration 1718 ti = proto_tree_add_item(tree, hf_sgeonw_duration, tvb, *offset, 2, ENC_NA); 1719 subtree = proto_item_add_subtree(ti, ett_sgeonw_duration); 1720 proto_tree_add_item(subtree, hf_sgeonw_duration_unit, tvb, *offset, 2, ENC_BIG_ENDIAN); 1721 proto_tree_add_item(subtree, hf_sgeonw_duration_value, tvb, *offset, 2, ENC_BIG_ENDIAN); 1722 *offset += 2; 1723 break; 1724 case region: 1725 dissect_sec_geographicregion(tvb, offset, pinfo, tree); 1726 break; 1727 default: 1728 // Opaque 1729 param_len = dissect_sec_var_len(tvb, offset, pinfo, tree); 1730 proto_tree_add_item(tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1731 *offset += param_len; 1732 } 1733 return (*offset) - start; 1734 } 1735 1736 static int dissect_sec_signer_info(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, guint8 version); 1737 1738 static int hf_sgeonw_certification_version = -1; 1739 1740 static int 1741 dissect_sec_certificate(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, guint8 version) 1742 { 1743 guint32 tmp_val; 1744 guint32 param_len; 1745 gint start = *offset; 1746 1747 proto_tree_add_item_ret_uint(tree, hf_sgeonw_certification_version, tvb, *offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1748 *offset += 1; 1749 if (version == 1) { 1750 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, tree); 1751 while (tmp_val > 0) { 1752 param_len = dissect_sec_signer_info(tvb, offset, pinfo, tree, version); 1753 tmp_val -= param_len; 1754 } 1755 } 1756 else { 1757 dissect_sec_signer_info(tvb, offset, pinfo, tree, version); 1758 } 1759 dissect_sec_subject_info(tvb, offset, pinfo, tree); 1760 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, tree); 1761 while (tmp_val > 0) { 1762 param_len = dissect_sec_subject_attributes(tvb, offset, pinfo, tree, version); 1763 tmp_val -= param_len; 1764 } 1765 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, tree); 1766 while (tmp_val > 0) { 1767 param_len = dissect_sec_validity_restrictions(tvb, offset, pinfo, tree); 1768 tmp_val -= param_len; 1769 } 1770 dissect_sec_signature(tvb, offset, pinfo, tree); 1771 1772 return (*offset) - start; 1773 } 1774 1775 static int 1776 dissect_sec_signer_info(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, guint8 version) 1777 { 1778 gint start = *offset; 1779 guint32 tmp_val; 1780 guint32 param_len; 1781 proto_item *ti; 1782 proto_tree *subtree; 1783 proto_item *tinner; 1784 proto_tree *insidetree; 1785 1786 tmp_val = tvb_get_guint8(tvb, *offset); 1787 if (tmp_val == self) { 1788 // No additional data shall be given 1789 proto_tree_add_item(tree, hf_sgeonw_signer_info_type, tvb, *offset, 1, ENC_BIG_ENDIAN); 1790 *offset += 1; 1791 } 1792 else { 1793 ti = proto_tree_add_item(tree, hf_sgeonw_signer_info, tvb, *offset, 0, ENC_NA); 1794 subtree = proto_item_add_subtree(ti, ett_sgeonw_field); 1795 proto_tree_add_item(subtree, hf_sgeonw_signer_info_type, tvb, *offset, 1, ENC_BIG_ENDIAN); 1796 *offset += 1; 1797 switch(tmp_val) { 1798 case certificate_digest_with_ecdsap256: 1799 // HashedId8 1800 proto_tree_add_item(subtree, hf_sgeonw_hashedid8, tvb, *offset, 8, ENC_NA); 1801 *offset += 8; 1802 break; 1803 case certificate: 1804 // Certificate 1805 tinner = proto_tree_add_item(subtree, hf_sgeonw_certificate, tvb, *offset, 0, ENC_NA); 1806 insidetree = proto_item_add_subtree(tinner, ett_sgeonw_field); 1807 dissect_sec_certificate(tvb, offset, pinfo, insidetree, version); 1808 proto_item_set_end(tinner, tvb, *offset); 1809 break; 1810 case certificate_chain: 1811 // variable-length vector of type Certificate 1812 tmp_val = dissect_sec_var_len(tvb, offset, pinfo, subtree); 1813 while (tmp_val > 0) { 1814 tinner = proto_tree_add_item(subtree, hf_sgeonw_certificate, tvb, *offset, 0, ENC_NA); 1815 insidetree = proto_item_add_subtree(tinner, ett_sgeonw_field); 1816 param_len = dissect_sec_certificate(tvb, offset, pinfo, insidetree, version); 1817 proto_item_set_end(tinner, tvb, *offset); 1818 tmp_val -= param_len; 1819 } 1820 break; 1821 case certificate_digest_with_other_algorithm: 1822 // HashedId8 1823 proto_tree_add_item(subtree, hf_sgeonw_public_key_algorithm, tvb, *offset, 1, ENC_BIG_ENDIAN); 1824 proto_tree_add_item(subtree, hf_sgeonw_hashedid8, tvb, 1+(*offset), 8, ENC_NA); 1825 *offset += 9; 1826 break; 1827 default: 1828 // Opaque 1829 param_len = dissect_sec_var_len(tvb, offset, pinfo, subtree); 1830 proto_tree_add_item(subtree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1831 *offset += param_len; 1832 } 1833 proto_item_set_end(ti, tvb, *offset); 1834 } 1835 return (*offset) - start; 1836 } 1837 1838 1839 static int hf_sgeonw_encrypted_key = -1; 1840 static int hf_sgeonw_auth_tag = -1; 1841 1842 // This structure defines how to transmit an EciesNistP256-encrypted symmetric key as defined in IEEE 1843 // Std 1363a-2004. 1844 // EciesNistP256EncryptedKey structure shall be preceded by an according 1845 // EncryptionParameters structure. 1846 static int 1847 dissect_sec_eciesnistp256entryptedkey(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, PublicKeyAlgorithm pub_alg, SymmetricAlgorithm symm_alg, guint8 version) 1848 { 1849 gint start = *offset; 1850 guint8 symm_key_len = etsits103097_table_4[symm_alg]; 1851 1852 dissect_sec_eccpoint(tvb, offset, pinfo, tree, pub_alg); 1853 proto_tree_add_item(tree, hf_sgeonw_encrypted_key, tvb, *offset, symm_key_len, ENC_NA); 1854 *offset += symm_key_len; 1855 proto_tree_add_item(tree, hf_sgeonw_auth_tag, tvb, *offset, version==1?20:16, ENC_NA); 1856 *offset += version==1?20:16; 1857 1858 return (*offset) - start; 1859 } 1860 1861 1862 static int 1863 dissect_sec_recipient_info(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *tree, guint8 version) 1864 { 1865 gint start = *offset; 1866 guint32 tmp_val; 1867 guint32 param_len; 1868 1869 proto_tree_add_item(tree, hf_sgeonw_hashedid8, tvb, *offset, 8, ENC_NA); 1870 proto_tree_add_item_ret_uint(tree, hf_sgeonw_public_key_algorithm, tvb, 8+*offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1871 *offset += 9; 1872 switch (tmp_val) { 1873 case ecies_nistp256: 1874 // EciesNistP256EncryptedKey 1875 // XXX SymmetricAlgorithm should be provided by preceding EncryptionParameter... 1876 dissect_sec_eciesnistp256entryptedkey(tvb, offset, pinfo, tree, (PublicKeyAlgorithm)tmp_val, aes_128_ccm, version); 1877 break; 1878 default: 1879 // Opaque 1880 param_len = dissect_sec_var_len(tvb, offset, pinfo, tree); 1881 proto_tree_add_item(tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1882 *offset += param_len; 1883 } 1884 1885 return (*offset) - start; 1886 } 1887 1888 1889 static int 1890 dissect_sec_payload(tvbuff_t *tvb, gint *offset, packet_info *pinfo, proto_tree *part_tree) 1891 { 1892 gint start = *offset; 1893 guint32 tmp_val; 1894 guint32 param_len; 1895 proto_tree *field_tree; 1896 proto_item *ti; 1897 1898 tmp_val = tvb_get_guint8(tvb, *offset); 1899 if (tmp_val == signed_external) { 1900 proto_tree_add_item(part_tree, hf_sgeonw_payload_field_type, tvb, *offset, 1, ENC_BIG_ENDIAN); 1901 *offset += 1; 1902 } 1903 else { 1904 ti = proto_tree_add_item(part_tree, hf_sgeonw_payload_field, tvb, *offset, 0, ENC_NA); 1905 field_tree = proto_item_add_subtree(ti, ett_sgeonw_field); 1906 proto_tree_add_item(field_tree, hf_sgeonw_payload_field_type, tvb, *offset, 1, ENC_BIG_ENDIAN); 1907 *offset += 1; 1908 switch(tmp_val) { 1909 case unsecured: 1910 case signed_pl: 1911 param_len = dissect_sec_var_len(tvb, offset, pinfo, field_tree); 1912 if (param_len) { 1913 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, *offset, param_len); 1914 p_add_proto_data(wmem_file_scope(), pinfo, proto_geonw, 0, next_tvb); 1915 } 1916 *offset += param_len; 1917 break; 1918 case encrypted: 1919 case signed_and_encrypted: 1920 param_len = dissect_sec_var_len(tvb, offset, pinfo, field_tree); 1921 proto_tree_add_item(field_tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1922 *offset += param_len; 1923 break; 1924 default: 1925 // Opaque 1926 param_len = dissect_sec_var_len(tvb, offset, pinfo, field_tree); 1927 proto_tree_add_item(field_tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA); 1928 *offset += param_len; 1929 } 1930 proto_item_set_end(ti, tvb, *offset); 1931 } 1932 1933 return (*offset) - start; 1934 } 1935 1936 1937 static int 1938 dissect_secured_message(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, void *data _U_) 1939 { 1940 guint32 msg_id; // Or Application ID, depending on version 1941 guint8 version; 1942 guint32 var_len; 1943 proto_item *ti; 1944 guint32 tmp_val; 1945 guint32 param_len; 1946 proto_item *secmsg_item; 1947 proto_item *part_item; 1948 proto_tree *part_tree; 1949 proto_tree *field_tree; 1950 gint sec_start = offset; 1951 1952 // Secured message subtree 1953 secmsg_item = proto_tree_add_item(tree, hf_geonw_sec, tvb, offset, 0, ENC_NA); // Length cannot be determined now 1954 proto_tree *secmsg_tree = proto_item_add_subtree(secmsg_item, ett_geonw_sec); 1955 1956 version = tvb_get_guint8(tvb, offset); 1957 if (version == 3) { 1958 tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, offset); 1959 call_dissector(ieee1609dot2_handle, next_tvb, pinfo, secmsg_tree); 1960 // If unsecure or only signed, content is in private data 1961 return tvb_captured_length(tvb); 1962 } 1963 1964 proto_tree_add_item(secmsg_tree, hf_sgeonw_version, tvb, offset, 1, ENC_BIG_ENDIAN); 1965 offset+=1; 1966 if ((version < 1) || (version > 2)) 1967 return 1; 1968 if (version == 1) { 1969 proto_tree_add_item_ret_uint(secmsg_tree, hf_sgeonw_profile, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1970 offset += 1; 1971 } 1972 // Header Fields 1973 part_item = proto_tree_add_item(secmsg_tree, hf_sgeonw_hdr, tvb, offset, 0, ENC_NA); // Length cannot be determined now 1974 part_tree = proto_item_add_subtree(part_item, ett_sgeonw_hdr); 1975 1976 var_len = dissect_sec_var_len(tvb, &offset, pinfo, part_tree); 1977 while (var_len > 0) { 1978 1979 guint32 start = offset; 1980 1981 ti = proto_tree_add_item(part_tree, hf_sgeonw_header_field, tvb, offset, 0, ENC_NA); 1982 field_tree = proto_item_add_subtree(ti, ett_sgeonw_field); 1983 proto_tree_add_item_ret_uint(field_tree, version==1?hf_sgeonw_header_field_type_v1:hf_sgeonw_header_field_type_v2, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val); 1984 offset += 1; 1985 switch(tmp_val) { 1986 case generation_time: 1987 // Time64 1988 proto_tree_add_item(field_tree, hf_sgeonw_time64, tvb, offset, 8, ENC_BIG_ENDIAN); 1989 offset += 8; 1990 break; 1991 case generation_time_confidence: 1992 // Time64WithStandardDeviation 1993 proto_tree_add_item(field_tree, hf_sgeonw_time64, tvb, offset, 8, ENC_BIG_ENDIAN); 1994 proto_tree_add_item(field_tree, hf_sgeonw_conf, tvb, offset+8, 1, ENC_BIG_ENDIAN); 1995 offset += 9; 1996 break; 1997 case expiration: 1998 // Time32 1999 proto_tree_add_item(field_tree, hf_sgeonw_time32, tvb, offset, 4, ENC_BIG_ENDIAN); 2000 offset += 4; 2001 break; 2002 case generation_location: 2003 // ThreeDLocation 2004 proto_tree_add_item(field_tree, hf_sgeonw_lat, tvb, offset, 4, ENC_BIG_ENDIAN); 2005 proto_tree_add_item(field_tree, hf_sgeonw_lon, tvb, offset+4, 4, ENC_BIG_ENDIAN); 2006 proto_tree_add_item(field_tree, hf_sgeonw_elev, tvb, offset+8, 2, ENC_BIG_ENDIAN); 2007 offset += 10; 2008 break; 2009 case request_unrecognized_certificate: 2010 // HashedId3 2011 param_len = dissect_sec_var_len(tvb, &offset, pinfo, field_tree); 2012 proto_item_set_len(ti, (offset-start) + param_len); 2013 while (param_len) { 2014 proto_tree_add_item(field_tree, hf_sgeonw_hashedid3, tvb, offset, 3, ENC_NA); 2015 offset += 3; 2016 param_len -= 3; 2017 } 2018 break; 2019 case message_type: 2020 if (version == 1) { 2021 proto_tree_add_item_ret_uint(field_tree, hf_sgeonw_msg_id, tvb, offset, 2, ENC_BIG_ENDIAN, &msg_id); 2022 offset += 2; 2023 } 2024 else { 2025 dissect_sec_intx(tvb, &offset, pinfo, field_tree, hf_sgeonw_app_id, &msg_id); 2026 } 2027 break; 2028 case signer_info: 2029 // SignerInfo 2030 dissect_sec_signer_info(tvb, &offset, pinfo, field_tree, version); 2031 break; 2032 case recipient_info: 2033 // RecipientInfo 2034 param_len = dissect_sec_var_len(tvb, &offset, pinfo, field_tree); 2035 proto_item_set_len(ti, (offset-start) + param_len); 2036 while (param_len) { 2037 param_len -= dissect_sec_recipient_info(tvb, &offset, pinfo, field_tree, version); 2038 } 2039 offset += param_len; 2040 break; 2041 case encryption_parameters: 2042 // EncryptionParameters 2043 dissect_sec_encryption_parameters(tvb, &offset, pinfo, field_tree); 2044 break; 2045 default: 2046 // Opaque 2047 param_len = dissect_sec_var_len(tvb, &offset, pinfo, field_tree); 2048 proto_item_set_len(ti, (offset-start) + param_len); 2049 proto_tree_add_item(field_tree, hf_sgeonw_opaque, tvb, offset, param_len, ENC_NA); 2050 offset += param_len; 2051 } 2052 proto_item_set_end(ti, tvb, offset); 2053 /* EI var_len >= (offset-start) */ 2054 var_len -= (offset - start); 2055 } 2056 proto_item_set_end(part_item, tvb, offset); 2057 2058 // Payload 2059 part_item = proto_tree_add_item(secmsg_tree, hf_sgeonw_pl, tvb, offset, 0, ENC_NA); // Length cannot be determined now 2060 part_tree = proto_item_add_subtree(part_item, ett_sgeonw_hdr); 2061 2062 // Change in version 2: only one payload element here! 2063 if (version == 1) { 2064 var_len = dissect_sec_var_len(tvb, &offset, pinfo, part_tree); 2065 while (var_len > 0) { 2066 2067 guint32 start = offset; 2068 2069 dissect_sec_payload(tvb, &offset, pinfo, part_tree); 2070 if (var_len < (offset-start)) 2071 return 0; 2072 var_len -= (offset - start); 2073 } 2074 } 2075 else { 2076 dissect_sec_payload(tvb, &offset, pinfo, part_tree); 2077 } 2078 proto_item_set_end(part_item, tvb, offset); 2079 2080 // Trailer 2081 part_item = proto_tree_add_item(secmsg_tree, hf_sgeonw_trl, tvb, offset, 0, ENC_NA); // Length cannot be determined now 2082 part_tree = proto_item_add_subtree(part_item, ett_sgeonw_hdr); 2083 2084 var_len = dissect_sec_var_len(tvb, &offset, pinfo, part_tree); 2085 while (var_len > 0) { 2086 2087 guint32 start = offset; 2088 2089 ti = proto_tree_add_item(part_tree, hf_sgeonw_trailer_field, tvb, offset, 0, ENC_NA); 2090 field_tree = proto_item_add_subtree(ti, ett_sgeonw_field); 2091 proto_tree_add_item_ret_uint(field_tree, hf_sgeonw_trailer_field_type, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val); 2092 offset += 1; 2093 switch(tmp_val) { 2094 case signature: 2095 // Signature 2096 dissect_sec_signature(tvb, &offset, pinfo, field_tree); 2097 break; 2098 default: 2099 // Opaque 2100 param_len = dissect_sec_var_len(tvb, &offset, pinfo, field_tree); 2101 proto_tree_add_item(field_tree, hf_sgeonw_opaque, tvb, offset, param_len, ENC_NA); 2102 offset += param_len; 2103 } 2104 proto_item_set_end(ti, tvb, offset); 2105 var_len -= (offset - start); 2106 } 2107 proto_item_set_end(part_item, tvb, offset); 2108 proto_item_set_end(secmsg_item, tvb, offset); 2109 2110 return offset - sec_start; 2111 } 2112 2113 static int 2114 dissect_sgeonw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_) 2115 { 2116 // Just store the tvbuff for later, as it is embedded inside a secured geonetworking packet 2117 p_add_proto_data(wmem_file_scope(), pinfo, proto_geonw, 0, tvb); 2118 2119 return tvb_reported_length(tvb); 2120 } 2121 2122 // The actual dissector 2123 // XXX COL_INFO to be improved 2124 static int 2125 dissect_geonw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) 2126 { 2127 guint8 bh_next_header; 2128 guint32 ch_next_header; 2129 guint32 header_type; 2130 guint32 rhl; 2131 guint32 tmp_val; 2132 gint offset = 0; 2133 proto_item *ti; 2134 proto_item *top_item; 2135 gint hdr_len = 0; 2136 guint32 payload_len = 0; 2137 guint32 reserved; 2138 guint32 timestamp; 2139 guint32 sequence_number = SN_MAX + 1; 2140 struct geonwheader *geonwh; 2141 gint32 latlon; 2142 2143 geonwh = wmem_new0(pinfo->pool, struct geonwheader); 2144 2145 col_set_str(pinfo->cinfo, COL_PROTOCOL, "GEONW"); 2146 /* Clear out stuff in the info column */ 2147 col_clear(pinfo->cinfo,COL_INFO); 2148 2149 bh_next_header = tvb_get_guint8(tvb, 0) & 0x0f; 2150 header_type = tvb_get_guint8(tvb, 5); 2151 2152 if (bh_next_header == BH_NH_SECURED_PKT) { 2153 hdr_len = BH_LEN; 2154 } 2155 else { 2156 hdr_len = BH_LEN + CH_LEN; 2157 switch(header_type & HT_MASK) { 2158 case HT_BEACON: 2159 hdr_len += BEACON_LEN; 2160 break; 2161 case HT_GEOUNICAST: 2162 hdr_len += GUC_LEN; 2163 break; 2164 case HT_GEOANYCAST: 2165 hdr_len += GAC_LEN; 2166 break; 2167 case HT_GEOBROADCAST: 2168 hdr_len += GBC_LEN; 2169 break; 2170 case HT_TSB: 2171 hdr_len += TSB_LEN; 2172 break; 2173 case HT_LS: 2174 hdr_len += LS_REQUEST_LEN; 2175 if (header_type == HTST_LS_REPLY) { 2176 hdr_len += (LS_REPLY_LEN - LS_REQUEST_LEN); 2177 } 2178 break; 2179 default: 2180 hdr_len = -1; 2181 } 2182 } 2183 top_item = proto_tree_add_item(tree, proto_geonw, tvb, 0, hdr_len, ENC_NA); 2184 proto_tree *geonw_tree = proto_item_add_subtree(top_item, ett_geonw); 2185 2186 // Basic Header subtree 2187 ti = proto_tree_add_item(geonw_tree, hf_geonw_bh, tvb, 0, 4, ENC_NA); 2188 proto_tree *geonw_bh_tree = proto_item_add_subtree(ti, ett_geonw_bh); 2189 2190 ti = proto_tree_add_item_ret_uint(geonw_bh_tree, hf_geonw_bh_version, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val); 2191 geonwh->gnw_ver = tmp_val; 2192 // Shall be 0 or 1 2193 if (tmp_val > 1) { 2194 col_add_fstr(pinfo->cinfo, COL_INFO, 2195 "Bogus GeoNetworking version (%u, must be less than 2)", tmp_val); 2196 expert_add_info_format(pinfo, ti, &ei_geonw_version_err, "Bogus GeoNetworking version"); 2197 return tvb_captured_length(tvb); 2198 } 2199 proto_tree_add_item(geonw_bh_tree, hf_geonw_bh_next_header, tvb, offset, 1, ENC_BIG_ENDIAN); 2200 offset += 1; 2201 // Reserved byte 2202 // Expert info if not zero? 2203 ti = proto_tree_add_item_ret_uint(geonw_bh_tree, hf_geonw_bh_reserved, tvb, offset, 1, ENC_NA, &reserved); 2204 if (reserved) { 2205 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2206 } 2207 offset += 1; 2208 2209 // Subtree and lt_mult and lt_base 2210 ti = proto_tree_add_item_ret_uint(geonw_bh_tree, hf_geonw_bh_life_time, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val); 2211 geonwh->gnw_lt = tmp_val; 2212 proto_tree *geonw_bh_lt_tree = proto_item_add_subtree(ti, ett_geonw_bh_lt); 2213 2214 proto_tree_add_item(geonw_bh_lt_tree, hf_geonw_bh_lt_mult, tvb, offset, 1, ENC_BIG_ENDIAN); 2215 proto_tree_add_item(geonw_bh_lt_tree, hf_geonw_bh_lt_base, tvb, offset, 1, ENC_BIG_ENDIAN); 2216 offset += 1; 2217 2218 proto_item *rhl_ti = proto_tree_add_item_ret_uint(geonw_bh_tree, hf_geonw_bh_remain_hop_limit, tvb, offset, 1, ENC_BIG_ENDIAN, &rhl); 2219 geonwh->gnw_rhl = rhl; 2220 /* 2221 * Flag a low RHL if the next header is not a common header 2222 */ 2223 if (rhl < 5 && bh_next_header != BH_NH_COMMON_HDR) { 2224 expert_add_info_format(pinfo, rhl_ti, &ei_geonw_rhl_too_low, "\"Remain Hop Limit\" only %u", rhl); 2225 } 2226 offset += 1; 2227 2228 if (bh_next_header == BH_NH_SECURED_PKT) { 2229 dissect_secured_message(tvb, offset, pinfo, geonw_tree, NULL); 2230 tvbuff_t *next_tvb = (tvbuff_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_geonw, 0); 2231 if (next_tvb) { 2232 tvb = next_tvb; 2233 bh_next_header = BH_NH_COMMON_HDR; 2234 offset = 0; 2235 header_type = tvb_get_guint8(tvb, 1); 2236 2237 hdr_len = CH_LEN; 2238 switch(header_type & HT_MASK) { 2239 case HT_BEACON: 2240 hdr_len += BEACON_LEN; 2241 break; 2242 case HT_GEOUNICAST: 2243 hdr_len += GUC_LEN; 2244 break; 2245 case HT_GEOANYCAST: 2246 hdr_len += GAC_LEN; 2247 break; 2248 case HT_GEOBROADCAST: 2249 hdr_len += GBC_LEN; 2250 break; 2251 case HT_TSB: 2252 hdr_len += TSB_LEN; 2253 break; 2254 case HT_LS: 2255 hdr_len += LS_REQUEST_LEN; 2256 if (header_type == HTST_LS_REPLY) { 2257 hdr_len += (LS_REPLY_LEN - LS_REQUEST_LEN); 2258 } 2259 break; 2260 default: 2261 hdr_len = -1; 2262 } 2263 p_add_proto_data(wmem_file_scope(), pinfo, proto_geonw, 0, NULL); 2264 } 2265 } 2266 2267 if (bh_next_header == BH_NH_COMMON_HDR) { 2268 // Common Header subtree 2269 ti = proto_tree_add_item(geonw_tree, hf_geonw_ch, tvb, offset, 8, ENC_NA); 2270 proto_tree *geonw_ch_tree = proto_item_add_subtree(ti, ett_geonw_ch); 2271 2272 // Next Header 2273 proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_next_header, tvb, offset, 1, ENC_BIG_ENDIAN, &ch_next_header); 2274 geonwh->gnw_proto = ch_next_header; 2275 // Reserved 2276 ti = proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_reserved1, tvb, offset, 1, ENC_NA, &reserved); 2277 if (reserved) { 2278 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2279 } 2280 offset += 1; 2281 2282 // HT 2283 proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_header_type, tvb, offset, 1, ENC_BIG_ENDIAN, &header_type); 2284 geonwh->gnw_htype = header_type; 2285 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(header_type, ch_header_type_names, "Unknown (%u)")); 2286 offset += 1; 2287 2288 /* Now that we know the header type, lets add expert info on RHL 2289 * RHL shall be 2290 * = 1 if parameter Packet transport type in the service primitive 2291 * GN-DATA.request is SHB, or if Header type HT = 1 (BEACON) 2292 * = Value of optional Maximum hop limit parameter from service 2293 * primitive GN-DATA.request 2294 * = Otherwise GN protocol constant itsGnDefaultHopLimit if 2295 * GN-DATA.request parameter Packet transport type is GUC, GBC, GBC 2296 * or TSB 2297 * Flag a low RHL if the packet is not BEACON or SHB. 2298 */ 2299 if (header_type == HTST_BEACON || header_type == HTST_TSB_SINGLE) { 2300 if (rhl > 1) { 2301 expert_add_info_format(pinfo, rhl_ti, &ei_geonw_rhl_lncb, "\"Remain Hop Limit\" != 1 for BEACON or SHB (%u)", rhl); 2302 } 2303 } else if (rhl < 5) { 2304 expert_add_info_format(pinfo, rhl_ti, &ei_geonw_rhl_too_low, "\"Remain Hop Limit\" only %u", rhl); 2305 } 2306 2307 // TC 2308 ti = proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_traffic_class, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val); 2309 geonwh->gnw_tc = tmp_val; 2310 proto_tree *geonw_ch_tc_tree = proto_item_add_subtree(ti, ett_geonw_ch_tc); 2311 2312 proto_tree_add_item(geonw_ch_tc_tree, hf_geonw_ch_tc_scf, tvb, offset, 1, ENC_BIG_ENDIAN); 2313 proto_tree_add_item(geonw_ch_tc_tree, hf_geonw_ch_tc_offload, tvb, offset, 1, ENC_BIG_ENDIAN); 2314 proto_tree_add_item(geonw_ch_tc_tree, hf_geonw_ch_tc_id, tvb, offset, 1, ENC_BIG_ENDIAN); 2315 offset += 1; 2316 2317 ti = proto_tree_add_item(geonw_ch_tree, hf_geonw_ch_flags, tvb, offset, 1, ENC_NA); 2318 proto_tree *geonw_ch_flag_tree = proto_item_add_subtree(ti, ett_geonw_ch_tc); 2319 // Flag (itsGnIsMobile) 2320 proto_tree_add_item_ret_uint(geonw_ch_flag_tree, hf_geonw_ch_flags_mob, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val); 2321 geonwh->gnw_flags = tmp_val; 2322 ti = proto_tree_add_item_ret_uint(geonw_ch_flag_tree, hf_geonw_ch_flags_reserved, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved); 2323 if (reserved & 0x7f) { 2324 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2325 } 2326 offset += 1; 2327 2328 // PL (16 bits) 2329 ti = proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_payload_length, tvb, offset, 2, ENC_BIG_ENDIAN, &payload_len); 2330 geonwh->gnw_len = payload_len; 2331 if (hdr_len > 0) { // We know the length of the header 2332 if (payload_len) { 2333 if (((header_type & HT_MASK) == HT_LS) || (header_type == HT_BEACON)) { 2334 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2335 } 2336 else if ((payload_len + (unsigned) hdr_len) > tvb_reported_length(tvb)) { 2337 expert_add_info(pinfo, ti, &ei_geonw_payload_len); 2338 } 2339 else { 2340 /* 2341 * Now that we know that the total length of this GNW datagram isn't 2342 * obviously bogus, adjust the length of this tvbuff to include only 2343 * the GNW datagram. 2344 */ 2345 set_actual_length(tvb, hdr_len + payload_len); 2346 } 2347 } 2348 else { 2349 set_actual_length(tvb, hdr_len); 2350 } 2351 } 2352 offset += 2; 2353 2354 // MHL 2355 proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_max_hop_limit, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val); 2356 geonwh->gnw_mhl = tmp_val; 2357 // Expert mhl < rhl: packet will be ignored 2358 if (tmp_val < rhl) { 2359 expert_add_info_format(pinfo, rhl_ti, &ei_geonw_mhl_lt_rhl, "Ignored: \"Remain Hop Limit\" > %u (mhl)", tmp_val); 2360 } 2361 offset += 1; 2362 2363 // Reserved... 2364 ti = proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_reserved2, tvb, offset, 1, ENC_NA, &reserved); 2365 // Expert info if not zero 2366 if (reserved) { 2367 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2368 } 2369 offset += 1; 2370 2371 // Stop here if header_type unknown 2372 if (!IS_HT_KNOWN(header_type)) { 2373 // Update top level tree item 2374 proto_item_set_end(top_item, tvb, offset); 2375 return tvb_reported_length(tvb); 2376 } 2377 2378 geonwh->gnw_sn = SN_MAX+1; 2379 2380 proto_tree *geonw_sh_tree; 2381 switch(header_type & HT_MASK) { 2382 case HT_BEACON: 2383 ti = proto_tree_add_item(geonw_tree, hf_geonw_beacon, tvb, offset, hdr_len-offset, ENC_NA); 2384 break; 2385 case HT_GEOUNICAST: 2386 ti = proto_tree_add_item(geonw_tree, hf_geonw_guc, tvb, offset, hdr_len-offset, ENC_NA); 2387 break; 2388 case HT_GEOANYCAST: 2389 ti = proto_tree_add_item(geonw_tree, hf_geonw_gac, tvb, offset, hdr_len-offset, ENC_NA); 2390 break; 2391 case HT_GEOBROADCAST: 2392 ti = proto_tree_add_item(geonw_tree, hf_geonw_gbc, tvb, offset, hdr_len-offset, ENC_NA); 2393 break; 2394 case HT_TSB: 2395 ti = proto_tree_add_item(geonw_tree, hf_geonw_tsb, tvb, offset, hdr_len-offset, ENC_NA); 2396 break; 2397 case HT_LS: 2398 ti = proto_tree_add_item(geonw_tree, hf_geonw_ls, tvb, offset, hdr_len-offset, ENC_NA); 2399 break; 2400 default: 2401 // Exit if header_type unknown? 2402 return tvb_captured_length(tvb); 2403 } 2404 geonw_sh_tree = proto_item_add_subtree(ti, ett_geonw_sh); 2405 2406 switch(header_type) { 2407 case HTST_GEOUNICAST: 2408 case HTST_GAC_CIRCLE: 2409 case HTST_GAC_RECT: 2410 case HTST_GAC_ELLIPSE: 2411 case HTST_GBC_CIRCLE: 2412 case HTST_GBC_RECT: 2413 case HTST_GBC_ELLIPSE: 2414 case HTST_TSB_MULT: 2415 case HTST_LS_REQUEST: 2416 case HTST_LS_REPLY: 2417 // Seq num 2418 proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_seq_num, tvb, offset, 2, ENC_BIG_ENDIAN, &sequence_number); 2419 geonwh->gnw_sn = sequence_number; 2420 offset += 2; 2421 // 16 bits reserved 2422 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_reserved, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved); 2423 // Expert info if not zero? 2424 if (reserved) { 2425 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2426 } 2427 offset += 2; 2428 case HTST_TSB_SINGLE: 2429 case HTST_BEACON: 2430 break; 2431 } 2432 2433 // Every packet has source address 2434 ti = proto_tree_add_item(geonw_sh_tree, hf_geonw_so_pv, tvb, offset, 24, ENC_NA); 2435 proto_tree *geonw_so_tree = proto_item_add_subtree(ti, ett_geonw_so); 2436 2437 ti = proto_tree_add_item(geonw_so_tree, hf_geonw_so_pv_addr, tvb, offset, 8, ENC_NA); 2438 proto_tree *geonw_so_add_tree = proto_item_add_subtree(ti, ett_geonw_so); 2439 set_address_tvb(&pinfo->net_src, geonw_address_type, 8, tvb, offset); 2440 copy_address_shallow(&pinfo->src, &pinfo->net_src); 2441 copy_address_shallow(&geonwh->gnw_src, &pinfo->src); 2442 2443 proto_tree_add_item(geonw_so_add_tree, hf_geonw_so_pv_addr_manual, tvb, offset, 1, ENC_BIG_ENDIAN); 2444 proto_tree_add_item(geonw_so_add_tree, hf_geonw_so_pv_addr_type, tvb, offset, 1, ENC_BIG_ENDIAN); 2445 ti = proto_tree_add_item_ret_uint(geonw_so_add_tree, hf_geonw_so_pv_addr_country, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved); 2446 if (reserved > 999) { 2447 expert_add_info(pinfo, ti, &ei_geonw_scc_too_big); 2448 } 2449 offset += 2; 2450 proto_tree_add_item(geonw_so_add_tree, hf_geonw_so_pv_addr_mid, tvb, offset, 6, ENC_NA); 2451 offset += 6; 2452 2453 proto_tree_add_item_ret_uint(geonw_so_tree, hf_geonw_so_pv_time, tvb, offset, 4, ENC_BIG_ENDIAN, ×tamp); 2454 geonwh->gnw_tst = timestamp; 2455 2456 // XXX Is it possible to "follow" a station when updating its GN_ADDR? 2457 2458 if(geonw_analyze_seq && (geonwh->gnw_ver==0) && !(pinfo->fd->visited)) { 2459 // Duplication detection uses SN and TST or only TST (see Annex A of ETSI EN 302 636-4-1) 2460 // We rely on address type and hashtable as this shall be done on a per station basis (i.e. not over a conversation) 2461 // We do not try to consider GN_ADDR updates (due to duplicate address detection or anonymous setting) 2462 hashgeonw_t *tp = (hashgeonw_t *)wmem_map_lookup(geonw_hashtable, pinfo->net_src.data); 2463 if (tp == NULL) { 2464 tp = geonw_hash_new_entry((const guint8 *)pinfo->net_src.data, FALSE); 2465 tp->sequence_number = sequence_number; 2466 tp->timestamp = timestamp; 2467 } else { 2468 if ((sequence_number <= SN_MAX) && (tp->sequence_number > SN_MAX)) { 2469 tp->sequence_number = sequence_number; 2470 tp->timestamp = timestamp; 2471 } 2472 else if (sequence_number <= SN_MAX) { 2473 /* 2474 * 1 P is the received GeoNetworking packet 2475 * 2 SN(P) is the sequence number in the received GeoNetworking packet 2476 * 3 SN(SO) is the last received sequence number from source SO 2477 * 4 SN_MAX is the maximum sequence number = 2^16 - 1 2478 * 5 TST(P) is the timestamp in the received GeoNetworking packet 2479 * 6 TST(SO) is the last received timestamp from source SO 2480 * 7 TST_MAX is the maximum value of the timestamp = 2^32 - 1 2481 * 8 2482 * 9 IF (((TST(P) > TST(SO) AND ((TST(P) - TST(SO)) <= TST_MAX/2)) OR 2483 * ((TST(SO) > TST(P)) AND ((TST(SO) - TST(P)) > TST_MAX/2))) THEN 2484 * 10 # TST(P) is greater than TST(SO) 2485 * 11 TST(SO) = TST(P) 2486 * 12 SN(SO) = SN(P) # P is not a duplicate packet 2487 * 13 ELSEIF TST(P) = TST(SO) THEN 2488 * 14 IF (((SN(P) > SN(SO) AND ((SN(P) - SN(SO)) <= SN_MAX/2)) OR 2489 * ((SN(SO) > SN(P)) AND ((SN(SO) - SN(P)) > SN_MAX/2))) THEN 2490 * 15 # SN(P) is greater than SN(SO) 2491 * 16 TST(SO) = TST(P) 2492 * 17 SN(SO) = SN(P) # P is not a duplicate packet 2493 * 18 ELSE 2494 * 19 # SN(P) is not greater than SN(SO) 2495 * 20 # P is a duplicate 2496 * 21 ENDIF 2497 * 22 ELSE 2498 * 23 # TST(P) not greater than TST(SO) 2499 * 24 ENDIF 2500 */ 2501 if (((timestamp > tp->timestamp) && (((guint64)timestamp - (guint64)tp->timestamp) <= (guint64)TST_MAX/2)) || 2502 ((tp->timestamp > timestamp) && (((guint64)tp->timestamp - (guint64)timestamp) > (guint64)TST_MAX/2))) { 2503 // TST(P) is greater than TST(SO) 2504 tp->sequence_number = sequence_number; 2505 tp->timestamp = timestamp; // P is not a duplicate packet 2506 } else if (timestamp == tp->timestamp) { 2507 if (((sequence_number > tp->sequence_number) && ((sequence_number - tp->sequence_number) <= SN_MAX/2)) || 2508 ((tp->sequence_number > sequence_number) && ((tp->sequence_number - sequence_number) > SN_MAX/2))) { 2509 // SN(P) is greater than SN(SO) 2510 tp->timestamp = timestamp; 2511 tp->sequence_number = sequence_number; // P is not a duplicate packet 2512 } else { 2513 // SN(P) is not greater than SN(SO) 2514 // P is a duplicate 2515 ti = proto_tree_add_item(geonw_tree, hf_geonw_analysis_flags, tvb, 0, 0, ENC_NA); 2516 proto_item_set_generated(ti); 2517 expert_add_info(pinfo, ti, &ei_geonw_analysis_duplicate); 2518 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Duplicate packet] "); 2519 } 2520 } // else { # TST(P) not greater than TST(SO) } 2521 } 2522 else { 2523 /* 2524 * 1 P is the received GeoNetworking packet 2525 * 2 TST(P) is the timestamp in the received GeoNetworking packet 2526 * 3 TST(SO) is the last received timestamp from source SO 2527 * 4 TS_MAX is the maximum value of the timestamp = 2^32 - 1 2528 * 5 2529 * 6 IF (((TST(P) > TST(SO) AND ((TST(P) - TST(SO)) <= TST_MAX/2)) OR 2530 * ((TST(SO) > TST(P)) AND ((TST(SO) - TST(P)) > TST_MAX/2))) THEN 2531 * 7 # TST(P) is greater than TST(SO) 2532 * 8 TST(SO) = TST(P) # P is not a duplicate packet 2533 * 9 ELSE 2534 * 10 # P is a duplicate 2535 * 11 ENDIF 2536 */ 2537 if (((timestamp > tp->timestamp) && (((guint64)timestamp - (guint64)tp->timestamp) <= (guint64)TST_MAX/2)) || 2538 ((tp->timestamp > timestamp) && (((guint64)tp->timestamp - (guint64)timestamp) > (guint64)TST_MAX/2))) { 2539 // TST(P) is greater than TST(SO) 2540 tp->timestamp = timestamp; // P is not a duplicate packet 2541 } else { 2542 // P is a duplicate 2543 ti = proto_tree_add_item(geonw_tree, hf_geonw_analysis_flags, tvb, 0, 0, ENC_NA); 2544 proto_item_set_generated(ti); 2545 expert_add_info(pinfo, ti, &ei_geonw_analysis_duplicate); 2546 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Duplicate packet] "); 2547 } 2548 } 2549 } 2550 } 2551 // XXX Implement DPD if version == 1 2552 2553 offset += 4; 2554 ti = proto_tree_add_item_ret_int(geonw_so_tree, hf_geonw_so_pv_lat, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon); 2555 if (latlon < -900000000 || latlon > 900000000) { 2556 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Latitude out of range (%f)", (float)latlon/10000000); 2557 } 2558 geonwh->gnw_lat = latlon; 2559 offset += 4; 2560 ti = proto_tree_add_item_ret_int(geonw_so_tree, hf_geonw_so_pv_lon, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon); 2561 if (latlon < -1800000000 || latlon > 1800000000) { 2562 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Longitude out of range (%f)", (float)latlon/10000000); 2563 } 2564 geonwh->gnw_lon = latlon; 2565 offset += 4; 2566 proto_tree_add_item(geonw_so_tree, hf_geonw_so_pv_pai, tvb, offset, 1, ENC_BIG_ENDIAN); 2567 proto_tree_add_item(geonw_so_tree, hf_geonw_so_pv_speed, tvb, offset, 2, ENC_BIG_ENDIAN); 2568 offset += 2; 2569 ti = proto_tree_add_item_ret_uint(geonw_so_tree, hf_geonw_so_pv_heading, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp_val); 2570 if (tmp_val > 3600) { 2571 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Out of range [0..360] (%f)", (float)tmp_val/10); 2572 } 2573 offset += 2; 2574 2575 proto_tree *geonw_de_tree = NULL; 2576 proto_tree *geonw_de_add_tree = NULL; 2577 switch(header_type) { 2578 case HTST_GEOUNICAST: 2579 case HTST_LS_REPLY: 2580 // Destination address 2581 ti = proto_tree_add_item(geonw_sh_tree, hf_geonw_de_pv, tvb, offset, 20, ENC_NA); 2582 geonw_de_tree = proto_item_add_subtree(ti, ett_geonw_de); 2583 2584 ti = proto_tree_add_item(geonw_de_tree, hf_geonw_de_pv_addr, tvb, offset, 8, ENC_NA); 2585 geonw_de_add_tree = proto_item_add_subtree(ti, ett_geonw_de); 2586 set_address_tvb(&pinfo->net_dst, geonw_address_type, 8, tvb, offset); 2587 copy_address_shallow(&pinfo->dst, &pinfo->net_dst); 2588 copy_address_shallow(&geonwh->gnw_dst, &pinfo->dst); 2589 2590 if (header_type == HTST_LS_REPLY) { 2591 transaction_end(pinfo, geonw_tree); 2592 } 2593 2594 proto_tree_add_item(geonw_de_add_tree, hf_geonw_de_pv_addr_manual, tvb, offset, 1, ENC_BIG_ENDIAN); 2595 proto_tree_add_item(geonw_de_add_tree, hf_geonw_de_pv_addr_type, tvb, offset, 1, ENC_BIG_ENDIAN); 2596 ti = proto_tree_add_item_ret_uint(geonw_de_add_tree, hf_geonw_de_pv_addr_country, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved); 2597 if (reserved > 999) { 2598 expert_add_info(pinfo, ti, &ei_geonw_scc_too_big); 2599 } 2600 offset += 2; 2601 proto_tree_add_item(geonw_de_add_tree, hf_geonw_de_pv_addr_mid, tvb, offset, 6, ENC_NA); 2602 offset += 6; 2603 2604 proto_tree_add_item(geonw_de_tree, hf_geonw_de_pv_time, tvb, offset, 4, ENC_BIG_ENDIAN); 2605 offset += 4; 2606 ti = proto_tree_add_item_ret_int(geonw_de_tree, hf_geonw_de_pv_lat, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon); 2607 if (latlon < -900000000 || latlon > 900000000) { 2608 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Latitude out of range (%f)", (float)latlon/10000000); 2609 } 2610 offset += 4; 2611 ti = proto_tree_add_item_ret_int(geonw_de_tree, hf_geonw_de_pv_lon, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon); 2612 if (latlon < -1800000000 || latlon > 1800000000) { 2613 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Longitude out of range (%f)", (float)latlon/10000000); 2614 } 2615 offset += 4; 2616 break; 2617 case HTST_TSB_SINGLE: 2618 // Reserved 32 bits 2619 // See usage in 636-4 subpart 2 for ITS-5G 2620 reserved = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN); 2621 if (reserved) { 2622 ti = proto_tree_add_item(geonw_sh_tree, hf_geonw_dccmco, tvb, offset, 4, ENC_NA); 2623 proto_tree *dccmco = proto_item_add_subtree(ti, ett_geonw_dccmco); 2624 proto_tree_add_item(dccmco, hf_geonw_dccmco_cbr_l_0_hop, tvb, offset, 1, ENC_BIG_ENDIAN); 2625 proto_tree_add_item(dccmco, hf_geonw_dccmco_cbr_l_1_hop, tvb, offset+1, 1, ENC_BIG_ENDIAN); 2626 proto_tree_add_item(dccmco, hf_geonw_dccmco_output_power, tvb, offset+2, 1, ENC_BIG_ENDIAN); 2627 proto_tree_add_item(dccmco, hf_geonw_dccmco_reserved, tvb, offset+2, 1, ENC_BIG_ENDIAN); 2628 proto_tree_add_item(dccmco, hf_geonw_shb_reserved, tvb, offset+3, 1, ENC_BIG_ENDIAN); 2629 } 2630 else { 2631 proto_tree_add_item(geonw_sh_tree, hf_geonw_shb_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); 2632 } 2633 offset += 4; 2634 break; 2635 case HTST_GAC_CIRCLE: 2636 case HTST_GAC_RECT: 2637 case HTST_GAC_ELLIPSE: 2638 case HTST_GBC_CIRCLE: 2639 case HTST_GBC_RECT: 2640 case HTST_GBC_ELLIPSE: 2641 ti = proto_tree_add_item_ret_int(geonw_sh_tree, hf_geonw_gxc_latitude, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon); 2642 if (latlon < -900000000 || latlon > 900000000) { 2643 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Latitude out of range (%f)", (float)latlon/10000000); 2644 } 2645 offset += 4; 2646 ti = proto_tree_add_item_ret_int(geonw_sh_tree, hf_geonw_gxc_longitude, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon); 2647 if (latlon < -1800000000 || latlon > 1800000000) { 2648 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Longitude out of range (%f)", (float)latlon/10000000); 2649 } 2650 offset += 4; 2651 switch(header_type&0x0f) { 2652 case HST_CIRCULAR: 2653 /* 2654 * According to EN 302 363-4-1: 2655 * In case of a circular area (GeoNetworking packet 2656 * sub-type HST = 0), the fields shall be set to the 2657 * following values: 2658 * 1) Distance a is set to the radius r. 2659 * 2) Distance b is set to 0. 2660 * 3) Angle is set to 0. 2661 */ 2662 proto_tree_add_item(geonw_sh_tree, hf_geonw_gxc_radius, tvb, offset, 2, ENC_BIG_ENDIAN); 2663 offset += 2; 2664 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_gxc_distanceb, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved); 2665 if (reserved) { 2666 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2667 } 2668 offset += 2; 2669 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_gxc_angle, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved); 2670 if (reserved) { 2671 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2672 } 2673 offset += 2; 2674 break; 2675 case HST_RECTANGULAR: 2676 case HST_ELLIPSOIDAL: 2677 proto_tree_add_item(geonw_sh_tree, hf_geonw_gxc_distancea, tvb, offset, 2, ENC_BIG_ENDIAN); 2678 offset += 2; 2679 proto_tree_add_item(geonw_sh_tree, hf_geonw_gxc_distanceb, tvb, offset, 2, ENC_BIG_ENDIAN); 2680 offset += 2; 2681 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_gxc_angle, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp_val); 2682 if (tmp_val > 360) { 2683 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Out of range [0..360] (%f)", (float)tmp_val); 2684 } 2685 offset += 2; 2686 } 2687 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_gxc_reserved, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved); 2688 if (reserved) { 2689 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved); 2690 } 2691 offset += 2; 2692 break; 2693 case HTST_LS_REQUEST: 2694 // GN_ADDR 2695 ti = proto_tree_add_item(geonw_sh_tree, hf_geonw_lsrq_addr, tvb, offset, 8, ENC_NA); 2696 geonw_de_add_tree = proto_item_add_subtree(ti, ett_geonw_lsrq_add); 2697 set_address_tvb(&pinfo->net_dst, geonw_address_type, 8, tvb, offset); 2698 copy_address_shallow(&pinfo->dst, &pinfo->net_dst); 2699 2700 proto_tree_add_item(geonw_de_add_tree, hf_geonw_lsrq_addr_manual, tvb, offset, 1, ENC_BIG_ENDIAN); 2701 proto_tree_add_item(geonw_de_add_tree, hf_geonw_lsrq_addr_type, tvb, offset, 1, ENC_BIG_ENDIAN); 2702 ti = proto_tree_add_item_ret_uint(geonw_de_add_tree, hf_geonw_lsrq_addr_country, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved); 2703 if (reserved > 999) { 2704 expert_add_info(pinfo, ti, &ei_geonw_scc_too_big); 2705 } 2706 offset += 2; 2707 proto_tree_add_item(geonw_de_add_tree, hf_geonw_lsrq_addr_mid, tvb, offset, 6, ENC_NA); 2708 offset += 6; 2709 transaction_start(pinfo, geonw_tree); 2710 break; 2711 //case HTST_BEACON: 2712 //case HTST_TSB_MULT: 2713 } 2714 proto_item_set_end(top_item, tvb, offset); 2715 2716 tap_queue_packet(geonw_tap, pinfo, geonwh); 2717 2718 if (payload_len) { 2719 // TODO expert info if payload_len different from remaining 2720 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, payload_len); 2721 switch(ch_next_header) { 2722 case CH_NH_BTP_A: 2723 call_dissector(btpa_handle, next_tvb, pinfo, tree); 2724 break; 2725 case CH_NH_BTP_B: 2726 call_dissector(btpb_handle, next_tvb, pinfo, tree); 2727 break; 2728 case CH_NH_IPV6: 2729 call_dissector(ipv6_handle, next_tvb, pinfo, tree); 2730 break; 2731 default: 2732 if (!dissector_try_uint(geonw_subdissector_table, ch_next_header, next_tvb, pinfo, tree)) { 2733 call_data_dissector(next_tvb, pinfo, tree); 2734 } 2735 } 2736 } 2737 2738 } 2739 2740 return tvb_captured_length(tvb); 2741 } 2742 2743 /* 2744 * Decode_as 2745 */ 2746 static void 2747 btpa_src_prompt(packet_info *pinfo _U_, gchar* result) 2748 { 2749 guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_btpa_srcport, pinfo->curr_layer_num)); 2750 2751 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "source (%u%s)", port, UTF8_RIGHTWARDS_ARROW); 2752 } 2753 2754 static gpointer 2755 btpa_src_value(packet_info *pinfo _U_) 2756 { 2757 return p_get_proto_data(pinfo->pool, pinfo, hf_btpa_srcport, pinfo->curr_layer_num); 2758 } 2759 2760 static void 2761 btpa_dst_prompt(packet_info *pinfo, gchar *result) 2762 { 2763 guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_btpa_dstport, pinfo->curr_layer_num)); 2764 2765 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW, port); 2766 } 2767 2768 static gpointer 2769 btpa_dst_value(packet_info *pinfo) 2770 { 2771 return p_get_proto_data(pinfo->pool, pinfo, hf_btpa_dstport, pinfo->curr_layer_num); 2772 } 2773 2774 static void 2775 btpa_both_prompt(packet_info *pinfo, gchar *result) 2776 { 2777 guint32 srcport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_btpa_srcport, pinfo->curr_layer_num)), 2778 destport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_btpa_dstport, pinfo->curr_layer_num)); 2779 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "both (%u%s%u)", srcport, UTF8_LEFT_RIGHT_ARROW, destport); 2780 } 2781 2782 static void 2783 btpb_dst_prompt(packet_info *pinfo, gchar *result) 2784 { 2785 guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_btpb_dstport, pinfo->curr_layer_num)); 2786 2787 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW, port); 2788 } 2789 2790 static gpointer 2791 btpb_dst_value(packet_info *pinfo) 2792 { 2793 return p_get_proto_data(pinfo->pool, pinfo, hf_btpb_dstport, pinfo->curr_layer_num); 2794 } 2795 2796 /* 2797 * Register 2798 */ 2799 void 2800 proto_register_btpa(void) 2801 { 2802 static hf_register_info hf_btpa[] = { 2803 // BTP A 2804 { &hf_btpa_dstport, 2805 { "Destination Port", "btpa.dstport", 2806 FT_UINT16, BASE_PT_UDP, NULL, 0x0, 2807 NULL, HFILL }}, 2808 2809 { &hf_btpa_srcport, 2810 { "Source Port", "btpa.srcport", 2811 FT_UINT16, BASE_PT_UDP, NULL, 0x0, 2812 NULL, HFILL }}, 2813 2814 { &hf_btpa_port, 2815 { "Port", "btpa.port", 2816 FT_UINT16, BASE_PT_UDP, NULL, 0x0, 2817 NULL, HFILL }}, 2818 2819 }; 2820 static gint *ett[] = { 2821 &ett_btpa, 2822 }; 2823 proto_btpa = proto_register_protocol("BTP-A", "BTPA", "btpa"); 2824 btpa_handle = register_dissector("btpa", dissect_btpa, proto_btpa); 2825 proto_register_field_array(proto_btpa, hf_btpa, array_length(hf_btpa)); 2826 2827 proto_register_subtree_array(ett, array_length(ett)); 2828 2829 // Register subdissector table 2830 btpa_subdissector_table = register_dissector_table("btpa.port", 2831 "BTP-A port", proto_btpa, FT_UINT16, BASE_HEX); 2832 2833 btpa_heur_subdissector_list = register_heur_dissector_list("btpa.payload", proto_btpa); 2834 2835 // Decode as 2836 static build_valid_func btpa_da_src_values[1] = {btpa_src_value}; 2837 static build_valid_func btpa_da_dst_values[1] = {btpa_dst_value}; 2838 static build_valid_func btpa_da_both_values[2] = {btpa_src_value, btpa_dst_value}; 2839 static decode_as_value_t btpa_da_values[3] = {{btpa_src_prompt, 1, btpa_da_src_values}, {btpa_dst_prompt, 1, btpa_da_dst_values}, {btpa_both_prompt, 2, btpa_da_both_values}}; 2840 static decode_as_t btpa_da = {"btpa", "btpa.port", 3, 2, btpa_da_values, "BTP-A", "port(s) as", 2841 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL}; 2842 2843 register_decode_as(&btpa_da); 2844 } 2845 2846 void 2847 proto_reg_handoff_btpa(void) 2848 { 2849 dissector_handle_t btpa_handle_; 2850 2851 btpa_handle_ = create_dissector_handle(dissect_btpa, proto_btpa); 2852 dissector_add_uint("geonw.ch.nh", 1, btpa_handle_); 2853 2854 find_dissector_add_dependency("gnw", proto_btpa); 2855 2856 btpa_tap = register_tap("btpa"); 2857 btpa_follow_tap = register_tap("btpa_follow"); 2858 } 2859 2860 void 2861 proto_register_btpb(void) 2862 { 2863 static hf_register_info hf_btpb[] = { 2864 // BTP B 2865 { &hf_btpb_dstport, 2866 { "Destination Port", "btpb.dstport", 2867 FT_UINT16, BASE_PT_UDP, NULL, 0x0, 2868 NULL, HFILL }}, 2869 2870 { &hf_btpb_dstport_info, 2871 { "Destination Port info", "btpb.dstportinf", 2872 FT_UINT16, BASE_HEX, NULL, 0x0, 2873 NULL, HFILL }}, 2874 2875 }; 2876 static gint *ett[] = { 2877 &ett_btpb, 2878 }; 2879 proto_btpb = proto_register_protocol("BTP-B", "BTPB", "btpb"); 2880 btpb_handle = register_dissector("btpb", dissect_btpb, proto_btpb); 2881 proto_register_field_array(proto_btpb, hf_btpb, array_length(hf_btpb)); 2882 2883 proto_register_subtree_array(ett, array_length(ett)); 2884 2885 // Register subdissector table 2886 btpb_subdissector_table = register_dissector_table("btpb.port", 2887 "BTP-B dst port", proto_btpb, FT_UINT16, BASE_HEX); 2888 2889 btpb_heur_subdissector_list = register_heur_dissector_list("btpb.payload", proto_btpb); 2890 2891 // Decode as 2892 static build_valid_func btpb_da_build_value[1] = {btpb_dst_value}; 2893 static decode_as_value_t btpb_da_values = {btpb_dst_prompt, 1, btpb_da_build_value}; 2894 static decode_as_t btpb_da = {"btpb", "btpb.port", 1, 0, &btpb_da_values, NULL, NULL, 2895 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL}; 2896 2897 register_decode_as(&btpb_da); 2898 } 2899 2900 void 2901 proto_reg_handoff_btpb(void) 2902 { 2903 dissector_handle_t btpb_handle_; 2904 2905 btpb_handle_ = create_dissector_handle(dissect_btpb, proto_btpb); 2906 dissector_add_uint("geonw.ch.nh", 2, btpb_handle_); 2907 2908 find_dissector_add_dependency("gnw", proto_btpb); 2909 2910 btpb_tap = register_tap("btpb"); 2911 btpb_follow_tap = register_tap("btpb_follow"); 2912 } 2913 2914 // Display functions 2915 static void 2916 display_latitude( gchar *result, gint32 hexver ) 2917 { 2918 g_snprintf( result, ITEM_LABEL_LENGTH, "%ud%u'%.2f\"%c (%d)", 2919 abs(hexver)/10000000, 2920 abs(hexver%10000000)*6/1000000, 2921 abs(hexver*6%1000000)*6./100000., 2922 hexver>=0?'N':'S', 2923 hexver); 2924 } 2925 2926 static void 2927 display_longitude( gchar *result, gint32 hexver ) 2928 { 2929 g_snprintf( result, ITEM_LABEL_LENGTH, "%ud%u'%.2f\"%c (%d)", 2930 abs(hexver)/10000000, 2931 abs(hexver%10000000)*6/1000000, 2932 abs(hexver*6%1000000)*6./100000., 2933 hexver>=0?'E':'W', 2934 hexver); 2935 } 2936 2937 static void 2938 display_speed( gchar *result, gint32 hexver ) 2939 { 2940 g_snprintf( result, ITEM_LABEL_LENGTH, "%.2f m/s", hexver/100.); 2941 } 2942 2943 static void 2944 display_heading( gchar *result, guint32 hexver ) 2945 { 2946 g_snprintf( result, ITEM_LABEL_LENGTH, "%.1f degrees", hexver/10.); 2947 } 2948 2949 static void 2950 display_elevation( gchar *result, gint32 hexver ) 2951 { 2952 // 0x0000 to 0xEFFF: positive numbers with a range from 0 to +6 143,9 meters. All numbers above +6 143,9 are 2953 // also represented by 0xEFFF. 2954 // 0xF001 to 0xFFFF: negative numbers with a range from -409,5 to -0,1 meters. All numbers below -409,5 are 2955 // also represented by 0xF001. 2956 // 0xF000: an unknown elevation 2957 if (hexver == -4096) 2958 g_snprintf( result, ITEM_LABEL_LENGTH, "Unknown (%4x)", hexver); 2959 else 2960 g_snprintf( result, ITEM_LABEL_LENGTH, "%.1fm", hexver/10.); 2961 } 2962 2963 void 2964 proto_register_geonw(void) 2965 { 2966 static const value_string bh_next_header_names[] = { 2967 { 0, "ANY" }, 2968 { 1, "Common Header" }, 2969 { 2, "Secured Packet" }, 2970 { 0, NULL} 2971 }; 2972 2973 static const value_string bh_lt_base_names[] = { 2974 { 0, "50 ms" }, 2975 { 1, "1 s" }, 2976 { 2, "10 s" }, 2977 { 3, "100 s"}, 2978 { 0, NULL} 2979 }; 2980 2981 static const value_string ch_next_header_names[] = { 2982 { 0, "ANY" }, 2983 { CH_NH_BTP_A, "BTP-A Transport protocol" }, 2984 { CH_NH_BTP_B, "BTP-B Transport protocol" }, 2985 { CH_NH_IPV6, "IPv6 header" }, 2986 { 0, NULL} 2987 }; 2988 2989 static const value_string traffic_classes_its_g5_names[] = { 2990 { 0, "ITS-G5 Access Category Voice" }, 2991 { 1, "ITS-G5 Access Category Video" }, 2992 { 2, "ITS-G5 Access Category Best effort" }, 2993 { 3, "ITS-G5 Access Category Background" }, 2994 { 0, NULL } 2995 }; 2996 2997 static const value_string itss_type_names[] = { 2998 { 0, "Unknown" }, 2999 { 1, "Pedestrian" }, 3000 { 2, "Cyclist" }, 3001 { 3, "Moped" }, 3002 { 4, "Motorcycle" }, 3003 { 5, "Passenger Car" }, 3004 { 6, "Bus" }, 3005 { 7, "Light Truck" }, 3006 { 8, "Heavy Truck" }, 3007 { 9, "Trailer" }, 3008 { 10, "Special Vehicle" }, 3009 { 11, "Tram" }, 3010 { 15, "Road Side Unit" }, 3011 { 0, NULL} 3012 }; 3013 3014 static hf_register_info hf_geonw[] = { 3015 3016 { &hf_geonw_bh, 3017 { "Basic Header", "geonw.bh", FT_NONE, BASE_NONE, NULL, 0x0, 3018 NULL, HFILL }}, 3019 3020 { &hf_geonw_bh_version, 3021 { "Version", "geonw.bh.version", 3022 FT_UINT8, BASE_DEC, NULL, 0xF0, 3023 NULL, HFILL }}, 3024 3025 { &hf_geonw_bh_reserved, 3026 { "Reserved", "geonw.bh.reserved", FT_UINT8, 3027 BASE_HEX, NULL, 0x0, "It SHOULD be set to 0", HFILL }}, 3028 3029 { &hf_geonw_bh_next_header, 3030 { "Next Header", "geonw.bh.nh", 3031 FT_UINT8, BASE_DEC, VALS(bh_next_header_names), 0x0F, 3032 NULL, HFILL }}, 3033 3034 { &hf_geonw_bh_life_time, 3035 { "Life Time", "geonw.bh.lt", 3036 FT_UINT8, BASE_DEC, NULL, 0x00, 3037 NULL, HFILL }}, 3038 3039 { &hf_geonw_bh_lt_mult, 3040 { "Life Time multiplier", "geonw.bh.lt.mult", 3041 FT_UINT8, BASE_DEC, NULL, 0xFC, 3042 NULL, HFILL }}, 3043 3044 { &hf_geonw_bh_lt_base, 3045 { "Life Time base", "geonw.bh.lt.base", 3046 FT_UINT8, BASE_DEC, VALS(bh_lt_base_names), 0x03, 3047 NULL, HFILL }}, 3048 3049 { &hf_geonw_bh_remain_hop_limit, 3050 { "Remaining Hop Limit", "geonw.bh.rhl", 3051 FT_UINT8, BASE_DEC, NULL, 0x00, 3052 NULL, HFILL }}, 3053 3054 { &hf_geonw_ch, 3055 { "Common Header", "geonw.ch", FT_NONE, BASE_NONE, NULL, 0x0, 3056 NULL, HFILL }}, 3057 3058 { &hf_geonw_ch_next_header, 3059 { "Next Header", "geonw.ch.nh", 3060 FT_UINT8, BASE_DEC, VALS(ch_next_header_names), 0xF0, 3061 NULL, HFILL }}, 3062 3063 { &hf_geonw_ch_reserved1, 3064 { "Reserved", "geonw.ch.reserved1", FT_UINT8, 3065 BASE_HEX, NULL, 0x0F, "It SHOULD be set to 0", HFILL }}, 3066 3067 { &hf_geonw_ch_header_type, 3068 { "Header type", "geonw.ch.htype", 3069 FT_UINT8, BASE_HEX, VALS(ch_header_type_names), 0x00, 3070 NULL, HFILL }}, 3071 3072 { &hf_geonw_ch_traffic_class, 3073 { "Traffic class", "geonw.ch.tclass", 3074 FT_UINT8, BASE_DEC, NULL, 0x00, 3075 NULL, HFILL }}, 3076 3077 { &hf_geonw_ch_tc_scf, 3078 { "Store Carry Forward", "geonw.ch.tc.buffer", 3079 FT_UINT8, BASE_DEC, NULL, 0x80, 3080 NULL, HFILL }}, 3081 3082 { &hf_geonw_ch_tc_offload, 3083 { "Channel offload", "geonw.ch.tc.offload", 3084 FT_UINT8, BASE_DEC, NULL, 0x40, 3085 NULL, HFILL }}, 3086 3087 { &hf_geonw_ch_tc_id, 3088 { "Traffic class ID", "geonw.ch.tc.id", 3089 FT_UINT8, BASE_DEC, VALS(traffic_classes_its_g5_names), 0x3F, 3090 NULL, HFILL }}, 3091 3092 { &hf_geonw_ch_flags, 3093 { "Flags", "geonw.ch.flags", FT_NONE, 3094 BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3095 3096 { &hf_geonw_ch_flags_mob, 3097 { "Mobility flag", "geonw.ch.flags.mob", 3098 FT_UINT8, BASE_DEC, NULL, 0x80, 3099 NULL, HFILL }}, 3100 3101 { &hf_geonw_ch_flags_reserved, 3102 { "Reserved", "geonw.ch.flags.reserved", 3103 FT_UINT8, BASE_DEC, NULL, 0x7F, 3104 NULL, HFILL }}, 3105 3106 { &hf_geonw_ch_payload_length, 3107 { "Payload length", "geonw.ch.plength", 3108 FT_UINT16, BASE_DEC, NULL, 0x00, 3109 NULL, HFILL }}, 3110 3111 { &hf_geonw_ch_max_hop_limit, 3112 { "Maximum Hop Limit", "geonw.ch.mhl", 3113 FT_UINT8, BASE_DEC, NULL, 0x00, 3114 NULL, HFILL }}, 3115 3116 { &hf_geonw_ch_reserved2, 3117 { "Reserved", "geonw.ch.reserved2", FT_UINT8, 3118 BASE_HEX, NULL, 0x00, "It SHOULD be set to 0", HFILL }}, 3119 3120 { &hf_geonw_seq_num, 3121 { "Sequence number", "geonw.seq_num", 3122 FT_UINT16, BASE_HEX, NULL, 0x00, 3123 NULL, HFILL }}, 3124 3125 { &hf_geonw_reserved, 3126 { "Reserved", "geonw.reserved", 3127 FT_UINT16, BASE_DEC, NULL, 0x00, 3128 NULL, HFILL }}, 3129 3130 // Long Position 3131 { &hf_geonw_so_pv, 3132 { "Source position", "geonw.src_pos", 3133 FT_BYTES, BASE_NONE, NULL, 0x00, 3134 NULL, HFILL }}, 3135 3136 { &hf_geonw_so_pv_addr, 3137 { "GN_ADDR", "geonw.src_pos.addr", 3138 FT_BYTES, BASE_NONE, NULL, 0x00, 3139 NULL, HFILL }}, 3140 3141 { &hf_geonw_so_pv_addr_manual, 3142 { "Manual", "geonw.src_pos.addr.manual", 3143 FT_UINT8, BASE_DEC, NULL, 0x80, 3144 NULL, HFILL }}, 3145 3146 { &hf_geonw_so_pv_addr_type, 3147 { "ITS-S type", "geonw.src_pos.addr.type", 3148 FT_UINT8, BASE_DEC, VALS(itss_type_names), 0x7C, 3149 NULL, HFILL }}, 3150 3151 { &hf_geonw_so_pv_addr_country, 3152 { "ITS-S Country Code", "geonw.src_pos.addr.country", 3153 FT_UINT16, BASE_DEC, VALS(E164_country_code_value), 0x03FF, 3154 NULL, HFILL }}, 3155 3156 { &hf_geonw_so_pv_addr_mid, 3157 { "MID", "geonw.src_pos.addr.mid", 3158 FT_ETHER, BASE_NONE, NULL, 0x0, 3159 NULL, HFILL }}, 3160 3161 { &hf_geonw_so_pv_time, 3162 { "Timestamp", "geonw.src_pos.tst", 3163 FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_milliseconds, 0x00, 3164 NULL, HFILL }}, 3165 3166 { &hf_geonw_so_pv_lat, 3167 { "Latitude", "geonw.src_pos.lat", 3168 FT_INT32, BASE_CUSTOM, CF_FUNC(display_latitude), 0x00, 3169 NULL, HFILL }}, 3170 3171 { &hf_geonw_so_pv_lon, 3172 { "Longitude", "geonw.src_pos.long", 3173 FT_INT32, BASE_CUSTOM, CF_FUNC(display_longitude), 0x00, 3174 NULL, HFILL }}, 3175 3176 { &hf_geonw_so_pv_pai, 3177 { "Position accuracy indicator", "geonw.src_pos.pai", 3178 FT_UINT8, BASE_DEC, NULL, 0x80, 3179 NULL, HFILL }}, 3180 3181 { &hf_geonw_so_pv_speed, 3182 { "Speed", "geonw.src_pos.speed", 3183 FT_INT16, BASE_CUSTOM, CF_FUNC(display_speed), 0x7FFF, 3184 NULL, HFILL }}, 3185 3186 { &hf_geonw_so_pv_heading, 3187 { "Heading", "geonw.src_pos.hdg", 3188 FT_UINT16, BASE_CUSTOM, CF_FUNC(display_heading), 0x00, 3189 NULL, HFILL }}, 3190 3191 // Decentralized Congestion Control - Multi Channel Operation 3192 { &hf_geonw_dccmco, 3193 { "Decentralized Congestion Control - Multi Channel Operation", "geonw.dccmco", 3194 FT_NONE, BASE_NONE, NULL, 0x00, 3195 NULL, HFILL }}, 3196 3197 { &hf_geonw_dccmco_cbr_l_0_hop, 3198 { "Local channel busy ratio", "geonw.cbr_l0hop", 3199 FT_UINT8, BASE_DEC, NULL, 0x80, 3200 NULL, HFILL }}, 3201 3202 { &hf_geonw_dccmco_cbr_l_1_hop, 3203 { "Max neighbouring CBR", "geonw.cbr_l1hop", 3204 FT_UINT8, BASE_DEC, NULL, 0x80, 3205 NULL, HFILL }}, 3206 3207 { &hf_geonw_dccmco_output_power, 3208 { "Output power", "geonw.outpower", 3209 FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_dbm, 0xf8, 3210 NULL, HFILL }}, 3211 3212 { &hf_geonw_dccmco_reserved, 3213 { "Reserved", "geonw.dccmco.reserved", 3214 FT_UINT8, BASE_DEC, NULL, 0x07, 3215 NULL, HFILL }}, 3216 3217 // Short Position 3218 { &hf_geonw_de_pv, 3219 { "Destination position", "geonw.dst_pos", 3220 FT_BYTES, BASE_NONE, NULL, 0x00, 3221 NULL, HFILL }}, 3222 3223 { &hf_geonw_de_pv_addr, 3224 { "GN_ADDR", "geonw.dst_pos.addr", 3225 FT_BYTES, BASE_NONE, NULL, 0x00, 3226 NULL, HFILL }}, 3227 3228 { &hf_geonw_de_pv_addr_manual, 3229 { "Manual", "geonw.dst_pos.addr.manual", 3230 FT_UINT8, BASE_DEC, NULL, 0x80, 3231 NULL, HFILL }}, 3232 3233 { &hf_geonw_de_pv_addr_type, 3234 { "ITS-S type", "geonw.dst_pos.addr.type", 3235 FT_UINT8, BASE_DEC, VALS(itss_type_names), 0x7C, 3236 NULL, HFILL }}, 3237 3238 { &hf_geonw_de_pv_addr_country, 3239 { "ITS-S Country Code", "geonw.dst_pos.addr.country", 3240 FT_UINT16, BASE_DEC, VALS(E164_country_code_value), 0x03FF, 3241 NULL, HFILL }}, 3242 3243 { &hf_geonw_de_pv_addr_mid, 3244 { "MID", "geonw.dst_pos.addr.mid", 3245 FT_ETHER, BASE_NONE, NULL, 0x0, 3246 NULL, HFILL }}, 3247 3248 { &hf_geonw_de_pv_time, 3249 { "Timestamp", "geonw.dst_pos.tst", 3250 FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_milliseconds, 0x00, 3251 NULL, HFILL }}, 3252 3253 { &hf_geonw_de_pv_lat, 3254 { "Latitude", "geonw.dst_pos.lat", 3255 FT_INT32, BASE_CUSTOM, CF_FUNC(display_latitude), 0x00, 3256 NULL, HFILL }}, 3257 3258 { &hf_geonw_de_pv_lon, 3259 { "Longitude", "geonw.dst_pos.long", 3260 FT_INT32, BASE_CUSTOM, CF_FUNC(display_longitude), 0x00, 3261 NULL, HFILL }}, 3262 3263 // GBC/GAC 3264 { &hf_geonw_gxc_latitude, 3265 { "Latitude", "geonw.gxc.latitude", 3266 FT_INT32, BASE_CUSTOM, CF_FUNC(display_latitude), 0x00, 3267 NULL, HFILL }}, 3268 3269 { &hf_geonw_gxc_longitude, 3270 { "Longitude", "geonw.gxc.longitude", 3271 FT_INT32, BASE_CUSTOM, CF_FUNC(display_longitude), 0x00, 3272 NULL, HFILL }}, 3273 3274 { &hf_geonw_gxc_radius, 3275 { "Radius r", "geonw.gxc.radius", 3276 FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_meters, 0x00, 3277 NULL, HFILL }}, 3278 3279 { &hf_geonw_gxc_distancea, 3280 { "Distance a", "geonw.gxc.distancea", 3281 FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_meters, 0x00, 3282 NULL, HFILL }}, 3283 3284 { &hf_geonw_gxc_distanceb, 3285 { "Distance b", "geonw.gxc.distanceb", 3286 FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_meters, 0x00, 3287 NULL, HFILL }}, 3288 3289 { &hf_geonw_gxc_angle, 3290 { "Angle", "geonw.gxc.angle", 3291 FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_degree_degrees, 0x00, 3292 NULL, HFILL }}, 3293 3294 { &hf_geonw_gxc_reserved, 3295 { "Reserved", "geonw.gxc.reserved", 3296 FT_UINT16, BASE_DEC, NULL, 0x00, 3297 NULL, HFILL }}, 3298 3299 // SHB 3300 { &hf_geonw_shb_reserved, 3301 { "Reserved", "geonw.shb.reserved", 3302 FT_UINT32, BASE_DEC, NULL, 0x00, 3303 NULL, HFILL }}, 3304 3305 // LS Request 3306 { &hf_geonw_lsrq_addr, 3307 { "GN_ADDR", "geonw.ls_req.addr", 3308 FT_BYTES, BASE_NONE, NULL, 0x00, 3309 NULL, HFILL }}, 3310 3311 { &hf_geonw_lsrq_addr_manual, 3312 { "Manual", "geonw.ls_req.addr.manual", 3313 FT_UINT8, BASE_DEC, NULL, 0x80, 3314 NULL, HFILL }}, 3315 3316 { &hf_geonw_lsrq_addr_type, 3317 { "ITS-S type", "geonw.ls_req.addr.type", 3318 FT_UINT8, BASE_DEC, VALS(itss_type_names), 0x7C, 3319 NULL, HFILL }}, 3320 3321 { &hf_geonw_lsrq_addr_country, 3322 { "ITS-S Country Code", "geonw.ls_req.addr.country", 3323 FT_UINT16, BASE_DEC, VALS(E164_country_code_value), 0x03FF, 3324 NULL, HFILL }}, 3325 3326 { &hf_geonw_lsrq_addr_mid, 3327 { "MID", "geonw.ls_req.addr.mid", 3328 FT_ETHER, BASE_NONE, NULL, 0x0, 3329 NULL, HFILL }}, 3330 3331 { &hf_geonw_beacon, 3332 { "Beacon Packet", "geonw.beacon", FT_NONE, 3333 BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3334 3335 { &hf_geonw_guc, 3336 { "GeoUniCast Packet", "geonw.guc", FT_NONE, 3337 BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3338 3339 { &hf_geonw_gac, 3340 { "GeoAnyCast Packet", "geonw.gac", FT_NONE, 3341 BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3342 3343 { &hf_geonw_gbc, 3344 { "GeoBroadCast Packet", "geonw.gbc", FT_NONE, 3345 BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3346 3347 { &hf_geonw_tsb, 3348 { "Topologically-Scoped Broadcast Packet", "geonw.tsb", FT_NONE, 3349 BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3350 3351 { &hf_geonw_ls, 3352 { "Location Service Packet", "geonw.ls", FT_NONE, 3353 BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3354 3355 { &hf_geonw_resp_in, 3356 { "Response frame", "geonw.resp_in", FT_FRAMENUM, BASE_NONE, 3357 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0, 3358 "The frame number of the corresponding response", 3359 HFILL}}, 3360 3361 { &hf_geonw_no_resp, 3362 { "No response seen", "geonw.no_resp", FT_NONE, BASE_NONE, 3363 NULL, 0x0, 3364 "No corresponding response frame was seen", 3365 HFILL}}, 3366 3367 { &hf_geonw_resp_to, 3368 { "Request frame", "geonw.resp_to", FT_FRAMENUM, BASE_NONE, 3369 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0, 3370 "The frame number of the corresponding request", HFILL}}, 3371 3372 { &hf_geonw_resptime, 3373 { "Response time", "geonw.resptime", FT_DOUBLE, BASE_NONE, 3374 NULL, 0x0, 3375 "The time between the request and the response, in ms.", 3376 HFILL}}, 3377 3378 { &hf_geonw_analysis_flags, 3379 { "GeoNetworking Analysis Flags", "geonw.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0, 3380 "This frame has some of the GeoNetworking analysis flags set", HFILL }}, 3381 3382 // Secures packets 3383 { &hf_geonw_sec, 3384 { "Secured Packet", "geonw.sec", FT_NONE, BASE_NONE, NULL, 0x0, 3385 NULL, HFILL }}, 3386 3387 { &hf_sgeonw_version, 3388 { "Version", "geonw.sec.version", 3389 FT_UINT8, BASE_DEC, NULL, 0x0, 3390 NULL, HFILL }}, 3391 3392 { &hf_sgeonw_profile, 3393 { "Profile", "geonw.sec.profile", 3394 FT_UINT8, BASE_DEC, NULL, 0x0, 3395 NULL, HFILL }}, 3396 3397 { &hf_sgeonw_hdr, 3398 { "Header fields", "geonw.sec.hdr", FT_NONE, BASE_NONE, NULL, 0x0, 3399 NULL, HFILL }}, 3400 3401 { &hf_sgeonw_pl, 3402 { "Payload fields", "geonw.sec.pl", FT_NONE, BASE_NONE, NULL, 0x0, 3403 NULL, HFILL }}, 3404 3405 { &hf_sgeonw_trl, 3406 { "Trailer fields", "geonw.sec.trl", FT_NONE, BASE_NONE, NULL, 0x0, 3407 NULL, HFILL }}, 3408 3409 { &hf_sgeonw_public_key, 3410 { "Public key", "geonw.sec.pub_key", FT_NONE, BASE_NONE, NULL, 0x0, 3411 NULL, HFILL }}, 3412 3413 { &hf_sgeonw_certificate, 3414 { "Certificate", "geonw.sec.certif", FT_NONE, BASE_NONE, NULL, 0x0, 3415 NULL, HFILL }}, 3416 3417 { &hf_sgeonw_var_len, 3418 { "Var length", "geonw.sec.var_len", FT_NONE, BASE_NONE, NULL, 0x0, 3419 NULL, HFILL }}, 3420 3421 { &hf_sgeonw_var_len_det, 3422 { "Var length determinant", "geonw.sec.var_len.det", 3423 FT_UINT8, BASE_HEX, NULL, 0x0, 3424 NULL, HFILL }}, 3425 3426 { &hf_sgeonw_var_len_val, 3427 { "Var length value", "geonw.sec.var_len.value", 3428 FT_UINT32, BASE_DEC, NULL, 0x0, 3429 NULL, HFILL }}, 3430 3431 { &hf_sgeonw_intx, 3432 { "IntX", "geonw.sec.intx", FT_NONE, BASE_NONE, NULL, 0x0, 3433 NULL, HFILL }}, 3434 3435 { &hf_sgeonw_header_field, 3436 { "Header field", "geonw.sec.hdr_field", FT_NONE, BASE_NONE, NULL, 0x0, 3437 NULL, HFILL }}, 3438 3439 { &hf_sgeonw_payload_field, 3440 { "Payload field", "geonw.sec.pl_field", FT_NONE, BASE_NONE, NULL, 0x0, 3441 NULL, HFILL }}, 3442 3443 { &hf_sgeonw_trailer_field, 3444 { "Trailer field", "geonw.sec.trl_field", FT_NONE, BASE_NONE, NULL, 0x0, 3445 NULL, HFILL }}, 3446 3447 { &hf_sgeonw_signer_info, 3448 { "Signer info", "geonw.sec.signer_info", FT_NONE, BASE_NONE, NULL, 0x0, 3449 NULL, HFILL }}, 3450 3451 { &hf_sgeonw_eccpoint, 3452 { "ECC Point", "geonw.sec.eccpoint", FT_NONE, BASE_NONE, NULL, 0x0, 3453 NULL, HFILL }}, 3454 3455 { &hf_sgeonw_duration, 3456 { "Duration", "geonw.sec.duration", FT_NONE, BASE_NONE, NULL, 0x0, 3457 NULL, HFILL }}, 3458 3459 { &hf_sgeonw_subject_assurance, 3460 { "Subject assurance", "geonw.sec.subj_assur", FT_NONE, BASE_NONE, NULL, 0x0, 3461 NULL, HFILL }}, 3462 3463 { &hf_sgeonw_encryption_parameter, 3464 { "Encryption parameter", "geonw.sec.encrypt_param", FT_NONE, BASE_NONE, NULL, 0x0, 3465 NULL, HFILL }}, 3466 3467 { &hf_sgeonw_signature, 3468 { "Signature", "geonw.sec.signature", FT_NONE, BASE_NONE, NULL, 0x0, 3469 NULL, HFILL }}, 3470 3471 { &hf_sgeonw_subject_info, 3472 { "Subject info", "geonw.sec.subj_info", FT_NONE, BASE_NONE, NULL, 0x0, 3473 NULL, HFILL }}, 3474 3475 { &hf_sgeonw_subject_attribute, 3476 { "Subject attribute", "geonw.sec.subj_attr", FT_NONE, BASE_NONE, NULL, 0x0, 3477 NULL, HFILL }}, 3478 3479 { &hf_sgeonw_opaque, 3480 { "Opaque", "geonw.sec.opaque", FT_BYTES, BASE_NONE, NULL, 0x0, 3481 NULL, HFILL }}, 3482 3483 { &hf_sgeonw_encrypted_key, 3484 { "Encrypted key", "geonw.sec.enc_key", FT_BYTES, BASE_NONE, NULL, 0x0, 3485 NULL, HFILL }}, 3486 3487 { &hf_sgeonw_auth_tag, 3488 { "Authentication tag", "geonw.sec.auth_tag", FT_BYTES, BASE_NONE, NULL, 0x0, 3489 NULL, HFILL }}, 3490 3491 { &hf_sgeonw_ecdsasignature_s, 3492 { "s", "geonw.sec.signature.s", FT_BYTES, BASE_NONE, NULL, 0x0, 3493 NULL, HFILL }}, 3494 3495 { &hf_sgeonw_eccpoint_x, 3496 { "x", "geonw.sec.eccpoint.x", FT_BYTES, BASE_NONE, NULL, 0x0, 3497 NULL, HFILL }}, 3498 3499 { &hf_sgeonw_eccpoint_y, 3500 { "y", "geonw.sec.eccpoint.y", FT_BYTES, BASE_NONE, NULL, 0x0, 3501 NULL, HFILL }}, 3502 3503 { &hf_sgeonw_hashedid8, 3504 { "Hashed ID 8", "geonw.sec.hashedid8", FT_BYTES, BASE_NONE, NULL, 0x0, 3505 NULL, HFILL }}, 3506 3507 { &hf_sgeonw_encryption_parameter_nonce, 3508 { "Nonce", "geonw.sec.nonce", FT_BYTES, BASE_NONE, NULL, 0x0, 3509 NULL, HFILL }}, 3510 3511 { &hf_sgeonw_header_field_type_v1, { "Header field type", "geonw.sec.hdr_fld_type", FT_UINT8, BASE_DEC, VALS(header_field_type_v1_names), 0x0, NULL, HFILL }}, 3512 { &hf_sgeonw_header_field_type_v2, { "Header field type", "geonw.sec.hdr_fld_type", FT_UINT8, BASE_DEC, VALS(header_field_type_v2_names), 0x0, NULL, HFILL }}, 3513 { &hf_sgeonw_payload_field_type, { "Payload field type", "geonw.sec.pl_fld_type", FT_UINT8, BASE_DEC, VALS(payload_field_type_names), 0x0, NULL, HFILL }}, 3514 { &hf_sgeonw_trailer_field_type, { "Trailer field type", "geonw.sec.trl_fld_type", FT_UINT8, BASE_DEC, VALS(trailer_field_type_names), 0x0, NULL, HFILL }}, 3515 { &hf_sgeonw_public_key_algorithm, { "Public key algorithm", "geonw.sec.pubkeyalgo", FT_UINT8, BASE_DEC, VALS(public_key_algorithm_names), 0x0, NULL, HFILL }}, 3516 { &hf_sgeonw_eccpoint_type, { "EccPoint type", "geonw.sec.eccpoint_type", FT_UINT8, BASE_DEC, VALS(eccpoint_type_names), 0x0, NULL, HFILL }}, 3517 { &hf_sgeonw_signer_info_type, { "Signer info type", "geonw.sec.signer_info_type", FT_UINT8, BASE_DEC, VALS(signer_info_type_names), 0x0, NULL, HFILL }}, 3518 { &hf_sgeonw_validity_restriction_type, { "Validity restriction type", "geonw.sec.val_rest_type", FT_UINT8, BASE_DEC, VALS(validity_restriction_type_names), 0x0, NULL, HFILL }}, 3519 { &hf_sgeonw_subject_type, { "Subject type", "geonw.sec.subject_type", FT_UINT8, BASE_DEC, VALS(subject_type_names), 0x0, NULL, HFILL }}, 3520 { &hf_sgeonw_subject_attribute_type_v1, { "Subject attribute", "geonw.sec.subject_attr", FT_UINT8, BASE_DEC, VALS(subject_attribute_type_v1_names), 0x0, NULL, HFILL }}, 3521 { &hf_sgeonw_subject_attribute_type_v2, { "Subject attribute", "geonw.sec.subject_attr", FT_UINT8, BASE_DEC, VALS(subject_attribute_type_v2_names), 0x0, NULL, HFILL }}, 3522 { &hf_sgeonw_symmetric_algorithm, { "Symmetric algorithm", "geonw.sec.symalgo", FT_UINT8, BASE_DEC, VALS(symmetric_algorithm_names), 0x0, NULL, HFILL }}, 3523 { &hf_sgeonw_region_type, { "Region type", "geonw.sec.regiontype", FT_UINT8, BASE_DEC, VALS(region_type_names), 0x0, NULL, HFILL }}, 3524 { &hf_sgeonw_region_dictionary, { "Region dictionary", "geonw.sec.regiondict", FT_UINT8, BASE_DEC, VALS(region_dictionary_names), 0x0, NULL, HFILL }}, 3525 3526 { &hf_sgeonw_region_identifier, { "Region identifier", "geonw.sec.regionid", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3527 { &hf_sgeonw_local_region, { "Local region", "geonw.sec.local_region", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3528 3529 { &hf_sgeonw_certification_version, { "Certification version", "geonw.sec.certif.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3530 3531 { &hf_sgeonw_time64, { "Time64", "geonw.sec.time64", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3532 { &hf_sgeonw_conf, { "Confidence", "geonw.sec.confidence", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3533 { &hf_sgeonw_time32, { "Time32", "geonw.sec.time32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3534 { &hf_sgeonw_lat, { "Latitude", "geonw.sec.lat", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3535 { &hf_sgeonw_lon, { "Longitude", "geonw.sec.lon", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3536 { &hf_sgeonw_elev, { "Elevation", "geonw.sec.elev", FT_INT16, BASE_CUSTOM, CF_FUNC(display_elevation), 0x0, NULL, HFILL }}, 3537 { &hf_sgeonw_hashedid3, { "Hashed ID 3", "geonw.sec.hashedid3", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3538 { &hf_sgeonw_duration_unit, { "Unit", "geonw.sec.duration.unit", FT_UINT16, BASE_DEC, VALS(sgeonw_duration_unit_names), 0xe000, NULL, HFILL }}, 3539 { &hf_sgeonw_duration_value, { "Value", "geonw.sec.duration.value", FT_UINT16, BASE_DEC, NULL, 0x1fff, NULL, HFILL }}, 3540 { &hf_sgeonw_radius, { "Radius", "geonw.sec.radius", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3541 { &hf_sgeonw_priority, { "Priority", "geonw.sec.priority", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3542 { &hf_sgeonw_subject_assurance_assurance, { "Subject assurance", "geonw.sec.subj_assur.assurance", FT_UINT8, BASE_DEC, NULL, 0xe0, NULL, HFILL }}, 3543 { &hf_sgeonw_subject_assurance_reserved, { "Reserved", "geonw.sec.subj_assur.reserved", FT_UINT8, BASE_DEC, NULL, 0x1c, NULL, HFILL }}, 3544 { &hf_sgeonw_subject_assurance_confidence, { "Subject assurance", "geonw.sec.subj_assur.confidence", FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL }}, 3545 { &hf_sgeonw_msg_id, { "Message ID", "geonw.sec.msg_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3546 { &hf_sgeonw_app_id, { "Application ID", "geonw.sec.app_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, 3547 3548 }; 3549 3550 static ei_register_info ei[] = { 3551 { &ei_geonw_nz_reserved, { "geonw.reserved_not_zero", PI_PROTOCOL, PI_WARN, "Incorrect, should be 0", EXPFILL }}, 3552 { &ei_geonw_version_err, { "geonw.bogus_version", PI_MALFORMED, PI_ERROR, "Bogus GeoNetworking Version", EXPFILL }}, 3553 { &ei_geonw_rhl_lncb, { "geonw.rhl.lncb", PI_SEQUENCE, PI_NOTE, "Remaining Hop Limit", EXPFILL }}, 3554 { &ei_geonw_rhl_too_low, { "geonw.rhl.too_small", PI_SEQUENCE, PI_NOTE, "Remaining Hop Limit", EXPFILL }}, 3555 { &ei_geonw_mhl_lt_rhl, { "geonw.rhl.ht_mhl", PI_SEQUENCE, PI_WARN, "Remaining Hop Limit To Live", EXPFILL }}, 3556 { &ei_geonw_scc_too_big, { "geonw.scc_too_big", PI_MALFORMED, PI_ERROR, "Country code should be less than 1000", EXPFILL }}, 3557 { &ei_geonw_analysis_duplicate, { "geonw.analysis_duplicate", PI_SEQUENCE, PI_NOTE, "Duplicate packet", EXPFILL }}, 3558 { &ei_geonw_resp_not_found, { "geonw.resp_not_found", PI_SEQUENCE, PI_WARN, "Response not found", EXPFILL }}, 3559 { &ei_geonw_out_of_range, { "geonw.position_oor", PI_MALFORMED, PI_WARN, "Position out of range", EXPFILL }}, 3560 { &ei_geonw_payload_len, { "geonw.bogus_geonw_length", PI_PROTOCOL, PI_ERROR, "Bogus GeoNetworking length", EXPFILL }}, 3561 { &ei_sgeonw_len_unsupported, { "geonw.sec.len_unsup", PI_MALFORMED, PI_ERROR, "Length not supported", EXPFILL }}, 3562 { &ei_sgeonw_len_too_long, { "geonw.sec.bogus_len", PI_MALFORMED, PI_ERROR, "Length of int shall be at most 7 bits long", EXPFILL }}, 3563 { &ei_sgeonw_subj_info_too_long, { "geonw.sec.bogus_sinfo", PI_MALFORMED, PI_ERROR, "Subject info length shall be at most 255", EXPFILL }}, 3564 { &ei_sgeonw_ssp_too_long, { "geonw.sec.bogus_ssp", PI_MALFORMED, PI_ERROR, "Service specific permission length shall be at most 31", EXPFILL }}, 3565 { &ei_sgeonw_bogus, { "geonw.sec.bogus", PI_MALFORMED, PI_ERROR, "Malformed message (check length)", EXPFILL }}, 3566 }; 3567 static gint *ett[] = { 3568 &ett_geonw, 3569 &ett_geonw_bh, 3570 &ett_geonw_bh_lt, 3571 &ett_geonw_ch, 3572 &ett_geonw_ch_tc, 3573 &ett_geonw_sh, 3574 &ett_geonw_so, 3575 &ett_geonw_so_add, 3576 &ett_geonw_de, 3577 &ett_geonw_de_add, 3578 &ett_geonw_lsrq_add, 3579 &ett_geonw_analysis, 3580 &ett_geonw_dccmco, 3581 3582 &ett_geonw_sec, // Secured packet 3583 &ett_sgeonw_hdr, // Parts (header, payload or trailer) subtree 3584 &ett_sgeonw_field, // Field subtree 3585 &ett_sgeonw_var_len, // Variable length subtree 3586 &ett_sgeonw_intx, 3587 &ett_sgeonw_duration, 3588 &ett_sgeonw_eccpoint, 3589 &ett_sgeonw_subject_assurance, 3590 &ett_sgeonw_public_key, 3591 &ett_sgeonw_encryption_parameter, 3592 &ett_sgeonw_signature, 3593 &ett_sgeonw_subject_info, 3594 &ett_sgeonw_subject_attribute, 3595 &ett_sgeonw_ssp, 3596 }; 3597 3598 expert_module_t* expert_geonw; 3599 module_t *geonw_module; 3600 3601 proto_geonw = proto_register_protocol("GeoNetworking", "GNW", "gnw"); 3602 3603 3604 geonw_handle = register_dissector("gnw", dissect_geonw, proto_geonw); 3605 3606 proto_register_field_array(proto_geonw, hf_geonw, array_length(hf_geonw)); 3607 proto_register_subtree_array(ett, array_length(ett)); 3608 3609 expert_geonw = expert_register_protocol(proto_geonw); 3610 expert_register_field_array(expert_geonw, ei, array_length(ei)); 3611 3612 geonw_subdissector_table = register_dissector_table("geonw.ch.nh", 3613 "GeoNetworking Next Header", proto_geonw, FT_UINT8, BASE_HEX); 3614 3615 ssp_subdissector_table = register_dissector_table("geonw.ssp", 3616 "ATS-AID/PSID based dissector for Service Specific Permissions (SSP)", proto_geonw, FT_UINT32, BASE_HEX); 3617 3618 geonw_address_type = address_type_dissector_register("AT_GEONW", "GeoNetworking address", geonw_to_str, geonw_str_len, NULL, geonw_col_filter_str, geonw_len, geonw_name_resolution_str, geonw_name_resolution_len); 3619 3620 /* Register configuration preferences */ 3621 geonw_module = prefs_register_protocol(proto_geonw, NULL); 3622 prefs_register_bool_preference(geonw_module, "analyze_sequence_numbers", 3623 "Analyze GeoNetworking sequence numbers", 3624 "Make the GeoNetworking dissector analyze GeoNetworking sequence numbers to find and flag duplicate packet (Annex A)", 3625 &geonw_analyze_seq); 3626 3627 geonw_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), geonw_addr_hash, geonw_addr_cmp); 3628 } 3629 3630 void 3631 proto_reg_handoff_geonw(void) 3632 { 3633 dissector_handle_t geonw_handle_; 3634 dissector_handle_t sgeonw_handle_; 3635 3636 geonw_handle_ = create_dissector_handle(dissect_geonw, proto_geonw); 3637 sgeonw_handle_ = create_dissector_handle(dissect_sgeonw, proto_geonw); 3638 3639 dissector_add_uint_with_preference("ethertype", ETHERTYPE_GEONETWORKING, geonw_handle_); 3640 3641 // IPv6 over GeoNetworking Protocols 3642 ipv6_handle = find_dissector("ipv6"); 3643 dissector_add_uint("geonw.ch.nh", 3, ipv6_handle); 3644 3645 geonw_tap = register_tap("geonw"); 3646 3647 ieee1609dot2_handle = find_dissector_add_dependency("ieee1609dot2.data", proto_geonw); 3648 3649 dissector_add_uint("ieee1609dot2.psid", psid_den_basic_services, sgeonw_handle_); 3650 dissector_add_uint("ieee1609dot2.psid", psid_ca_basic_services, sgeonw_handle_); 3651 dissector_add_uint("ieee1609dot2.psid", psid_traffic_light_manoeuver_service, sgeonw_handle_); 3652 dissector_add_uint("ieee1609dot2.psid", psid_road_and_lane_topology_service, sgeonw_handle_); 3653 dissector_add_uint("ieee1609dot2.psid", psid_infrastructure_to_vehicle_information_service, sgeonw_handle_); 3654 dissector_add_uint("ieee1609dot2.psid", psid_traffic_light_control_requests_service, sgeonw_handle_); 3655 dissector_add_uint("ieee1609dot2.psid", psid_geonetworking_management_communications, sgeonw_handle_); 3656 dissector_add_uint("ieee1609dot2.psid", psid_traffic_light_control_status_service, sgeonw_handle_); 3657 dissector_add_uint("ieee1609dot2.psid", psid_collective_perception_service, sgeonw_handle_); 3658 3659 } 3660 3661 /* 3662 * Editor modelines - https://www.wireshark.org/tools/modelines.html 3663 * 3664 * Local variables: 3665 * c-basic-offset: 4 3666 * tab-width: 8 3667 * indent-tabs-mode: nil 3668 * End: 3669 * 3670 * vi: set shiftwidth=4 tabstop=8 expandtab: 3671 * :indentSize=4:tabSize=8:noTabs=true: 3672 */ 3673