Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-someip-sd.c
Line
Count
Source
1
/* packet-someip-sd.c
2
 * SOME/IP-SD dissector.
3
 * By Dr. Lars Voelker <lars.voelker@technica-engineering.de> / <lars.voelker@bmw.de>
4
 * Copyright 2012-2024 Dr. Lars Voelker
5
 * Copyright 2020      Ayoub Kaanich
6
 * Copyright 2019      Ana Pantar
7
 * Copyright 2019      Guenter Ebermann
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
16
#include <config.h>
17
18
#include <epan/prefs.h>
19
#include <epan/expert.h>
20
#include <epan/to_str.h>
21
#include <epan/stats_tree.h>
22
#include <epan/tfs.h>
23
#include <wsutil/array.h>
24
#include "packet-udp.h"
25
#include "packet-someip.h"
26
27
 /*
28
  * Dissector for SOME/IP Service Discovery (SOME/IP-SD).
29
  *
30
  * See
31
  *     http://www.some-ip.com
32
  */
33
34
16
#define SOMEIP_SD_MESSAGEID                     0xffff8100
35
0
#define SOMEIP_SD_SERVICE_ID_OTHER_SERVICE      0xfffe
36
37
38
 /* Header */
39
16
#define SOMEIP_SD_REBOOT_FLAG                   0x80
40
16
#define SOMEIP_SD_UNICAST_FLAG                  0x40
41
16
#define SOMEIP_SD_EXPL_INIT_EVENT_REQ_FLAG      0x20
42
0
#define SOMEIP_SD_MIN_LENGTH                    12
43
44
/* Entries */
45
0
#define SD_ENTRY_LENGTH                         16
46
47
0
#define SD_ENTRY_UNKNOWN                        0x00
48
0
#define SD_ENTRY_SERVICE                        0x01
49
0
#define SD_ENTRY_EVENTGROUP                     0x02
50
/* TTL>0 */
51
0
#define SD_ENTRY_FIND_SERVICE                   0x00
52
0
#define SD_ENTRY_OFFER_SERVICE                  0x01
53
0
#define SD_ENTRY_SUBSCRIBE_EVENTGROUP           0x06
54
0
#define SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK       0x07
55
/* TTL=0 */
56
0
#define SD_ENTRY_STOP_OFFER_SERVICE             0x01
57
0
#define SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP      0x06
58
0
#define SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK      0x07
59
60
16
#define SD_EVENTGROUP_ENTRY_COUNTER_MASK        0x0f
61
16
#define SD_EVENTGROUP_ENTRY_RES2_MASK           0x70
62
16
#define SD_ENTRY_INIT_EVENT_REQ_MASK            0x80
63
64
/* Options */
65
0
#define SD_OPTION_MINLENGTH                     3
66
0
#define SD_OPTION_IPV4_LENGTH                   12
67
0
#define SD_OPTION_IPV6_LENGTH                   24
68
69
#define SD_OPTION_UNKNOWN                       0x00
70
0
#define SD_OPTION_CONFIGURATION                 0x01
71
0
#define SD_OPTION_LOADBALANCING                 0x02
72
0
#define SD_OPTION_IPV4_ENDPOINT                 0x04
73
0
#define SD_OPTION_IPV6_ENDPOINT                 0x06
74
0
#define SD_OPTION_IPV4_MULTICAST                0x14
75
0
#define SD_OPTION_IPV6_MULTICAST                0x16
76
0
#define SD_OPTION_IPV4_SD_ENDPOINT              0x24
77
0
#define SD_OPTION_IPV6_SD_ENDPOINT              0x26
78
79
0
#define SD_OPTION_L4PROTO_TCP                   6
80
0
#define SD_OPTION_L4PROTO_UDP                   17
81
82
/* option start 0..255, num 0..15 -> 0..270 */
83
0
#define SD_MAX_NUM_OPTIONS                      271
84
85
/* ID wireshark identifies the dissector by */
86
static int proto_someip_sd;
87
88
/* header field */
89
static int hf_someip_sd_flags;
90
static int hf_someip_sd_rebootflag;
91
static int hf_someip_sd_unicastflag;
92
static int hf_someip_sd_explicitiniteventflag;
93
static int hf_someip_sd_reserved;
94
95
static int hf_someip_sd_length_entriesarray;
96
static int hf_someip_sd_entries;
97
98
static int hf_someip_sd_entry;
99
static int hf_someip_sd_entry_type;
100
static int hf_someip_sd_entry_type_offerservice;
101
static int hf_someip_sd_entry_type_stopofferservice;
102
static int hf_someip_sd_entry_type_findservice;
103
static int hf_someip_sd_entry_type_subscribeeventgroup;
104
static int hf_someip_sd_entry_type_stopsubscribeeventgroup;
105
static int hf_someip_sd_entry_type_subscribeeventgroupack;
106
static int hf_someip_sd_entry_type_subscribeeventgroupnack;
107
static int hf_someip_sd_entry_index1;
108
static int hf_someip_sd_entry_index2;
109
static int hf_someip_sd_entry_numopt1;
110
static int hf_someip_sd_entry_numopt2;
111
static int hf_someip_sd_entry_opts_referenced;
112
static int hf_someip_sd_entry_serviceid;
113
static int hf_someip_sd_entry_servicename;
114
static int hf_someip_sd_entry_instanceid;
115
static int hf_someip_sd_entry_majorver;
116
static int hf_someip_sd_entry_ttl;
117
static int hf_someip_sd_entry_minorver;
118
static int hf_someip_sd_entry_eventgroupid;
119
static int hf_someip_sd_entry_eventgroupname;
120
static int hf_someip_sd_entry_reserved;
121
static int hf_someip_sd_entry_counter;
122
static int hf_someip_sd_entry_intial_event_flag;
123
static int hf_someip_sd_entry_reserved2;
124
125
static int hf_someip_sd_length_optionsarray;
126
static int hf_someip_sd_options;
127
128
static int hf_someip_sd_option_type;
129
static int hf_someip_sd_option_length;
130
static int hf_someip_sd_option_reserved;
131
static int hf_someip_sd_option_ipv4;
132
static int hf_someip_sd_option_ipv6;
133
static int hf_someip_sd_option_port;
134
static int hf_someip_sd_option_proto;
135
static int hf_someip_sd_option_reserved2;
136
static int hf_someip_sd_option_data;
137
static int hf_someip_sd_option_config_string;
138
static int hf_someip_sd_option_config_string_element;
139
static int hf_someip_sd_option_lb_priority;
140
static int hf_someip_sd_option_lb_weight;
141
142
/* protocol tree items */
143
static int ett_someip_sd;
144
static int ett_someip_sd_flags;
145
static int ett_someip_sd_entries;
146
static int ett_someip_sd_entry;
147
static int ett_someip_sd_options;
148
static int ett_someip_sd_option;
149
static int ett_someip_sd_config_string;
150
151
152
/*** Taps ***/
153
static int tap_someip_sd_entries = -1;
154
155
typedef struct _someip_sd_entries_tap {
156
    uint8_t entry_type;
157
    uint16_t service_id;
158
    uint8_t major_version;
159
    uint32_t minor_version;
160
    uint16_t instance_id;
161
    uint16_t eventgroup_id;
162
    uint32_t ttl;
163
} someip_sd_entries_tap_t;
164
165
166
/*** Stats ***/
167
static const char *st_str_ip_src = "Source Addresses";
168
static const char *st_str_ip_dst = "Destination Addresses";
169
170
static int st_node_ip_src = -1;
171
static int st_node_ip_dst = -1;
172
173
/*** Preferences ***/
174
static range_t *someip_ignore_ports_udp;
175
static range_t *someip_ignore_ports_tcp;
176
177
/* SOME/IP-SD Entry Names for TTL>0 */
178
static const value_string sd_entry_type_positive[] = {
179
    {SD_ENTRY_FIND_SERVICE,                                             "Find Service"},
180
    {SD_ENTRY_OFFER_SERVICE,                                            "Offer Service"},
181
    {SD_ENTRY_SUBSCRIBE_EVENTGROUP,                                     "Subscribe Eventgroup"},
182
    {SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK,                                 "Subscribe Eventgroup Ack"},
183
    {0, NULL}
184
};
185
186
/* SOME/IP-SD Entry Names for TTL=0 */
187
static const value_string sd_entry_type_negative[] = {
188
    {SD_ENTRY_STOP_OFFER_SERVICE,                                       "Stop Offer Service"},
189
    {SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP,                                "Stop Subscribe Eventgroup"},
190
    {SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK,                                "Subscribe Eventgroup Negative Ack"},
191
    {0, NULL}
192
};
193
194
static const value_string sd_serviceid_vs[] = {
195
    {0xFFFF,        "ANY"},
196
    {0, NULL}
197
};
198
199
static const value_string sd_instanceid_vs[] = {
200
    {0xFFFF,        "ANY"},
201
    {0, NULL}
202
};
203
204
static const value_string sd_majorversion_vs[] = {
205
    {0xFF,          "ANY"},
206
    {0, NULL}
207
};
208
209
static const value_string sd_minorversion_vs[] = {
210
    {0xFFFFFFFF,    "ANY"},
211
    {0, NULL}
212
};
213
214
static const value_string sd_eventgroupid_vs[] = {
215
    {0xFFFF,        "ANY"},
216
    {0, NULL}
217
};
218
219
/* SOME/IP-SD Option Names */
220
static const value_string sd_option_type[] = {
221
    {SD_OPTION_UNKNOWN,                                                 "Unknown"},
222
    {SD_OPTION_CONFIGURATION,                                           "Configuration"},
223
    {SD_OPTION_LOADBALANCING,                                           "Load Balancing"},
224
    {SD_OPTION_IPV4_ENDPOINT,                                           "IPv4 Endpoint"},
225
    {SD_OPTION_IPV6_ENDPOINT,                                           "IPv6 Endpoint"},
226
    {SD_OPTION_IPV4_MULTICAST,                                          "IPv4 Multicast"},
227
    {SD_OPTION_IPV6_MULTICAST,                                          "IPv6 Multicast"},
228
    {SD_OPTION_IPV4_SD_ENDPOINT,                                        "IPv4 SD Endpoint"},
229
    {SD_OPTION_IPV6_SD_ENDPOINT,                                        "IPv6 SD Endpoint"},
230
    {0, NULL}
231
};
232
233
/* L4 Protocol Names for SOME/IP-SD Endpoints */
234
static const value_string sd_option_l4protos[] = {
235
    {SD_OPTION_L4PROTO_TCP,                                             "TCP"},
236
    {SD_OPTION_L4PROTO_UDP,                                             "UDP"},
237
    {0, NULL}
238
};
239
240
static const true_false_string sd_reboot_flag = {
241
    "Session ID did not roll over since last reboot",
242
    "Session ID rolled over since last reboot"
243
};
244
245
static const true_false_string sd_unicast_flag = {
246
    "Unicast messages support",
247
    "Unicast messages not supported (deprecated)"
248
};
249
250
static const true_false_string sd_eiec_flag = {
251
    "Explicit Initial Event control supported",
252
    "Explicit Initial Event control not supported"
253
};
254
255
/*** expert info items ***/
256
static expert_field ei_someipsd_message_truncated;
257
static expert_field ei_someipsd_entry_array_malformed;
258
static expert_field ei_someipsd_entry_array_empty;
259
static expert_field ei_someipsd_entry_unknown;
260
static expert_field ei_someipsd_offer_without_endpoint;
261
static expert_field ei_someipsd_entry_stopsubsub;
262
static expert_field ei_someipsd_option_array_truncated;
263
static expert_field ei_someipsd_option_array_bytes_left;
264
static expert_field ei_someipsd_option_unknown;
265
static expert_field ei_someipsd_option_wrong_length;
266
static expert_field ei_someipsd_L4_protocol_unsupported;
267
static expert_field ei_someipsd_config_string_malformed;
268
static expert_field ei_someipsd_too_many_options;
269
270
/*** prototypes ***/
271
void proto_register_someip_sd(void);
272
void proto_reg_handoff_someip_sd(void);
273
274
static dissector_handle_t someip_sd_handle;
275
276
/**************************************
277
 ******** SOME/IP-SD Dissector ********
278
 *************************************/
