Coverage Report

Created: 2026-11-12 07:01

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