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
dissect_btpa(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)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
dissect_btpb(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)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
geonw_str_len(const address * addr _U_)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
_geonw_to_str(const guint8 * addrdata,gchar * buf,int buf_len _U_)486 _geonw_to_str(const guint8* addrdata, gchar *buf, int buf_len _U_)
487 {
488 address eth_addr;
489
490 // Initial or Manual
491 if (addrdata[0] & 0x80)
492 *buf++ = '1';
493 else
494 *buf++ = '0';
495 *buf++ = '.';
496 // Station Type
497 guint32_to_str_buf((addrdata[0] & 0x7C) >> 2, buf, 26);
498 buf += (unsigned) strlen(buf);
499 *buf++ = '.';
500 // Country Code
501 guint32_to_str_buf(((guint32)(addrdata[0] & 0x03) << 8) + addrdata[1], buf, 23); // > 23
502 buf += (unsigned) strlen(buf);
503 *buf++ = '.';
504 // LL_ADDR
505 set_address(ð_addr, AT_ETHER, 6, &(addrdata[2]));
506 ether_to_str(ð_addr, buf, 18);
507
508 return 28;
509 }
510
511 static int
geonw_to_str(const address * addr,gchar * buf,int buf_len _U_)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*
geonw_col_filter_str(const address * addr _U_,gboolean is_src)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
geonw_len(void)527 geonw_len(void)
528 {
529 return 8;
530 }
531
532 static guint
geonw_addr_hash(gconstpointer key)533 geonw_addr_hash(gconstpointer key)
534 {
535 return wmem_strong_hash((const guint8 *)key, 8);
536 }
537
538 static gboolean
geonw_addr_cmp(gconstpointer a,gconstpointer b)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 *
geonw_addr_resolve(hashgeonw_t * tp)566 geonw_addr_resolve(hashgeonw_t *tp) {
567 const guint8 *addr = tp->addr;
568 guint16 val;
569 char *rname = tp->resolved_name;
570 address eth_addr;
571 guint8 l1, l2;
572
573 // Initial or Manual
574 if (addr[0] & 0x80)
575 *rname++ = 'm';
576 else
577 *rname++ = 'i';
578 *rname++ = '.';
579 // Station Type
580 val = (addr[0] & 0x7C) >> 2;
581 const char *string = try_val_to_str(val, itss_type_small_names);
582 if (string == NULL) {
583 guint32_to_str_buf(val, rname, MAXNAMELEN-2);
584 l1 = (guint8) strlen(rname);
585 }
586 else {
587 l1 = (guint8) g_strlcpy(rname, string, MAXNAMELEN-2);
588 }
589 rname += l1;
590 *rname++ = '.';
591 // Country Code
592 val = ((guint32)(addr[0] & 0x03) << 8) + addr[1];
593 string = try_val_to_str(val, E164_ISO3166_country_code_short_value);
594 if (string == NULL) {
595 guint32_to_str_buf(val, rname, MAXNAMELEN-12);
596 l2 = (guint8) strlen(rname);
597 }
598 else {
599 l2 = (guint8) g_strlcpy(rname, string, MAXNAMELEN-l1-3);
600 }
601 rname += l2;
602 //l1 += l2;
603 *rname++ = '.';
604 // LL_ADDR
605 set_address(ð_addr, AT_ETHER, 6, &(addr[2]));
606 ether_to_str(ð_addr, rname, 18);
607 // We could use ether_name_resolution_str:
608 // (void) g_strlcpy(rname, ether_name_resolution_str(ð_addr), MAXNAMELEN-l1-4);
609
610 tp->status = 1;
611
612 return tp;
613 }
614
615 static hashgeonw_t *
geonw_hash_new_entry(const guint8 * addr,gboolean resolve)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 *
geonw_name_lookup(const guint8 * addr,gboolean resolve)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 *
get_geonw_name(const guint8 * addr)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
geonw_name_resolution_str(const address * addr)668 const gchar* geonw_name_resolution_str(const address* addr)
669 {
670 return get_geonw_name((const guint8 *)addr->data);
671 }
672
geonw_name_resolution_len(void)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 ... */
transaction_start(packet_info * pinfo,proto_tree * tree)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
transaction_end(packet_info * pinfo,proto_tree * tree)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
dissect_sec_var_len(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_intx(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree,int hf,guint32 * ret)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
dissect_sec_eccpoint(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree,PublicKeyAlgorithm algorithm)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
dissect_sec_publickey(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_encryption_parameters(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_ecdsasignature(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree,PublicKeyAlgorithm algorithm)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
dissect_sec_signature(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_2dlocation(tvbuff_t * tvb,gint * offset,proto_tree * tree)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
dissect_sec_subject_info(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_itsaidssp(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_itsaidpriority(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_itsaidpriorityssp(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_subject_attributes(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree,guint8 version)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
dissect_sec_circularregion(tvbuff_t * tvb,gint * offset,proto_tree * tree)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
dissect_sec_rectangularregion(tvbuff_t * tvb,gint * offset,proto_tree * tree)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
dissect_sec_polygonalregion(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_identifiedregion(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_geographicregion(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_validity_restrictions(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree)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
dissect_sec_certificate(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree,guint8 version)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
dissect_sec_signer_info(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree,guint8 version)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
dissect_sec_eciesnistp256entryptedkey(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree,PublicKeyAlgorithm pub_alg,SymmetricAlgorithm symm_alg,guint8 version)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
dissect_sec_recipient_info(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * tree,guint8 version)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
dissect_sec_payload(tvbuff_t * tvb,gint * offset,packet_info * pinfo,proto_tree * part_tree)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
dissect_secured_message(tvbuff_t * tvb,gint offset,packet_info * pinfo,proto_tree * tree,void * data _U_)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
dissect_sgeonw(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree _U_,void * data _U_)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
dissect_geonw(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2125 dissect_geonw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2126 {
2127 guint8 bh_next_header;
2128 guint32 ch_next_header;
2129 guint32 header_type;
2130 guint32 rhl;
2131 guint32 tmp_val;
2132 gint offset = 0;
2133 proto_item *ti;
2134 proto_item *top_item;
2135 gint hdr_len = 0;
2136 guint32 payload_len = 0;
2137 guint32 reserved;
2138 guint32 timestamp;
2139 guint32 sequence_number = SN_MAX + 1;
2140 struct geonwheader *geonwh;
2141 gint32 latlon;
2142
2143 geonwh = wmem_new0(pinfo->pool, struct geonwheader);
2144
2145 col_set_str(pinfo->cinfo, COL_PROTOCOL, "GEONW");
2146 /* Clear out stuff in the info column */
2147 col_clear(pinfo->cinfo,COL_INFO);
2148
2149 bh_next_header = tvb_get_guint8(tvb, 0) & 0x0f;
2150 header_type = tvb_get_guint8(tvb, 5);
2151
2152 if (bh_next_header == BH_NH_SECURED_PKT) {
2153 hdr_len = BH_LEN;
2154 }
2155 else {
2156 hdr_len = BH_LEN + CH_LEN;
2157 switch(header_type & HT_MASK) {
2158 case HT_BEACON:
2159 hdr_len += BEACON_LEN;
2160 break;
2161 case HT_GEOUNICAST:
2162 hdr_len += GUC_LEN;
2163 break;
2164 case HT_GEOANYCAST:
2165 hdr_len += GAC_LEN;
2166 break;
2167 case HT_GEOBROADCAST:
2168 hdr_len += GBC_LEN;
2169 break;
2170 case HT_TSB:
2171 hdr_len += TSB_LEN;
2172 break;
2173 case HT_LS:
2174 hdr_len += LS_REQUEST_LEN;
2175 if (header_type == HTST_LS_REPLY) {
2176 hdr_len += (LS_REPLY_LEN - LS_REQUEST_LEN);
2177 }
2178 break;
2179 default:
2180 hdr_len = -1;
2181 }
2182 }
2183 top_item = proto_tree_add_item(tree, proto_geonw, tvb, 0, hdr_len, ENC_NA);
2184 proto_tree *geonw_tree = proto_item_add_subtree(top_item, ett_geonw);
2185
2186 // Basic Header subtree
2187 ti = proto_tree_add_item(geonw_tree, hf_geonw_bh, tvb, 0, 4, ENC_NA);
2188 proto_tree *geonw_bh_tree = proto_item_add_subtree(ti, ett_geonw_bh);
2189
2190 ti = proto_tree_add_item_ret_uint(geonw_bh_tree, hf_geonw_bh_version, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val);
2191 geonwh->gnw_ver = tmp_val;
2192 // Shall be 0 or 1
2193 if (tmp_val > 1) {
2194 col_add_fstr(pinfo->cinfo, COL_INFO,
2195 "Bogus GeoNetworking version (%u, must be less than 2)", tmp_val);
2196 expert_add_info_format(pinfo, ti, &ei_geonw_version_err, "Bogus GeoNetworking version");
2197 return tvb_captured_length(tvb);
2198 }
2199 proto_tree_add_item(geonw_bh_tree, hf_geonw_bh_next_header, tvb, offset, 1, ENC_BIG_ENDIAN);
2200 offset += 1;
2201 // Reserved byte
2202 // Expert info if not zero?
2203 ti = proto_tree_add_item_ret_uint(geonw_bh_tree, hf_geonw_bh_reserved, tvb, offset, 1, ENC_NA, &reserved);
2204 if (reserved) {
2205 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2206 }
2207 offset += 1;
2208
2209 // Subtree and lt_mult and lt_base
2210 ti = proto_tree_add_item_ret_uint(geonw_bh_tree, hf_geonw_bh_life_time, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val);
2211 geonwh->gnw_lt = tmp_val;
2212 proto_tree *geonw_bh_lt_tree = proto_item_add_subtree(ti, ett_geonw_bh_lt);
2213
2214 proto_tree_add_item(geonw_bh_lt_tree, hf_geonw_bh_lt_mult, tvb, offset, 1, ENC_BIG_ENDIAN);
2215 proto_tree_add_item(geonw_bh_lt_tree, hf_geonw_bh_lt_base, tvb, offset, 1, ENC_BIG_ENDIAN);
2216 offset += 1;
2217
2218 proto_item *rhl_ti = proto_tree_add_item_ret_uint(geonw_bh_tree, hf_geonw_bh_remain_hop_limit, tvb, offset, 1, ENC_BIG_ENDIAN, &rhl);
2219 geonwh->gnw_rhl = rhl;
2220 /*
2221 * Flag a low RHL if the next header is not a common header
2222 */
2223 if (rhl < 5 && bh_next_header != BH_NH_COMMON_HDR) {
2224 expert_add_info_format(pinfo, rhl_ti, &ei_geonw_rhl_too_low, "\"Remain Hop Limit\" only %u", rhl);
2225 }
2226 offset += 1;
2227
2228 if (bh_next_header == BH_NH_SECURED_PKT) {
2229 dissect_secured_message(tvb, offset, pinfo, geonw_tree, NULL);
2230 tvbuff_t *next_tvb = (tvbuff_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_geonw, 0);
2231 if (next_tvb) {
2232 tvb = next_tvb;
2233 bh_next_header = BH_NH_COMMON_HDR;
2234 offset = 0;
2235 header_type = tvb_get_guint8(tvb, 1);
2236
2237 hdr_len = CH_LEN;
2238 switch(header_type & HT_MASK) {
2239 case HT_BEACON:
2240 hdr_len += BEACON_LEN;
2241 break;
2242 case HT_GEOUNICAST:
2243 hdr_len += GUC_LEN;
2244 break;
2245 case HT_GEOANYCAST:
2246 hdr_len += GAC_LEN;
2247 break;
2248 case HT_GEOBROADCAST:
2249 hdr_len += GBC_LEN;
2250 break;
2251 case HT_TSB:
2252 hdr_len += TSB_LEN;
2253 break;
2254 case HT_LS:
2255 hdr_len += LS_REQUEST_LEN;
2256 if (header_type == HTST_LS_REPLY) {
2257 hdr_len += (LS_REPLY_LEN - LS_REQUEST_LEN);
2258 }
2259 break;
2260 default:
2261 hdr_len = -1;
2262 }
2263 p_add_proto_data(wmem_file_scope(), pinfo, proto_geonw, 0, NULL);
2264 }
2265 }
2266
2267 if (bh_next_header == BH_NH_COMMON_HDR) {
2268 // Common Header subtree
2269 ti = proto_tree_add_item(geonw_tree, hf_geonw_ch, tvb, offset, 8, ENC_NA);
2270 proto_tree *geonw_ch_tree = proto_item_add_subtree(ti, ett_geonw_ch);
2271
2272 // Next Header
2273 proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_next_header, tvb, offset, 1, ENC_BIG_ENDIAN, &ch_next_header);
2274 geonwh->gnw_proto = ch_next_header;
2275 // Reserved
2276 ti = proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_reserved1, tvb, offset, 1, ENC_NA, &reserved);
2277 if (reserved) {
2278 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2279 }
2280 offset += 1;
2281
2282 // HT
2283 proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_header_type, tvb, offset, 1, ENC_BIG_ENDIAN, &header_type);
2284 geonwh->gnw_htype = header_type;
2285 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(header_type, ch_header_type_names, "Unknown (%u)"));
2286 offset += 1;
2287
2288 /* Now that we know the header type, lets add expert info on RHL
2289 * RHL shall be
2290 * = 1 if parameter Packet transport type in the service primitive
2291 * GN-DATA.request is SHB, or if Header type HT = 1 (BEACON)
2292 * = Value of optional Maximum hop limit parameter from service
2293 * primitive GN-DATA.request
2294 * = Otherwise GN protocol constant itsGnDefaultHopLimit if
2295 * GN-DATA.request parameter Packet transport type is GUC, GBC, GBC
2296 * or TSB
2297 * Flag a low RHL if the packet is not BEACON or SHB.
2298 */
2299 if (header_type == HTST_BEACON || header_type == HTST_TSB_SINGLE) {
2300 if (rhl > 1) {
2301 expert_add_info_format(pinfo, rhl_ti, &ei_geonw_rhl_lncb, "\"Remain Hop Limit\" != 1 for BEACON or SHB (%u)", rhl);
2302 }
2303 } else if (rhl < 5) {
2304 expert_add_info_format(pinfo, rhl_ti, &ei_geonw_rhl_too_low, "\"Remain Hop Limit\" only %u", rhl);
2305 }
2306
2307 // TC
2308 ti = proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_traffic_class, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val);
2309 geonwh->gnw_tc = tmp_val;
2310 proto_tree *geonw_ch_tc_tree = proto_item_add_subtree(ti, ett_geonw_ch_tc);
2311
2312 proto_tree_add_item(geonw_ch_tc_tree, hf_geonw_ch_tc_scf, tvb, offset, 1, ENC_BIG_ENDIAN);
2313 proto_tree_add_item(geonw_ch_tc_tree, hf_geonw_ch_tc_offload, tvb, offset, 1, ENC_BIG_ENDIAN);
2314 proto_tree_add_item(geonw_ch_tc_tree, hf_geonw_ch_tc_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2315 offset += 1;
2316
2317 ti = proto_tree_add_item(geonw_ch_tree, hf_geonw_ch_flags, tvb, offset, 1, ENC_NA);
2318 proto_tree *geonw_ch_flag_tree = proto_item_add_subtree(ti, ett_geonw_ch_tc);
2319 // Flag (itsGnIsMobile)
2320 proto_tree_add_item_ret_uint(geonw_ch_flag_tree, hf_geonw_ch_flags_mob, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val);
2321 geonwh->gnw_flags = tmp_val;
2322 ti = proto_tree_add_item_ret_uint(geonw_ch_flag_tree, hf_geonw_ch_flags_reserved, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved);
2323 if (reserved & 0x7f) {
2324 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2325 }
2326 offset += 1;
2327
2328 // PL (16 bits)
2329 ti = proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_payload_length, tvb, offset, 2, ENC_BIG_ENDIAN, &payload_len);
2330 geonwh->gnw_len = payload_len;
2331 if (hdr_len > 0) { // We know the length of the header
2332 if (payload_len) {
2333 if (((header_type & HT_MASK) == HT_LS) || (header_type == HT_BEACON)) {
2334 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2335 }
2336 else if ((payload_len + (unsigned) hdr_len) > tvb_reported_length(tvb)) {
2337 expert_add_info(pinfo, ti, &ei_geonw_payload_len);
2338 }
2339 else {
2340 /*
2341 * Now that we know that the total length of this GNW datagram isn't
2342 * obviously bogus, adjust the length of this tvbuff to include only
2343 * the GNW datagram.
2344 */
2345 set_actual_length(tvb, hdr_len + payload_len);
2346 }
2347 }
2348 else {
2349 set_actual_length(tvb, hdr_len);
2350 }
2351 }
2352 offset += 2;
2353
2354 // MHL
2355 proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_max_hop_limit, tvb, offset, 1, ENC_BIG_ENDIAN, &tmp_val);
2356 geonwh->gnw_mhl = tmp_val;
2357 // Expert mhl < rhl: packet will be ignored
2358 if (tmp_val < rhl) {
2359 expert_add_info_format(pinfo, rhl_ti, &ei_geonw_mhl_lt_rhl, "Ignored: \"Remain Hop Limit\" > %u (mhl)", tmp_val);
2360 }
2361 offset += 1;
2362
2363 // Reserved...
2364 ti = proto_tree_add_item_ret_uint(geonw_ch_tree, hf_geonw_ch_reserved2, tvb, offset, 1, ENC_NA, &reserved);
2365 // Expert info if not zero
2366 if (reserved) {
2367 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2368 }
2369 offset += 1;
2370
2371 // Stop here if header_type unknown
2372 if (!IS_HT_KNOWN(header_type)) {
2373 // Update top level tree item
2374 proto_item_set_end(top_item, tvb, offset);
2375 return tvb_reported_length(tvb);
2376 }
2377
2378 geonwh->gnw_sn = SN_MAX+1;
2379
2380 proto_tree *geonw_sh_tree;
2381 switch(header_type & HT_MASK) {
2382 case HT_BEACON:
2383 ti = proto_tree_add_item(geonw_tree, hf_geonw_beacon, tvb, offset, hdr_len-offset, ENC_NA);
2384 break;
2385 case HT_GEOUNICAST:
2386 ti = proto_tree_add_item(geonw_tree, hf_geonw_guc, tvb, offset, hdr_len-offset, ENC_NA);
2387 break;
2388 case HT_GEOANYCAST:
2389 ti = proto_tree_add_item(geonw_tree, hf_geonw_gac, tvb, offset, hdr_len-offset, ENC_NA);
2390 break;
2391 case HT_GEOBROADCAST:
2392 ti = proto_tree_add_item(geonw_tree, hf_geonw_gbc, tvb, offset, hdr_len-offset, ENC_NA);
2393 break;
2394 case HT_TSB:
2395 ti = proto_tree_add_item(geonw_tree, hf_geonw_tsb, tvb, offset, hdr_len-offset, ENC_NA);
2396 break;
2397 case HT_LS:
2398 ti = proto_tree_add_item(geonw_tree, hf_geonw_ls, tvb, offset, hdr_len-offset, ENC_NA);
2399 break;
2400 default:
2401 // Exit if header_type unknown?
2402 return tvb_captured_length(tvb);
2403 }
2404 geonw_sh_tree = proto_item_add_subtree(ti, ett_geonw_sh);
2405
2406 switch(header_type) {
2407 case HTST_GEOUNICAST:
2408 case HTST_GAC_CIRCLE:
2409 case HTST_GAC_RECT:
2410 case HTST_GAC_ELLIPSE:
2411 case HTST_GBC_CIRCLE:
2412 case HTST_GBC_RECT:
2413 case HTST_GBC_ELLIPSE:
2414 case HTST_TSB_MULT:
2415 case HTST_LS_REQUEST:
2416 case HTST_LS_REPLY:
2417 // Seq num
2418 proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_seq_num, tvb, offset, 2, ENC_BIG_ENDIAN, &sequence_number);
2419 geonwh->gnw_sn = sequence_number;
2420 offset += 2;
2421 // 16 bits reserved
2422 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_reserved, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved);
2423 // Expert info if not zero?
2424 if (reserved) {
2425 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2426 }
2427 offset += 2;
2428 case HTST_TSB_SINGLE:
2429 case HTST_BEACON:
2430 break;
2431 }
2432
2433 // Every packet has source address
2434 ti = proto_tree_add_item(geonw_sh_tree, hf_geonw_so_pv, tvb, offset, 24, ENC_NA);
2435 proto_tree *geonw_so_tree = proto_item_add_subtree(ti, ett_geonw_so);
2436
2437 ti = proto_tree_add_item(geonw_so_tree, hf_geonw_so_pv_addr, tvb, offset, 8, ENC_NA);
2438 proto_tree *geonw_so_add_tree = proto_item_add_subtree(ti, ett_geonw_so);
2439 set_address_tvb(&pinfo->net_src, geonw_address_type, 8, tvb, offset);
2440 copy_address_shallow(&pinfo->src, &pinfo->net_src);
2441 copy_address_shallow(&geonwh->gnw_src, &pinfo->src);
2442
2443 proto_tree_add_item(geonw_so_add_tree, hf_geonw_so_pv_addr_manual, tvb, offset, 1, ENC_BIG_ENDIAN);
2444 proto_tree_add_item(geonw_so_add_tree, hf_geonw_so_pv_addr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2445 ti = proto_tree_add_item_ret_uint(geonw_so_add_tree, hf_geonw_so_pv_addr_country, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved);
2446 if (reserved > 999) {
2447 expert_add_info(pinfo, ti, &ei_geonw_scc_too_big);
2448 }
2449 offset += 2;
2450 proto_tree_add_item(geonw_so_add_tree, hf_geonw_so_pv_addr_mid, tvb, offset, 6, ENC_NA);
2451 offset += 6;
2452
2453 proto_tree_add_item_ret_uint(geonw_so_tree, hf_geonw_so_pv_time, tvb, offset, 4, ENC_BIG_ENDIAN, ×tamp);
2454 geonwh->gnw_tst = timestamp;
2455
2456 // XXX Is it possible to "follow" a station when updating its GN_ADDR?
2457
2458 if(geonw_analyze_seq && (geonwh->gnw_ver==0) && !(pinfo->fd->visited)) {
2459 // Duplication detection uses SN and TST or only TST (see Annex A of ETSI EN 302 636-4-1)
2460 // We rely on address type and hashtable as this shall be done on a per station basis (i.e. not over a conversation)
2461 // We do not try to consider GN_ADDR updates (due to duplicate address detection or anonymous setting)
2462 hashgeonw_t *tp = (hashgeonw_t *)wmem_map_lookup(geonw_hashtable, pinfo->net_src.data);
2463 if (tp == NULL) {
2464 tp = geonw_hash_new_entry((const guint8 *)pinfo->net_src.data, FALSE);
2465 tp->sequence_number = sequence_number;
2466 tp->timestamp = timestamp;
2467 } else {
2468 if ((sequence_number <= SN_MAX) && (tp->sequence_number > SN_MAX)) {
2469 tp->sequence_number = sequence_number;
2470 tp->timestamp = timestamp;
2471 }
2472 else if (sequence_number <= SN_MAX) {
2473 /*
2474 * 1 P is the received GeoNetworking packet
2475 * 2 SN(P) is the sequence number in the received GeoNetworking packet
2476 * 3 SN(SO) is the last received sequence number from source SO
2477 * 4 SN_MAX is the maximum sequence number = 2^16 - 1
2478 * 5 TST(P) is the timestamp in the received GeoNetworking packet
2479 * 6 TST(SO) is the last received timestamp from source SO
2480 * 7 TST_MAX is the maximum value of the timestamp = 2^32 - 1
2481 * 8
2482 * 9 IF (((TST(P) > TST(SO) AND ((TST(P) - TST(SO)) <= TST_MAX/2)) OR
2483 * ((TST(SO) > TST(P)) AND ((TST(SO) - TST(P)) > TST_MAX/2))) THEN
2484 * 10 # TST(P) is greater than TST(SO)
2485 * 11 TST(SO) = TST(P)
2486 * 12 SN(SO) = SN(P) # P is not a duplicate packet
2487 * 13 ELSEIF TST(P) = TST(SO) THEN
2488 * 14 IF (((SN(P) > SN(SO) AND ((SN(P) - SN(SO)) <= SN_MAX/2)) OR
2489 * ((SN(SO) > SN(P)) AND ((SN(SO) - SN(P)) > SN_MAX/2))) THEN
2490 * 15 # SN(P) is greater than SN(SO)
2491 * 16 TST(SO) = TST(P)
2492 * 17 SN(SO) = SN(P) # P is not a duplicate packet
2493 * 18 ELSE
2494 * 19 # SN(P) is not greater than SN(SO)
2495 * 20 # P is a duplicate
2496 * 21 ENDIF
2497 * 22 ELSE
2498 * 23 # TST(P) not greater than TST(SO)
2499 * 24 ENDIF
2500 */
2501 if (((timestamp > tp->timestamp) && (((guint64)timestamp - (guint64)tp->timestamp) <= (guint64)TST_MAX/2)) ||
2502 ((tp->timestamp > timestamp) && (((guint64)tp->timestamp - (guint64)timestamp) > (guint64)TST_MAX/2))) {
2503 // TST(P) is greater than TST(SO)
2504 tp->sequence_number = sequence_number;
2505 tp->timestamp = timestamp; // P is not a duplicate packet
2506 } else if (timestamp == tp->timestamp) {
2507 if (((sequence_number > tp->sequence_number) && ((sequence_number - tp->sequence_number) <= SN_MAX/2)) ||
2508 ((tp->sequence_number > sequence_number) && ((tp->sequence_number - sequence_number) > SN_MAX/2))) {
2509 // SN(P) is greater than SN(SO)
2510 tp->timestamp = timestamp;
2511 tp->sequence_number = sequence_number; // P is not a duplicate packet
2512 } else {
2513 // SN(P) is not greater than SN(SO)
2514 // P is a duplicate
2515 ti = proto_tree_add_item(geonw_tree, hf_geonw_analysis_flags, tvb, 0, 0, ENC_NA);
2516 proto_item_set_generated(ti);
2517 expert_add_info(pinfo, ti, &ei_geonw_analysis_duplicate);
2518 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Duplicate packet] ");
2519 }
2520 } // else { # TST(P) not greater than TST(SO) }
2521 }
2522 else {
2523 /*
2524 * 1 P is the received GeoNetworking packet
2525 * 2 TST(P) is the timestamp in the received GeoNetworking packet
2526 * 3 TST(SO) is the last received timestamp from source SO
2527 * 4 TS_MAX is the maximum value of the timestamp = 2^32 - 1
2528 * 5
2529 * 6 IF (((TST(P) > TST(SO) AND ((TST(P) - TST(SO)) <= TST_MAX/2)) OR
2530 * ((TST(SO) > TST(P)) AND ((TST(SO) - TST(P)) > TST_MAX/2))) THEN
2531 * 7 # TST(P) is greater than TST(SO)
2532 * 8 TST(SO) = TST(P) # P is not a duplicate packet
2533 * 9 ELSE
2534 * 10 # P is a duplicate
2535 * 11 ENDIF
2536 */
2537 if (((timestamp > tp->timestamp) && (((guint64)timestamp - (guint64)tp->timestamp) <= (guint64)TST_MAX/2)) ||
2538 ((tp->timestamp > timestamp) && (((guint64)tp->timestamp - (guint64)timestamp) > (guint64)TST_MAX/2))) {
2539 // TST(P) is greater than TST(SO)
2540 tp->timestamp = timestamp; // P is not a duplicate packet
2541 } else {
2542 // P is a duplicate
2543 ti = proto_tree_add_item(geonw_tree, hf_geonw_analysis_flags, tvb, 0, 0, ENC_NA);
2544 proto_item_set_generated(ti);
2545 expert_add_info(pinfo, ti, &ei_geonw_analysis_duplicate);
2546 col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Duplicate packet] ");
2547 }
2548 }
2549 }
2550 }
2551 // XXX Implement DPD if version == 1
2552
2553 offset += 4;
2554 ti = proto_tree_add_item_ret_int(geonw_so_tree, hf_geonw_so_pv_lat, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon);
2555 if (latlon < -900000000 || latlon > 900000000) {
2556 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Latitude out of range (%f)", (float)latlon/10000000);
2557 }
2558 geonwh->gnw_lat = latlon;
2559 offset += 4;
2560 ti = proto_tree_add_item_ret_int(geonw_so_tree, hf_geonw_so_pv_lon, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon);
2561 if (latlon < -1800000000 || latlon > 1800000000) {
2562 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Longitude out of range (%f)", (float)latlon/10000000);
2563 }
2564 geonwh->gnw_lon = latlon;
2565 offset += 4;
2566 proto_tree_add_item(geonw_so_tree, hf_geonw_so_pv_pai, tvb, offset, 1, ENC_BIG_ENDIAN);
2567 proto_tree_add_item(geonw_so_tree, hf_geonw_so_pv_speed, tvb, offset, 2, ENC_BIG_ENDIAN);
2568 offset += 2;
2569 ti = proto_tree_add_item_ret_uint(geonw_so_tree, hf_geonw_so_pv_heading, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp_val);
2570 if (tmp_val > 3600) {
2571 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Out of range [0..360] (%f)", (float)tmp_val/10);
2572 }
2573 offset += 2;
2574
2575 proto_tree *geonw_de_tree = NULL;
2576 proto_tree *geonw_de_add_tree = NULL;
2577 switch(header_type) {
2578 case HTST_GEOUNICAST:
2579 case HTST_LS_REPLY:
2580 // Destination address
2581 ti = proto_tree_add_item(geonw_sh_tree, hf_geonw_de_pv, tvb, offset, 20, ENC_NA);
2582 geonw_de_tree = proto_item_add_subtree(ti, ett_geonw_de);
2583
2584 ti = proto_tree_add_item(geonw_de_tree, hf_geonw_de_pv_addr, tvb, offset, 8, ENC_NA);
2585 geonw_de_add_tree = proto_item_add_subtree(ti, ett_geonw_de);
2586 set_address_tvb(&pinfo->net_dst, geonw_address_type, 8, tvb, offset);
2587 copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
2588 copy_address_shallow(&geonwh->gnw_dst, &pinfo->dst);
2589
2590 if (header_type == HTST_LS_REPLY) {
2591 transaction_end(pinfo, geonw_tree);
2592 }
2593
2594 proto_tree_add_item(geonw_de_add_tree, hf_geonw_de_pv_addr_manual, tvb, offset, 1, ENC_BIG_ENDIAN);
2595 proto_tree_add_item(geonw_de_add_tree, hf_geonw_de_pv_addr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2596 ti = proto_tree_add_item_ret_uint(geonw_de_add_tree, hf_geonw_de_pv_addr_country, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved);
2597 if (reserved > 999) {
2598 expert_add_info(pinfo, ti, &ei_geonw_scc_too_big);
2599 }
2600 offset += 2;
2601 proto_tree_add_item(geonw_de_add_tree, hf_geonw_de_pv_addr_mid, tvb, offset, 6, ENC_NA);
2602 offset += 6;
2603
2604 proto_tree_add_item(geonw_de_tree, hf_geonw_de_pv_time, tvb, offset, 4, ENC_BIG_ENDIAN);
2605 offset += 4;
2606 ti = proto_tree_add_item_ret_int(geonw_de_tree, hf_geonw_de_pv_lat, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon);
2607 if (latlon < -900000000 || latlon > 900000000) {
2608 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Latitude out of range (%f)", (float)latlon/10000000);
2609 }
2610 offset += 4;
2611 ti = proto_tree_add_item_ret_int(geonw_de_tree, hf_geonw_de_pv_lon, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon);
2612 if (latlon < -1800000000 || latlon > 1800000000) {
2613 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Longitude out of range (%f)", (float)latlon/10000000);
2614 }
2615 offset += 4;
2616 break;
2617 case HTST_TSB_SINGLE:
2618 // Reserved 32 bits
2619 // See usage in 636-4 subpart 2 for ITS-5G
2620 reserved = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
2621 if (reserved) {
2622 ti = proto_tree_add_item(geonw_sh_tree, hf_geonw_dccmco, tvb, offset, 4, ENC_NA);
2623 proto_tree *dccmco = proto_item_add_subtree(ti, ett_geonw_dccmco);
2624 proto_tree_add_item(dccmco, hf_geonw_dccmco_cbr_l_0_hop, tvb, offset, 1, ENC_BIG_ENDIAN);
2625 proto_tree_add_item(dccmco, hf_geonw_dccmco_cbr_l_1_hop, tvb, offset+1, 1, ENC_BIG_ENDIAN);
2626 proto_tree_add_item(dccmco, hf_geonw_dccmco_output_power, tvb, offset+2, 1, ENC_BIG_ENDIAN);
2627 proto_tree_add_item(dccmco, hf_geonw_dccmco_reserved, tvb, offset+2, 1, ENC_BIG_ENDIAN);
2628 proto_tree_add_item(dccmco, hf_geonw_shb_reserved, tvb, offset+3, 1, ENC_BIG_ENDIAN);
2629 }
2630 else {
2631 proto_tree_add_item(geonw_sh_tree, hf_geonw_shb_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
2632 }
2633 offset += 4;
2634 break;
2635 case HTST_GAC_CIRCLE:
2636 case HTST_GAC_RECT:
2637 case HTST_GAC_ELLIPSE:
2638 case HTST_GBC_CIRCLE:
2639 case HTST_GBC_RECT:
2640 case HTST_GBC_ELLIPSE:
2641 ti = proto_tree_add_item_ret_int(geonw_sh_tree, hf_geonw_gxc_latitude, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon);
2642 if (latlon < -900000000 || latlon > 900000000) {
2643 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Latitude out of range (%f)", (float)latlon/10000000);
2644 }
2645 offset += 4;
2646 ti = proto_tree_add_item_ret_int(geonw_sh_tree, hf_geonw_gxc_longitude, tvb, offset, 4, ENC_BIG_ENDIAN, &latlon);
2647 if (latlon < -1800000000 || latlon > 1800000000) {
2648 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Longitude out of range (%f)", (float)latlon/10000000);
2649 }
2650 offset += 4;
2651 switch(header_type&0x0f) {
2652 case HST_CIRCULAR:
2653 /*
2654 * According to EN 302 363-4-1:
2655 * In case of a circular area (GeoNetworking packet
2656 * sub-type HST = 0), the fields shall be set to the
2657 * following values:
2658 * 1) Distance a is set to the radius r.
2659 * 2) Distance b is set to 0.
2660 * 3) Angle is set to 0.
2661 */
2662 proto_tree_add_item(geonw_sh_tree, hf_geonw_gxc_radius, tvb, offset, 2, ENC_BIG_ENDIAN);
2663 offset += 2;
2664 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_gxc_distanceb, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved);
2665 if (reserved) {
2666 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2667 }
2668 offset += 2;
2669 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_gxc_angle, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved);
2670 if (reserved) {
2671 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2672 }
2673 offset += 2;
2674 break;
2675 case HST_RECTANGULAR:
2676 case HST_ELLIPSOIDAL:
2677 proto_tree_add_item(geonw_sh_tree, hf_geonw_gxc_distancea, tvb, offset, 2, ENC_BIG_ENDIAN);
2678 offset += 2;
2679 proto_tree_add_item(geonw_sh_tree, hf_geonw_gxc_distanceb, tvb, offset, 2, ENC_BIG_ENDIAN);
2680 offset += 2;
2681 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_gxc_angle, tvb, offset, 2, ENC_BIG_ENDIAN, &tmp_val);
2682 if (tmp_val > 360) {
2683 expert_add_info_format(pinfo, ti, &ei_geonw_out_of_range, "Out of range [0..360] (%f)", (float)tmp_val);
2684 }
2685 offset += 2;
2686 }
2687 ti = proto_tree_add_item_ret_uint(geonw_sh_tree, hf_geonw_gxc_reserved, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved);
2688 if (reserved) {
2689 expert_add_info(pinfo, ti, &ei_geonw_nz_reserved);
2690 }
2691 offset += 2;
2692 break;
2693 case HTST_LS_REQUEST:
2694 // GN_ADDR
2695 ti = proto_tree_add_item(geonw_sh_tree, hf_geonw_lsrq_addr, tvb, offset, 8, ENC_NA);
2696 geonw_de_add_tree = proto_item_add_subtree(ti, ett_geonw_lsrq_add);
2697 set_address_tvb(&pinfo->net_dst, geonw_address_type, 8, tvb, offset);
2698 copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
2699
2700 proto_tree_add_item(geonw_de_add_tree, hf_geonw_lsrq_addr_manual, tvb, offset, 1, ENC_BIG_ENDIAN);
2701 proto_tree_add_item(geonw_de_add_tree, hf_geonw_lsrq_addr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2702 ti = proto_tree_add_item_ret_uint(geonw_de_add_tree, hf_geonw_lsrq_addr_country, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved);
2703 if (reserved > 999) {
2704 expert_add_info(pinfo, ti, &ei_geonw_scc_too_big);
2705 }
2706 offset += 2;
2707 proto_tree_add_item(geonw_de_add_tree, hf_geonw_lsrq_addr_mid, tvb, offset, 6, ENC_NA);
2708 offset += 6;
2709 transaction_start(pinfo, geonw_tree);
2710 break;
2711 //case HTST_BEACON:
2712 //case HTST_TSB_MULT:
2713 }
2714 proto_item_set_end(top_item, tvb, offset);
2715
2716 tap_queue_packet(geonw_tap, pinfo, geonwh);
2717
2718 if (payload_len) {
2719 // TODO expert info if payload_len different from remaining
2720 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, payload_len);
2721 switch(ch_next_header) {
2722 case CH_NH_BTP_A:
2723 call_dissector(btpa_handle, next_tvb, pinfo, tree);
2724 break;
2725 case CH_NH_BTP_B:
2726 call_dissector(btpb_handle, next_tvb, pinfo, tree);
2727 break;
2728 case CH_NH_IPV6:
2729 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
2730 break;
2731 default:
2732 if (!dissector_try_uint(geonw_subdissector_table, ch_next_header, next_tvb, pinfo, tree)) {
2733 call_data_dissector(next_tvb, pinfo, tree);
2734 }
2735 }
2736 }
2737
2738 }
2739
2740 return tvb_captured_length(tvb);
2741 }
2742
2743 /*
2744 * Decode_as
2745 */
2746 static void
btpa_src_prompt(packet_info * pinfo _U_,gchar * result)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
btpa_src_value(packet_info * pinfo _U_)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
btpa_dst_prompt(packet_info * pinfo,gchar * result)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
btpa_dst_value(packet_info * pinfo)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
btpa_both_prompt(packet_info * pinfo,gchar * result)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
btpb_dst_prompt(packet_info * pinfo,gchar * result)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
btpb_dst_value(packet_info * pinfo)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
proto_register_btpa(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
proto_reg_handoff_btpa(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
proto_register_btpb(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
proto_reg_handoff_btpb(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
display_latitude(gchar * result,gint32 hexver)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
display_longitude(gchar * result,gint32 hexver)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
display_speed(gchar * result,gint32 hexver)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
display_heading(gchar * result,guint32 hexver)2944 display_heading( gchar *result, guint32 hexver )
2945 {
2946 g_snprintf( result, ITEM_LABEL_LENGTH, "%.1f degrees", hexver/10.);
2947 }
2948
2949 static void
display_elevation(gchar * result,gint32 hexver)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
proto_register_geonw(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
proto_reg_handoff_geonw(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