279
280
static void
281
0
someip_sd_register_ports(uint32_t opt_index, uint32_t opt_num, uint32_t option_count, uint32_t option_ports[]) {
282
0
    unsigned i;
283
284
0
    for (i = opt_index; i < opt_index + opt_num && i < option_count; i++) {
285
0
        uint32_t l4port = 0x0000ffff & option_ports[i];
286
0
        uint32_t l4proto = (0xff000000 & option_ports[i]) >> 24;
287
288
0
        if (l4proto == SD_OPTION_L4PROTO_UDP && !value_is_in_range(someip_ignore_ports_udp, l4port)) {
289
0
            register_someip_port_udp(l4port);
290
0
        }
291
0
        if (l4proto == SD_OPTION_L4PROTO_TCP && !value_is_in_range(someip_ignore_ports_tcp, l4port)) {
292
0
            register_someip_port_tcp(l4port);
293
0
        }
294
295
        /* delete port from list to ensure only registering once per SD message */
296
0
        option_ports[i] = 0;
297
0
    }
298
0
}
299
300
static void
301
0
dissect_someip_sd_pdu_option_configuration(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, uint32_t length, unsigned optionnum) {
302
0
    uint32_t        offset_orig = offset;
303
0
    const uint8_t  *config_string;
304
0
    proto_item     *ti;
305
0
    proto_tree     *subtree;
306
307
0
    tree = proto_tree_add_subtree_format(tree, tvb, offset, length, ett_someip_sd_option, NULL, "%u: Configuration Option", optionnum);
308
309
    /* Add common fields */
310
0
    proto_tree_add_item(tree, hf_someip_sd_option_length, tvb, offset, 2, ENC_BIG_ENDIAN);
311
0
    offset += 2;
312
313
0
    proto_tree_add_item(tree, hf_someip_sd_option_type, tvb, offset, 1, ENC_NA);
314
0
    offset += 1;
315
316
0
    proto_tree_add_item(tree, hf_someip_sd_option_reserved, tvb, offset, 1, ENC_NA);
317
0
    offset += 1;
318
319
0
    int config_string_length = length - offset + offset_orig;
320
0
    ti = proto_tree_add_item_ret_string(tree, hf_someip_sd_option_config_string, tvb, offset, config_string_length, ENC_ASCII | ENC_NA, pinfo->pool, &config_string);
321
0
    subtree = proto_item_add_subtree(ti, ett_someip_sd_config_string);
322
323
0
    uint8_t pos = 0;
324
0
    uint8_t element_length;
325
0
    while (config_string != NULL && config_string_length - pos > 0) {
326
0
        element_length = config_string[pos];
327
0
        pos++;
328
329
0
        if (element_length == 0) {
330
0
            break;
331
0
        }
332
333
0
        if (element_length > config_string_length - pos) {
334
0
            expert_add_info(pinfo, ti, &ei_someipsd_config_string_malformed);
335
0
            break;
336
0
        }
337
338
0
        proto_tree_add_item(subtree, hf_someip_sd_option_config_string_element, tvb, offset + pos, element_length, ENC_ASCII);
339
0
        pos += element_length;
340
0
    }
341
0
}
342
343
static void
344
0
dissect_someip_sd_pdu_option_loadbalancing(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, uint32_t offset, uint32_t length, unsigned optionnum) {
345
0
    tree = proto_tree_add_subtree_format(tree, tvb, offset, length, ett_someip_sd_option, NULL, "%u: Load Balancing Option", optionnum);
346
347
    /* Add common fields */
348
0
    proto_tree_add_item(tree, hf_someip_sd_option_length, tvb, offset, 2, ENC_BIG_ENDIAN);
349
0
    offset += 2;
350
351
0
    proto_tree_add_item(tree, hf_someip_sd_option_type, tvb, offset, 1, ENC_NA);
352
0
    offset += 1;
353
354
0
    proto_tree_add_item(tree, hf_someip_sd_option_reserved, tvb, offset, 1, ENC_NA);
355
0
    offset += 1;
356
357
0
    proto_tree_add_item(tree, hf_someip_sd_option_lb_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
358
0
    offset += 2;
359
360
0
    proto_tree_add_item(tree, hf_someip_sd_option_lb_weight, tvb, offset, 2, ENC_BIG_ENDIAN);
361
0
}
362
363
static void
364
0
dissect_someip_sd_pdu_option_ipv4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, uint32_t length, unsigned optionnum, uint32_t option_ports[]) {
365
0
    uint8_t             type = 255;
366
0
    const char         *description = NULL;
367
0
    uint32_t            l4port = 0;
368
0
    uint32_t            l4proto = 0;
369
0
    const char         *l4protoname = NULL;
370
0
    const char         *ipstring = NULL;
371
372
0
    proto_item         *ti = NULL;
373
0
    proto_item         *ti_top = NULL;
374
375
0
    type = tvb_get_uint8(tvb, offset + 2);
376
0
    description = val_to_str(pinfo->pool, type, sd_option_type, "(Unknown Option: %d)");
377
0
    tree = proto_tree_add_subtree_format(tree, tvb, offset, length, ett_someip_sd_option, &ti_top, "%u: %s Option", optionnum, description);
378
379
0
    if (length != SD_OPTION_IPV4_LENGTH) {
380
0
        expert_add_info(pinfo, ti_top, &ei_someipsd_option_wrong_length);
381
0
        return;
382
0
    }
383
384
    /* Add common fields */
385
0
    proto_tree_add_item(tree, hf_someip_sd_option_length, tvb, offset, 2, ENC_BIG_ENDIAN);
386
0
    offset += 2;
387
388
0
    proto_tree_add_item(tree, hf_someip_sd_option_type, tvb, offset, 1, ENC_NA);
389
0
    offset += 1;
390
391
0
    proto_tree_add_item(tree, hf_someip_sd_option_reserved, tvb, offset, 1, ENC_NA);
392
0
    offset += 1;
393
394
0
    proto_tree_add_item(tree, hf_someip_sd_option_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
395
0
    ipstring = tvb_ip_to_str(pinfo->pool, tvb, offset);
396
0
    offset += 4;
397
398
0
    proto_tree_add_item(tree, hf_someip_sd_option_reserved2, tvb, offset, 1, ENC_NA);
399
0
    offset += 1;
400
401
0
    ti = proto_tree_add_item_ret_uint(tree, hf_someip_sd_option_proto, tvb, offset, 1, ENC_NA, &l4proto);
402
0
    l4protoname = val_to_str(pinfo->pool, l4proto, sd_option_l4protos, "Unknown Transport Protocol: %d");
403
0
    proto_item_append_text(ti, " (%s)", l4protoname);
404
405
0
    if (type != SD_OPTION_IPV4_ENDPOINT && l4proto == SD_OPTION_L4PROTO_TCP) {
406
0
        expert_add_info(pinfo, ti_top, &ei_someipsd_L4_protocol_unsupported);
407
0
    }
408
0
    offset += 1;
409
410
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_option_port, tvb, offset, 2, ENC_BIG_ENDIAN, &l4port);
411
412
0
    proto_item_append_text(ti_top, " (%s:%d (%s))", ipstring, l4port, l4protoname);
413
414
0
    option_ports[optionnum] = ((uint32_t)l4proto << 24) + l4port;
415
0
}
416
417
static void
418
0
dissect_someip_sd_pdu_option_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, uint32_t length, unsigned optionnum, uint32_t option_ports[]) {
419
0
    uint8_t             type = 255;
420
0
    const char         *description = NULL;
421
0
    uint32_t            l4port = 0;
422
0
    uint32_t            l4proto = 0;
423
0
    const char         *l4protoname = NULL;
424
0
    const char         *ipstring = NULL;
425
0
    proto_item         *ti = NULL;
426
0
    proto_item         *ti_top = NULL;
427
428
0
    type = tvb_get_uint8(tvb, offset + 2);
429
0
    description = val_to_str(pinfo->pool, type, sd_option_type, "(Unknown Option: %d)");
430
431
0
    tree = proto_tree_add_subtree_format(tree, tvb, offset, length, ett_someip_sd_option, &ti_top, "%u: %s Option", optionnum, description);
432
433
0
    if (length != SD_OPTION_IPV6_LENGTH) {
434
0
        expert_add_info(pinfo, ti_top, &ei_someipsd_option_wrong_length);
435
0
        return;
436
0
    }
437
438
0
    proto_tree_add_item(tree, hf_someip_sd_option_length, tvb, offset, 2, ENC_BIG_ENDIAN);
439
0
    offset += 2;
440
441
0
    proto_tree_add_item(tree, hf_someip_sd_option_type, tvb, offset, 1, ENC_NA);
442
0
    offset += 1;
443
444
0
    proto_tree_add_item(tree, hf_someip_sd_option_reserved, tvb, offset, 1, ENC_NA);
445
0
    offset += 1;
446
447
0
    proto_tree_add_item(tree, hf_someip_sd_option_ipv6, tvb, offset, 16, ENC_NA);
448
0
    ipstring = tvb_ip6_to_str(pinfo->pool, tvb, offset);
449
0
    offset += 16;
450
451
0
    proto_tree_add_item(tree, hf_someip_sd_option_reserved2, tvb, offset, 1, ENC_NA);
452
0
    offset += 1;
453
454
0
    ti = proto_tree_add_item_ret_uint(tree, hf_someip_sd_option_proto, tvb, offset, 1, ENC_NA, &l4proto);
455
0
    l4protoname = val_to_str(pinfo->pool, l4proto, sd_option_l4protos, "(Unknown Transport Protocol: %d)");
456
0
    proto_item_append_text(ti, " (%s)", l4protoname);
457
458
0
    if (type != SD_OPTION_IPV6_ENDPOINT && l4proto == SD_OPTION_L4PROTO_TCP) {
459
0
        expert_add_info(pinfo, ti_top, &ei_someipsd_L4_protocol_unsupported);
460
0
    }
461
0
    offset += 1;
462
463
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_option_port, tvb, offset, 2, ENC_BIG_ENDIAN, &l4port);
464
465
0
    proto_item_append_text(ti_top, " (%s:%d (%s))", ipstring, l4port, l4protoname);
