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