Coverage Report

Created: 2026-05-14 06:28

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