466
467
0
    option_ports[optionnum] = ((uint32_t)l4proto << 24) + l4port;
468
0
}
469
470
static void
471
0
dissect_someip_sd_pdu_option_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, uint32_t length, unsigned optionnum) {
472
0
    uint32_t            len = 0;
473
0
    proto_item         *ti;
474
475
0
    tree = proto_tree_add_subtree_format(tree, tvb, offset, length, ett_someip_sd_option, &ti, "%u: %s Option", optionnum,
476
0
        val_to_str_const(tvb_get_uint8(tvb, offset + 2), sd_option_type, "Unknown"));
477
478
0
    expert_add_info(pinfo, ti, &ei_someipsd_option_unknown);
479
480
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_option_length, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
481
0
    offset += 2;
482
483
0
    proto_tree_add_item(tree, hf_someip_sd_option_type, tvb, offset, 1, ENC_NA);
484
0
    offset += 1;
485
486
0
    if (length > 3) {
487
0
        proto_tree_add_item(tree, hf_someip_sd_option_reserved, tvb, offset, 1, ENC_NA);
488
0
        offset += 1;
489
490
0
        if (length > 4) {
491
0
            proto_tree_add_item(tree, hf_someip_sd_option_data, tvb, offset, length - 4, ENC_NA);
492
0
        }
493
0
    }
494
0
}
495
496
static int
497
0
dissect_someip_sd_pdu_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti, uint32_t offset_orig, uint32_t length, uint32_t option_ports[], unsigned *option_count) {
498
0
    uint16_t            real_length = 0;
499
0
    uint8_t             option_type = 0;
500
0
    unsigned            optionnum = 0;
501
0
    tvbuff_t           *subtvb = NULL;
502
503
0
    uint32_t            offset = offset_orig;
504
505
0
    if (!tvb_bytes_exist(tvb, offset, SD_OPTION_MINLENGTH) || !tvb_bytes_exist(tvb, offset, length)) {
506
0
        expert_add_info(pinfo, ti, &ei_someipsd_option_array_truncated);
507
0
        return offset;
508
0
    }
509
510
0
    while (tvb_bytes_exist(tvb, offset, SD_OPTION_MINLENGTH)) {
511
0
        if (optionnum >= SD_MAX_NUM_OPTIONS) {
512
0
            expert_add_info(pinfo, ti, &ei_someipsd_too_many_options);
513
0
            break;
514
0
        }
515
516
0
        option_ports[optionnum] = 0;
517
518
0
        real_length = tvb_get_ntohs(tvb, offset) + 3;
519
0
        option_type = tvb_get_uint8(tvb, offset + 2);
520
521
0
        if (!tvb_bytes_exist(tvb, offset, (int)real_length) || offset - offset_orig + real_length > length) {
522
0
            expert_add_info(pinfo, ti, &ei_someipsd_option_array_truncated);
523
0
            return offset;
524
0
        }
525
526
0
        subtvb = tvb_new_subset_length(tvb, offset, (int)real_length);
527
528
0
        switch (option_type) {
529
0
        case SD_OPTION_CONFIGURATION:
530
0
            dissect_someip_sd_pdu_option_configuration(subtvb, pinfo, tree, 0, real_length, optionnum);
531
0
            break;
532
0
        case SD_OPTION_LOADBALANCING:
533
0
            dissect_someip_sd_pdu_option_loadbalancing(subtvb, pinfo, tree, 0, real_length, optionnum);
534
0
            break;
535
0
        case SD_OPTION_IPV4_ENDPOINT:
536
0
        case SD_OPTION_IPV4_MULTICAST:
537
0
        case SD_OPTION_IPV4_SD_ENDPOINT:
538
0
            dissect_someip_sd_pdu_option_ipv4(subtvb, pinfo, tree, 0, real_length, optionnum, option_ports);
539
0
            break;
540
541
0
        case SD_OPTION_IPV6_ENDPOINT:
542
0
        case SD_OPTION_IPV6_MULTICAST:
543
0
        case SD_OPTION_IPV6_SD_ENDPOINT:
544
0
            dissect_someip_sd_pdu_option_ipv6(subtvb, pinfo, tree, 0, real_length, optionnum, option_ports);
545
0
            break;
546
547
0
        default:
548
0
            dissect_someip_sd_pdu_option_unknown(subtvb, pinfo, tree, 0, real_length, optionnum);
549
0
            break;
550
0
        }
551
0
        optionnum++;
552
0
        offset += real_length;
553
0
    }
554
555
0
    *option_count = optionnum;
556
557
0
    return offset;
558
0
}
559
560
static void
561
0
someip_sd_pdu_entry_append_text(proto_item *ti_entry, uint8_t category, uint16_t serviceid, uint16_t instanceid, uint8_t majorver, uint32_t minorver, uint16_t eventgroupid, char *buf_opt_ref) {
562
0
    if (category != SD_ENTRY_SERVICE && category != SD_ENTRY_EVENTGROUP) {
563
0
        return;
564
0
    }
565
566
0
    if (serviceid == 0xffff) {
567
0
        proto_item_append_text(ti_entry, " (Service ID ANY");
568
0
    } else {
569
0
        proto_item_append_text(ti_entry, " (Service ID 0x%04x", serviceid);
570
0
    }
571
572
0
    if (instanceid == 0xffff) {
573
0
        proto_item_append_text(ti_entry, ", Instance ID ANY");
574
0
    } else {
575
0
        proto_item_append_text(ti_entry, ", Instance ID 0x%04x", instanceid);
576
0
    }
577
578
0
    if (majorver == 0xff) {
579
0
        proto_item_append_text(ti_entry, ", Version ANY");
580
0
    } else {
581
0
        proto_item_append_text(ti_entry, ", Version %u", majorver);
582
0
    }
583
584
0
    switch (category) {
585
0
    case SD_ENTRY_SERVICE:
586
0
        if (minorver == 0xffffffff) {
587
0
            proto_item_append_text(ti_entry, ".ANY");
588
0
        } else {
589
0
            proto_item_append_text(ti_entry, ".%u", minorver);
590
0
        }
591
0
        break;
592
593
0
    case SD_ENTRY_EVENTGROUP:
594
0
        if (eventgroupid == 0xffff) {
595
0
            proto_item_append_text(ti_entry, ", Eventgroup ID ANY");
596
0
        } else {
597
0
            proto_item_append_text(ti_entry, ", Eventgroup ID 0x%04x", eventgroupid);
598
0
        }
599
0
        break;
600
0
    }
601
602
0
    proto_item_append_text(ti_entry, ", Options: %s)", buf_opt_ref);
603
0
}
604
605
static void
606
0
dissect_someip_sd_pdu_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset_orig, uint32_t length, uint8_t *type, uint32_t *ttl, uint64_t *uniqueid, uint32_t option_ports[], unsigned option_count, proto_item **ti_entry) {
607
0
    uint32_t            serviceid = 0;
608
0
    uint32_t            instanceid = 0;
609
0
    uint32_t            eventgroupid = 0;
610
0
    uint32_t            majorver = 0;
611
0
    uint32_t            minorver = 0;
612
0
    uint32_t            opt_index1;
613
0
    uint32_t            opt_index2;
614
0
    uint32_t            opt_num1;
615
0
    uint32_t            opt_num2;
616
617
0
    uint8_t             category = SD_ENTRY_UNKNOWN;
618
619
0
    const char         *description = NULL;
620
0
    static char         buf_opt_ref[32];
621
622
0
    proto_item         *ti;
623
624
0
    uint32_t            offset = offset_orig;
625
626
0
    *uniqueid = 0;
627
0
    *type = 255;
628
0
    *ttl = 0;
629
630
0
    if (length < SD_ENTRY_LENGTH || !tvb_bytes_exist(tvb, offset, length)) {
631
0
        return;
632
0
    }
633
634
    /* lets look ahead and find out the type and ttl */
635
0
    *type = tvb_get_uint8(tvb, offset);
636
0
    *ttl = tvb_get_ntoh24(tvb, offset + 9);
637
638
0
    if (*type < 4) {
639
0
        category = SD_ENTRY_SERVICE;
640
0
    } else if (*type >= 4 && *type < 8) {
641
0
        category = SD_ENTRY_EVENTGROUP;
642
0
    } else {
643
0
        *ti_entry = proto_tree_add_none_format(tree, hf_someip_sd_entry, tvb, offset, SD_ENTRY_LENGTH, "Unknown Entry (Type: %d)", *type);
644
0
        expert_add_info(pinfo, *ti_entry, &ei_someipsd_entry_unknown);
645
0
        return;
646
0
    }
647
648
0
    description = val_to_str_const(*type,
649
0
                                   (*ttl == 0) ? sd_entry_type_negative : sd_entry_type_positive,
650
0
                                   "Unknown");
651
652
0
    *ti_entry = proto_tree_add_none_format(tree, hf_someip_sd_entry, tvb, offset, SD_ENTRY_LENGTH, "%s Entry", description);
653
0
    tree = proto_item_add_subtree(*ti_entry, ett_someip_sd_entry);
654
655
0
    proto_tree_add_uint_format_value(tree, hf_someip_sd_entry_type, tvb, offset, 1, *type, "0x%02x (%s)", *type, description);
656
0
    offset += 1;
657
658
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_index1, tvb, offset, 1, ENC_BIG_ENDIAN, &opt_index1);
659
0
    offset += 1;
660
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_index2, tvb, offset, 1, ENC_BIG_ENDIAN, &opt_index2);
661
0
    offset += 1;
662
663
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_numopt1, tvb, offset, 1, ENC_NA, &opt_num1);
664
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_numopt2, tvb, offset, 1, ENC_NA, &opt_num2);
665
0
    offset += 1;
666
667
0
    if (opt_num1 != 0 && opt_num2 == 0) {
668
0
        snprintf(buf_opt_ref, 32, "%d-%d", opt_index1, opt_index1 + opt_num1 - 1);
669
0
    } else if (opt_num1 == 0 && opt_num2 != 0) {
670
0
        snprintf(buf_opt_ref, 32, "%d-%d", opt_index2, opt_index2 + opt_num2 - 1);
671
0
    } else if (opt_num1 != 0 && opt_num2 != 0) {
672
0
        snprintf(buf_opt_ref, 32, "%d-%d,%d-%d", opt_index1, opt_index1 + opt_num1 - 1, opt_index2, opt_index2 + opt_num2 - 1);
673
0
    } else {
674
0
        snprintf(buf_opt_ref, 32, "None");
675
0
    }
676
677
0
    ti = proto_tree_add_string(tree, hf_someip_sd_entry_opts_referenced, tvb, offset - 3, 3, buf_opt_ref);
678
0
    proto_item_set_generated(ti);
679
680
0
    ti = proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_serviceid, tvb, offset, 2, ENC_BIG_ENDIAN, &serviceid);
681
0
    description = someip_lookup_service_name((uint16_t)serviceid);
682
0
    if (description != NULL) {
683
0
        proto_item_append_text(ti, " (%s)", description);
684
0
        ti = proto_tree_add_string(tree, hf_someip_sd_entry_servicename, tvb, offset, 2, description);
685
0
        proto_item_set_generated(ti);
686
0
        proto_item_set_hidden(ti);
687
0
    }
688
0
    offset += 2;
689
690
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_instanceid, tvb, offset, 2, ENC_BIG_ENDIAN, &instanceid);
691
0
    offset += 2;
692
693
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_majorver, tvb, offset, 1, ENC_BIG_ENDIAN, &majorver);
694
0
    offset += 1;
695
696
0
    proto_tree_add_item(tree, hf_someip_sd_entry_ttl, tvb, offset, 3, ENC_BIG_ENDIAN);
697
0
    offset += 3;
698
699
    /* Add specific fields - i.e. the last line */
700
0
    if (category == SD_ENTRY_SERVICE) {
701
0
        proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_minorver, tvb, offset, 4, ENC_BIG_ENDIAN, &minorver);
702
0
        someip_sd_pdu_entry_append_text(*ti_entry, category, serviceid, instanceid, majorver, minorver, 0, buf_opt_ref);
703
0
    } else if (category == SD_ENTRY_EVENTGROUP) {
704
0
        proto_tree_add_item(tree, hf_someip_sd_entry_reserved, tvb, offset, 1, ENC_NA);
705
0
        offset += 1;
706
707
0
        proto_tree_add_item(tree, hf_someip_sd_entry_intial_event_flag, tvb, offset, 1, ENC_NA);
708
0
        proto_tree_add_item(tree, hf_someip_sd_entry_reserved2, tvb, offset, 1, ENC_NA);
709
0
        proto_tree_add_item(tree, hf_someip_sd_entry_counter, tvb, offset, 1, ENC_NA);
710
0
        offset += 1;
711
712
0
        ti = proto_tree_add_item_ret_uint(tree, hf_someip_sd_entry_eventgroupid, tvb, offset, 2, ENC_BIG_ENDIAN, &eventgroupid);
713
0
        description = someip_lookup_eventgroup_name((uint16_t)serviceid, (uint16_t)eventgroupid);
714
0
        if (description != NULL) {
715
0
            proto_item_append_text(ti, " (%s)", description);
716
0
            ti = proto_tree_add_string(tree, hf_someip_sd_entry_eventgroupname, tvb, offset, 2, description);
717
0
            proto_item_set_generated(ti);
718
0
            proto_item_set_hidden(ti);
719
0
        }
720
721
0
        someip_sd_pdu_entry_append_text(*ti_entry, category, serviceid, instanceid, majorver, 0, eventgroupid, buf_opt_ref);
722
0
    }
723
724
    /* lets add some combined filtering term */
725
0
    *uniqueid = (((uint64_t)serviceid) << 32) | (uint64_t)instanceid << 16 | (uint64_t)eventgroupid;
726
727
0
    ti = NULL;
728
0
    if (*ttl > 0) {
729
0
        switch (*type) {
730
0
        case SD_ENTRY_FIND_SERVICE:
731
0
            ti = proto_tree_add_uint64_format_value(tree, hf_someip_sd_entry_type_findservice, tvb, offset_orig, SD_ENTRY_LENGTH, *uniqueid, "on 0x%012" PRIx64, *uniqueid);
732
0
            break;
733
0
        case SD_ENTRY_OFFER_SERVICE:
734
0
            ti = proto_tree_add_uint64_format_value(tree, hf_someip_sd_entry_type_offerservice, tvb, offset_orig, SD_ENTRY_LENGTH, *uniqueid, "on 0x%012" PRIx64, *uniqueid);
735
0
            break;
736
0
        case SD_ENTRY_SUBSCRIBE_EVENTGROUP:
737
0
            ti = proto_tree_add_uint64_format_value(tree, hf_someip_sd_entry_type_subscribeeventgroup, tvb, offset_orig, SD_ENTRY_LENGTH, *uniqueid, "on 0x%012" PRIx64, *uniqueid);
738
0
            break;
739
0
        case SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK:
740
0
            ti = proto_tree_add_uint64_format_value(tree, hf_someip_sd_entry_type_subscribeeventgroupack, tvb, offset_orig, SD_ENTRY_LENGTH, *uniqueid, "on 0x%012" PRIx64, *uniqueid);
741
0
            break;
742
0
        }
743
0
    } else {
744
0
        switch (*type) {
745
0
        case SD_ENTRY_STOP_OFFER_SERVICE:
746
0
            ti = proto_tree_add_uint64_format_value(tree, hf_someip_sd_entry_type_stopofferservice, tvb, offset_orig, SD_ENTRY_LENGTH, *uniqueid, "on 0x%012" PRIx64, *uniqueid);
747
0
            break;
748
0
        case SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP:
749
0
            ti = proto_tree_add_uint64_format_value(tree, hf_someip_sd_entry_type_stopsubscribeeventgroup, tvb, offset_orig, SD_ENTRY_LENGTH, *uniqueid, "on 0x%012" PRIx64, *uniqueid);
750
0
            break;
751
0
        case SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK:
752
0
            ti = proto_tree_add_uint64_format_value(tree, hf_someip_sd_entry_type_subscribeeventgroupnack, tvb, offset_orig, SD_ENTRY_LENGTH, *uniqueid, "on 0x%012" PRIx64, *uniqueid);
753
0
            break;
754
0
        }
755
0
    }
756
757
0
    proto_item_set_hidden(ti);
758
759
    /* check for Offer Entry without referenced Endpoints */
760
0
    if (opt_num1 == 0 && opt_num2 == 0 && *type == SD_ENTRY_OFFER_SERVICE && *ttl > 0) {
761
0
        expert_add_info(pinfo, *ti_entry, &ei_someipsd_offer_without_endpoint);
762
0
    }
763
764
    /* register ports but we skip 0xfffe because of other-serv */
765
0
    if (serviceid != SOMEIP_SD_SERVICE_ID_OTHER_SERVICE && !PINFO_FD_VISITED(pinfo)) {
766
0
        someip_sd_register_ports(opt_index1, opt_num1, option_count, option_ports);
767
0
        someip_sd_register_ports(opt_index2, opt_num2, option_count, option_ports);
768
0
    }
769
770
    /* TAP */
771
0
    if (have_tap_listener(tap_someip_sd_entries)) {
772
0
        someip_sd_entries_tap_t *data = wmem_alloc(pinfo->pool, sizeof(someip_sd_entries_tap_t));
773
0
        data->entry_type = *type;
774
0
        data->service_id = (uint16_t)serviceid;
775
0
        data->major_version = (uint8_t)majorver;
776
0
        data->minor_version = minorver;
777
0
        data->instance_id = (uint16_t)instanceid;
778
0
        data->eventgroup_id = (uint16_t)eventgroupid;
779
0
        data->ttl = *ttl;
780
781
0
        tap_queue_packet(tap_someip_sd_entries, pinfo, data);
782
0
    }
783
0
}
784
785
static int
786
0
dissect_someip_sd_pdu_entries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti, uint32_t offset, uint32_t length, uint32_t option_ports[], unsigned option_count) {
787
0
    proto_item *ti_entry;
788
789
0
    uint8_t     type;
790
0
    uint32_t    ttl;
791
0
    uint32_t    entry_flags = 0;
792
0
    uint32_t    stop_entry_flags = 0;
793
794
0
    uint64_t    uniqueid;
795
0
    uint64_t    last_uniqueid = 0xffffffffffffffff;
796
797
798
0
    while (length >= SD_ENTRY_LENGTH) {
799
0
        dissect_someip_sd_pdu_entry(tvb, pinfo, tree, offset, SD_ENTRY_LENGTH, &type, &ttl, &uniqueid, option_ports, option_count, &ti_entry);
800
0
        offset += SD_ENTRY_LENGTH;
801
0
        length -= SD_ENTRY_LENGTH;
802
803
        /* mark for attaching to info column */
804
0
        if (type < 32) {
805
0
            if (ttl == 0) {
806
0
                stop_entry_flags = stop_entry_flags | (1 << type);
807
0
            } else {
808
0
                entry_flags = entry_flags | (1 << type);
809
0
            }
810
0
        }
811
812
0
        if (type == SD_ENTRY_SUBSCRIBE_EVENTGROUP && ttl == 0) {
813
0
            last_uniqueid = uniqueid;
814
0
        } else {
815
0
            if ( (type == SD_ENTRY_SUBSCRIBE_EVENTGROUP && ttl > 0) && last_uniqueid == uniqueid ) {
816
0
                expert_add_info(pinfo, ti_entry, &ei_someipsd_entry_stopsubsub);
817
0
            }
818
819
0
            last_uniqueid = 0xffffffffffffffff;
820
0
        }
821
0
    }
822
823
    /* Add entry flags */
824
0
    if (stop_entry_flags != 0 || entry_flags != 0) {
825
0
        col_append_str(pinfo->cinfo, COL_INFO, " ");
826
0
    }
827
828
0
    if (entry_flags & (1 << SD_ENTRY_FIND_SERVICE)) {
829
0
        col_append_str(pinfo->cinfo, COL_INFO, "[Find]");
830
0
    }
831
832
0
    if (stop_entry_flags & (1 << SD_ENTRY_OFFER_SERVICE)) {
833
0
        col_append_str(pinfo->cinfo, COL_INFO, "[StopOffer]");
834
0
    }
835
836
0
    if (entry_flags & (1 << SD_ENTRY_OFFER_SERVICE)) {
837
0
        col_append_str(pinfo->cinfo, COL_INFO, "[Offer]");
838
0
    }
839
840
0
    if (stop_entry_flags & (1 << SD_ENTRY_SUBSCRIBE_EVENTGROUP)) {
841
0
        col_append_str(pinfo->cinfo, COL_INFO, "[StopSubscribe]");
842
0
    }
843
844
0
    if (entry_flags & (1 << SD_ENTRY_SUBSCRIBE_EVENTGROUP)) {
845
0
        col_append_str(pinfo->cinfo, COL_INFO, "[Subscribe]");
846
0
    }
847
848
0
    if (stop_entry_flags & (1 << SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK)) {
849
0
        col_append_str(pinfo->cinfo, COL_INFO, "[SubscribeNack]");
850
0
    }
851
852
0
    if (entry_flags & (1 << SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK)) {
853
0
        col_append_str(pinfo->cinfo, COL_INFO, "[SubscribeAck]");
854
0
    }
855
856
0
    if (length != 0) {
857
0
        expert_add_info(pinfo, ti, &ei_someipsd_entry_array_malformed);
858
0
    }
859
860
0
    return length;
861
0
}
862
863
static int
864
0
dissect_someip_sd_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
865
0
    uint32_t        offset = 0;
866
0
    uint32_t        length_entriesarray = 0;
867
0
    uint32_t        length_optionsarray = 0;
868
869
0
    proto_item     *ti = NULL;
870
0
    proto_item     *ti_sd_entries = NULL;
871
872
0
    proto_tree     *someip_sd_entries_tree = NULL;
873
0
    proto_tree     *someip_sd_options_tree = NULL;
874
0
    bool            stop_parsing_after_entries = false;
875
0
    uint32_t        offset_entriesarray;
876
877
    /* format for option_ports entries: 1 byte proto | 1 byte reserved | 2 byte port number*/
878
0
    static uint32_t option_ports[SD_MAX_NUM_OPTIONS];
879
0
    unsigned        option_count = 0;
880
881
0
    static int * const someipsd_flags[] = {
882
0
        &hf_someip_sd_rebootflag,
883
0
        &hf_someip_sd_unicastflag,
884
0
        &hf_someip_sd_explicitiniteventflag,
885
0
        NULL
886
0
    };
887
888
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SOME/IP-SD");
889
0
    col_set_str(pinfo->cinfo, COL_INFO, "SOME/IP-SD");
890
891
0
    ti = proto_tree_add_item(tree, proto_someip_sd, tvb, offset, -1, ENC_NA);
892
0
    tree = proto_item_add_subtree(ti, ett_someip_sd);
893
894
0
    if (!tvb_bytes_exist(tvb, offset, SOMEIP_SD_MIN_LENGTH)) {
895
0
        expert_add_info(pinfo, ti, &ei_someipsd_message_truncated);
896
0
        return tvb_reported_length(tvb);
897
0
    }
898
899
    /* add flags */
900
0
    proto_tree_add_bitmask(tree, tvb, offset, hf_someip_sd_flags, ett_someip_sd_flags, someipsd_flags, ENC_BIG_ENDIAN);
901
0
    offset += 1;
902
903
    /* add reserved */
904
0
    proto_tree_add_item(tree, hf_someip_sd_reserved, tvb, offset, 3, ENC_BIG_ENDIAN);
905
0
    offset += 3;
906
907
    /* add length of entries */
908
0
    proto_tree_add_item_ret_uint(tree, hf_someip_sd_length_entriesarray, tvb, offset, 4, ENC_BIG_ENDIAN, &length_entriesarray);
909
0
    offset += 4;
910
911
0
    if (!tvb_bytes_exist(tvb, offset, length_entriesarray)) {
912
0
        expert_add_info(pinfo, ti   , &ei_someipsd_message_truncated);
913
0
        return tvb_reported_length(tvb);
914
0
    }
915
916
0
    if (!tvb_bytes_exist(tvb, offset, length_entriesarray)) {
917
        /* truncated SD message - need to shorten buffer */
918
0
        length_entriesarray = tvb_captured_length_remaining(tvb, offset);
919
0
        expert_add_info(pinfo, ti, &ei_someipsd_message_truncated);
920
0
        stop_parsing_after_entries = true;
921
0
    }
922
923
    /* preparing entries array but not parsing it yet */
924
0
    ti_sd_entries = proto_tree_add_item(tree, hf_someip_sd_entries, tvb, offset, length_entriesarray, ENC_NA);
925
0
    someip_sd_entries_tree = proto_item_add_subtree(ti_sd_entries, ett_someip_sd_entries);
926
    /* save offset to parse entries later since we need to parse options first */
927
0
    offset_entriesarray = offset;
928
0
    offset += length_entriesarray;
929
930
0
    if (!stop_parsing_after_entries) {
931
        /* make sure we have a length field */
932
0
        if (tvb_bytes_exist(tvb, offset, 4)) {
933
934
            /* add options length */
935
0
            proto_tree_add_item_ret_uint(tree, hf_someip_sd_length_optionsarray, tvb, offset, 4, ENC_BIG_ENDIAN, &length_optionsarray);
936
0
            offset += 4;
937
938
0
            if (length_optionsarray > 0) {
939
0
                if (tvb_bytes_exist(tvb, offset, 1)) {
940
0
                    ti = proto_tree_add_item(tree, hf_someip_sd_options, tvb, offset, -1, ENC_NA);
941
0
                    someip_sd_options_tree = proto_item_add_subtree(ti, ett_someip_sd_options);
942
943
                    /* check, if enough bytes are left for optionsarray */
944
0
                    if (!tvb_bytes_exist(tvb, offset, length_optionsarray)) {
945
0
                        length_optionsarray = tvb_captured_length_remaining(tvb, offset);
946
0
                        expert_add_info(pinfo, ti, &ei_someipsd_message_truncated);
947
0
                        proto_item_append_text(ti, " (truncated!)");
948
0
                    }
949
950
                    /* updating to length we will work with */
951
0
                    if (length_optionsarray > 0) {
952
0
                        proto_item_set_len(ti, length_optionsarray);
953
0
                    }
954
955
0
                    dissect_someip_sd_pdu_options(tvb, pinfo, someip_sd_options_tree, ti, offset, length_optionsarray, option_ports, &option_count);
956
0
                    offset += length_optionsarray;
957
0
                } else {
958
0
                    expert_add_info(pinfo, ti, &ei_someipsd_message_truncated);
959
0
                }
960
0
            }
961
0
        }
962
0
    }
963
964
0
    if (length_entriesarray >= SD_ENTRY_LENGTH) {
965
0
        offset += dissect_someip_sd_pdu_entries(tvb, pinfo, someip_sd_entries_tree, ti_sd_entries, offset_entriesarray, length_entriesarray, option_ports, option_count);
966
0
    } else {
967
0
        expert_add_info(pinfo, ti_sd_entries, &ei_someipsd_entry_array_empty);
968
0
    }
969
0
    return offset;
970
0
}
971
972
/*******************************************
973
 **************** Statistics ***************
974
 *******************************************/
975
976
static void
977
0
someipsd_entries_stats_tree_init(stats_tree *st) {
978
0
    st_node_ip_src = stats_tree_create_node(st, st_str_ip_src, 0, STAT_DT_INT, true);
979
0
    stat_node_set_flags(st, st_str_ip_src, 0, false, ST_FLG_SORT_TOP);
980
0
    st_node_ip_dst = stats_tree_create_node(st, st_str_ip_dst, 0, STAT_DT_INT, true);
981
0
}
982
983
static void
984
0
stat_number_to_string_with_any(uint32_t value, unsigned max, char *format_string, char *ret, size_t size_limit) {
985
0
    if (value == max) {
986
0
        snprintf(ret, size_limit, "%s", "MAX");
987
0
    } else {
988
0
        snprintf(ret, size_limit, format_string, value);
989
0
    }
990
0
}
991
992
static void
993
0
stat_create_entry_summary_string(const someip_sd_entries_tap_t *data, char *ret, size_t size_limit) {
994
0
    char service_str[16];
995
0
    char instance_str[16];
996
0
    char majorver_str[16];
997
0
    char minorver_str[16];
998
0
    char eventgrp_str[16];
999
1000
0
    int bytes_written;
1001
1002
0
    char *service_name  = someip_lookup_service_name(data->service_id);
1003
0
    char *eventgrp_name = someip_lookup_eventgroup_name(data->service_id, data->eventgroup_id);
1004
1005
0
    stat_number_to_string_with_any(data->service_id, UINT32_MAX, "0x%04x", service_str, sizeof(service_str));
1006
0
    stat_number_to_string_with_any(data->instance_id, UINT32_MAX, "0x%04x", instance_str, sizeof(instance_str));
1007
0
    stat_number_to_string_with_any(data->major_version, UINT8_MAX, "%d", majorver_str, sizeof(majorver_str));
1008
1009
0
    switch (data->entry_type) {
1010
0
    case SD_ENTRY_FIND_SERVICE:
1011
0
    case SD_ENTRY_OFFER_SERVICE:
1012
0
        stat_number_to_string_with_any(data->minor_version, UINT32_MAX, "%d", minorver_str, sizeof(minorver_str));
1013
0
        if (service_name != NULL) {
1014
0
            snprintf(ret, size_limit, "Service %s (%s) Version %s.%s Instance %s", service_str, service_name, majorver_str, minorver_str, instance_str);
1015
0
        } else {
1016
0
            snprintf(ret, size_limit, "Service %s Version %s.%s Instance %s", service_str, majorver_str, minorver_str, instance_str);
1017
0
        }
1018
0
        break;
1019
1020
0
    case SD_ENTRY_SUBSCRIBE_EVENTGROUP:
1021
0
    case SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK:
1022
0
        stat_number_to_string_with_any(data->eventgroup_id, UINT32_MAX, "0x%04x", eventgrp_str, sizeof(eventgrp_str));
1023
0
        if (service_name != NULL) {
1024
0
            bytes_written = snprintf(ret, size_limit, "Service %s (%s) Version %s Instance %s Eventgroup %s", service_str, service_name, majorver_str, instance_str, eventgrp_str);
1025
0
        } else {
1026
0
            bytes_written = snprintf(ret, size_limit, "Service %s Version %s Instance %s Eventgroup %s", service_str, majorver_str, instance_str, eventgrp_str);
1027
0
        }
1028
0
        if (bytes_written > 0 && ((size_t)bytes_written < size_limit) && eventgrp_name != NULL) {
1029
0
            snprintf(&ret[bytes_written], size_limit - bytes_written, " (%s)", eventgrp_name);
1030
0
        }
1031
0
        break;
1032
0
    }
1033
0
}
1034
1035
static tap_packet_status
1036
0
someipsd_entries_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p, tap_flags_t flags _U_) {
1037
0
    DISSECTOR_ASSERT(p);
1038
0
    const someip_sd_entries_tap_t *data = (const someip_sd_entries_tap_t *)p;
1039
0
    static char tmp_addr_str[256];
1040
1041
0
    snprintf(tmp_addr_str, sizeof(tmp_addr_str) - 1, "%s (%s)", address_to_str(pinfo->pool, &pinfo->net_src), address_to_name(&pinfo->net_src));
1042
0
    tick_stat_node(st, st_str_ip_src, 0, false);
1043
0
    int src_id = tick_stat_node(st, tmp_addr_str, st_node_ip_src, true);
1044
1045
0
    snprintf(tmp_addr_str, sizeof(tmp_addr_str) - 1, "%s (%s)", address_to_str(pinfo->pool, &pinfo->net_dst), address_to_name(&pinfo->net_dst));
1046
0
    tick_stat_node(st, st_str_ip_dst, 0, false);
1047
0
    int dst_id = tick_stat_node(st, tmp_addr_str, st_node_ip_dst, true);
1048
1049
0
    int tmp_id;
1050
0
    static char tmp_str[128];
1051
1052
0
    if (data->ttl == 0) {
1053
0
        switch (data->entry_type) {
1054
0
        case SD_ENTRY_STOP_OFFER_SERVICE:
1055
0
            stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1);
1056
0
            tmp_id = tick_stat_node(st, "Stop Offer Service", src_id, true);
1057
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1058
0
            tmp_id = tick_stat_node(st, "Stop Offer Service", dst_id, true);
1059
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1060
0
            break;
1061
0
        case SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP:
1062
0
            stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1);
1063
0
            tmp_id = tick_stat_node(st, "Stop Subscribe Eventgroup", src_id, true);
1064
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1065
0
            tmp_id = tick_stat_node(st, "Stop Subscribe Eventgroup", dst_id, true);
1066
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1067
0
            break;
1068
0
        case SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK:
1069
0
            stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1);
1070
0
            tmp_id = tick_stat_node(st, "Subscribe Eventgroup Nack", src_id, true);
1071
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1072
0
            tmp_id = tick_stat_node(st, "Subscribe Eventgroup Nack", dst_id, true);
1073
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1074
0
            break;
1075
0
        }
1076
0
    } else {
1077
0
        switch (data->entry_type) {
1078
0
        case SD_ENTRY_FIND_SERVICE:
1079
0
            stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1);
1080
0
            tmp_id = tick_stat_node(st, "Find Service", src_id, true);
1081
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1082
0
            tmp_id = tick_stat_node(st, "Find Service", dst_id, true);
1083
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1084
0
            break;
1085
0
        case SD_ENTRY_OFFER_SERVICE:
1086
0
            stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1);
1087
0
            tmp_id = tick_stat_node(st, "Offer Service", src_id, true);
1088
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1089
0
            tmp_id = tick_stat_node(st, "Offer Service", dst_id, true);
1090
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1091
0
            break;
1092
0
        case SD_ENTRY_SUBSCRIBE_EVENTGROUP:
1093
0
            stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1);
1094
0
            tmp_id = tick_stat_node(st, "Subscribe Eventgroup", src_id, true);
1095
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1096
0
            tmp_id = tick_stat_node(st, "Subscribe Eventgroup", dst_id, true);
1097
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1098
0
            break;
1099
0
        case SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK:
1100
0
            stat_create_entry_summary_string(data, tmp_str, sizeof(tmp_str) - 1);
1101
0
            tmp_id = tick_stat_node(st, "Subscribe Eventgroup Ack", src_id, true);
1102
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1103
0
            tmp_id = tick_stat_node(st, "Subscribe Eventgroup Ack", dst_id, true);
1104
0
            tick_stat_node(st, tmp_str, tmp_id, false);
1105
0
            break;
1106
0
        }
1107
0
    }
1108
1109
0
    return TAP_PACKET_REDRAW;
1110
0
}
1111
1112
void
1113
16
proto_register_someip_sd(void) {
1114
16
    module_t *someipsd_module;
1115
1116
16
    expert_module_t *expert_module_someip_sd;
1117
1118
    /* data fields */
1119
16
    static hf_register_info hf_sd[] = {
1120
16
        { &hf_someip_sd_flags,
1121
16
            { "Flags", "someipsd.flags",
1122
16
            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1123
16
        { &hf_someip_sd_rebootflag,
1124
16
            { "Reboot Flag", "someipsd.flags.reboot",
1125
16
            FT_BOOLEAN, 8, TFS(&sd_reboot_flag), SOMEIP_SD_REBOOT_FLAG, NULL, HFILL }},
1126
16
        { &hf_someip_sd_unicastflag,
1127
16
            { "Unicast Flag", "someipsd.flags.unicast",
1128
16
            FT_BOOLEAN, 8, TFS(&sd_unicast_flag), SOMEIP_SD_UNICAST_FLAG, NULL, HFILL }},
1129
16
        { &hf_someip_sd_explicitiniteventflag,
1130
16
            { "Explicit Initial Events Flag", "someipsd.flags.exp_init_events",
1131
16
            FT_BOOLEAN, 8, TFS(&sd_eiec_flag), SOMEIP_SD_EXPL_INIT_EVENT_REQ_FLAG, NULL, HFILL }},
1132
16
        { &hf_someip_sd_reserved,
1133
16
            { "Reserved", "someipsd.reserved",
1134
16
            FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1135
1136
16
        { &hf_someip_sd_length_entriesarray,
1137
16
            { "Length of Entries Array", "someipsd.length_entriesarray",
1138
16
            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1139
16
        { &hf_someip_sd_entries,
1140
16
            { "Entries Array", "someipsd.entries",
1141
16
            FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1142
16
        { &hf_someip_sd_entry,
1143
16
            { "Entry", "someipsd.entry",
1144
16
            FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1145
16
        { &hf_someip_sd_entry_type,
1146
16
            { "Type", "someipsd.entry.type",
1147
16
            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1148
16
        { &hf_someip_sd_entry_index1,
1149
16
            { "Index 1", "someipsd.entry.index1",
1150
16
            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1151
16
        { &hf_someip_sd_entry_index2,
1152
16
            { "Index 2", "someipsd.entry.index2",
1153
16
            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1154
16
        { &hf_someip_sd_entry_numopt1,
1155
16
            { "Number of Opts 1", "someipsd.entry.numopt1",
1156
16
            FT_UINT8, BASE_HEX, NULL, 0xf0, NULL, HFILL }},
1157
16
        { &hf_someip_sd_entry_numopt2,
1158
16
            { "Number of Opts 2", "someipsd.entry.numopt2",
1159
16
            FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }},
1160
16
        { &hf_someip_sd_entry_opts_referenced,
1161
16
            { "Options referenced", "someipsd.entry.optionsreferenced",
1162
16
            FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1163
1164
16
        { &hf_someip_sd_entry_serviceid,
1165
16
            { "Service ID", "someipsd.entry.serviceid",
1166
16
            FT_UINT16, BASE_HEX | BASE_SPECIAL_VALS, VALS(sd_serviceid_vs), 0x0, NULL, HFILL }},
1167
16
        { &hf_someip_sd_entry_servicename,
1168
16
            { "Service Name", "someipsd.entry.servicename",
1169
16
            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1170
16
        { &hf_someip_sd_entry_instanceid,
1171
16
            { "Instance ID", "someipsd.entry.instanceid",
1172
16
            FT_UINT16, BASE_HEX | BASE_SPECIAL_VALS, VALS(sd_instanceid_vs), 0x0, NULL, HFILL }},
1173
16
        { &hf_someip_sd_entry_majorver,
1174
16
            { "Major Version", "someipsd.entry.majorver",
1175
16
            FT_UINT8, BASE_DEC | BASE_SPECIAL_VALS, VALS(sd_majorversion_vs), 0x0, NULL, HFILL }},
1176
16
        { &hf_someip_sd_entry_ttl,
1177
16
            { "TTL", "someipsd.entry.ttl",
1178
16
            FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1179
16
        { &hf_someip_sd_entry_minorver,
1180
16
            { "Minor Version", "someipsd.entry.minorver",
1181
16
            FT_UINT32, BASE_DEC | BASE_SPECIAL_VALS, VALS(sd_minorversion_vs), 0x0, NULL, HFILL }},
1182
16
        { &hf_someip_sd_entry_eventgroupid,
1183
16
            { "Eventgroup ID", "someipsd.entry.eventgroupid",
1184
16
            FT_UINT16, BASE_HEX | BASE_SPECIAL_VALS, VALS(sd_eventgroupid_vs), 0x0, NULL, HFILL }},
1185
16
        { &hf_someip_sd_entry_eventgroupname,
1186
16
            { "Eventgroup Name", "someipsd.entry.eventgroupname",
1187
16
            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1188
16
        { &hf_someip_sd_entry_reserved,
1189
16
            { "Reserved", "someipsd.entry.reserved",
1190
16
            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1191
16
        { &hf_someip_sd_entry_counter,
1192
16
            { "Counter", "someipsd.entry.counter",
1193
16
            FT_UINT8, BASE_HEX, NULL, SD_EVENTGROUP_ENTRY_COUNTER_MASK, NULL, HFILL } },
1194
16
        { &hf_someip_sd_entry_reserved2,
1195
16
            { "Reserved", "someipsd.entry.reserved2",
1196
16
            FT_UINT8, BASE_HEX, NULL, SD_EVENTGROUP_ENTRY_RES2_MASK, NULL, HFILL } },
1197
16
        { &hf_someip_sd_entry_intial_event_flag,
1198
16
            { "Initial Event Request", "someipsd.entry.initialevents",
1199
16
            FT_BOOLEAN, 8, NULL, SD_ENTRY_INIT_EVENT_REQ_MASK, NULL, HFILL } },
1200
1201
16
        { &hf_someip_sd_length_optionsarray,
1202
16
            { "Length of Options Array", "someipsd.length_optionsarray",
1203
16
            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1204
16
        { &hf_someip_sd_options,
1205
16
            { "Options Array", "someipsd.options",
1206
16
            FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1207
1208
16
        { &hf_someip_sd_option_type,
1209
16
            { "Type", "someipsd.option.type",
1210
16
            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1211
16
        { &hf_someip_sd_option_length,
1212
16
            { "Length", "someipsd.option.length",
1213
16
            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1214
16
        { &hf_someip_sd_option_reserved,
1215
16
            { "Reserved", "someipsd.option.reserved",
1216
16
            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1217
16
        { &hf_someip_sd_option_ipv4,
1218
16
            { "IPv4 Address", "someipsd.option.ipv4address",
1219
16
            FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1220
16
        { &hf_someip_sd_option_ipv6,
1221
16
            { "IPv6 Address", "someipsd.option.ipv6address",
1222
16
            FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1223
16
        { &hf_someip_sd_option_port,
1224
16
            { "Port", "someipsd.option.port",
1225
16
            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1226
16
        { &hf_someip_sd_option_proto,
1227
16
            { "Protocol", "someipsd.option.proto",
1228
16
            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1229
16
        { &hf_someip_sd_option_reserved2,
1230
16
            { "Reserved 2", "someipsd.option.reserved2",
1231
16
            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1232
16
        { &hf_someip_sd_option_data,
1233
16
            { "Unknown Data", "someipsd.option.unknown_data",
1234
16
            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1235
16
        { &hf_someip_sd_option_config_string,
1236
16
            { "Configuration String", "someipsd.option.config_string",
1237
16
            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1238
16
        { &hf_someip_sd_option_config_string_element,
1239
16
            { "Configuration String Element", "someipsd.option.config_string_element",
1240
16
            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1241
16
        { &hf_someip_sd_option_lb_priority,
1242
16
            { "Priority", "someipsd.option.priority",
1243
16
            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1244
16
        { &hf_someip_sd_option_lb_weight,
1245
16
            { "Weight", "someipsd.option.weight",
1246
16
            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1247
16
        { &hf_someip_sd_entry_type_offerservice,
1248
16
            { "Offer Service", "someipsd.entry.offerservice",
1249
16
            FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1250
16
        { &hf_someip_sd_entry_type_stopofferservice,
1251
16
            { "Stop Offer Service", "someipsd.entry.stopofferservice",
1252
16
            FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1253
16
        { &hf_someip_sd_entry_type_findservice,
1254
16
            { "Find Service", "someipsd.entry.findservice",
1255
16
            FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1256
1257
16
        { &hf_someip_sd_entry_type_subscribeeventgroup,
1258
16
            { "Subscribe Eventgroup", "someipsd.entry.subscribeeventgroup",
1259
16
            FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1260
16
        { &hf_someip_sd_entry_type_stopsubscribeeventgroup,
1261
16
            { "Stop Subscribe Eventgroup", "someipsd.entry.stopsubscribeeventgroup",
1262
16
            FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1263
1264
16
        { &hf_someip_sd_entry_type_subscribeeventgroupack,
1265
16
            { "Subscribe Eventgroup ACK", "someipsd.entry.subscribeeventgroupack",
1266
16
            FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1267
16
        { &hf_someip_sd_entry_type_subscribeeventgroupnack,
1268
16
            { "Subscribe Eventgroup NACK", "someipsd.entry.subscribeeventgroupnack",
1269
16
            FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1270
16
    };
1271
1272
16
    static int *ett_sd[] = {
1273
16
        &ett_someip_sd,
1274
16
        &ett_someip_sd_flags,
1275
16
        &ett_someip_sd_entries,
1276
16
        &ett_someip_sd_entry,
1277
16
        &ett_someip_sd_options,
1278
16
        &ett_someip_sd_option,
1279
16
        &ett_someip_sd_config_string,
1280
16
    };
1281
1282
16
    static ei_register_info ei_sd[] = {
1283
16
        { &ei_someipsd_message_truncated,{ "someipsd.message_truncated", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Truncated message", EXPFILL } },
1284
16
        { &ei_someipsd_entry_array_malformed,{ "someipsd.entry_array_malformed", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Entry Array length not multiple of 16 bytes", EXPFILL } },
1285
16
        { &ei_someipsd_entry_array_empty,{ "someipsd.entry_array_empty", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Empty Entry Array", EXPFILL } },
1286
16
        { &ei_someipsd_entry_unknown,{ "someipsd.entry_unknown", PI_MALFORMED, PI_WARN, "SOME/IP-SD Unknown Entry", EXPFILL } },
1287
16
        { &ei_someipsd_offer_without_endpoint,{ "someipsd.offer_no_endpoints", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Offer Service references no endpoints", EXPFILL } },
1288
16
        { &ei_someipsd_entry_stopsubsub,{ "someipsd.stopsub_sub", PI_PROTOCOL, PI_WARN, "SOME/IP-SD Subscribe after Stop Subscribe", EXPFILL } },
1289
16
        { &ei_someipsd_option_array_truncated,{ "someipsd.option_array_truncated", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Option Array truncated", EXPFILL } },
1290
16
        { &ei_someipsd_option_array_bytes_left,{ "someipsd.option_array_bytes_left", PI_MALFORMED, PI_WARN, "SOME/IP-SD Option Array bytes left after parsing options", EXPFILL } },
1291
16
        { &ei_someipsd_option_unknown,{ "someipsd.option_unknown", PI_MALFORMED, PI_WARN, "SOME/IP-SD Unknown Option", EXPFILL } },
1292
16
        { &ei_someipsd_option_wrong_length,{ "someipsd.option_wrong_length", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Option length is incorrect", EXPFILL } },
1293
16
        { &ei_someipsd_L4_protocol_unsupported,{ "someipsd.L4_protocol_unsupported", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Unsupported Layer 4 Protocol", EXPFILL } },
1294
16
        { &ei_someipsd_config_string_malformed,{ "someipsd.config_string_malformed", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Configuration String malformed", EXPFILL } },
1295
16
        { &ei_someipsd_too_many_options,{ "someipsd.too_many_options", PI_MALFORMED, PI_ERROR, "SOME/IP-SD Too many options", EXPFILL } },
1296
16
    };
1297
1298
    /* Register Protocol, Fields, ETTs, Expert Info, Taps, Dissector */
1299
16
    proto_someip_sd = proto_register_protocol("SOME/IP Service Discovery Protocol", "SOME/IP-SD", "someipsd");
1300
16
    proto_register_field_array(proto_someip_sd, hf_sd, array_length(hf_sd));
1301
16
    proto_register_subtree_array(ett_sd, array_length(ett_sd));
1302
16
    expert_module_someip_sd = expert_register_protocol(proto_someip_sd);
1303
16
    expert_register_field_array(expert_module_someip_sd, ei_sd, array_length(ei_sd));
1304
16
    tap_someip_sd_entries = register_tap("someipsd_entries");
1305
16
    someip_sd_handle = register_dissector("someipsd", dissect_someip_sd_pdu, proto_someip_sd);
1306
1307
    /* Register preferences */
1308
16
    someipsd_module = prefs_register_protocol(proto_someip_sd, NULL);
1309
1310
16
    range_convert_str(wmem_epan_scope(), &someip_ignore_ports_udp, "", 65535);
1311
16
    prefs_register_range_preference(someipsd_module, "ports.udp.ignore", "UDP Ports ignored",
1312
16
        "SOME/IP Ignore Port Ranges UDP. These ports are not automatically added by the SOME/IP-SD.",
1313
16
        &someip_ignore_ports_udp, 65535);
1314
1315
16
    range_convert_str(wmem_epan_scope(), &someip_ignore_ports_tcp, "", 65535);
1316
16
    prefs_register_range_preference(someipsd_module, "ports.tcp.ignore", "TCP Ports ignored",
1317
16
        "SOME/IP Ignore Port Ranges TCP. These ports are not automatically added by the SOME/IP-SD.",
1318
16
        &someip_ignore_ports_tcp, 65535);
1319
16
 }
1320
1321
void
1322
16
proto_reg_handoff_someip_sd(void) {
1323
16
    dissector_add_uint("someip.messageid", SOMEIP_SD_MESSAGEID, someip_sd_handle);
1324
    stats_tree_register("someipsd_entries", "someipsd_entries", "SOME/IP-SD Entries", 0, someipsd_entries_stats_tree_packet, someipsd_entries_stats_tree_init, NULL);
1325
16
}
1326
1327
/*
1328
 * Editor modelines
1329
 *
1330
 * Local Variables:
1331
 * c-basic-offset: 4
1332
 * tab-width: 8
1333
 * indent-tabs-mode: nil
1334
 * End:
1335
 *
1336
 * ex: set shiftwidth=4 tabstop=8 expandtab:
1337
 * :indentSize=4:tabSize=8:noTabs=true:
1338
 */