Coverage Report

Created: 2025-02-15 06:25

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