2 * Routines for GeoNetworking and BTP-A/B dissection
3 * Coyright 2018, C. Guerber <cguerber@yahoo.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
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)
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)
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
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
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
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)
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
58 #include <epan/packet.h>
59 #include <epan/expert.h>
60 #include <epan/decode_as.h>
61 #include <epan/proto_data.h>
62 #include <epan/address_types.h>
63 #include <epan/addr_resolv.h>
64 #include <epan/to_str.h>
65 #include <epan/conversation.h>
67 #include <epan/etypes.h>
68 #include <epan/unit_strings.h>
70 #include <wsutil/utf8_entities.h>
72 #include "packet-e164.h"
73 #include "packet-ieee1609dot2.h"
74 #include "packet-geonw.h"
79 void proto_reg_handoff_btpb(void);
80 void proto_register_btpb(void);
81 void proto_reg_handoff_btpa(void);
82 void proto_register_btpa(void);
83 void proto_reg_handoff_geonw(void);
84 void proto_register_geonw(void);
92 // Definition of header types See section 8.7.4 table 9
93 #define HT_BEACON 0x10
94 #define HT_GEOUNICAST 0x20
95 #define HT_GEOANYCAST 0x30
96 #define HT_GEOBROADCAST 0x40
101 #define HST_CIRCULAR 0x00
102 #define HST_RECTANGULAR 0x01
103 #define HST_ELLIPSOIDAL 0x02
106 #define HST_SINGLE_HOP 0x00
107 #define HST_MULTI_HOP 0x01
110 #define HST_REQUEST 0x00
111 #define HST_REPLY 0x01
113 // Types and subtype combined
114 #define HTST_BEACON (HT_BEACON)
115 #define HTST_GEOUNICAST (HT_GEOUNICAST)
116 #define HTST_GAC_CIRCLE (HT_GEOANYCAST|HST_CIRCULAR)
117 #define HTST_GAC_RECT (HT_GEOANYCAST|HST_RECTANGULAR)
118 #define HTST_GAC_ELLIPSE (HT_GEOANYCAST|HST_ELLIPSOIDAL)
119 #define HTST_GBC_CIRCLE (HT_GEOBROADCAST|HST_CIRCULAR)
120 #define HTST_GBC_RECT (HT_GEOBROADCAST|HST_RECTANGULAR)
121 #define HTST_GBC_ELLIPSE (HT_GEOBROADCAST|HST_ELLIPSOIDAL)
122 #define HTST_TSB_SINGLE (HT_TSB|HST_SINGLE_HOP)
123 #define HTST_TSB_MULT (HT_TSB|HST_MULTI_HOP)
124 #define HTST_LS_REQUEST (HT_LS|HST_REQUEST)
125 #define HTST_LS_REPLY (HT_LS|HST_REPLY)
127 #define HT_GET(ht) ((ht)&HT_MASK)
128 #define HST_GET(ht) ((ht)&HST_MASK)
129 #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)))))
132 #define BH_NH_COMMON_HDR 1
133 #define BH_NH_SECURED_PKT 2
136 #define CH_NH_BTP_A 1
137 #define CH_NH_BTP_B 2
144 #define BEACON_LEN 24
145 #define LS_REQUEST_LEN 36
146 #define LS_REPLY_LEN 48
148 #define TST_MAX 0xffffffff
150 #define SEC_TVB_KEY 0
155 static wmem_map_t
*geonw_hashtable
;
157 static int proto_geonw
;
158 static int proto_btpa
;
159 static int proto_btpb
;
161 static int geonw_tap
;
163 static int btpa_follow_tap
;
165 static int btpb_follow_tap
;
167 static int hf_geonw_bh
;
168 static int hf_geonw_bh_version
;
169 static int hf_geonw_bh_next_header
;
170 static int hf_geonw_bh_reserved
;
171 static int hf_geonw_bh_life_time
;
172 static int hf_geonw_bh_lt_mult
;
173 static int hf_geonw_bh_lt_base
;
174 static int hf_geonw_bh_remain_hop_limit
;
176 static int hf_geonw_ch
;
177 static int hf_geonw_ch_next_header
;
178 static int hf_geonw_ch_reserved1
;
179 static int hf_geonw_ch_header_type
;
180 //static int hf_geonw_ch_header_subtype;
181 static int hf_geonw_ch_traffic_class
;
182 static int hf_geonw_ch_tc_scf
;
183 static int hf_geonw_ch_tc_offload
;
184 static int hf_geonw_ch_tc_id
;
185 static int hf_geonw_ch_flags
;
186 static int hf_geonw_ch_flags_mob
;
187 static int hf_geonw_ch_flags_reserved
;
188 static int hf_geonw_ch_payload_length
;
189 static int hf_geonw_ch_max_hop_limit
;
190 static int hf_geonw_ch_reserved2
;
192 static int hf_geonw_seq_num
;
193 static int hf_geonw_reserved
;
194 static int hf_geonw_so_pv
;
195 static int hf_geonw_so_pv_addr
;
196 static int hf_geonw_so_pv_addr_manual
;
197 static int hf_geonw_so_pv_addr_type
;
198 static int hf_geonw_so_pv_addr_country
;
199 static int hf_geonw_so_pv_addr_mid
;
200 static int hf_geonw_so_pv_time
;
201 static int hf_geonw_so_pv_lat
;
202 static int hf_geonw_so_pv_lon
;
203 static int hf_geonw_so_pv_pai
;
204 static int hf_geonw_so_pv_speed
;
205 static int hf_geonw_so_pv_heading
;
206 static int hf_geonw_de_pv
;
207 static int hf_geonw_de_pv_addr
;
208 static int hf_geonw_de_pv_addr_manual
;
209 static int hf_geonw_de_pv_addr_type
;
210 static int hf_geonw_de_pv_addr_country
;
211 static int hf_geonw_de_pv_addr_mid
;
212 static int hf_geonw_de_pv_time
;
213 static int hf_geonw_de_pv_lat
;
214 static int hf_geonw_de_pv_lon
;
216 static int hf_geonw_gxc_latitude
;
217 static int hf_geonw_gxc_longitude
;
218 static int hf_geonw_gxc_radius
;
219 static int hf_geonw_gxc_distancea
;
220 static int hf_geonw_gxc_distanceb
;
221 static int hf_geonw_gxc_angle
;
222 static int hf_geonw_gxc_reserved
;
224 static int hf_geonw_shb_reserved
;
226 static int hf_geonw_lsrq_addr
;
227 static int hf_geonw_lsrq_addr_manual
;
228 static int hf_geonw_lsrq_addr_type
;
229 static int hf_geonw_lsrq_addr_country
;
230 static int hf_geonw_lsrq_addr_mid
;
232 static int hf_geonw_beacon
;
233 static int hf_geonw_guc
;
234 static int hf_geonw_gac
;
235 static int hf_geonw_gbc
;
236 static int hf_geonw_tsb
;
237 static int hf_geonw_ls
;
238 static int hf_geonw_analysis_flags
;
240 static int hf_btpa_dstport
;
241 static int hf_btpa_srcport
;
242 static int hf_btpa_port
;
243 static int hf_btpb_dstport
;
244 static int hf_btpb_dstport_info
;
246 static int hf_geonw_resp_in
;
247 static int hf_geonw_resp_to
;
248 static int hf_geonw_no_resp
;
249 static int hf_geonw_resptime
;
251 static int hf_geonw_dccmco
;
252 static int hf_geonw_dccmco_cbr_l_0_hop
;
253 static int hf_geonw_dccmco_cbr_l_1_hop
;
254 static int hf_geonw_dccmco_output_power
;
255 static int hf_geonw_dccmco_reserved
;
257 static int ett_geonw
;
258 static int ett_geonw_bh
;
259 static int ett_geonw_bh_lt
;
260 static int ett_geonw_ch
;
261 static int ett_geonw_ch_tc
;
262 static int ett_geonw_sh
;
263 static int ett_geonw_so
;
264 static int ett_geonw_so_add
;
265 static int ett_geonw_de
;
266 static int ett_geonw_de_add
;
267 static int ett_geonw_lsrq_add
;
268 static int ett_geonw_analysis
;
269 static int ett_geonw_dccmco
;
273 static int geonw_address_type
= -1;
275 static expert_field ei_geonw_nz_reserved
;
276 static expert_field ei_geonw_version_err
;
277 static expert_field ei_geonw_rhl_lncb
;
278 static expert_field ei_geonw_rhl_too_low
;
279 static expert_field ei_geonw_mhl_lt_rhl
;
280 static expert_field ei_geonw_scc_too_big
;
281 static expert_field ei_geonw_analysis_duplicate
;
282 static expert_field ei_geonw_resp_not_found
;
283 static expert_field ei_geonw_out_of_range
;
284 static expert_field ei_geonw_payload_len
;
285 static expert_field ei_geonw_intx_too_big
;
287 static dissector_table_t geonw_subdissector_table
;
288 static dissector_table_t ssp_subdissector_table
;
289 static dissector_table_t btpa_subdissector_table
;
290 static dissector_table_t btpb_subdissector_table
;
292 static const value_string ch_header_type_names
[] = {
293 { HTST_BEACON
, "Beacon" },
294 { HTST_GEOUNICAST
, "Geo Unicast" },
295 { HTST_GAC_CIRCLE
, "Geo-scoped Anycast Circular area" },
296 { HTST_GAC_RECT
, "Geo-scoped Anycast Rectangular area" },
297 { HTST_GAC_ELLIPSE
, "Geo-scoped Anycast Ellipsoidal area" },
298 { HTST_GBC_CIRCLE
, "Geo-scoped Broadcast Circular area" },
299 { HTST_GBC_RECT
, "Geo-scoped Broadcast Rectangular area" },
300 { HTST_GBC_ELLIPSE
, "Geo-scoped Broadcast Ellipsoidal area" },
301 { HTST_TSB_SINGLE
, "Topologically-scoped broadcast Single-hop broadcast (SHB)" },
302 { HTST_TSB_MULT
, "Topologically-scoped broadcast Multi-hop broadcast (TSB)" },
303 { HTST_LS_REQUEST
, "Location Service Request" },
304 { HTST_LS_REPLY
, "Location Service Reply" },
308 static dissector_handle_t ieee1609dot2_handle
;
309 static dissector_handle_t geonw_handle
;
310 static dissector_handle_t btpa_handle
;
311 static dissector_handle_t btpb_handle
;
312 static dissector_handle_t ipv6_handle
;
314 static heur_dissector_list_t btpa_heur_subdissector_list
;
315 static heur_dissector_list_t btpb_heur_subdissector_list
;
318 * Basic Transport Protocol A dissector
321 dissect_btpa(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
323 heur_dtbl_entry_t
*hdtbl_entry
;
324 int low_port
, high_port
;
325 int dst_port
, src_port
;
326 proto_item
*hidden_item
;
327 struct btpaheader
*btpah
;
329 btpah
= wmem_new0(pinfo
->pool
, struct btpaheader
);
331 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "BTPA");
332 /* Clear out stuff in the info column */
333 col_clear(pinfo
->cinfo
,COL_INFO
);
335 proto_item
*ti
= proto_tree_add_item(tree
, proto_btpa
, tvb
, 0, 4, ENC_NA
);
336 proto_tree
*btpa_tree
= proto_item_add_subtree(ti
, ett_btpa
);
338 proto_tree_add_item_ret_uint(btpa_tree
, hf_btpa_dstport
, tvb
, 0, 2, ENC_BIG_ENDIAN
, &dst_port
);
339 proto_tree_add_item_ret_uint(btpa_tree
, hf_btpa_srcport
, tvb
, 2, 2, ENC_BIG_ENDIAN
, &src_port
);
341 pinfo
->srcport
= src_port
;
342 pinfo
->destport
= dst_port
;
344 col_append_ports(pinfo
->cinfo
, COL_INFO
, PT_NONE
, pinfo
->srcport
, pinfo
->destport
);
346 // Add hidden port field
347 hidden_item
= proto_tree_add_item(btpa_tree
, hf_btpa_port
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
348 proto_item_set_hidden(hidden_item
);
349 hidden_item
= proto_tree_add_item(btpa_tree
, hf_btpa_port
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
350 proto_item_set_hidden(hidden_item
);
352 btpah
->btp_psrc
= src_port
;
353 btpah
->btp_pdst
= dst_port
;
354 copy_address_shallow(&btpah
->gnw_src
, &pinfo
->src
);
355 copy_address_shallow(&btpah
->gnw_dst
, &pinfo
->dst
);
356 tap_queue_packet(btpa_tap
, pinfo
, btpah
);
358 tvbuff_t
*next_tvb
= tvb_new_subset_remaining(tvb
, 4);
360 if (have_tap_listener(btpa_follow_tap
))
361 tap_queue_packet(btpa_follow_tap
, pinfo
, next_tvb
);
363 if (src_port
> dst_port
) {
365 high_port
= src_port
;
368 high_port
= dst_port
;
371 if (dissector_try_uint_with_data(btpa_subdissector_table
, low_port
, next_tvb
, pinfo
, tree
, true, NULL
))
372 return tvb_captured_length(tvb
);
374 if (dissector_try_uint_with_data(btpa_subdissector_table
, high_port
, next_tvb
, pinfo
, tree
, true, NULL
))
375 return tvb_captured_length(tvb
);
377 if (dissector_try_heuristic(btpa_heur_subdissector_list
, next_tvb
, pinfo
, tree
, &hdtbl_entry
, NULL
))
378 return tvb_captured_length(tvb
);
380 call_data_dissector(next_tvb
, pinfo
, tree
);
381 return tvb_captured_length(tvb
);
385 * Basic Transport Protocol B dissector
388 dissect_btpb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
390 heur_dtbl_entry_t
*hdtbl_entry
;
393 struct btpbheader
*btpbh
;
395 btpbh
= wmem_new0(pinfo
->pool
, struct btpbheader
);
397 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "BTPB");
398 /* Clear out stuff in the info column */
399 col_clear(pinfo
->cinfo
,COL_INFO
);
401 proto_item
*ti
= proto_tree_add_item(tree
, proto_btpb
, tvb
, 0, 4, ENC_NA
);
402 proto_tree
*btpb_tree
= proto_item_add_subtree(ti
, ett_btpb
);
404 proto_tree_add_item_ret_uint(btpb_tree
, hf_btpb_dstport
, tvb
, 0, 2, ENC_BIG_ENDIAN
, &dst_port
);
405 proto_tree_add_item_ret_uint(btpb_tree
, hf_btpb_dstport_info
, tvb
, 2, 2, ENC_BIG_ENDIAN
, &dst_info
);
407 pinfo
->destport
= dst_port
;
409 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " " UTF8_RIGHTWARDS_ARROW
" %u", dst_port
);
411 btpbh
->btp_pdst
= dst_port
;
412 btpbh
->btp_idst
= dst_info
;
413 copy_address_shallow(&btpbh
->gnw_src
, &pinfo
->src
);
414 copy_address_shallow(&btpbh
->gnw_dst
, &pinfo
->dst
);
415 tap_queue_packet(btpb_tap
, pinfo
, btpbh
);
417 tvbuff_t
*next_tvb
= tvb_new_subset_remaining(tvb
, 4);
419 if (have_tap_listener(btpb_follow_tap
))
420 tap_queue_packet(btpb_follow_tap
, pinfo
, next_tvb
);
422 if (dissector_try_uint_with_data(btpb_subdissector_table
, dst_port
, next_tvb
, pinfo
, tree
, true, NULL
)) {
423 return tvb_captured_length(tvb
);
425 if (dissector_try_heuristic(btpb_heur_subdissector_list
, next_tvb
, pinfo
, tree
, &hdtbl_entry
, NULL
)) {
426 return tvb_captured_length(tvb
);
429 call_data_dissector(next_tvb
, pinfo
, tree
);
430 return tvb_captured_length(tvb
);
434 * ===========================================================================
435 * GeoNetworking dissector
436 * ===========================================================================
439 typedef struct _geonw_transaction_t
{
444 } geonw_transaction_t
;
446 typedef struct _geonw_conv_info_t
{
447 wmem_stack_t
*unmatched_pdus
;
448 wmem_tree_t
*matched_pdus
;
451 static const char * get_geonw_name(const uint8_t *addr
);
452 static const char* geonw_name_resolution_str(const address
* addr
);
453 static int geonw_name_resolution_len(void);
455 static geonw_transaction_t
*transaction_start(packet_info
* pinfo
, proto_tree
* tree
);
456 static geonw_transaction_t
*transaction_end(packet_info
* pinfo
, proto_tree
* tree
);
458 static bool geonw_analyze_seq
= true;
461 * GeoNetworking Address Type
464 /* Adapter from ethernet and ipv4 Address Type code */
466 typedef struct hashgeonw hashgeonw_t
;
472 char resolved_name
[MAXNAMELEN
];
474 // Node follow up used for duplication detection
476 uint32_t sequence_number
;
481 geonw_str_len(const address
* addr _U_
)
483 // (0/1)'.'(0..31)'.'(0..1023)'.'{eth}
488 _geonw_to_str(const uint8_t* addrdata
, char *buf
, int buf_len _U_
)
493 if (addrdata
[0] & 0x80)
499 uint32_to_str_buf((addrdata
[0] & 0x7C) >> 2, buf
, 26);
500 buf
+= (unsigned) strlen(buf
);
503 uint32_to_str_buf(((uint32_t)(addrdata
[0] & 0x03) << 8) + addrdata
[1], buf
, 23); // > 23
504 buf
+= (unsigned) strlen(buf
);
507 set_address(ð_addr
, AT_ETHER
, 6, &(addrdata
[2]));
508 ether_to_str(ð_addr
, buf
, 18);
514 geonw_to_str(const address
* addr
, char *buf
, int buf_len _U_
)
516 return _geonw_to_str((const uint8_t *)addr
->data
, buf
, buf_len
);
520 geonw_col_filter_str(const address
* addr _U_
, bool is_src
)
523 return "geonw.src_pos.addr";
525 return "geonw.dst_pos.addr";
535 geonw_addr_hash(const void *key
)
537 return wmem_strong_hash((const uint8_t *)key
, 8);
541 geonw_addr_cmp(const void *a
, const void *b
)
543 return (memcmp(a
, b
, 8) == 0);
547 * These two value_string are used for address resolv:
549 static const value_string itss_type_small_names
[] = {
566 /* Resolve geonetworking address */
568 geonw_addr_resolve(hashgeonw_t
*tp
) {
569 const uint8_t *addr
= tp
->addr
;
571 char *rname
= tp
->resolved_name
;
582 val
= (addr
[0] & 0x7C) >> 2;
583 const char *string
= try_val_to_str(val
, itss_type_small_names
);
584 if (string
== NULL
) {
585 uint32_to_str_buf(val
, rname
, MAXNAMELEN
-2);
586 l1
= (uint8_t) strlen(rname
);
589 l1
= (uint8_t) g_strlcpy(rname
, string
, MAXNAMELEN
-2);
594 val
= ((uint32_t)(addr
[0] & 0x03) << 8) + addr
[1];
595 string
= try_val_to_str(val
, E164_ISO3166_country_code_short_value
);
596 if (string
== NULL
) {
597 uint32_to_str_buf(val
, rname
, MAXNAMELEN
-12);
598 l2
= (uint8_t) strlen(rname
);
601 l2
= (uint8_t) g_strlcpy(rname
, string
, MAXNAMELEN
-l1
-3);
607 set_address(ð_addr
, AT_ETHER
, 6, &(addr
[2]));
608 ether_to_str(ð_addr
, rname
, 18);
609 // We could use ether_name_resolution_str:
610 // (void) g_strlcpy(rname, ether_name_resolution_str(ð_addr), MAXNAMELEN-l1-4);
618 geonw_hash_new_entry(const uint8_t *addr
, bool resolve
)
622 tp
= wmem_new(wmem_file_scope(), hashgeonw_t
);
623 memcpy(tp
->addr
, addr
, sizeof(tp
->addr
));
624 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
625 _geonw_to_str(addr
, tp
->hexaddr
, 28);
626 tp
->resolved_name
[0] = '\0';
629 tp
->sequence_number
= SN_MAX
+ 1;
632 geonw_addr_resolve(tp
);
634 wmem_map_insert(geonw_hashtable
, tp
->addr
, tp
);
637 } /* geonw_hash_new_entry */
640 geonw_name_lookup(const uint8_t *addr
, bool resolve
)
644 tp
= (hashgeonw_t
*)wmem_map_lookup(geonw_hashtable
, addr
);
647 tp
= geonw_hash_new_entry(addr
, resolve
);
649 if (resolve
&& !tp
->status
) {
650 geonw_addr_resolve(tp
); /* Found but needs to be resolved */
656 } /* geonw_name_lookup */
659 get_geonw_name(const uint8_t *addr
)
662 bool resolve
= gbl_resolv_flags
.network_name
;
664 tp
= geonw_name_lookup(addr
, resolve
);
666 return resolve
? tp
->resolved_name
: tp
->hexaddr
;
668 } /* get_geonw_name */
670 const char* geonw_name_resolution_str(const address
* addr
)
672 return get_geonw_name((const uint8_t *)addr
->data
);
675 int geonw_name_resolution_len(void)
677 return MAX_ADDR_STR_LEN
; /* XXX - This can be lower */
681 * Conversations for GeoNetworking
684 /* Adapted from ICMP echo request/reply code */
686 /* GeoNw LS request/reply transaction statistics ... */
687 static geonw_transaction_t
*transaction_start(packet_info
* pinfo
, proto_tree
* tree
)
689 conversation_t
*conversation
;
690 geonw_conv_info_t
*geonw_info
;
691 geonw_transaction_t
*geonw_trans
;
692 wmem_tree_key_t geonw_key
[3];
695 /* Handle the conversation tracking */
696 conversation
= find_conversation(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
), HT_LS
, HT_LS
, 0);
697 if (conversation
== NULL
) {
698 /* No, this is a new conversation. */
699 conversation
= conversation_new(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
), HT_LS
, HT_LS
, 0);
701 geonw_info
= (geonw_conv_info_t
*)conversation_get_proto_data(conversation
, proto_geonw
);
702 if (geonw_info
== NULL
) {
703 geonw_info
= wmem_new(wmem_file_scope(), geonw_conv_info_t
);
704 geonw_info
->unmatched_pdus
= wmem_stack_new(wmem_file_scope());
705 geonw_info
->matched_pdus
= wmem_tree_new(wmem_file_scope());
706 conversation_add_proto_data(conversation
, proto_geonw
, geonw_info
);
709 if (!PINFO_FD_VISITED(pinfo
)) {
710 /* this is a new request, create a new transaction structure and map it to the
713 geonw_trans
= wmem_new(wmem_file_scope(), geonw_transaction_t
);
714 geonw_trans
->rqst_frame
= pinfo
->num
;
715 geonw_trans
->resp_frame
= 0;
716 geonw_trans
->rqst_time
= pinfo
->abs_ts
;
717 nstime_set_zero(&geonw_trans
->resp_time
);
718 wmem_stack_push(geonw_info
->unmatched_pdus
, (void *) geonw_trans
);
720 /* Already visited this frame */
721 uint32_t frame_num
= pinfo
->num
;
723 geonw_key
[0].length
= 1;
724 geonw_key
[0].key
= &frame_num
;
725 geonw_key
[1].length
= 0;
726 geonw_key
[1].key
= NULL
;
728 geonw_trans
= (geonw_transaction_t
*)wmem_tree_lookup32_array(geonw_info
->matched_pdus
, geonw_key
);
730 if (geonw_trans
== NULL
) {
731 if (PINFO_FD_VISITED(pinfo
)) {
732 /* No response found - add field and expert info */
733 it
= proto_tree_add_item(tree
, hf_geonw_no_resp
, NULL
, 0, 0, ENC_NA
);
734 proto_item_set_generated(it
);
736 col_append_str(pinfo
->cinfo
, COL_INFO
, " (no response found!)");
739 expert_add_info_format(pinfo
, it
, &ei_geonw_resp_not_found
, "No response seen to LS Request");
745 /* Print state tracking in the tree */
746 if (geonw_trans
->resp_frame
) {
747 it
= proto_tree_add_uint(tree
, hf_geonw_resp_in
, NULL
, 0, 0, geonw_trans
->resp_frame
);
748 proto_item_set_generated(it
);
750 col_append_frame_number(pinfo
, COL_INFO
, " (reply in %u)", geonw_trans
->resp_frame
);
755 } /* transaction_start() */
757 static geonw_transaction_t
*transaction_end(packet_info
* pinfo
, proto_tree
* tree
)
759 conversation_t
*conversation
;
760 geonw_conv_info_t
*geonw_info
;
761 geonw_transaction_t
*geonw_trans
;
762 wmem_tree_key_t geonw_key
[3];
767 conversation
= find_conversation(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, conversation_pt_to_conversation_type(pinfo
->ptype
), HT_LS
, HT_LS
, 0);
768 if (conversation
== NULL
) {
772 geonw_info
= (geonw_conv_info_t
*)conversation_get_proto_data(conversation
, proto_geonw
);
773 if (geonw_info
== NULL
) {
777 if (!PINFO_FD_VISITED(pinfo
)) {
780 geonw_trans
= (geonw_transaction_t
*)wmem_stack_peek(geonw_info
->unmatched_pdus
);
781 if (geonw_trans
== NULL
) {
785 /* we have already seen this response, or an identical one */
786 if (geonw_trans
->resp_frame
!= 0) {
790 geonw_trans
->resp_frame
= pinfo
->num
;
792 /* we found a match. Add entries to the matched table for both request and reply frames
794 geonw_key
[0].length
= 1;
795 geonw_key
[0].key
= &frame_num
;
796 geonw_key
[1].length
= 0;
797 geonw_key
[1].key
= NULL
;
799 frame_num
= geonw_trans
->rqst_frame
;
800 wmem_tree_insert32_array(geonw_info
->matched_pdus
, geonw_key
, (void *) geonw_trans
);
802 frame_num
= geonw_trans
->resp_frame
;
803 wmem_tree_insert32_array(geonw_info
->matched_pdus
, geonw_key
, (void *) geonw_trans
);
805 /* Already visited this frame */
806 uint32_t frame_num
= pinfo
->num
;
808 geonw_key
[0].length
= 1;
809 geonw_key
[0].key
= &frame_num
;
810 geonw_key
[1].length
= 0;
811 geonw_key
[1].key
= NULL
;
813 geonw_trans
= (geonw_transaction_t
*)wmem_tree_lookup32_array(geonw_info
->matched_pdus
, geonw_key
);
815 if (geonw_trans
== NULL
) {
821 it
= proto_tree_add_uint(tree
, hf_geonw_resp_to
, NULL
, 0, 0, geonw_trans
->rqst_frame
);
822 proto_item_set_generated(it
);
824 nstime_delta(&ns
, &pinfo
->abs_ts
, &geonw_trans
->rqst_time
);
825 geonw_trans
->resp_time
= ns
;
826 resp_time
= nstime_to_msec(&ns
);
827 it
= proto_tree_add_double_format_value(tree
, hf_geonw_resptime
, NULL
, 0, 0, resp_time
, "%.3f ms", resp_time
);
828 proto_item_set_generated(it
);
830 col_append_frame_number(pinfo
, COL_INFO
, " (request in %d)", geonw_trans
->rqst_frame
);
834 } /* transaction_end() */
836 // Adapted from TCP sequence number analysis
839 struct geonw_analysis
{
840 // Node follow up used for duplication detection
842 uint16_t sequence_number
;
846 * Secured geonetworking
849 static int hf_geonw_sec
;
850 static int hf_sgeonw_version
;
851 static int hf_sgeonw_profile
;
852 static int hf_sgeonw_hdr
;
853 static int hf_sgeonw_pl
;
854 static int hf_sgeonw_trl
;
855 static int hf_sgeonw_var_len
;
856 static int hf_sgeonw_var_len_det
;
857 static int hf_sgeonw_var_len_val
;
858 static int hf_sgeonw_header_field
;
859 static int hf_sgeonw_header_field_type_v1
;
860 static int hf_sgeonw_header_field_type_v2
;
861 static int hf_sgeonw_opaque
;
863 static int hf_sgeonw_payload_field
;
864 static int hf_sgeonw_payload_field_type
;
866 static int hf_sgeonw_trailer_field
;
867 static int hf_sgeonw_trailer_field_type
;
869 static int hf_sgeonw_certificate
;
870 static int hf_sgeonw_encryption_parameter
;
871 static int hf_sgeonw_signature
;
872 static int hf_sgeonw_subject_info
;
873 static int hf_sgeonw_subject_attribute
;
875 static int hf_sgeonw_intx
;
876 static int hf_sgeonw_time64
;
877 static int hf_sgeonw_conf
;
878 static int hf_sgeonw_time32
;
879 static int hf_sgeonw_lat
;
880 static int hf_sgeonw_lon
;
881 static int hf_sgeonw_elev
;
882 static int hf_sgeonw_hashedid3
;
883 static int hf_sgeonw_hashedid8
;
884 static int hf_sgeonw_duration
;
885 static int hf_sgeonw_duration_unit
;
886 static int hf_sgeonw_duration_value
;
887 static int hf_sgeonw_encryption_parameter_nonce
;
889 static int hf_sgeonw_msg_id
;
890 static int hf_sgeonw_app_id
;
892 static int ett_geonw_sec
;
893 static int ett_sgeonw_hdr
;
894 static int ett_sgeonw_field
;
895 static int ett_sgeonw_var_len
;
896 static int ett_sgeonw_intx
;
897 static int ett_sgeonw_duration
;
898 static int ett_sgeonw_encryption_parameter
;
899 static int ett_sgeonw_signature
;
900 static int ett_sgeonw_subject_info
;
901 static int ett_sgeonw_subject_attribute
;
902 static int ett_sgeonw_ssp
;
904 static expert_field ei_sgeonw_len_unsupported
;
905 static expert_field ei_sgeonw_len_too_long
;
906 static expert_field ei_sgeonw_subj_info_too_long
;
907 static expert_field ei_sgeonw_ssp_too_long
;
908 static expert_field ei_sgeonw_bogus
;
912 generation_time_confidence
= 1,
914 generation_location
= 3,
915 request_unrecognized_certificate
= 4,
918 recipient_info
= 129,
919 encryption_parameters
= 130,
921 last_hdr_type
= (2<<8)-1
924 static const value_string header_field_type_v1_names
[] = {
925 { generation_time
, "Generation time" },
926 { generation_time_confidence
, "Generation time confidence" },
927 { expiration
, "Expiration" },
928 { generation_location
, "Generation location" },
929 { request_unrecognized_certificate
, "Request unrecognized certificate" },
930 { message_type
, "Message type" },
931 { signer_info
, "Signer info" },
932 { recipient_info
, "Recipient info" },
933 { encryption_parameters
, "Encryption parameters" },
937 static const value_string header_field_type_v2_names
[] = {
938 { generation_time
, "Generation time" },
939 { generation_time_confidence
, "Generation time standard deviation" },
940 { expiration
, "Expiration" },
941 { generation_location
, "Generation location" },
942 { request_unrecognized_certificate
, "Request unrecognized certificate" },
943 { message_type
, "ITS Application ID" }, // Change in definition
944 { signer_info
, "Signer info" },
945 { recipient_info
, "Encryption parameters" }, // Change in definition
946 { encryption_parameters
, "Recipient info" }, // Change in definition
955 signed_and_encrypted
= 4,
957 last_pl_type
= (2<<8)-1
960 static const value_string payload_field_type_names
[] = {
961 { unsecured
, "Unsecured" },
962 { signed_pl
, "Signed" },
963 { encrypted
, "Encrypted" },
964 { signed_external
, "Signed external" },
965 { signed_and_encrypted
, "Signed and encrypted" },
972 last_trl_type
= (2<<8)-1
975 static const value_string trailer_field_type_names
[] = {
976 { signature
, "signature" },
980 static int hf_sgeonw_signer_info
;
981 static int hf_sgeonw_signer_info_type
;
985 certificate_digest_with_ecdsap256
= 1,
987 certificate_chain
= 3,
988 certificate_digest_with_other_algorithm
= 4,
990 //reserved(240..255),
992 last_sif_type
= (2<<8)-1
995 static const value_string signer_info_type_names
[] = {
996 { self
, "Self signed" },
997 { certificate_digest_with_ecdsap256
, "Certificate digest with ecdsap256" },
998 { certificate
, "Certificate" },
999 { certificate_chain
, "Certificate chain" },
1000 { certificate_digest_with_other_algorithm
, "Certificate digest with other algorithm" },
1004 static int hf_sgeonw_public_key
;
1005 static int ett_sgeonw_public_key
;
1006 static int hf_sgeonw_public_key_algorithm
;
1007 static int hf_sgeonw_ecdsasignature_s
;
1010 ecdsa_nistp256_with_sha256
= 0,
1013 // reserved(240..255),
1015 last_pubkey_algo
= (2<<8)-1
1016 } PublicKeyAlgorithm
;
1018 static const value_string public_key_algorithm_names
[] = {
1019 { ecdsa_nistp256_with_sha256
, "ECDSA nistp256 with SHA256" },
1020 { ecies_nistp256
, "ECIES nistp256" },
1024 static const int etsits103097_table_2
[] = {
1025 32, // ecdsa_nistp256_with_sha256(0)
1026 32 // ecies_nistp256(1)
1029 static int hf_sgeonw_symmetric_algorithm
;
1033 // reserved(240..255),
1034 last_sym_algo
= (2<<8)-1
1035 } SymmetricAlgorithm
;
1037 static const value_string symmetric_algorithm_names
[] = {
1038 { aes_128_ccm
, "aes_128_ccm" },
1042 static const int etsits103097_table_4
[] = {
1043 16 // aes_128_ccm(0)
1046 static int hf_sgeonw_region_type
;
1047 static int hf_sgeonw_radius
;
1056 // reserved(240..255),
1058 last_regiontype
= (2<<8)-1
1061 static const value_string region_type_names
[] = {
1063 { circle
, "circle" },
1064 { rectangle
, "rectangle" },
1065 { polygon
, "polygon" },
1070 static int hf_sgeonw_region_dictionary
;
1071 static int hf_sgeonw_region_identifier
;
1072 static int hf_sgeonw_local_region
;
1078 last_regiondictionary
= (2<<8)-1
1081 static const value_string region_dictionary_names
[] = {
1082 { iso_3166_1
, "Numeric country codes as in ISO 3166-1" },
1083 { un_stats
, "Defined by UN Statistics Division" },
1087 static int hf_sgeonw_subject_type
;
1090 enrollment_credential
= 0,
1091 authorization_ticket
= 1,
1092 authorization_authority
= 2,
1093 enrollment_authority
= 3,
1097 last_subjecttype
= (2<<8)-1
1100 static const value_string subject_type_names
[] = {
1101 { enrollment_credential
, "enrollment_credential" },
1102 { authorization_ticket
, "authorization_ticket" },
1103 { authorization_authority
, "authorization_authority" },
1104 { enrollment_authority
, "enrollment_authority" },
1105 { root_ca
, "root_ca" },
1106 { crl_signer
, "crl_signer" },
1111 static int hf_sgeonw_subject_attribute_type_v1
;
1112 static int hf_sgeonw_subject_attribute_type_v2
;
1115 verification_key
= 0,
1117 assurance_level
= 2,
1118 reconstruction_value
= 3,
1120 its_aid_ssp_list
= 33,
1121 priority_its_aid_list
= 34,
1122 priority_ssp_list
= 35,
1124 last_subjectattributetype
= (2<<8)-1
1125 } SubjectAttributeType
;
1127 static const value_string subject_attribute_type_v1_names
[] = {
1128 { verification_key
, "verification_key" },
1129 { encryption_key
, "encryption_key" },
1130 { assurance_level
, "assurance_level" },
1131 { reconstruction_value
, "reconstruction_value" },
1132 { its_aid_list
, "its_aid_list" },
1133 { its_aid_ssp_list
, "its_aid_ssp_list" },
1134 { priority_its_aid_list
, "priority_its_aid_list" },
1135 { priority_ssp_list
, "priority_ssp_list" },
1139 static const value_string subject_attribute_type_v2_names
[] = {
1140 { verification_key
, "verification_key" },
1141 { encryption_key
, "encryption_key" },
1142 { assurance_level
, "assurance_level" },
1143 { reconstruction_value
, "reconstruction_value" },
1144 { its_aid_list
, "its_aid_list" },
1145 { its_aid_ssp_list
, "its_aid_ssp_list" },
1149 static int hf_sgeonw_validity_restriction_type
;
1153 time_start_and_end
= 1,
1154 time_start_and_duration
= 2,
1157 last_validityrestrictiontype
= (2<<8)-1
1158 } ValidityRestrictionType
;
1160 static const value_string validity_restriction_type_names
[] = {
1161 { time_end
, "time_end" },
1162 { time_start_and_end
, "time_start_and_end" },
1163 { time_start_and_duration
, "time_start_and_duration" },
1164 { region
, "region" },
1169 static int hf_sgeonw_eccpoint
;
1170 static int ett_sgeonw_eccpoint
;
1171 static int hf_sgeonw_eccpoint_type
;
1172 static int hf_sgeonw_eccpoint_x
;
1173 static int hf_sgeonw_eccpoint_y
;
1176 x_coordinate_only
= 0,
1177 compressed_lsb_y_0
= 2,
1178 compressed_lsb_y_1
= 3,
1181 last_eccpointtype
= (2<<8)-1
1184 static const value_string eccpoint_type_names
[] = {
1185 { x_coordinate_only
, "x_coordinate_only" },
1186 { compressed_lsb_y_0
, "compressed_lsb_y_0" },
1187 { compressed_lsb_y_1
, "compressed_lsb_y_1" },
1188 { uncompressed
, "uncompressed" },
1193 // Dissects a length and returns the value
1194 // 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
1196 dissect_sec_var_len(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1201 int start
= *offset
;
1203 proto_tree
*subtree
;
1206 var_len
= tvb_get_uint8(tvb
, *offset
);
1209 while(mask
&& (var_len
& mask
)) {
1210 tmp_val
= tvb_get_uint8(tvb
, *offset
);
1212 var_len
= ((var_len
& ~mask
) << 8) + tmp_val
;
1215 ti
= proto_tree_add_item(tree
, hf_sgeonw_var_len
, tvb
, start
, (*offset
) - start
, ENC_NA
); // Length cannot be determined now
1216 subtree
= proto_item_add_subtree(ti
, ett_sgeonw_var_len
);
1217 proto_tree_add_bits_item(subtree
, hf_sgeonw_var_len_det
, tvb
, start
<< 3, (*offset
) - start
, ENC_NA
);
1218 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
);
1219 // EI Error if !mask (more than 32 bits)
1221 expert_add_info(pinfo
, ti
, &ei_sgeonw_len_unsupported
);
1227 dissect_sec_intx(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, int hf
, uint32_t *ret
)
1229 //uint8_t var_len = 1;
1232 int start
= *offset
;
1234 proto_tree
*subtree
;
1237 tmp_val
= tvb_get_uint8(tvb
, *offset
);
1240 while(mask
&& (tmp_val
& mask
)) {
1243 tmp_val
+= tvb_get_uint8(tvb
, *offset
);
1248 ti
= proto_tree_add_item(tree
, hf_sgeonw_intx
, tvb
, start
, (*offset
) - start
, ENC_NA
);
1249 subtree
= proto_item_add_subtree(ti
, ett_sgeonw_intx
);
1250 proto_tree_add_bits_item(subtree
, hf_sgeonw_var_len_det
, tvb
, start
<< 3, (*offset
) - start
, ENC_NA
);
1251 if ((hf
!= hf_sgeonw_app_id
) || ((*offset
) - start
) > 4) {
1252 proto_tree_add_uint64_bits_format_value(subtree
, hf
, tvb
, (start
<< 3) + (*offset
) - start
,
1253 (((*offset
) - start
) << 3) - ((*offset
) - start
), tmp_val
, ENC_BIG_ENDIAN
, "%" PRIu64
, tmp_val
);
1256 proto_tree_add_uint_bits_format_value(subtree
, hf
, tvb
, (start
<< 3) + (*offset
) - start
,
1257 (((*offset
) - start
) << 3) - ((*offset
) - start
), (uint32_t)tmp_val
, ENC_BIG_ENDIAN
, "%s(%u)", val64_to_str_const(tmp_val
, ieee1609dot2_Psid_vals
, "Unknown") , (uint32_t)tmp_val
);
1259 // ETSI TS 103 097 V1.2.1: The encoding of the length shall use at most 7 bits set to 1.
1261 // EI Error if more than 7
1262 expert_add_info(pinfo
, ti
, &ei_sgeonw_len_too_long
);
1264 if(tmp_val
& 0xffffffff00000000) {
1265 expert_add_info(pinfo
, ti
, &ei_geonw_intx_too_big
);
1267 *ret
= (uint32_t) tmp_val
;
1270 return (*offset
) - start
;
1274 dissect_sec_eccpoint(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, PublicKeyAlgorithm algorithm
)
1278 uint32_t start
= *offset
;
1280 proto_tree
*subtree
;
1281 int field_size
= etsits103097_table_2
[algorithm
];
1283 ti
= proto_tree_add_item(tree
, hf_sgeonw_eccpoint
, tvb
, *offset
, 0, ENC_NA
);
1284 subtree
= proto_item_add_subtree(ti
, ett_sgeonw_eccpoint
);
1285 proto_tree_add_item_ret_uint(subtree
, hf_sgeonw_eccpoint_type
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1286 // Opaque[field_size]
1287 proto_tree_add_item(subtree
, hf_sgeonw_eccpoint_x
, tvb
, 1+(*offset
), field_size
, ENC_NA
);
1288 *offset
+= field_size
+1;
1290 case x_coordinate_only
:
1291 case compressed_lsb_y_0
:
1292 case compressed_lsb_y_1
:
1295 // Opaque[field_size]
1296 proto_tree_add_item(subtree
, hf_sgeonw_eccpoint_y
, tvb
, *offset
, field_size
, ENC_NA
);
1297 *offset
+= field_size
;
1301 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, subtree
);
1302 proto_tree_add_item(subtree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1303 *offset
+= param_len
;
1305 proto_item_set_end(ti
, tvb
, *offset
);
1306 return (*offset
) - start
;
1310 dissect_sec_publickey(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1314 int start
= *offset
;
1315 proto_item
*part_item
;
1316 proto_tree
*part_tree
;
1318 part_item
= proto_tree_add_item(tree
, hf_sgeonw_public_key
, tvb
, *offset
, 0, ENC_NA
); // Length cannot be determined now
1319 part_tree
= proto_item_add_subtree(part_item
, ett_sgeonw_public_key
);
1320 proto_tree_add_item_ret_uint(part_tree
, hf_sgeonw_public_key_algorithm
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1323 case ecdsa_nistp256_with_sha256
:
1325 dissect_sec_eccpoint(tvb
, offset
, pinfo
, part_tree
, (PublicKeyAlgorithm
) tmp_val
);
1327 case ecies_nistp256
:
1328 // SymAlgo + EccPoint
1329 proto_tree_add_item(part_tree
, hf_sgeonw_symmetric_algorithm
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1331 dissect_sec_eccpoint(tvb
, offset
, pinfo
, part_tree
, (PublicKeyAlgorithm
) tmp_val
);
1335 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, part_tree
);
1336 proto_tree_add_item(part_tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1337 *offset
+= param_len
;
1339 proto_item_set_end(part_item
, tvb
, *offset
);
1340 return (*offset
) - start
;
1344 dissect_sec_encryption_parameters(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1348 uint32_t start
= *offset
;
1349 proto_item
*part_item
;
1350 proto_tree
*part_tree
;
1352 part_item
= proto_tree_add_item(tree
, hf_sgeonw_encryption_parameter
, tvb
, *offset
, 0, ENC_NA
); // Length cannot be determined now
1353 part_tree
= proto_item_add_subtree(part_item
, ett_sgeonw_encryption_parameter
);
1354 proto_tree_add_item_ret_uint(part_tree
, hf_sgeonw_symmetric_algorithm
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1357 case ecdsa_nistp256_with_sha256
:
1359 proto_tree_add_item(part_tree
, hf_sgeonw_encryption_parameter_nonce
, tvb
, *offset
, 12, ENC_NA
);
1364 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, part_tree
);
1365 proto_tree_add_item(part_tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1366 *offset
+= param_len
;
1368 proto_item_set_end(part_item
, tvb
, *offset
);
1369 return (*offset
) - start
;
1373 dissect_sec_ecdsasignature(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, PublicKeyAlgorithm algorithm
)
1375 uint32_t start
= *offset
;
1376 int field_size
= etsits103097_table_2
[algorithm
];
1378 dissect_sec_eccpoint(tvb
, offset
, pinfo
, tree
, algorithm
);
1379 proto_tree_add_item(tree
, hf_sgeonw_ecdsasignature_s
, tvb
, *offset
, field_size
, ENC_NA
);
1380 *offset
+= field_size
;
1381 return (*offset
) - start
;
1385 dissect_sec_signature(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1387 int start
= *offset
;
1390 proto_item
*part_item
;
1391 proto_tree
*part_tree
;
1393 part_item
= proto_tree_add_item(tree
, hf_sgeonw_signature
, tvb
, *offset
, 0, ENC_NA
); // Length cannot be determined now
1394 part_tree
= proto_item_add_subtree(part_item
, ett_sgeonw_signature
);
1395 proto_tree_add_item_ret_uint(part_tree
, hf_sgeonw_public_key_algorithm
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1398 case ecdsa_nistp256_with_sha256
:
1400 dissect_sec_ecdsasignature(tvb
, offset
, pinfo
, part_tree
, ecdsa_nistp256_with_sha256
);
1404 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, part_tree
);
1405 proto_tree_add_item(part_tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1406 *offset
+= param_len
;
1408 proto_item_set_end(part_item
, tvb
, *offset
);
1409 return (*offset
) - start
;
1413 dissect_sec_2dlocation(tvbuff_t
*tvb
, int *offset
, proto_tree
*tree
)
1415 proto_tree_add_item(tree
, hf_sgeonw_lat
, tvb
, *offset
, 4, ENC_BIG_ENDIAN
);
1416 proto_tree_add_item(tree
, hf_sgeonw_lon
, tvb
, 4+*offset
, 4, ENC_BIG_ENDIAN
);
1424 dissect_sec_subject_info(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1427 int start
= *offset
;
1429 proto_item
*part_item
;
1430 proto_tree
*part_tree
;
1432 part_item
= proto_tree_add_item(tree
, hf_sgeonw_subject_info
, tvb
, *offset
, 0, ENC_NA
); // Length cannot be determined now
1433 part_tree
= proto_item_add_subtree(part_item
, ett_sgeonw_subject_info
);
1434 proto_tree_add_item(part_tree
, hf_sgeonw_subject_type
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1436 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, part_tree
);
1437 ti
= proto_tree_add_item(part_tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1438 // Expert info: shall be at most 255 bytes long
1439 if (param_len
> 255)
1440 expert_add_info(pinfo
, ti
, &ei_sgeonw_subj_info_too_long
);
1441 *offset
+= param_len
;
1442 proto_item_set_end(part_item
, tvb
, *offset
);
1444 return (*offset
) - start
;
1448 dissect_sec_itsaidssp(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1450 int start
= *offset
;
1454 proto_tree
*subtree
;
1456 dissect_sec_intx(tvb
, offset
, pinfo
, tree
, hf_sgeonw_app_id
, &appid
);
1457 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1458 ti
= proto_tree_add_item(tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1459 // Expert info: shall be at most 31 bytes long
1460 if (param_len
> 31) {
1461 expert_add_info(pinfo
, ti
, &ei_sgeonw_ssp_too_long
);
1464 subtree
= proto_item_add_subtree(ti
, ett_sgeonw_ssp
);
1465 tvbuff_t
*next_tvb
= tvb_new_subset_length(tvb
, *offset
, param_len
);
1466 dissector_try_uint(ssp_subdissector_table
, appid
, next_tvb
, pinfo
, subtree
);
1468 *offset
+= param_len
;
1470 return (*offset
) - start
;
1473 static int hf_sgeonw_priority
;
1476 dissect_sec_itsaidpriority(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1478 int start
= *offset
;
1480 dissect_sec_intx(tvb
, offset
, pinfo
, tree
, hf_sgeonw_app_id
, NULL
);
1481 proto_tree_add_item(tree
, hf_sgeonw_priority
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1484 return (*offset
) - start
;
1488 dissect_sec_itsaidpriorityssp(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1490 int start
= *offset
;
1494 dissect_sec_intx(tvb
, offset
, pinfo
, tree
, hf_sgeonw_app_id
, NULL
);
1495 proto_tree_add_item(tree
, hf_sgeonw_priority
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1497 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1498 ti
= proto_tree_add_item(tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1499 // Expert info: shall be at most 31 bytes long
1501 expert_add_info(pinfo
, ti
, &ei_sgeonw_ssp_too_long
);
1502 *offset
+= param_len
;
1504 return (*offset
) - start
;
1507 static int hf_sgeonw_subject_assurance
;
1508 static int ett_sgeonw_subject_assurance
;
1509 static int hf_sgeonw_subject_assurance_assurance
;
1510 static int hf_sgeonw_subject_assurance_reserved
;
1511 static int hf_sgeonw_subject_assurance_confidence
;
1514 dissect_sec_subject_attributes(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, uint8_t version
)
1516 int start
= *offset
;
1520 proto_item
*part_item
;
1521 proto_tree
*subtree
;
1523 part_item
= proto_tree_add_item(tree
, hf_sgeonw_subject_attribute
, tvb
, *offset
, 0, ENC_NA
);
1524 subtree
= proto_item_add_subtree(part_item
, ett_sgeonw_subject_attribute
);
1525 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
);
1528 case verification_key
:
1529 case encryption_key
:
1530 dissect_sec_publickey(tvb
,offset
,pinfo
,subtree
);
1532 case assurance_level
:
1533 ti
= proto_tree_add_item(subtree
, hf_sgeonw_subject_assurance
, tvb
, *offset
, 1, ENC_NA
);
1534 subtree
= proto_item_add_subtree(ti
, ett_sgeonw_subject_assurance
);
1535 proto_tree_add_item(subtree
, hf_sgeonw_subject_assurance_assurance
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1536 proto_tree_add_item(subtree
, hf_sgeonw_subject_assurance_reserved
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1537 proto_tree_add_item(subtree
, hf_sgeonw_subject_assurance_confidence
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1540 case reconstruction_value
:
1541 dissect_sec_eccpoint(tvb
,offset
,pinfo
,subtree
,ecdsa_nistp256_with_sha256
); // XXX Which algorithm? hack as only one algo defined
1544 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, subtree
);
1545 while (tmp_val
> 0) {
1546 param_len
= dissect_sec_intx(tvb
,offset
,pinfo
, subtree
, hf_sgeonw_app_id
, NULL
);
1547 if(tmp_val
< param_len
) {
1548 expert_add_info(pinfo
, ti
, &ei_sgeonw_bogus
);
1549 return *offset
- start
;
1551 tmp_val
-= param_len
;
1554 case its_aid_ssp_list
:
1555 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, subtree
);
1556 while (tmp_val
> 0) {
1557 param_len
= dissect_sec_itsaidssp(tvb
, offset
, pinfo
, subtree
);
1558 if(tmp_val
< param_len
) {
1559 expert_add_info(pinfo
, ti
, &ei_sgeonw_bogus
);
1560 return *offset
- start
;
1562 tmp_val
-= param_len
;
1565 case priority_its_aid_list
:
1566 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, subtree
);
1567 while (tmp_val
> 0) {
1568 param_len
= dissect_sec_itsaidpriority(tvb
, offset
, pinfo
, subtree
);
1569 if(tmp_val
< param_len
) {
1570 expert_add_info(pinfo
, ti
, &ei_sgeonw_bogus
);
1571 return *offset
- start
;
1573 tmp_val
-= param_len
;
1576 case priority_ssp_list
:
1577 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, subtree
);
1578 while (tmp_val
> 0) {
1579 param_len
= dissect_sec_itsaidpriorityssp(tvb
, offset
, pinfo
, subtree
);
1580 if(tmp_val
< param_len
) {
1581 expert_add_info(pinfo
, ti
, &ei_sgeonw_bogus
);
1582 return *offset
- start
;
1584 tmp_val
-= param_len
;
1589 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, subtree
);
1590 proto_tree_add_item(subtree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1591 *offset
+= param_len
;
1593 proto_item_set_end(part_item
, tvb
, *offset
);
1595 return (*offset
) - start
;
1599 dissect_sec_circularregion(tvbuff_t
*tvb
, int *offset
, proto_tree
*tree
)
1601 dissect_sec_2dlocation(tvb
, offset
, tree
);
1603 proto_tree_add_item(tree
, hf_sgeonw_radius
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
1610 dissect_sec_rectangularregion(tvbuff_t
*tvb
, int *offset
, proto_tree
*tree
)
1612 dissect_sec_2dlocation(tvb
, offset
, tree
);
1613 dissect_sec_2dlocation(tvb
, offset
, tree
);
1619 dissect_sec_polygonalregion(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1621 int start
= *offset
;
1625 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1627 param_len
= dissect_sec_2dlocation(tvb
, offset
, tree
);
1628 if(tmp_val
< param_len
)
1629 return *offset
- start
;
1630 tmp_val
-= param_len
;
1633 return (*offset
) - start
;
1637 dissect_sec_identifiedregion(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1639 int start
= *offset
;
1641 proto_tree_add_item(tree
, hf_sgeonw_region_dictionary
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1642 proto_tree_add_item(tree
, hf_sgeonw_region_identifier
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
1644 dissect_sec_intx(tvb
, offset
, pinfo
, tree
, hf_sgeonw_local_region
, NULL
);
1646 return (*offset
) - start
;
1650 dissect_sec_geographicregion(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1652 int start
= *offset
;
1656 proto_tree_add_item_ret_uint(tree
, hf_sgeonw_region_type
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1662 dissect_sec_circularregion(tvb
,offset
,tree
);
1665 dissect_sec_rectangularregion(tvb
,offset
,tree
);
1668 dissect_sec_polygonalregion(tvb
, offset
, pinfo
, tree
);
1671 dissect_sec_identifiedregion(tvb
, offset
, pinfo
, tree
);
1675 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1676 proto_tree_add_item(tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1677 *offset
+= param_len
;
1680 return (*offset
) - start
;
1683 static const value_string sgeonw_duration_unit_names
[] = {
1687 { 3, "60 Hours block" },
1693 dissect_sec_validity_restrictions(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
)
1695 int start
= *offset
;
1699 proto_tree
*subtree
;
1701 proto_tree_add_item_ret_uint(tree
, hf_sgeonw_validity_restriction_type
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1706 proto_tree_add_item(tree
, hf_sgeonw_time32
, tvb
, *offset
, 4, ENC_BIG_ENDIAN
);
1709 case time_start_and_end
:
1711 proto_tree_add_item(tree
, hf_sgeonw_time32
, tvb
, *offset
, 4, ENC_BIG_ENDIAN
);
1714 proto_tree_add_item(tree
, hf_sgeonw_time32
, tvb
, *offset
, 4, ENC_BIG_ENDIAN
);
1717 case time_start_and_duration
:
1719 proto_tree_add_item(tree
, hf_sgeonw_time32
, tvb
, *offset
, 4, ENC_BIG_ENDIAN
);
1722 ti
= proto_tree_add_item(tree
, hf_sgeonw_duration
, tvb
, *offset
, 2, ENC_NA
);
1723 subtree
= proto_item_add_subtree(ti
, ett_sgeonw_duration
);
1724 proto_tree_add_item(subtree
, hf_sgeonw_duration_unit
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
1725 proto_tree_add_item(subtree
, hf_sgeonw_duration_value
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
1729 dissect_sec_geographicregion(tvb
, offset
, pinfo
, tree
);
1733 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1734 proto_tree_add_item(tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1735 *offset
+= param_len
;
1737 return (*offset
) - start
;
1740 static int dissect_sec_signer_info(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, uint8_t version
);
1742 static int hf_sgeonw_certification_version
;
1745 // NOLINTNEXTLINE(misc-no-recursion)
1746 dissect_sec_certificate(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, uint8_t version
)
1750 int start
= *offset
;
1752 proto_tree_add_item_ret_uint(tree
, hf_sgeonw_certification_version
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1755 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1756 while (tmp_val
> 0) {
1757 param_len
= dissect_sec_signer_info(tvb
, offset
, pinfo
, tree
, version
);
1758 tmp_val
-= param_len
;
1762 dissect_sec_signer_info(tvb
, offset
, pinfo
, tree
, version
);
1764 dissect_sec_subject_info(tvb
, offset
, pinfo
, tree
);
1765 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1766 while (tmp_val
> 0) {
1767 param_len
= dissect_sec_subject_attributes(tvb
, offset
, pinfo
, tree
, version
);
1768 tmp_val
-= param_len
;
1770 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1771 while (tmp_val
> 0) {
1772 param_len
= dissect_sec_validity_restrictions(tvb
, offset
, pinfo
, tree
);
1773 tmp_val
-= param_len
;
1775 dissect_sec_signature(tvb
, offset
, pinfo
, tree
);
1777 return (*offset
) - start
;
1781 // NOLINTNEXTLINE(misc-no-recursion)
1782 dissect_sec_signer_info(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, uint8_t version
)
1784 int start
= *offset
;
1788 proto_tree
*subtree
;
1790 proto_tree
*insidetree
;
1792 increment_dissection_depth(pinfo
);
1794 tmp_val
= tvb_get_uint8(tvb
, *offset
);
1795 if (tmp_val
== self
) {
1796 // No additional data shall be given
1797 proto_tree_add_item(tree
, hf_sgeonw_signer_info_type
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1801 ti
= proto_tree_add_item(tree
, hf_sgeonw_signer_info
, tvb
, *offset
, 0, ENC_NA
);
1802 subtree
= proto_item_add_subtree(ti
, ett_sgeonw_field
);
1803 proto_tree_add_item(subtree
, hf_sgeonw_signer_info_type
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1806 case certificate_digest_with_ecdsap256
:
1808 proto_tree_add_item(subtree
, hf_sgeonw_hashedid8
, tvb
, *offset
, 8, ENC_NA
);
1813 tinner
= proto_tree_add_item(subtree
, hf_sgeonw_certificate
, tvb
, *offset
, 0, ENC_NA
);
1814 insidetree
= proto_item_add_subtree(tinner
, ett_sgeonw_field
);
1815 dissect_sec_certificate(tvb
, offset
, pinfo
, insidetree
, version
);
1816 proto_item_set_end(tinner
, tvb
, *offset
);
1818 case certificate_chain
:
1819 // variable-length vector of type Certificate
1820 tmp_val
= dissect_sec_var_len(tvb
, offset
, pinfo
, subtree
);
1821 while (tmp_val
> 0) {
1822 tinner
= proto_tree_add_item(subtree
, hf_sgeonw_certificate
, tvb
, *offset
, 0, ENC_NA
);
1823 insidetree
= proto_item_add_subtree(tinner
, ett_sgeonw_field
);
1824 param_len
= dissect_sec_certificate(tvb
, offset
, pinfo
, insidetree
, version
);
1825 proto_item_set_end(tinner
, tvb
, *offset
);
1826 tmp_val
-= param_len
;
1829 case certificate_digest_with_other_algorithm
:
1831 proto_tree_add_item(subtree
, hf_sgeonw_public_key_algorithm
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1832 proto_tree_add_item(subtree
, hf_sgeonw_hashedid8
, tvb
, 1+(*offset
), 8, ENC_NA
);
1837 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, subtree
);
1838 proto_tree_add_item(subtree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1839 *offset
+= param_len
;
1841 proto_item_set_end(ti
, tvb
, *offset
);
1843 decrement_dissection_depth(pinfo
);
1844 return (*offset
) - start
;
1848 static int hf_sgeonw_encrypted_key
;
1849 static int hf_sgeonw_auth_tag
;
1851 // This structure defines how to transmit an EciesNistP256-encrypted symmetric key as defined in IEEE
1853 // EciesNistP256EncryptedKey structure shall be preceded by an according
1854 // EncryptionParameters structure.
1856 dissect_sec_eciesnistp256entryptedkey(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, PublicKeyAlgorithm pub_alg
, SymmetricAlgorithm symm_alg
, uint8_t version
)
1858 int start
= *offset
;
1859 uint8_t symm_key_len
= etsits103097_table_4
[symm_alg
];
1861 dissect_sec_eccpoint(tvb
, offset
, pinfo
, tree
, pub_alg
);
1862 proto_tree_add_item(tree
, hf_sgeonw_encrypted_key
, tvb
, *offset
, symm_key_len
, ENC_NA
);
1863 *offset
+= symm_key_len
;
1864 proto_tree_add_item(tree
, hf_sgeonw_auth_tag
, tvb
, *offset
, version
==1?20:16, ENC_NA
);
1865 *offset
+= version
==1?20:16;
1867 return (*offset
) - start
;
1872 dissect_sec_recipient_info(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*tree
, uint8_t version
)
1874 int start
= *offset
;
1878 proto_tree_add_item(tree
, hf_sgeonw_hashedid8
, tvb
, *offset
, 8, ENC_NA
);
1879 proto_tree_add_item_ret_uint(tree
, hf_sgeonw_public_key_algorithm
, tvb
, 8+*offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1882 case ecies_nistp256
:
1883 // EciesNistP256EncryptedKey
1884 // XXX SymmetricAlgorithm should be provided by preceding EncryptionParameter...
1885 dissect_sec_eciesnistp256entryptedkey(tvb
, offset
, pinfo
, tree
, (PublicKeyAlgorithm
)tmp_val
, aes_128_ccm
, version
);
1889 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, tree
);
1890 proto_tree_add_item(tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1891 *offset
+= param_len
;
1894 return (*offset
) - start
;
1899 dissect_sec_payload(tvbuff_t
*tvb
, int *offset
, packet_info
*pinfo
, proto_tree
*part_tree
)
1901 int start
= *offset
;
1904 proto_tree
*field_tree
;
1907 tmp_val
= tvb_get_uint8(tvb
, *offset
);
1908 if (tmp_val
== signed_external
) {
1909 proto_tree_add_item(part_tree
, hf_sgeonw_payload_field_type
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1913 ti
= proto_tree_add_item(part_tree
, hf_sgeonw_payload_field
, tvb
, *offset
, 0, ENC_NA
);
1914 field_tree
= proto_item_add_subtree(ti
, ett_sgeonw_field
);
1915 proto_tree_add_item(field_tree
, hf_sgeonw_payload_field_type
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
1920 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, field_tree
);
1922 tvbuff_t
*next_tvb
= tvb_new_subset_length(tvb
, *offset
, param_len
);
1923 p_add_proto_data(pinfo
->pool
, pinfo
, proto_geonw
, SEC_TVB_KEY
, next_tvb
);
1925 *offset
+= param_len
;
1928 case signed_and_encrypted
:
1929 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, field_tree
);
1930 proto_tree_add_item(field_tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1931 *offset
+= param_len
;
1935 param_len
= dissect_sec_var_len(tvb
, offset
, pinfo
, field_tree
);
1936 proto_tree_add_item(field_tree
, hf_sgeonw_opaque
, tvb
, *offset
, param_len
, ENC_NA
);
1937 *offset
+= param_len
;
1939 proto_item_set_end(ti
, tvb
, *offset
);
1942 return (*offset
) - start
;
1947 dissect_secured_message(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1949 uint32_t msg_id
; // Or Application ID, depending on version
1955 proto_item
*secmsg_item
;
1956 proto_item
*part_item
;
1957 proto_tree
*part_tree
;
1958 proto_tree
*field_tree
;
1959 int sec_start
= offset
;
1961 // Secured message subtree
1962 secmsg_item
= proto_tree_add_item(tree
, hf_geonw_sec
, tvb
, offset
, 0, ENC_NA
); // Length cannot be determined now
1963 proto_tree
*secmsg_tree
= proto_item_add_subtree(secmsg_item
, ett_geonw_sec
);
1965 version
= tvb_get_uint8(tvb
, offset
);
1967 tvbuff_t
*next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1968 call_dissector(ieee1609dot2_handle
, next_tvb
, pinfo
, secmsg_tree
);
1969 // If unsecure or only signed, content is in private data
1970 return tvb_captured_length(tvb
);
1973 proto_tree_add_item(secmsg_tree
, hf_sgeonw_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1975 if ((version
< 1) || (version
> 2))
1978 proto_tree_add_item_ret_uint(secmsg_tree
, hf_sgeonw_profile
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
1982 part_item
= proto_tree_add_item(secmsg_tree
, hf_sgeonw_hdr
, tvb
, offset
, 0, ENC_NA
); // Length cannot be determined now
1983 part_tree
= proto_item_add_subtree(part_item
, ett_sgeonw_hdr
);
1985 var_len
= dissect_sec_var_len(tvb
, &offset
, pinfo
, part_tree
);
1986 while (var_len
> 0) {
1988 uint32_t start
= offset
;
1990 ti
= proto_tree_add_item(part_tree
, hf_sgeonw_header_field
, tvb
, offset
, 0, ENC_NA
);
1991 field_tree
= proto_item_add_subtree(ti
, ett_sgeonw_field
);
1992 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
);
1995 case generation_time
:
1997 proto_tree_add_item(field_tree
, hf_sgeonw_time64
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
2000 case generation_time_confidence
:
2001 // Time64WithStandardDeviation
2002 proto_tree_add_item(field_tree
, hf_sgeonw_time64
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
2003 proto_tree_add_item(field_tree
, hf_sgeonw_conf
, tvb
, offset
+8, 1, ENC_BIG_ENDIAN
);
2008 proto_tree_add_item(field_tree
, hf_sgeonw_time32
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2011 case generation_location
:
2013 proto_tree_add_item(field_tree
, hf_sgeonw_lat
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2014 proto_tree_add_item(field_tree
, hf_sgeonw_lon
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
2015 proto_tree_add_item(field_tree
, hf_sgeonw_elev
, tvb
, offset
+8, 2, ENC_BIG_ENDIAN
);
2018 case request_unrecognized_certificate
:
2020 param_len
= dissect_sec_var_len(tvb
, &offset
, pinfo
, field_tree
);
2021 proto_item_set_len(ti
, (offset
-start
) + param_len
);
2023 proto_tree_add_item(field_tree
, hf_sgeonw_hashedid3
, tvb
, offset
, 3, ENC_NA
);
2030 proto_tree_add_item_ret_uint(field_tree
, hf_sgeonw_msg_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &msg_id
);
2034 dissect_sec_intx(tvb
, &offset
, pinfo
, field_tree
, hf_sgeonw_app_id
, &msg_id
);
2039 dissect_sec_signer_info(tvb
, &offset
, pinfo
, field_tree
, version
);
2041 case recipient_info
:
2043 param_len
= dissect_sec_var_len(tvb
, &offset
, pinfo
, field_tree
);
2044 proto_item_set_len(ti
, (offset
-start
) + param_len
);
2046 param_len
-= dissect_sec_recipient_info(tvb
, &offset
, pinfo
, field_tree
, version
);
2048 offset
+= param_len
;
2050 case encryption_parameters
:
2051 // EncryptionParameters
2052 dissect_sec_encryption_parameters(tvb
, &offset
, pinfo
, field_tree
);
2056 param_len
= dissect_sec_var_len(tvb
, &offset
, pinfo
, field_tree
);
2057 proto_item_set_len(ti
, (offset
-start
) + param_len
);
2058 proto_tree_add_item(field_tree
, hf_sgeonw_opaque
, tvb
, offset
, param_len
, ENC_NA
);
2059 offset
+= param_len
;
2061 proto_item_set_end(ti
, tvb
, offset
);
2062 /* EI var_len >= (offset-start) */
2063 var_len
-= (offset
- start
);
2065 proto_item_set_end(part_item
, tvb
, offset
);
2068 part_item
= proto_tree_add_item(secmsg_tree
, hf_sgeonw_pl
, tvb
, offset
, 0, ENC_NA
); // Length cannot be determined now
2069 part_tree
= proto_item_add_subtree(part_item
, ett_sgeonw_hdr
);
2071 // Change in version 2: only one payload element here!
2073 var_len
= dissect_sec_var_len(tvb
, &offset
, pinfo
, part_tree
);
2074 while (var_len
> 0) {
2076 uint32_t start
= offset
;
2078 dissect_sec_payload(tvb
, &offset
, pinfo
, part_tree
);
2079 if (var_len
< (offset
-start
))
2081 var_len
-= (offset
- start
);
2085 dissect_sec_payload(tvb
, &offset
, pinfo
, part_tree
);
2087 proto_item_set_end(part_item
, tvb
, offset
);
2090 part_item
= proto_tree_add_item(secmsg_tree
, hf_sgeonw_trl
, tvb
, offset
, 0, ENC_NA
); // Length cannot be determined now
2091 part_tree
= proto_item_add_subtree(part_item
, ett_sgeonw_hdr
);
2093 var_len
= dissect_sec_var_len(tvb
, &offset
, pinfo
, part_tree
);
2094 while (var_len
> 0) {
2096 uint32_t start
= offset
;
2098 ti
= proto_tree_add_item(part_tree
, hf_sgeonw_trailer_field
, tvb
, offset
, 0, ENC_NA
);
2099 field_tree
= proto_item_add_subtree(ti
, ett_sgeonw_field
);
2100 proto_tree_add_item_ret_uint(field_tree
, hf_sgeonw_trailer_field_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
2105 dissect_sec_signature(tvb
, &offset
, pinfo
, field_tree
);
2109 param_len
= dissect_sec_var_len(tvb
, &offset
, pinfo
, field_tree
);
2110 proto_tree_add_item(field_tree
, hf_sgeonw_opaque
, tvb
, offset
, param_len
, ENC_NA
);
2111 offset
+= param_len
;
2113 proto_item_set_end(ti
, tvb
, offset
);
2114 var_len
-= (offset
- start
);
2116 proto_item_set_end(part_item
, tvb
, offset
);
2117 proto_item_set_end(secmsg_item
, tvb
, offset
);
2119 return offset
- sec_start
;
2123 dissect_sgeonw(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, void *data _U_
)
2125 // Just store the tvbuff for later, as it is embedded inside a secured geonetworking packet
2126 p_add_proto_data(pinfo
->pool
, pinfo
, proto_geonw
, SEC_TVB_KEY
, tvb
);
2128 return tvb_reported_length(tvb
);
2131 // The actual dissector
2133 // 0 - do not skip, complete GNW packet with Basic Header
2134 // BH_NH_COMMON_HDR - skip and continue to Common Header
2135 // BH_NH_SECURED_PKT - skip and continue to Secured Packet
2136 // XXX COL_INFO to be improved
2138 dissect_geonw_internal(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
, uint8_t skip_bh
)
2140 uint8_t bh_next_header
;
2141 uint32_t ch_next_header
;
2142 uint32_t header_type
;
2147 proto_item
*top_item
;
2148 proto_item
* rhl_ti
= NULL
;
2150 uint32_t payload_len
= 0;
2153 uint32_t sequence_number
= SN_MAX
+ 1;
2154 struct geonwheader
*geonwh
;
2157 geonwh
= wmem_new0(pinfo
->pool
, struct geonwheader
);
2159 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "GEONW");
2160 /* Clear out stuff in the info column */
2161 col_clear(pinfo
->cinfo
,COL_INFO
);
2164 bh_next_header
= tvb_get_uint8(tvb
, 0) & 0x0f;
2167 bh_next_header
= skip_bh
;
2170 if (bh_next_header
== BH_NH_COMMON_HDR
) {
2171 header_type
= tvb_get_uint8(tvb
, hdr_len
+ 1);
2173 switch(header_type
& HT_MASK
) {
2175 hdr_len
+= BEACON_LEN
;
2183 case HT_GEOBROADCAST
:
2190 hdr_len
+= LS_REQUEST_LEN
;
2191 if (header_type
== HTST_LS_REPLY
) {
2192 hdr_len
+= (LS_REPLY_LEN
- LS_REQUEST_LEN
);
2200 top_item
= proto_tree_add_item(tree
, proto_geonw
, tvb
, 0, hdr_len
, ENC_NA
);
2201 proto_tree
*geonw_tree
= proto_item_add_subtree(top_item
, ett_geonw
);
2204 // Basic Header subtree
2205 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_bh
, tvb
, 0, 4, ENC_NA
);
2206 proto_tree
* geonw_bh_tree
= proto_item_add_subtree(ti
, ett_geonw_bh
);
2208 ti
= proto_tree_add_item_ret_uint(geonw_bh_tree
, hf_geonw_bh_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
2209 geonwh
->gnw_ver
= tmp_val
;
2212 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
2213 "Bogus GeoNetworking version (%u, must be less than 2)", tmp_val
);
2214 expert_add_info_format(pinfo
, ti
, &ei_geonw_version_err
, "Bogus GeoNetworking version");
2215 return tvb_captured_length(tvb
);
2217 proto_tree_add_item(geonw_bh_tree
, hf_geonw_bh_next_header
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2220 // Expert info if not zero?
2221 ti
= proto_tree_add_item_ret_uint(geonw_bh_tree
, hf_geonw_bh_reserved
, tvb
, offset
, 1, ENC_NA
, &reserved
);
2223 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2227 // Subtree and lt_mult and lt_base
2228 ti
= proto_tree_add_item_ret_uint(geonw_bh_tree
, hf_geonw_bh_life_time
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
2229 geonwh
->gnw_lt
= tmp_val
;
2230 proto_tree
* geonw_bh_lt_tree
= proto_item_add_subtree(ti
, ett_geonw_bh_lt
);
2232 proto_tree_add_item(geonw_bh_lt_tree
, hf_geonw_bh_lt_mult
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2233 proto_tree_add_item(geonw_bh_lt_tree
, hf_geonw_bh_lt_base
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2236 rhl_ti
= proto_tree_add_item_ret_uint(geonw_bh_tree
, hf_geonw_bh_remain_hop_limit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &rhl
);
2237 geonwh
->gnw_rhl
= rhl
;
2239 * Flag a low RHL if the next header is not a common header
2241 if (rhl
< 5 && bh_next_header
!= BH_NH_COMMON_HDR
) {
2242 expert_add_info_format(pinfo
, rhl_ti
, &ei_geonw_rhl_too_low
, "\"Remain Hop Limit\" only %u", rhl
);
2247 if (bh_next_header
== BH_NH_SECURED_PKT
) {
2248 dissect_secured_message(tvb
, offset
, pinfo
, geonw_tree
, NULL
);
2249 tvbuff_t
*next_tvb
= (tvbuff_t
*)p_get_proto_data(pinfo
->pool
, pinfo
, proto_geonw
, SEC_TVB_KEY
);
2252 bh_next_header
= BH_NH_COMMON_HDR
;
2254 header_type
= tvb_get_uint8(tvb
, 1);
2257 switch(header_type
& HT_MASK
) {
2259 hdr_len
+= BEACON_LEN
;
2267 case HT_GEOBROADCAST
:
2274 hdr_len
+= LS_REQUEST_LEN
;
2275 if (header_type
== HTST_LS_REPLY
) {
2276 hdr_len
+= (LS_REPLY_LEN
- LS_REQUEST_LEN
);
2285 if (bh_next_header
== BH_NH_COMMON_HDR
) {
2286 // Common Header subtree
2287 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_ch
, tvb
, offset
, 8, ENC_NA
);
2288 proto_tree
*geonw_ch_tree
= proto_item_add_subtree(ti
, ett_geonw_ch
);
2291 proto_tree_add_item_ret_uint(geonw_ch_tree
, hf_geonw_ch_next_header
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &ch_next_header
);
2292 geonwh
->gnw_proto
= ch_next_header
;
2294 ti
= proto_tree_add_item_ret_uint(geonw_ch_tree
, hf_geonw_ch_reserved1
, tvb
, offset
, 1, ENC_NA
, &reserved
);
2296 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2301 proto_tree_add_item_ret_uint(geonw_ch_tree
, hf_geonw_ch_header_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &header_type
);
2302 geonwh
->gnw_htype
= header_type
;
2303 col_add_str(pinfo
->cinfo
, COL_INFO
, val_to_str(header_type
, ch_header_type_names
, "Unknown (%u)"));
2307 /* Now that we know the header type, lets add expert info on RHL
2309 * = 1 if parameter Packet transport type in the service primitive
2310 * GN-DATA.request is SHB, or if Header type HT = 1 (BEACON)
2311 * = Value of optional Maximum hop limit parameter from service
2312 * primitive GN-DATA.request
2313 * = Otherwise GN protocol constant itsGnDefaultHopLimit if
2314 * GN-DATA.request parameter Packet transport type is GUC, GBC, GBC
2316 * Flag a low RHL if the packet is not BEACON or SHB.
2318 if (header_type
== HTST_BEACON
|| header_type
== HTST_TSB_SINGLE
) {
2320 expert_add_info_format(pinfo
, rhl_ti
, &ei_geonw_rhl_lncb
, "\"Remain Hop Limit\" != 1 for BEACON or SHB (%u)", rhl
);
2324 expert_add_info_format(pinfo
, rhl_ti
, &ei_geonw_rhl_too_low
, "\"Remain Hop Limit\" only %u", rhl
);
2329 ti
= proto_tree_add_item_ret_uint(geonw_ch_tree
, hf_geonw_ch_traffic_class
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
2330 geonwh
->gnw_tc
= tmp_val
;
2331 proto_tree
*geonw_ch_tc_tree
= proto_item_add_subtree(ti
, ett_geonw_ch_tc
);
2333 proto_tree_add_item(geonw_ch_tc_tree
, hf_geonw_ch_tc_scf
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2334 proto_tree_add_item(geonw_ch_tc_tree
, hf_geonw_ch_tc_offload
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2335 proto_tree_add_item(geonw_ch_tc_tree
, hf_geonw_ch_tc_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2338 ti
= proto_tree_add_item(geonw_ch_tree
, hf_geonw_ch_flags
, tvb
, offset
, 1, ENC_NA
);
2339 proto_tree
*geonw_ch_flag_tree
= proto_item_add_subtree(ti
, ett_geonw_ch_tc
);
2340 // Flag (itsGnIsMobile)
2341 proto_tree_add_item_ret_uint(geonw_ch_flag_tree
, hf_geonw_ch_flags_mob
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
2342 geonwh
->gnw_flags
= tmp_val
;
2343 ti
= proto_tree_add_item_ret_uint(geonw_ch_flag_tree
, hf_geonw_ch_flags_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &reserved
);
2344 if (reserved
& 0x7f) {
2345 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2350 ti
= proto_tree_add_item_ret_uint(geonw_ch_tree
, hf_geonw_ch_payload_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &payload_len
);
2351 geonwh
->gnw_len
= payload_len
;
2352 if (hdr_len
> 0) { // We know the length of the header
2354 if (((header_type
& HT_MASK
) == HT_LS
) || (header_type
== HT_BEACON
)) {
2355 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2357 else if ((payload_len
+ (unsigned) hdr_len
) > tvb_reported_length(tvb
)) {
2358 expert_add_info(pinfo
, ti
, &ei_geonw_payload_len
);
2362 * Now that we know that the total length of this GNW datagram isn't
2363 * obviously bogus, adjust the length of this tvbuff to include only
2366 set_actual_length(tvb
, hdr_len
+ payload_len
);
2370 set_actual_length(tvb
, hdr_len
);
2376 proto_tree_add_item_ret_uint(geonw_ch_tree
, hf_geonw_ch_max_hop_limit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &tmp_val
);
2377 geonwh
->gnw_mhl
= tmp_val
;
2380 // Expert mhl < rhl: packet will be ignored
2381 if (tmp_val
< rhl
) {
2382 expert_add_info_format(pinfo
, rhl_ti
, &ei_geonw_mhl_lt_rhl
, "Ignored: \"Remain Hop Limit\" > %u (mhl)", tmp_val
);
2387 ti
= proto_tree_add_item_ret_uint(geonw_ch_tree
, hf_geonw_ch_reserved2
, tvb
, offset
, 1, ENC_NA
, &reserved
);
2388 // Expert info if not zero
2390 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2394 // Stop here if header_type unknown
2395 if (!IS_HT_KNOWN(header_type
)) {
2396 // Update top level tree item
2397 proto_item_set_end(top_item
, tvb
, offset
);
2398 return tvb_reported_length(tvb
);
2401 geonwh
->gnw_sn
= SN_MAX
+1;
2403 proto_tree
*geonw_sh_tree
;
2404 switch(header_type
& HT_MASK
) {
2406 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_beacon
, tvb
, offset
, hdr_len
-offset
, ENC_NA
);
2409 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_guc
, tvb
, offset
, hdr_len
-offset
, ENC_NA
);
2412 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_gac
, tvb
, offset
, hdr_len
-offset
, ENC_NA
);
2414 case HT_GEOBROADCAST
:
2415 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_gbc
, tvb
, offset
, hdr_len
-offset
, ENC_NA
);
2418 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_tsb
, tvb
, offset
, hdr_len
-offset
, ENC_NA
);
2421 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_ls
, tvb
, offset
, hdr_len
-offset
, ENC_NA
);
2424 // Exit if header_type unknown?
2425 return tvb_captured_length(tvb
);
2427 geonw_sh_tree
= proto_item_add_subtree(ti
, ett_geonw_sh
);
2429 switch(header_type
) {
2430 case HTST_GEOUNICAST
:
2431 case HTST_GAC_CIRCLE
:
2433 case HTST_GAC_ELLIPSE
:
2434 case HTST_GBC_CIRCLE
:
2436 case HTST_GBC_ELLIPSE
:
2438 case HTST_LS_REQUEST
:
2441 proto_tree_add_item_ret_uint(geonw_sh_tree
, hf_geonw_seq_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &sequence_number
);
2442 geonwh
->gnw_sn
= sequence_number
;
2445 ti
= proto_tree_add_item_ret_uint(geonw_sh_tree
, hf_geonw_reserved
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &reserved
);
2446 // Expert info if not zero?
2448 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2451 case HTST_TSB_SINGLE
:
2456 // Every packet has source address
2457 ti
= proto_tree_add_item(geonw_sh_tree
, hf_geonw_so_pv
, tvb
, offset
, 24, ENC_NA
);
2458 proto_tree
*geonw_so_tree
= proto_item_add_subtree(ti
, ett_geonw_so
);
2460 ti
= proto_tree_add_item(geonw_so_tree
, hf_geonw_so_pv_addr
, tvb
, offset
, 8, ENC_NA
);
2461 proto_tree
*geonw_so_add_tree
= proto_item_add_subtree(ti
, ett_geonw_so
);
2462 set_address_tvb(&pinfo
->net_src
, geonw_address_type
, 8, tvb
, offset
);
2463 copy_address_shallow(&pinfo
->src
, &pinfo
->net_src
);
2464 copy_address_shallow(&geonwh
->gnw_src
, &pinfo
->src
);
2466 proto_tree_add_item(geonw_so_add_tree
, hf_geonw_so_pv_addr_manual
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2467 proto_tree_add_item(geonw_so_add_tree
, hf_geonw_so_pv_addr_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2468 ti
= proto_tree_add_item_ret_uint(geonw_so_add_tree
, hf_geonw_so_pv_addr_country
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &reserved
);
2469 if (reserved
> 999) {
2470 expert_add_info(pinfo
, ti
, &ei_geonw_scc_too_big
);
2473 proto_tree_add_item(geonw_so_add_tree
, hf_geonw_so_pv_addr_mid
, tvb
, offset
, 6, ENC_NA
);
2476 proto_tree_add_item_ret_uint(geonw_so_tree
, hf_geonw_so_pv_time
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, ×tamp
);
2477 geonwh
->gnw_tst
= timestamp
;
2479 // XXX Is it possible to "follow" a station when updating its GN_ADDR?
2481 if(geonw_analyze_seq
&& (geonwh
->gnw_ver
==0) && !(pinfo
->fd
->visited
)) {
2482 // Duplication detection uses SN and TST or only TST (see Annex A of ETSI EN 302 636-4-1)
2483 // We rely on address type and hashtable as this shall be done on a per station basis (i.e. not over a conversation)
2484 // We do not try to consider GN_ADDR updates (due to duplicate address detection or anonymous setting)
2485 hashgeonw_t
*tp
= (hashgeonw_t
*)wmem_map_lookup(geonw_hashtable
, pinfo
->net_src
.data
);
2487 tp
= geonw_hash_new_entry((const uint8_t *)pinfo
->net_src
.data
, false);
2488 tp
->sequence_number
= sequence_number
;
2489 tp
->timestamp
= timestamp
;
2491 if ((sequence_number
<= SN_MAX
) && (tp
->sequence_number
> SN_MAX
)) {
2492 tp
->sequence_number
= sequence_number
;
2493 tp
->timestamp
= timestamp
;
2495 else if (sequence_number
<= SN_MAX
) {
2497 * 1 P is the received GeoNetworking packet
2498 * 2 SN(P) is the sequence number in the received GeoNetworking packet
2499 * 3 SN(SO) is the last received sequence number from source SO
2500 * 4 SN_MAX is the maximum sequence number = 2^16 - 1
2501 * 5 TST(P) is the timestamp in the received GeoNetworking packet
2502 * 6 TST(SO) is the last received timestamp from source SO
2503 * 7 TST_MAX is the maximum value of the timestamp = 2^32 - 1
2505 * 9 IF (((TST(P) > TST(SO) AND ((TST(P) - TST(SO)) <= TST_MAX/2)) OR
2506 * ((TST(SO) > TST(P)) AND ((TST(SO) - TST(P)) > TST_MAX/2))) THEN
2507 * 10 # TST(P) is greater than TST(SO)
2508 * 11 TST(SO) = TST(P)
2509 * 12 SN(SO) = SN(P) # P is not a duplicate packet
2510 * 13 ELSEIF TST(P) = TST(SO) THEN
2511 * 14 IF (((SN(P) > SN(SO) AND ((SN(P) - SN(SO)) <= SN_MAX/2)) OR
2512 * ((SN(SO) > SN(P)) AND ((SN(SO) - SN(P)) > SN_MAX/2))) THEN
2513 * 15 # SN(P) is greater than SN(SO)
2514 * 16 TST(SO) = TST(P)
2515 * 17 SN(SO) = SN(P) # P is not a duplicate packet
2517 * 19 # SN(P) is not greater than SN(SO)
2518 * 20 # P is a duplicate
2521 * 23 # TST(P) not greater than TST(SO)
2524 if (((timestamp
> tp
->timestamp
) && (((uint64_t)timestamp
- (uint64_t)tp
->timestamp
) <= (uint64_t)TST_MAX
/2)) ||
2525 ((tp
->timestamp
> timestamp
) && (((uint64_t)tp
->timestamp
- (uint64_t)timestamp
) > (uint64_t)TST_MAX
/2))) {
2526 // TST(P) is greater than TST(SO)
2527 tp
->sequence_number
= sequence_number
;
2528 tp
->timestamp
= timestamp
; // P is not a duplicate packet
2529 } else if (timestamp
== tp
->timestamp
) {
2530 if (((sequence_number
> tp
->sequence_number
) && ((sequence_number
- tp
->sequence_number
) <= SN_MAX
/2)) ||
2531 ((tp
->sequence_number
> sequence_number
) && ((tp
->sequence_number
- sequence_number
) > SN_MAX
/2))) {
2532 // SN(P) is greater than SN(SO)
2533 tp
->timestamp
= timestamp
;
2534 tp
->sequence_number
= sequence_number
; // P is not a duplicate packet
2536 // SN(P) is not greater than SN(SO)
2538 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_analysis_flags
, tvb
, 0, 0, ENC_NA
);
2539 proto_item_set_generated(ti
);
2540 expert_add_info(pinfo
, ti
, &ei_geonw_analysis_duplicate
);
2541 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[Duplicate packet] ");
2543 } // else { # TST(P) not greater than TST(SO) }
2547 * 1 P is the received GeoNetworking packet
2548 * 2 TST(P) is the timestamp in the received GeoNetworking packet
2549 * 3 TST(SO) is the last received timestamp from source SO
2550 * 4 TS_MAX is the maximum value of the timestamp = 2^32 - 1
2552 * 6 IF (((TST(P) > TST(SO) AND ((TST(P) - TST(SO)) <= TST_MAX/2)) OR
2553 * ((TST(SO) > TST(P)) AND ((TST(SO) - TST(P)) > TST_MAX/2))) THEN
2554 * 7 # TST(P) is greater than TST(SO)
2555 * 8 TST(SO) = TST(P) # P is not a duplicate packet
2557 * 10 # P is a duplicate
2560 if (((timestamp
> tp
->timestamp
) && (((uint64_t)timestamp
- (uint64_t)tp
->timestamp
) <= (uint64_t)TST_MAX
/2)) ||
2561 ((tp
->timestamp
> timestamp
) && (((uint64_t)tp
->timestamp
- (uint64_t)timestamp
) > (uint64_t)TST_MAX
/2))) {
2562 // TST(P) is greater than TST(SO)
2563 tp
->timestamp
= timestamp
; // P is not a duplicate packet
2566 ti
= proto_tree_add_item(geonw_tree
, hf_geonw_analysis_flags
, tvb
, 0, 0, ENC_NA
);
2567 proto_item_set_generated(ti
);
2568 expert_add_info(pinfo
, ti
, &ei_geonw_analysis_duplicate
);
2569 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[Duplicate packet] ");
2574 // XXX Implement DPD if version == 1
2577 ti
= proto_tree_add_item_ret_int(geonw_so_tree
, hf_geonw_so_pv_lat
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &latlon
);
2578 if (latlon
< -900000000 || latlon
> 900000000) {
2579 expert_add_info_format(pinfo
, ti
, &ei_geonw_out_of_range
, "Latitude out of range (%f)", (float)latlon
/10000000);
2581 geonwh
->gnw_lat
= latlon
;
2583 ti
= proto_tree_add_item_ret_int(geonw_so_tree
, hf_geonw_so_pv_lon
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &latlon
);
2584 if (latlon
< -1800000000 || latlon
> 1800000000) {
2585 expert_add_info_format(pinfo
, ti
, &ei_geonw_out_of_range
, "Longitude out of range (%f)", (float)latlon
/10000000);
2587 geonwh
->gnw_lon
= latlon
;
2589 proto_tree_add_item(geonw_so_tree
, hf_geonw_so_pv_pai
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2590 proto_tree_add_item(geonw_so_tree
, hf_geonw_so_pv_speed
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2592 ti
= proto_tree_add_item_ret_uint(geonw_so_tree
, hf_geonw_so_pv_heading
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &tmp_val
);
2593 if (tmp_val
> 3600) {
2594 expert_add_info_format(pinfo
, ti
, &ei_geonw_out_of_range
, "Out of range [0..360] (%f)", (float)tmp_val
/10);
2598 proto_tree
*geonw_de_tree
= NULL
;
2599 proto_tree
*geonw_de_add_tree
= NULL
;
2600 switch(header_type
) {
2601 case HTST_GEOUNICAST
:
2603 // Destination address
2604 ti
= proto_tree_add_item(geonw_sh_tree
, hf_geonw_de_pv
, tvb
, offset
, 20, ENC_NA
);
2605 geonw_de_tree
= proto_item_add_subtree(ti
, ett_geonw_de
);
2607 ti
= proto_tree_add_item(geonw_de_tree
, hf_geonw_de_pv_addr
, tvb
, offset
, 8, ENC_NA
);
2608 geonw_de_add_tree
= proto_item_add_subtree(ti
, ett_geonw_de
);
2609 set_address_tvb(&pinfo
->net_dst
, geonw_address_type
, 8, tvb
, offset
);
2610 copy_address_shallow(&pinfo
->dst
, &pinfo
->net_dst
);
2611 copy_address_shallow(&geonwh
->gnw_dst
, &pinfo
->dst
);
2613 if (header_type
== HTST_LS_REPLY
) {
2614 transaction_end(pinfo
, geonw_tree
);
2617 proto_tree_add_item(geonw_de_add_tree
, hf_geonw_de_pv_addr_manual
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2618 proto_tree_add_item(geonw_de_add_tree
, hf_geonw_de_pv_addr_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2619 ti
= proto_tree_add_item_ret_uint(geonw_de_add_tree
, hf_geonw_de_pv_addr_country
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &reserved
);
2620 if (reserved
> 999) {
2621 expert_add_info(pinfo
, ti
, &ei_geonw_scc_too_big
);
2624 proto_tree_add_item(geonw_de_add_tree
, hf_geonw_de_pv_addr_mid
, tvb
, offset
, 6, ENC_NA
);
2627 proto_tree_add_item(geonw_de_tree
, hf_geonw_de_pv_time
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2629 ti
= proto_tree_add_item_ret_int(geonw_de_tree
, hf_geonw_de_pv_lat
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &latlon
);
2630 if (latlon
< -900000000 || latlon
> 900000000) {
2631 expert_add_info_format(pinfo
, ti
, &ei_geonw_out_of_range
, "Latitude out of range (%f)", (float)latlon
/10000000);
2634 ti
= proto_tree_add_item_ret_int(geonw_de_tree
, hf_geonw_de_pv_lon
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &latlon
);
2635 if (latlon
< -1800000000 || latlon
> 1800000000) {
2636 expert_add_info_format(pinfo
, ti
, &ei_geonw_out_of_range
, "Longitude out of range (%f)", (float)latlon
/10000000);
2640 case HTST_TSB_SINGLE
:
2642 // See usage in 636-4 subpart 2 for ITS-5G
2643 reserved
= tvb_get_uint32(tvb
, offset
, ENC_BIG_ENDIAN
);
2645 ti
= proto_tree_add_item(geonw_sh_tree
, hf_geonw_dccmco
, tvb
, offset
, 4, ENC_NA
);
2646 proto_tree
*dccmco
= proto_item_add_subtree(ti
, ett_geonw_dccmco
);
2647 proto_tree_add_item(dccmco
, hf_geonw_dccmco_cbr_l_0_hop
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2648 proto_tree_add_item(dccmco
, hf_geonw_dccmco_cbr_l_1_hop
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
2649 proto_tree_add_item(dccmco
, hf_geonw_dccmco_output_power
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
2650 proto_tree_add_item(dccmco
, hf_geonw_dccmco_reserved
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
2651 proto_tree_add_item(dccmco
, hf_geonw_shb_reserved
, tvb
, offset
+3, 1, ENC_BIG_ENDIAN
);
2654 proto_tree_add_item(geonw_sh_tree
, hf_geonw_shb_reserved
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2658 case HTST_GAC_CIRCLE
:
2660 case HTST_GAC_ELLIPSE
:
2661 case HTST_GBC_CIRCLE
:
2663 case HTST_GBC_ELLIPSE
:
2664 ti
= proto_tree_add_item_ret_int(geonw_sh_tree
, hf_geonw_gxc_latitude
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &latlon
);
2665 if (latlon
< -900000000 || latlon
> 900000000) {
2666 expert_add_info_format(pinfo
, ti
, &ei_geonw_out_of_range
, "Latitude out of range (%f)", (float)latlon
/10000000);
2669 ti
= proto_tree_add_item_ret_int(geonw_sh_tree
, hf_geonw_gxc_longitude
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &latlon
);
2670 if (latlon
< -1800000000 || latlon
> 1800000000) {
2671 expert_add_info_format(pinfo
, ti
, &ei_geonw_out_of_range
, "Longitude out of range (%f)", (float)latlon
/10000000);
2674 switch(header_type
&0x0f) {
2677 * According to EN 302 363-4-1:
2678 * In case of a circular area (GeoNetworking packet
2679 * sub-type HST = 0), the fields shall be set to the
2681 * 1) Distance a is set to the radius r.
2682 * 2) Distance b is set to 0.
2683 * 3) Angle is set to 0.
2685 proto_tree_add_item(geonw_sh_tree
, hf_geonw_gxc_radius
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2687 ti
= proto_tree_add_item_ret_uint(geonw_sh_tree
, hf_geonw_gxc_distanceb
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &reserved
);
2689 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2692 ti
= proto_tree_add_item_ret_uint(geonw_sh_tree
, hf_geonw_gxc_angle
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &reserved
);
2694 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2698 case HST_RECTANGULAR
:
2699 case HST_ELLIPSOIDAL
:
2700 proto_tree_add_item(geonw_sh_tree
, hf_geonw_gxc_distancea
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2702 proto_tree_add_item(geonw_sh_tree
, hf_geonw_gxc_distanceb
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2704 ti
= proto_tree_add_item_ret_uint(geonw_sh_tree
, hf_geonw_gxc_angle
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &tmp_val
);
2705 if (tmp_val
> 360) {
2706 expert_add_info_format(pinfo
, ti
, &ei_geonw_out_of_range
, "Out of range [0..360] (%f)", (float)tmp_val
);
2710 ti
= proto_tree_add_item_ret_uint(geonw_sh_tree
, hf_geonw_gxc_reserved
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &reserved
);
2712 expert_add_info(pinfo
, ti
, &ei_geonw_nz_reserved
);
2716 case HTST_LS_REQUEST
:
2718 ti
= proto_tree_add_item(geonw_sh_tree
, hf_geonw_lsrq_addr
, tvb
, offset
, 8, ENC_NA
);
2719 geonw_de_add_tree
= proto_item_add_subtree(ti
, ett_geonw_lsrq_add
);
2720 set_address_tvb(&pinfo
->net_dst
, geonw_address_type
, 8, tvb
, offset
);
2721 copy_address_shallow(&pinfo
->dst
, &pinfo
->net_dst
);
2723 proto_tree_add_item(geonw_de_add_tree
, hf_geonw_lsrq_addr_manual
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2724 proto_tree_add_item(geonw_de_add_tree
, hf_geonw_lsrq_addr_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2725 ti
= proto_tree_add_item_ret_uint(geonw_de_add_tree
, hf_geonw_lsrq_addr_country
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &reserved
);
2726 if (reserved
> 999) {
2727 expert_add_info(pinfo
, ti
, &ei_geonw_scc_too_big
);
2730 proto_tree_add_item(geonw_de_add_tree
, hf_geonw_lsrq_addr_mid
, tvb
, offset
, 6, ENC_NA
);
2732 transaction_start(pinfo
, geonw_tree
);
2735 //case HTST_TSB_MULT:
2737 proto_item_set_end(top_item
, tvb
, offset
);
2739 tap_queue_packet(geonw_tap
, pinfo
, geonwh
);
2742 // TODO expert info if payload_len different from remaining
2743 tvbuff_t
*next_tvb
= tvb_new_subset_length(tvb
, offset
, payload_len
);
2744 switch(ch_next_header
) {
2746 call_dissector(btpa_handle
, next_tvb
, pinfo
, tree
);
2749 call_dissector(btpb_handle
, next_tvb
, pinfo
, tree
);
2752 call_dissector(ipv6_handle
, next_tvb
, pinfo
, tree
);
2755 if (!dissector_try_uint(geonw_subdissector_table
, ch_next_header
, next_tvb
, pinfo
, tree
)) {
2756 call_data_dissector(next_tvb
, pinfo
, tree
);
2763 return tvb_captured_length(tvb
);
2770 btpa_src_prompt(packet_info
*pinfo _U_
, char* result
)
2772 uint32_t port
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_btpa_srcport
, pinfo
->curr_layer_num
));
2774 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "source (%u%s)", port
, UTF8_RIGHTWARDS_ARROW
);
2778 btpa_src_value(packet_info
*pinfo _U_
)
2780 return p_get_proto_data(pinfo
->pool
, pinfo
, hf_btpa_srcport
, pinfo
->curr_layer_num
);
2784 btpa_dst_prompt(packet_info
*pinfo
, char *result
)
2786 uint32_t port
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_btpa_dstport
, pinfo
->curr_layer_num
));
2788 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW
, port
);
2792 btpa_dst_value(packet_info
*pinfo
)
2794 return p_get_proto_data(pinfo
->pool
, pinfo
, hf_btpa_dstport
, pinfo
->curr_layer_num
);
2798 btpa_both_prompt(packet_info
*pinfo
, char *result
)
2800 uint32_t srcport
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_btpa_srcport
, pinfo
->curr_layer_num
)),
2801 destport
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_btpa_dstport
, pinfo
->curr_layer_num
));
2802 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "both (%u%s%u)", srcport
, UTF8_LEFT_RIGHT_ARROW
, destport
);
2806 btpb_dst_prompt(packet_info
*pinfo
, char *result
)
2808 uint32_t port
= GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, hf_btpb_dstport
, pinfo
->curr_layer_num
));
2810 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW
, port
);
2814 btpb_dst_value(packet_info
*pinfo
)
2816 return p_get_proto_data(pinfo
->pool
, pinfo
, hf_btpb_dstport
, pinfo
->curr_layer_num
);
2823 proto_register_btpa(void)
2825 static hf_register_info hf_btpa
[] = {
2828 { "Destination Port", "btpa.dstport",
2829 FT_UINT16
, BASE_PT_UDP
, NULL
, 0x0,
2833 { "Source Port", "btpa.srcport",
2834 FT_UINT16
, BASE_PT_UDP
, NULL
, 0x0,
2838 { "Port", "btpa.port",
2839 FT_UINT16
, BASE_PT_UDP
, NULL
, 0x0,
2843 static int *ett
[] = {
2846 proto_btpa
= proto_register_protocol("BTP-A", "BTPA", "btpa");
2847 btpa_handle
= register_dissector("btpa", dissect_btpa
, proto_btpa
);
2848 proto_register_field_array(proto_btpa
, hf_btpa
, array_length(hf_btpa
));
2850 proto_register_subtree_array(ett
, array_length(ett
));
2852 // Register subdissector table
2853 btpa_subdissector_table
= register_dissector_table("btpa.port",
2854 "BTP-A port", proto_btpa
, FT_UINT16
, BASE_HEX
);
2856 btpa_heur_subdissector_list
= register_heur_dissector_list_with_description("btpa.payload", "BTP-A payload fallback", proto_btpa
);
2859 static build_valid_func btpa_da_src_values
[1] = {btpa_src_value
};
2860 static build_valid_func btpa_da_dst_values
[1] = {btpa_dst_value
};
2861 static build_valid_func btpa_da_both_values
[2] = {btpa_src_value
, btpa_dst_value
};
2862 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
}};
2863 static decode_as_t btpa_da
= {"btpa", "btpa.port", 3, 2, btpa_da_values
, "BTP-A", "port(s) as",
2864 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
2866 register_decode_as(&btpa_da
);
2868 btpa_tap
= register_tap("btpa");
2869 btpa_follow_tap
= register_tap("btpa_follow");
2873 proto_reg_handoff_btpa(void)
2875 dissector_add_uint("geonw.ch.nh", 1, btpa_handle
);
2877 find_dissector_add_dependency("gnw", proto_btpa
);
2881 proto_register_btpb(void)
2883 static hf_register_info hf_btpb
[] = {
2886 { "Destination Port", "btpb.dstport",
2887 FT_UINT16
, BASE_PT_UDP
, NULL
, 0x0,
2890 { &hf_btpb_dstport_info
,
2891 { "Destination Port info", "btpb.dstportinf",
2892 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2896 static int *ett
[] = {
2899 proto_btpb
= proto_register_protocol("BTP-B", "BTPB", "btpb");
2900 btpb_handle
= register_dissector("btpb", dissect_btpb
, proto_btpb
);
2901 proto_register_field_array(proto_btpb
, hf_btpb
, array_length(hf_btpb
));
2903 proto_register_subtree_array(ett
, array_length(ett
));
2905 // Register subdissector table
2906 btpb_subdissector_table
= register_dissector_table("btpb.port",
2907 "BTP-B dst port", proto_btpb
, FT_UINT16
, BASE_HEX
);
2909 btpb_heur_subdissector_list
= register_heur_dissector_list_with_description("btpb.payload", "BTP-B payload fallback", proto_btpb
);
2912 static build_valid_func btpb_da_build_value
[1] = {btpb_dst_value
};
2913 static decode_as_value_t btpb_da_values
= {btpb_dst_prompt
, 1, btpb_da_build_value
};
2914 static decode_as_t btpb_da
= {"btpb", "btpb.port", 1, 0, &btpb_da_values
, NULL
, NULL
,
2915 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
2917 register_decode_as(&btpb_da
);
2919 btpb_tap
= register_tap("btpb");
2920 btpb_follow_tap
= register_tap("btpb_follow");
2924 proto_reg_handoff_btpb(void)
2926 dissector_add_uint("geonw.ch.nh", 2, btpb_handle
);
2928 find_dissector_add_dependency("gnw", proto_btpb
);
2931 // Display functions
2933 display_latitude( char *result
, int32_t hexver
)
2935 snprintf( result
, ITEM_LABEL_LENGTH
, "%ud%u'%.2f\"%c (%d)",
2936 abs(hexver
)/10000000,
2937 abs(hexver
%10000000)*6/1000000,
2938 abs(hexver
*6%1000000)*6./100000.,
2944 display_longitude( char *result
, int32_t hexver
)
2946 snprintf( result
, ITEM_LABEL_LENGTH
, "%ud%u'%.2f\"%c (%d)",
2947 abs(hexver
)/10000000,
2948 abs(hexver
%10000000)*6/1000000,
2949 abs(hexver
*6%1000000)*6./100000.,
2955 display_speed( char *result
, int32_t hexver
)
2957 snprintf( result
, ITEM_LABEL_LENGTH
, "%.2f m/s", hexver
/100.);
2961 display_heading( char *result
, uint32_t hexver
)
2963 snprintf( result
, ITEM_LABEL_LENGTH
, "%.1f degrees", hexver
/10.);
2967 display_elevation( char *result
, int32_t hexver
)
2969 // 0x0000 to 0xEFFF: positive numbers with a range from 0 to +6 143,9 meters. All numbers above +6 143,9 are
2970 // also represented by 0xEFFF.
2971 // 0xF001 to 0xFFFF: negative numbers with a range from -409,5 to -0,1 meters. All numbers below -409,5 are
2972 // also represented by 0xF001.
2973 // 0xF000: an unknown elevation
2974 if (hexver
== -4096)
2975 snprintf( result
, ITEM_LABEL_LENGTH
, "Unknown (%4x)", hexver
);
2977 snprintf( result
, ITEM_LABEL_LENGTH
, "%.1fm", hexver
/10.);
2981 dissect_geonw(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
)
2983 return dissect_geonw_internal(tvb
, pinfo
, tree
, data
, 0);
2987 dissect_geonw_comm(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
)
2989 return dissect_geonw_internal(tvb
, pinfo
, tree
, data
, BH_NH_COMMON_HDR
);
2993 dissect_geonw_sec(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data
)
2995 return dissect_geonw_internal(tvb
, pinfo
, tree
, data
, BH_NH_SECURED_PKT
);
2999 proto_register_geonw(void)
3001 static const value_string bh_next_header_names
[] = {
3003 { 1, "Common Header" },
3004 { 2, "Secured Packet" },
3008 static const value_string bh_lt_base_names
[] = {
3016 static const value_string ch_next_header_names
[] = {
3018 { CH_NH_BTP_A
, "BTP-A Transport protocol" },
3019 { CH_NH_BTP_B
, "BTP-B Transport protocol" },
3020 { CH_NH_IPV6
, "IPv6 header" },
3024 static const value_string traffic_classes_its_g5_names
[] = {
3025 { 0, "ITS-G5 Access Category Voice" },
3026 { 1, "ITS-G5 Access Category Video" },
3027 { 2, "ITS-G5 Access Category Best effort" },
3028 { 3, "ITS-G5 Access Category Background" },
3032 static const value_string itss_type_names
[] = {
3034 { 1, "Pedestrian" },
3037 { 4, "Motorcycle" },
3038 { 5, "Passenger Car" },
3040 { 7, "Light Truck" },
3041 { 8, "Heavy Truck" },
3043 { 10, "Special Vehicle" },
3045 { 15, "Road Side Unit" },
3049 static hf_register_info hf_geonw
[] = {
3052 { "Basic Header", "geonw.bh", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3055 { &hf_geonw_bh_version
,
3056 { "Version", "geonw.bh.version",
3057 FT_UINT8
, BASE_DEC
, NULL
, 0xF0,
3060 { &hf_geonw_bh_reserved
,
3061 { "Reserved", "geonw.bh.reserved", FT_UINT8
,
3062 BASE_HEX
, NULL
, 0x0, "It SHOULD be set to 0", HFILL
}},
3064 { &hf_geonw_bh_next_header
,
3065 { "Next Header", "geonw.bh.nh",
3066 FT_UINT8
, BASE_DEC
, VALS(bh_next_header_names
), 0x0F,
3069 { &hf_geonw_bh_life_time
,
3070 { "Life Time", "geonw.bh.lt",
3071 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3074 { &hf_geonw_bh_lt_mult
,
3075 { "Life Time multiplier", "geonw.bh.lt.mult",
3076 FT_UINT8
, BASE_DEC
, NULL
, 0xFC,
3079 { &hf_geonw_bh_lt_base
,
3080 { "Life Time base", "geonw.bh.lt.base",
3081 FT_UINT8
, BASE_DEC
, VALS(bh_lt_base_names
), 0x03,
3084 { &hf_geonw_bh_remain_hop_limit
,
3085 { "Remaining Hop Limit", "geonw.bh.rhl",
3086 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3090 { "Common Header", "geonw.ch", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3093 { &hf_geonw_ch_next_header
,
3094 { "Next Header", "geonw.ch.nh",
3095 FT_UINT8
, BASE_DEC
, VALS(ch_next_header_names
), 0xF0,
3098 { &hf_geonw_ch_reserved1
,
3099 { "Reserved", "geonw.ch.reserved1", FT_UINT8
,
3100 BASE_HEX
, NULL
, 0x0F, "It SHOULD be set to 0", HFILL
}},
3102 { &hf_geonw_ch_header_type
,
3103 { "Header type", "geonw.ch.htype",
3104 FT_UINT8
, BASE_HEX
, VALS(ch_header_type_names
), 0x00,
3107 { &hf_geonw_ch_traffic_class
,
3108 { "Traffic class", "geonw.ch.tclass",
3109 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3112 { &hf_geonw_ch_tc_scf
,
3113 { "Store Carry Forward", "geonw.ch.tc.buffer",
3114 FT_UINT8
, BASE_DEC
, NULL
, 0x80,
3117 { &hf_geonw_ch_tc_offload
,
3118 { "Channel offload", "geonw.ch.tc.offload",
3119 FT_UINT8
, BASE_DEC
, NULL
, 0x40,
3122 { &hf_geonw_ch_tc_id
,
3123 { "Traffic class ID", "geonw.ch.tc.id",
3124 FT_UINT8
, BASE_DEC
, VALS(traffic_classes_its_g5_names
), 0x3F,
3127 { &hf_geonw_ch_flags
,
3128 { "Flags", "geonw.ch.flags", FT_NONE
,
3129 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3131 { &hf_geonw_ch_flags_mob
,
3132 { "Mobility flag", "geonw.ch.flags.mob",
3133 FT_UINT8
, BASE_DEC
, NULL
, 0x80,
3136 { &hf_geonw_ch_flags_reserved
,
3137 { "Reserved", "geonw.ch.flags.reserved",
3138 FT_UINT8
, BASE_DEC
, NULL
, 0x7F,
3141 { &hf_geonw_ch_payload_length
,
3142 { "Payload length", "geonw.ch.plength",
3143 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
3146 { &hf_geonw_ch_max_hop_limit
,
3147 { "Maximum Hop Limit", "geonw.ch.mhl",
3148 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3151 { &hf_geonw_ch_reserved2
,
3152 { "Reserved", "geonw.ch.reserved2", FT_UINT8
,
3153 BASE_HEX
, NULL
, 0x00, "It SHOULD be set to 0", HFILL
}},
3155 { &hf_geonw_seq_num
,
3156 { "Sequence number", "geonw.seq_num",
3157 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
3160 { &hf_geonw_reserved
,
3161 { "Reserved", "geonw.reserved",
3162 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
3167 { "Source position", "geonw.src_pos",
3168 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
3171 { &hf_geonw_so_pv_addr
,
3172 { "GN_ADDR", "geonw.src_pos.addr",
3173 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
3176 { &hf_geonw_so_pv_addr_manual
,
3177 { "Manual", "geonw.src_pos.addr.manual",
3178 FT_UINT8
, BASE_DEC
, NULL
, 0x80,
3181 { &hf_geonw_so_pv_addr_type
,
3182 { "ITS-S type", "geonw.src_pos.addr.type",
3183 FT_UINT8
, BASE_DEC
, VALS(itss_type_names
), 0x7C,
3186 { &hf_geonw_so_pv_addr_country
,
3187 { "ITS-S Country Code", "geonw.src_pos.addr.country",
3188 FT_UINT16
, BASE_DEC
, VALS(E164_country_code_value
), 0x03FF,
3191 { &hf_geonw_so_pv_addr_mid
,
3192 { "MID", "geonw.src_pos.addr.mid",
3193 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
3196 { &hf_geonw_so_pv_time
,
3197 { "Timestamp", "geonw.src_pos.tst",
3198 FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_milliseconds
), 0x00,
3201 { &hf_geonw_so_pv_lat
,
3202 { "Latitude", "geonw.src_pos.lat",
3203 FT_INT32
, BASE_CUSTOM
, CF_FUNC(display_latitude
), 0x00,
3206 { &hf_geonw_so_pv_lon
,
3207 { "Longitude", "geonw.src_pos.long",
3208 FT_INT32
, BASE_CUSTOM
, CF_FUNC(display_longitude
), 0x00,
3211 { &hf_geonw_so_pv_pai
,
3212 { "Position accuracy indicator", "geonw.src_pos.pai",
3213 FT_UINT8
, BASE_DEC
, NULL
, 0x80,
3216 { &hf_geonw_so_pv_speed
,
3217 { "Speed", "geonw.src_pos.speed",
3218 FT_INT16
, BASE_CUSTOM
, CF_FUNC(display_speed
), 0x7FFF,
3221 { &hf_geonw_so_pv_heading
,
3222 { "Heading", "geonw.src_pos.hdg",
3223 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(display_heading
), 0x00,
3226 // Decentralized Congestion Control - Multi Channel Operation
3228 { "Decentralized Congestion Control - Multi Channel Operation", "geonw.dccmco",
3229 FT_NONE
, BASE_NONE
, NULL
, 0x00,
3232 { &hf_geonw_dccmco_cbr_l_0_hop
,
3233 { "Local channel busy ratio", "geonw.cbr_l0hop",
3234 FT_UINT8
, BASE_DEC
, NULL
, 0x80,
3237 { &hf_geonw_dccmco_cbr_l_1_hop
,
3238 { "Max neighbouring CBR", "geonw.cbr_l1hop",
3239 FT_UINT8
, BASE_DEC
, NULL
, 0x80,
3242 { &hf_geonw_dccmco_output_power
,
3243 { "Output power", "geonw.outpower",
3244 FT_UINT8
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_dbm
), 0xf8,
3247 { &hf_geonw_dccmco_reserved
,
3248 { "Reserved", "geonw.dccmco.reserved",
3249 FT_UINT8
, BASE_DEC
, NULL
, 0x07,
3254 { "Destination position", "geonw.dst_pos",
3255 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
3258 { &hf_geonw_de_pv_addr
,
3259 { "GN_ADDR", "geonw.dst_pos.addr",
3260 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
3263 { &hf_geonw_de_pv_addr_manual
,
3264 { "Manual", "geonw.dst_pos.addr.manual",
3265 FT_UINT8
, BASE_DEC
, NULL
, 0x80,
3268 { &hf_geonw_de_pv_addr_type
,
3269 { "ITS-S type", "geonw.dst_pos.addr.type",
3270 FT_UINT8
, BASE_DEC
, VALS(itss_type_names
), 0x7C,
3273 { &hf_geonw_de_pv_addr_country
,
3274 { "ITS-S Country Code", "geonw.dst_pos.addr.country",
3275 FT_UINT16
, BASE_DEC
, VALS(E164_country_code_value
), 0x03FF,
3278 { &hf_geonw_de_pv_addr_mid
,
3279 { "MID", "geonw.dst_pos.addr.mid",
3280 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
3283 { &hf_geonw_de_pv_time
,
3284 { "Timestamp", "geonw.dst_pos.tst",
3285 FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_milliseconds
), 0x00,
3288 { &hf_geonw_de_pv_lat
,
3289 { "Latitude", "geonw.dst_pos.lat",
3290 FT_INT32
, BASE_CUSTOM
, CF_FUNC(display_latitude
), 0x00,
3293 { &hf_geonw_de_pv_lon
,
3294 { "Longitude", "geonw.dst_pos.long",
3295 FT_INT32
, BASE_CUSTOM
, CF_FUNC(display_longitude
), 0x00,
3299 { &hf_geonw_gxc_latitude
,
3300 { "Latitude", "geonw.gxc.latitude",
3301 FT_INT32
, BASE_CUSTOM
, CF_FUNC(display_latitude
), 0x00,
3304 { &hf_geonw_gxc_longitude
,
3305 { "Longitude", "geonw.gxc.longitude",
3306 FT_INT32
, BASE_CUSTOM
, CF_FUNC(display_longitude
), 0x00,
3309 { &hf_geonw_gxc_radius
,
3310 { "Radius r", "geonw.gxc.radius",
3311 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_meters
), 0x00,
3314 { &hf_geonw_gxc_distancea
,
3315 { "Distance a", "geonw.gxc.distancea",
3316 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_meters
), 0x00,
3319 { &hf_geonw_gxc_distanceb
,
3320 { "Distance b", "geonw.gxc.distanceb",
3321 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_meters
), 0x00,
3324 { &hf_geonw_gxc_angle
,
3325 { "Angle", "geonw.gxc.angle",
3326 FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_degree_degrees
), 0x00,
3329 { &hf_geonw_gxc_reserved
,
3330 { "Reserved", "geonw.gxc.reserved",
3331 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
3335 { &hf_geonw_shb_reserved
,
3336 { "Reserved", "geonw.shb.reserved",
3337 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
3341 { &hf_geonw_lsrq_addr
,
3342 { "GN_ADDR", "geonw.ls_req.addr",
3343 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
3346 { &hf_geonw_lsrq_addr_manual
,
3347 { "Manual", "geonw.ls_req.addr.manual",
3348 FT_UINT8
, BASE_DEC
, NULL
, 0x80,
3351 { &hf_geonw_lsrq_addr_type
,
3352 { "ITS-S type", "geonw.ls_req.addr.type",
3353 FT_UINT8
, BASE_DEC
, VALS(itss_type_names
), 0x7C,
3356 { &hf_geonw_lsrq_addr_country
,
3357 { "ITS-S Country Code", "geonw.ls_req.addr.country",
3358 FT_UINT16
, BASE_DEC
, VALS(E164_country_code_value
), 0x03FF,
3361 { &hf_geonw_lsrq_addr_mid
,
3362 { "MID", "geonw.ls_req.addr.mid",
3363 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
3367 { "Beacon Packet", "geonw.beacon", FT_NONE
,
3368 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3371 { "GeoUniCast Packet", "geonw.guc", FT_NONE
,
3372 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3375 { "GeoAnyCast Packet", "geonw.gac", FT_NONE
,
3376 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3379 { "GeoBroadCast Packet", "geonw.gbc", FT_NONE
,
3380 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3383 { "Topologically-Scoped Broadcast Packet", "geonw.tsb", FT_NONE
,
3384 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3387 { "Location Service Packet", "geonw.ls", FT_NONE
,
3388 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3390 { &hf_geonw_resp_in
,
3391 { "Response frame", "geonw.resp_in", FT_FRAMENUM
, BASE_NONE
,
3392 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
3393 "The frame number of the corresponding response",
3396 { &hf_geonw_no_resp
,
3397 { "No response seen", "geonw.no_resp", FT_NONE
, BASE_NONE
,
3399 "No corresponding response frame was seen",
3402 { &hf_geonw_resp_to
,
3403 { "Request frame", "geonw.resp_to", FT_FRAMENUM
, BASE_NONE
,
3404 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
3405 "The frame number of the corresponding request", HFILL
}},
3407 { &hf_geonw_resptime
,
3408 { "Response time", "geonw.resptime", FT_DOUBLE
, BASE_NONE
,
3410 "The time between the request and the response, in ms.",
3413 { &hf_geonw_analysis_flags
,
3414 { "GeoNetworking Analysis Flags", "geonw.analysis.flags", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3415 "This frame has some of the GeoNetworking analysis flags set", HFILL
}},
3419 { "Secured Packet", "geonw.sec", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3422 { &hf_sgeonw_version
,
3423 { "Version", "geonw.sec.version",
3424 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3427 { &hf_sgeonw_profile
,
3428 { "Profile", "geonw.sec.profile",
3429 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3433 { "Header fields", "geonw.sec.hdr", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3437 { "Payload fields", "geonw.sec.pl", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3441 { "Trailer fields", "geonw.sec.trl", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3444 { &hf_sgeonw_public_key
,
3445 { "Public key", "geonw.sec.pub_key", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3448 { &hf_sgeonw_certificate
,
3449 { "Certificate", "geonw.sec.certif", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3452 { &hf_sgeonw_var_len
,
3453 { "Var length", "geonw.sec.var_len", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3456 { &hf_sgeonw_var_len_det
,
3457 { "Var length determinant", "geonw.sec.var_len.det",
3458 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
3461 { &hf_sgeonw_var_len_val
,
3462 { "Var length value", "geonw.sec.var_len.value",
3463 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3467 { "IntX", "geonw.sec.intx", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3470 { &hf_sgeonw_header_field
,
3471 { "Header field", "geonw.sec.hdr_field", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3474 { &hf_sgeonw_payload_field
,
3475 { "Payload field", "geonw.sec.pl_field", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3478 { &hf_sgeonw_trailer_field
,
3479 { "Trailer field", "geonw.sec.trl_field", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3482 { &hf_sgeonw_signer_info
,
3483 { "Signer info", "geonw.sec.signer_info", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3486 { &hf_sgeonw_eccpoint
,
3487 { "ECC Point", "geonw.sec.eccpoint", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3490 { &hf_sgeonw_duration
,
3491 { "Duration", "geonw.sec.duration", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3494 { &hf_sgeonw_subject_assurance
,
3495 { "Subject assurance", "geonw.sec.subj_assur", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3498 { &hf_sgeonw_encryption_parameter
,
3499 { "Encryption parameter", "geonw.sec.encrypt_param", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3502 { &hf_sgeonw_signature
,
3503 { "Signature", "geonw.sec.signature", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3506 { &hf_sgeonw_subject_info
,
3507 { "Subject info", "geonw.sec.subj_info", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3510 { &hf_sgeonw_subject_attribute
,
3511 { "Subject attribute", "geonw.sec.subj_attr", FT_NONE
, BASE_NONE
, NULL
, 0x0,
3514 { &hf_sgeonw_opaque
,
3515 { "Opaque", "geonw.sec.opaque", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3518 { &hf_sgeonw_encrypted_key
,
3519 { "Encrypted key", "geonw.sec.enc_key", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3522 { &hf_sgeonw_auth_tag
,
3523 { "Authentication tag", "geonw.sec.auth_tag", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3526 { &hf_sgeonw_ecdsasignature_s
,
3527 { "s", "geonw.sec.signature.s", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3530 { &hf_sgeonw_eccpoint_x
,
3531 { "x", "geonw.sec.eccpoint.x", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3534 { &hf_sgeonw_eccpoint_y
,
3535 { "y", "geonw.sec.eccpoint.y", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3538 { &hf_sgeonw_hashedid8
,
3539 { "Hashed ID 8", "geonw.sec.hashedid8", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3542 { &hf_sgeonw_encryption_parameter_nonce
,
3543 { "Nonce", "geonw.sec.nonce", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3546 { &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
}},
3547 { &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
}},
3548 { &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
}},
3549 { &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
}},
3550 { &hf_sgeonw_public_key_algorithm
, { "Public key algorithm", "geonw.sec.pubkeyalgo", FT_UINT8
, BASE_DEC
, VALS(public_key_algorithm_names
), 0x0, NULL
, HFILL
}},
3551 { &hf_sgeonw_eccpoint_type
, { "EccPoint type", "geonw.sec.eccpoint_type", FT_UINT8
, BASE_DEC
, VALS(eccpoint_type_names
), 0x0, NULL
, HFILL
}},
3552 { &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
}},
3553 { &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
}},
3554 { &hf_sgeonw_subject_type
, { "Subject type", "geonw.sec.subject_type", FT_UINT8
, BASE_DEC
, VALS(subject_type_names
), 0x0, NULL
, HFILL
}},
3555 { &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
}},
3556 { &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
}},
3557 { &hf_sgeonw_symmetric_algorithm
, { "Symmetric algorithm", "geonw.sec.symalgo", FT_UINT8
, BASE_DEC
, VALS(symmetric_algorithm_names
), 0x0, NULL
, HFILL
}},
3558 { &hf_sgeonw_region_type
, { "Region type", "geonw.sec.regiontype", FT_UINT8
, BASE_DEC
, VALS(region_type_names
), 0x0, NULL
, HFILL
}},
3559 { &hf_sgeonw_region_dictionary
, { "Region dictionary", "geonw.sec.regiondict", FT_UINT8
, BASE_DEC
, VALS(region_dictionary_names
), 0x0, NULL
, HFILL
}},
3561 { &hf_sgeonw_region_identifier
, { "Region identifier", "geonw.sec.regionid", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3562 { &hf_sgeonw_local_region
, { "Local region", "geonw.sec.local_region", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3564 { &hf_sgeonw_certification_version
, { "Certification version", "geonw.sec.certif.version", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3566 { &hf_sgeonw_time64
, { "Time64", "geonw.sec.time64", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3567 { &hf_sgeonw_conf
, { "Confidence", "geonw.sec.confidence", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3568 { &hf_sgeonw_time32
, { "Time32", "geonw.sec.time32", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3569 { &hf_sgeonw_lat
, { "Latitude", "geonw.sec.lat", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3570 { &hf_sgeonw_lon
, { "Longitude", "geonw.sec.lon", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3571 { &hf_sgeonw_elev
, { "Elevation", "geonw.sec.elev", FT_INT16
, BASE_CUSTOM
, CF_FUNC(display_elevation
), 0x0, NULL
, HFILL
}},
3572 { &hf_sgeonw_hashedid3
, { "Hashed ID 3", "geonw.sec.hashedid3", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3573 { &hf_sgeonw_duration_unit
, { "Unit", "geonw.sec.duration.unit", FT_UINT16
, BASE_DEC
, VALS(sgeonw_duration_unit_names
), 0xe000, NULL
, HFILL
}},
3574 { &hf_sgeonw_duration_value
, { "Value", "geonw.sec.duration.value", FT_UINT16
, BASE_DEC
, NULL
, 0x1fff, NULL
, HFILL
}},
3575 { &hf_sgeonw_radius
, { "Radius", "geonw.sec.radius", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3576 { &hf_sgeonw_priority
, { "Priority", "geonw.sec.priority", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3577 { &hf_sgeonw_subject_assurance_assurance
, { "Subject assurance", "geonw.sec.subj_assur.assurance", FT_UINT8
, BASE_DEC
, NULL
, 0xe0, NULL
, HFILL
}},
3578 { &hf_sgeonw_subject_assurance_reserved
, { "Reserved", "geonw.sec.subj_assur.reserved", FT_UINT8
, BASE_DEC
, NULL
, 0x1c, NULL
, HFILL
}},
3579 { &hf_sgeonw_subject_assurance_confidence
, { "Subject assurance", "geonw.sec.subj_assur.confidence", FT_UINT8
, BASE_DEC
, NULL
, 0x03, NULL
, HFILL
}},
3580 { &hf_sgeonw_msg_id
, { "Message ID", "geonw.sec.msg_id", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3581 { &hf_sgeonw_app_id
, { "Application ID", "geonw.sec.app_id", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
3585 static ei_register_info ei
[] = {
3586 { &ei_geonw_nz_reserved
, { "geonw.reserved_not_zero", PI_PROTOCOL
, PI_WARN
, "Incorrect, should be 0", EXPFILL
}},
3587 { &ei_geonw_version_err
, { "geonw.bogus_version", PI_MALFORMED
, PI_ERROR
, "Bogus GeoNetworking Version", EXPFILL
}},
3588 { &ei_geonw_rhl_lncb
, { "geonw.rhl.lncb", PI_SEQUENCE
, PI_NOTE
, "Remaining Hop Limit", EXPFILL
}},
3589 { &ei_geonw_rhl_too_low
, { "geonw.rhl.too_small", PI_SEQUENCE
, PI_NOTE
, "Remaining Hop Limit Too Low", EXPFILL
}},
3590 { &ei_geonw_mhl_lt_rhl
, { "geonw.rhl.ht_mhl", PI_SEQUENCE
, PI_WARN
, "Remaining Hop Limit To Live", EXPFILL
}},
3591 { &ei_geonw_scc_too_big
, { "geonw.scc_too_big", PI_MALFORMED
, PI_ERROR
, "Country code should be less than 1000", EXPFILL
}},
3592 { &ei_geonw_analysis_duplicate
, { "geonw.analysis_duplicate", PI_SEQUENCE
, PI_NOTE
, "Duplicate packet", EXPFILL
}},
3593 { &ei_geonw_resp_not_found
, { "geonw.resp_not_found", PI_SEQUENCE
, PI_WARN
, "Response not found", EXPFILL
}},
3594 { &ei_geonw_out_of_range
, { "geonw.position_oor", PI_MALFORMED
, PI_WARN
, "Position out of range", EXPFILL
}},
3595 { &ei_geonw_payload_len
, { "geonw.bogus_geonw_length", PI_PROTOCOL
, PI_ERROR
, "Bogus GeoNetworking length", EXPFILL
}},
3596 { &ei_sgeonw_len_unsupported
, { "geonw.sec.len_unsup", PI_MALFORMED
, PI_ERROR
, "Length not supported", EXPFILL
}},
3597 { &ei_sgeonw_len_too_long
, { "geonw.sec.bogus_len", PI_MALFORMED
, PI_ERROR
, "Length of int shall be at most 7 bits long", EXPFILL
}},
3598 { &ei_sgeonw_subj_info_too_long
, { "geonw.sec.bogus_sinfo", PI_MALFORMED
, PI_ERROR
, "Subject info length shall be at most 255", EXPFILL
}},
3599 { &ei_sgeonw_ssp_too_long
, { "geonw.sec.bogus_ssp", PI_MALFORMED
, PI_ERROR
, "Service specific permission length shall be at most 31", EXPFILL
}},
3600 { &ei_sgeonw_bogus
, { "geonw.sec.bogus", PI_MALFORMED
, PI_ERROR
, "Malformed message (check length)", EXPFILL
}},
3601 { &ei_geonw_intx_too_big
, { "geonw.intx_too_big", PI_MALFORMED
, PI_ERROR
, "IntX value exceeds 32 bits", EXPFILL
}},
3603 static int *ett
[] = {
3614 &ett_geonw_lsrq_add
,
3615 &ett_geonw_analysis
,
3618 &ett_geonw_sec
, // Secured packet
3619 &ett_sgeonw_hdr
, // Parts (header, payload or trailer) subtree
3620 &ett_sgeonw_field
, // Field subtree
3621 &ett_sgeonw_var_len
, // Variable length subtree
3623 &ett_sgeonw_duration
,
3624 &ett_sgeonw_eccpoint
,
3625 &ett_sgeonw_subject_assurance
,
3626 &ett_sgeonw_public_key
,
3627 &ett_sgeonw_encryption_parameter
,
3628 &ett_sgeonw_signature
,
3629 &ett_sgeonw_subject_info
,
3630 &ett_sgeonw_subject_attribute
,
3634 expert_module_t
* expert_geonw
;
3635 module_t
*geonw_module
;
3637 proto_geonw
= proto_register_protocol("GeoNetworking", "GNW", "gnw");
3640 geonw_handle
= register_dissector("gnw", dissect_geonw
, proto_geonw
);
3641 register_dissector("gnw.comm", dissect_geonw_comm
, proto_geonw
);
3642 register_dissector("gnw.sec", dissect_geonw_sec
, proto_geonw
);
3644 proto_register_field_array(proto_geonw
, hf_geonw
, array_length(hf_geonw
));
3645 proto_register_subtree_array(ett
, array_length(ett
));
3647 expert_geonw
= expert_register_protocol(proto_geonw
);
3648 expert_register_field_array(expert_geonw
, ei
, array_length(ei
));
3650 geonw_subdissector_table
= register_dissector_table("geonw.ch.nh",
3651 "GeoNetworking Next Header", proto_geonw
, FT_UINT8
, BASE_HEX
);
3653 ssp_subdissector_table
= register_dissector_table("geonw.ssp",
3654 "ATS-AID/PSID based dissector for Service Specific Permissions (SSP)", proto_geonw
, FT_UINT32
, BASE_HEX
);
3656 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
);
3658 /* Register configuration preferences */
3659 geonw_module
= prefs_register_protocol(proto_geonw
, NULL
);
3660 prefs_register_bool_preference(geonw_module
, "analyze_sequence_numbers",
3661 "Analyze GeoNetworking sequence numbers",
3662 "Make the GeoNetworking dissector analyze GeoNetworking sequence numbers to find and flag duplicate packet (Annex A)",
3663 &geonw_analyze_seq
);
3665 geonw_hashtable
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), geonw_addr_hash
, geonw_addr_cmp
);
3667 geonw_tap
= register_tap("geonw");
3671 proto_reg_handoff_geonw(void)
3673 dissector_handle_t sgeonw_handle_
;
3675 // This is a minimal dissector that just stores the tvbuff for later use;
3676 // not useful from outside a dissector table, so not using register_dissector()
3677 sgeonw_handle_
= create_dissector_handle(dissect_sgeonw
, proto_geonw
);
3679 dissector_add_uint_with_preference("ethertype", ETHERTYPE_GEONETWORKING
, geonw_handle
);
3681 // IPv6 over GeoNetworking Protocols
3682 ipv6_handle
= find_dissector("ipv6");
3683 dissector_add_uint("geonw.ch.nh", 3, ipv6_handle
);
3685 ieee1609dot2_handle
= find_dissector_add_dependency("ieee1609dot2.data", proto_geonw
);
3687 dissector_add_uint("ieee1609dot2.psid", psid_den_basic_services
, sgeonw_handle_
);
3688 dissector_add_uint("ieee1609dot2.psid", psid_ca_basic_services
, sgeonw_handle_
);
3689 dissector_add_uint("ieee1609dot2.psid", psid_traffic_light_manoeuver_service
, sgeonw_handle_
);
3690 dissector_add_uint("ieee1609dot2.psid", psid_road_and_lane_topology_service
, sgeonw_handle_
);
3691 dissector_add_uint("ieee1609dot2.psid", psid_infrastructure_to_vehicle_information_service
, sgeonw_handle_
);
3692 dissector_add_uint("ieee1609dot2.psid", psid_traffic_light_control_requests_service
, sgeonw_handle_
);
3693 dissector_add_uint("ieee1609dot2.psid", psid_geonetworking_management_communications
, sgeonw_handle_
);
3694 dissector_add_uint("ieee1609dot2.psid", psid_traffic_light_control_status_service
, sgeonw_handle_
);
3695 dissector_add_uint("ieee1609dot2.psid", psid_collective_perception_service
, sgeonw_handle_
);
3700 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3705 * indent-tabs-mode: nil
3708 * vi: set shiftwidth=4 tabstop=8 expandtab:
3709 * :indentSize=4:tabSize=8:noTabs=true: