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
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include <epan/prefs.h>
19 #include <epan/expert.h>
20 #include <epan/to_str.h>
21 #include <epan/stats_tree.h>
23 #include <wsutil/array.h>
24 #include "packet-udp.h"
25 #include "packet-someip.h"
28 * Dissector for SOME/IP Service Discovery (SOME/IP-SD).
31 * http://www.some-ip.com
34 #define SOMEIP_SD_NAME "SOME/IP-SD"
35 #define SOMEIP_SD_NAME_LONG "SOME/IP Service Discovery Protocol"
36 #define SOMEIP_SD_NAME_FILTER "someipsd"
38 #define SOMEIP_SD_MESSAGEID 0xffff8100
39 #define SOMEIP_SD_SERVICE_ID_OTHER_SERVICE 0xfffe
43 #define SOMEIP_SD_REBOOT_FLAG 0x80
44 #define SOMEIP_SD_UNICAST_FLAG 0x40
45 #define SOMEIP_SD_EXPL_INIT_EVENT_REQ_FLAG 0x20
46 #define SOMEIP_SD_MIN_LENGTH 12
49 #define SD_ENTRY_LENGTH 16
51 #define SD_ENTRY_UNKNOWN 0x00
52 #define SD_ENTRY_SERVICE 0x01
53 #define SD_ENTRY_EVENTGROUP 0x02
55 #define SD_ENTRY_FIND_SERVICE 0x00
56 #define SD_ENTRY_OFFER_SERVICE 0x01
57 #define SD_ENTRY_SUBSCRIBE_EVENTGROUP 0x06
58 #define SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK 0x07
60 #define SD_ENTRY_STOP_OFFER_SERVICE 0x01
61 #define SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP 0x06
62 #define SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK 0x07
64 #define SD_EVENTGROUP_ENTRY_COUNTER_MASK 0x0f
65 #define SD_EVENTGROUP_ENTRY_RES2_MASK 0x70
66 #define SD_ENTRY_INIT_EVENT_REQ_MASK 0x80
69 #define SD_OPTION_MINLENGTH 3
70 #define SD_OPTION_IPV4_LENGTH 12
71 #define SD_OPTION_IPV6_LENGTH 24
73 #define SD_OPTION_UNKNOWN 0x00
74 #define SD_OPTION_CONFIGURATION 0x01
75 #define SD_OPTION_LOADBALANCING 0x02
76 #define SD_OPTION_IPV4_ENDPOINT 0x04
77 #define SD_OPTION_IPV6_ENDPOINT 0x06
78 #define SD_OPTION_IPV4_MULTICAST 0x14
79 #define SD_OPTION_IPV6_MULTICAST 0x16
80 #define SD_OPTION_IPV4_SD_ENDPOINT 0x24
81 #define SD_OPTION_IPV6_SD_ENDPOINT 0x26
83 #define SD_OPTION_L4PROTO_TCP 6
84 #define SD_OPTION_L4PROTO_UDP 17
86 /* option start 0..255, num 0..15 -> 0..270 */
87 #define SD_MAX_NUM_OPTIONS 271
89 /* ID wireshark identifies the dissector by */
90 static int proto_someip_sd
;
93 static int hf_someip_sd_flags
;
94 static int hf_someip_sd_rebootflag
;
95 static int hf_someip_sd_unicastflag
;
96 static int hf_someip_sd_explicitiniteventflag
;
97 static int hf_someip_sd_reserved
;
99 static int hf_someip_sd_length_entriesarray
;
100 static int hf_someip_sd_entries
;
102 static int hf_someip_sd_entry
;
103 static int hf_someip_sd_entry_type
;
104 static int hf_someip_sd_entry_type_offerservice
;
105 static int hf_someip_sd_entry_type_stopofferservice
;
106 static int hf_someip_sd_entry_type_findservice
;
107 static int hf_someip_sd_entry_type_subscribeeventgroup
;
108 static int hf_someip_sd_entry_type_stopsubscribeeventgroup
;
109 static int hf_someip_sd_entry_type_subscribeeventgroupack
;
110 static int hf_someip_sd_entry_type_subscribeeventgroupnack
;
111 static int hf_someip_sd_entry_index1
;
112 static int hf_someip_sd_entry_index2
;
113 static int hf_someip_sd_entry_numopt1
;
114 static int hf_someip_sd_entry_numopt2
;
115 static int hf_someip_sd_entry_opts_referenced
;
116 static int hf_someip_sd_entry_serviceid
;
117 static int hf_someip_sd_entry_servicename
;
118 static int hf_someip_sd_entry_instanceid
;
119 static int hf_someip_sd_entry_majorver
;
120 static int hf_someip_sd_entry_ttl
;
121 static int hf_someip_sd_entry_minorver
;
122 static int hf_someip_sd_entry_eventgroupid
;
123 static int hf_someip_sd_entry_eventgroupname
;
124 static int hf_someip_sd_entry_reserved
;
125 static int hf_someip_sd_entry_counter
;
126 static int hf_someip_sd_entry_intial_event_flag
;
127 static int hf_someip_sd_entry_reserved2
;
129 static int hf_someip_sd_length_optionsarray
;
130 static int hf_someip_sd_options
;
132 static int hf_someip_sd_option_type
;
133 static int hf_someip_sd_option_length
;
134 static int hf_someip_sd_option_reserved
;
135 static int hf_someip_sd_option_ipv4
;
136 static int hf_someip_sd_option_ipv6
;
137 static int hf_someip_sd_option_port
;
138 static int hf_someip_sd_option_proto
;
139 static int hf_someip_sd_option_reserved2
;
140 static int hf_someip_sd_option_data
;
141 static int hf_someip_sd_option_config_string
;
142 static int hf_someip_sd_option_config_string_element
;
143 static int hf_someip_sd_option_lb_priority
;
144 static int hf_someip_sd_option_lb_weight
;
146 /* protocol tree items */
147 static int ett_someip_sd
;
148 static int ett_someip_sd_flags
;
149 static int ett_someip_sd_entries
;
150 static int ett_someip_sd_entry
;
151 static int ett_someip_sd_options
;
152 static int ett_someip_sd_option
;
153 static int ett_someip_sd_config_string
;
157 static int tap_someip_sd_entries
= -1;
159 typedef struct _someip_sd_entries_tap
{
162 uint8_t major_version
;
163 uint32_t minor_version
;
164 uint16_t instance_id
;
165 uint16_t eventgroup_id
;
167 } someip_sd_entries_tap_t
;
171 static const char *st_str_ip_src
= "Source Addresses";
172 static const char *st_str_ip_dst
= "Destination Addresses";
174 static int st_node_ip_src
= -1;
175 static int st_node_ip_dst
= -1;
177 /*** Preferences ***/
178 static range_t
*someip_ignore_ports_udp
;
179 static range_t
*someip_ignore_ports_tcp
;
181 /* SOME/IP-SD Entry Names for TTL>0 */
182 static const value_string sd_entry_type_positive
[] = {
183 {SD_ENTRY_FIND_SERVICE
, "Find Service"},
184 {SD_ENTRY_OFFER_SERVICE
, "Offer Service"},
185 {SD_ENTRY_SUBSCRIBE_EVENTGROUP
, "Subscribe Eventgroup"},
186 {SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK
, "Subscribe Eventgroup Ack"},
190 /* SOME/IP-SD Entry Names for TTL=0 */
191 static const value_string sd_entry_type_negative
[] = {
192 {SD_ENTRY_STOP_OFFER_SERVICE
, "Stop Offer Service"},
193 {SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP
, "Stop Subscribe Eventgroup"},
194 {SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK
, "Subscribe Eventgroup Negative Ack"},
198 static const value_string sd_serviceid_vs
[] = {
203 static const value_string sd_instanceid_vs
[] = {
208 static const value_string sd_majorversion_vs
[] = {
213 static const value_string sd_minorversion_vs
[] = {
218 static const value_string sd_eventgroupid_vs
[] = {
223 /* SOME/IP-SD Option Names */
224 static const value_string sd_option_type
[] = {
225 {SD_OPTION_UNKNOWN
, "Unknown"},
226 {SD_OPTION_CONFIGURATION
, "Configuration"},
227 {SD_OPTION_LOADBALANCING
, "Load Balancing"},
228 {SD_OPTION_IPV4_ENDPOINT
, "IPv4 Endpoint"},
229 {SD_OPTION_IPV6_ENDPOINT
, "IPv6 Endpoint"},
230 {SD_OPTION_IPV4_MULTICAST
, "IPv4 Multicast"},
231 {SD_OPTION_IPV6_MULTICAST
, "IPv6 Multicast"},
232 {SD_OPTION_IPV4_SD_ENDPOINT
, "IPv4 SD Endpoint"},
233 {SD_OPTION_IPV6_SD_ENDPOINT
, "IPv6 SD Endpoint"},
237 /* L4 Protocol Names for SOME/IP-SD Endpoints */
238 static const value_string sd_option_l4protos
[] = {
239 {SD_OPTION_L4PROTO_TCP
, "TCP"},
240 {SD_OPTION_L4PROTO_UDP
, "UDP"},
244 static const true_false_string sd_reboot_flag
= {
245 "Session ID did not roll over since last reboot",
246 "Session ID rolled over since last reboot"
249 static const true_false_string sd_unicast_flag
= {
250 "Unicast messages support",
251 "Unicast messages not supported (deprecated)"
254 static const true_false_string sd_eiec_flag
= {
255 "Explicit Initial Event control supported",
256 "Explicit Initial Event control not supported"
259 /*** expert info items ***/
260 static expert_field ei_someipsd_message_truncated
;
261 static expert_field ei_someipsd_entry_array_malformed
;
262 static expert_field ei_someipsd_entry_array_empty
;
263 static expert_field ei_someipsd_entry_unknown
;
264 static expert_field ei_someipsd_offer_without_endpoint
;
265 static expert_field ei_someipsd_entry_stopsubsub
;
266 static expert_field ei_someipsd_option_array_truncated
;
267 static expert_field ei_someipsd_option_array_bytes_left
;
268 static expert_field ei_someipsd_option_unknown
;
269 static expert_field ei_someipsd_option_wrong_length
;
270 static expert_field ei_someipsd_L4_protocol_unsupported
;
271 static expert_field ei_someipsd_config_string_malformed
;
274 void proto_register_someip_sd(void);
275 void proto_reg_handoff_someip_sd(void);
277 static dissector_handle_t someip_sd_handle
;
279 /**************************************
280 ******** SOME/IP-SD Dissector ********
281 *************************************/
284 someip_sd_register_ports(uint32_t opt_index
, uint32_t opt_num
, uint32_t option_count
, uint32_t option_ports
[]) {
287 for (i
= opt_index
; i
< opt_index
+ opt_num
&& i
< option_count
; i
++) {
288 uint32_t l4port
= 0x0000ffff & option_ports
[i
];
289 uint32_t l4proto
= (0xff000000 & option_ports
[i
]) >> 24;
291 if (l4proto
== SD_OPTION_L4PROTO_UDP
&& !value_is_in_range(someip_ignore_ports_udp
, l4port
)) {
292 register_someip_port_udp(l4port
);
294 if (l4proto
== SD_OPTION_L4PROTO_TCP
&& !value_is_in_range(someip_ignore_ports_tcp
, l4port
)) {
295 register_someip_port_tcp(l4port
);
298 /* delete port from list to ensure only registering once per SD message */
304 dissect_someip_sd_pdu_option_configuration(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint32_t offset
, uint32_t length
, int optionnum
) {
305 uint32_t offset_orig
= offset
;
306 const uint8_t *config_string
;
310 tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, length
, ett_someip_sd_option
, NULL
, "%d: Configuration Option", optionnum
);
312 /* Add common fields */
313 proto_tree_add_item(tree
, hf_someip_sd_option_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
316 proto_tree_add_item(tree
, hf_someip_sd_option_type
, tvb
, offset
, 1, ENC_NA
);
319 proto_tree_add_item(tree
, hf_someip_sd_option_reserved
, tvb
, offset
, 1, ENC_NA
);
322 int config_string_length
= length
- offset
+ offset_orig
;
323 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
);
324 subtree
= proto_item_add_subtree(ti
, ett_someip_sd_config_string
);
327 uint8_t element_length
;
328 while (config_string
!= NULL
&& config_string_length
- pos
> 0) {
329 element_length
= config_string
[pos
];
332 if (element_length
== 0) {
336 if (element_length
> config_string_length
- pos
) {
337 expert_add_info(pinfo
, ti
, &ei_someipsd_config_string_malformed
);
341 proto_tree_add_item(subtree
, hf_someip_sd_option_config_string_element
, tvb
, offset
+ pos
, element_length
, ENC_ASCII
| ENC_NA
);
342 pos
+= element_length
;
347 dissect_someip_sd_pdu_option_loadbalancing(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, uint32_t offset
, uint32_t length
, int optionnum
) {
348 tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, length
, ett_someip_sd_option
, NULL
, "%d: Load Balancing Option", optionnum
);
350 /* Add common fields */
351 proto_tree_add_item(tree
, hf_someip_sd_option_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
354 proto_tree_add_item(tree
, hf_someip_sd_option_type
, tvb
, offset
, 1, ENC_NA
);
357 proto_tree_add_item(tree
, hf_someip_sd_option_reserved
, tvb
, offset
, 1, ENC_NA
);
360 proto_tree_add_item(tree
, hf_someip_sd_option_lb_priority
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
363 proto_tree_add_item(tree
, hf_someip_sd_option_lb_weight
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
367 dissect_someip_sd_pdu_option_ipv4(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint32_t offset
, uint32_t length
, int optionnum
, uint32_t option_ports
[]) {
369 const char *description
= NULL
;
371 uint32_t l4proto
= 0;
372 const char *l4protoname
= NULL
;
373 const char *ipstring
= NULL
;
375 proto_item
*ti
= NULL
;
376 proto_item
*ti_top
= NULL
;
378 type
= tvb_get_uint8(tvb
, offset
+ 2);
379 description
= val_to_str(type
, sd_option_type
, "(Unknown Option: %d)");
380 tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, length
, ett_someip_sd_option
, &ti_top
, "%d: %s Option", optionnum
, description
);
382 if (length
!= SD_OPTION_IPV4_LENGTH
) {
383 expert_add_info(pinfo
, ti_top
, &ei_someipsd_option_wrong_length
);
387 /* Add common fields */
388 proto_tree_add_item(tree
, hf_someip_sd_option_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
391 proto_tree_add_item(tree
, hf_someip_sd_option_type
, tvb
, offset
, 1, ENC_NA
);
394 proto_tree_add_item(tree
, hf_someip_sd_option_reserved
, tvb
, offset
, 1, ENC_NA
);
397 proto_tree_add_item(tree
, hf_someip_sd_option_ipv4
, tvb
, offset
, 4, ENC_NA
);
398 ipstring
= tvb_ip_to_str(pinfo
->pool
, tvb
, offset
);
401 proto_tree_add_item(tree
, hf_someip_sd_option_reserved2
, tvb
, offset
, 1, ENC_NA
);
404 ti
= proto_tree_add_item_ret_uint(tree
, hf_someip_sd_option_proto
, tvb
, offset
, 1, ENC_NA
, &l4proto
);
405 l4protoname
= val_to_str(l4proto
, sd_option_l4protos
, "Unknown Transport Protocol: %d");
406 proto_item_append_text(ti
, " (%s)", l4protoname
);
408 if (type
!= SD_OPTION_IPV4_ENDPOINT
&& l4proto
== SD_OPTION_L4PROTO_TCP
) {
409 expert_add_info(pinfo
, ti_top
, &ei_someipsd_L4_protocol_unsupported
);
413 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_option_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &l4port
);
415 proto_item_append_text(ti_top
, " (%s:%d (%s))", ipstring
, l4port
, l4protoname
);
417 option_ports
[optionnum
] = ((uint32_t)l4proto
<< 24) + l4port
;
421 dissect_someip_sd_pdu_option_ipv6(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint32_t offset
, uint32_t length
, int optionnum
, uint32_t option_ports
[]) {
423 const char *description
= NULL
;
425 uint32_t l4proto
= 0;
426 const char *l4protoname
= NULL
;
427 const char *ipstring
= NULL
;
428 proto_item
*ti
= NULL
;
429 proto_item
*ti_top
= NULL
;
431 type
= tvb_get_uint8(tvb
, offset
+ 2);
432 description
= val_to_str(type
, sd_option_type
, "(Unknown Option: %d)");
434 tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, length
, ett_someip_sd_option
, &ti_top
, "%d: %s Option", optionnum
, description
);
436 if (length
!= SD_OPTION_IPV6_LENGTH
) {
437 expert_add_info(pinfo
, ti_top
, &ei_someipsd_option_wrong_length
);
441 proto_tree_add_item(tree
, hf_someip_sd_option_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
444 proto_tree_add_item(tree
, hf_someip_sd_option_type
, tvb
, offset
, 1, ENC_NA
);
447 proto_tree_add_item(tree
, hf_someip_sd_option_reserved
, tvb
, offset
, 1, ENC_NA
);
450 proto_tree_add_item(tree
, hf_someip_sd_option_ipv6
, tvb
, offset
, 16, ENC_NA
);
451 ipstring
= tvb_ip6_to_str(pinfo
->pool
, tvb
, offset
);
454 proto_tree_add_item(tree
, hf_someip_sd_option_reserved2
, tvb
, offset
, 1, ENC_NA
);
457 ti
= proto_tree_add_item_ret_uint(tree
, hf_someip_sd_option_proto
, tvb
, offset
, 1, ENC_NA
, &l4proto
);
458 l4protoname
= val_to_str(l4proto
, sd_option_l4protos
, "(Unknown Transport Protocol: %d)");
459 proto_item_append_text(ti
, " (%s)", l4protoname
);
461 if (type
!= SD_OPTION_IPV6_ENDPOINT
&& l4proto
== SD_OPTION_L4PROTO_TCP
) {
462 expert_add_info(pinfo
, ti_top
, &ei_someipsd_L4_protocol_unsupported
);
466 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_option_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &l4port
);
468 proto_item_append_text(ti_top
, " (%s:%d (%s))", ipstring
, l4port
, l4protoname
);
470 option_ports
[optionnum
] = ((uint32_t)l4proto
<< 24) + l4port
;
474 dissect_someip_sd_pdu_option_unknown(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint32_t offset
, uint32_t length
, int optionnum
) {
478 tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, length
, ett_someip_sd_option
, &ti
, "%d: %s Option", optionnum
,
479 val_to_str_const(tvb_get_uint8(tvb
, offset
+ 2), sd_option_type
, "Unknown"));
481 expert_add_info(pinfo
, ti
, &ei_someipsd_option_unknown
);
483 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_option_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &len
);
486 proto_tree_add_item(tree
, hf_someip_sd_option_type
, tvb
, offset
, 1, ENC_NA
);
490 proto_tree_add_item(tree
, hf_someip_sd_option_reserved
, tvb
, offset
, 1, ENC_NA
);
494 proto_tree_add_item(tree
, hf_someip_sd_option_data
, tvb
, offset
, length
- 4, ENC_NA
);
500 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
) {
501 uint16_t real_length
= 0;
502 uint8_t option_type
= 0;
504 tvbuff_t
*subtvb
= NULL
;
506 uint32_t offset
= offset_orig
;
508 if (!tvb_bytes_exist(tvb
, offset
, SD_OPTION_MINLENGTH
) || !tvb_bytes_exist(tvb
, offset
, length
)) {
509 expert_add_info(pinfo
, ti
, &ei_someipsd_option_array_truncated
);
513 while (tvb_bytes_exist(tvb
, offset
, SD_OPTION_MINLENGTH
)) {
514 ws_assert(optionnum
>= 0 && optionnum
< SD_MAX_NUM_OPTIONS
);
515 option_ports
[optionnum
] = 0;
517 real_length
= tvb_get_ntohs(tvb
, offset
) + 3;
518 option_type
= tvb_get_uint8(tvb
, offset
+ 2);
520 if (!tvb_bytes_exist(tvb
, offset
, (int)real_length
) || offset
- offset_orig
+ real_length
> length
) {
521 expert_add_info(pinfo
, ti
, &ei_someipsd_option_array_truncated
);
525 subtvb
= tvb_new_subset_length(tvb
, offset
, (int)real_length
);
527 switch (option_type
) {
528 case SD_OPTION_CONFIGURATION
:
529 dissect_someip_sd_pdu_option_configuration(subtvb
, pinfo
, tree
, 0, real_length
, optionnum
);
531 case SD_OPTION_LOADBALANCING
:
532 dissect_someip_sd_pdu_option_loadbalancing(subtvb
, pinfo
, tree
, 0, real_length
, optionnum
);
534 case SD_OPTION_IPV4_ENDPOINT
:
535 case SD_OPTION_IPV4_MULTICAST
:
536 case SD_OPTION_IPV4_SD_ENDPOINT
:
537 dissect_someip_sd_pdu_option_ipv4(subtvb
, pinfo
, tree
, 0, real_length
, optionnum
, option_ports
);
540 case SD_OPTION_IPV6_ENDPOINT
:
541 case SD_OPTION_IPV6_MULTICAST
:
542 case SD_OPTION_IPV6_SD_ENDPOINT
:
543 dissect_someip_sd_pdu_option_ipv6(subtvb
, pinfo
, tree
, 0, real_length
, optionnum
, option_ports
);
547 dissect_someip_sd_pdu_option_unknown(subtvb
, pinfo
, tree
, 0, real_length
, optionnum
);
551 offset
+= real_length
;
554 *option_count
= optionnum
;
560 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
) {
561 if (category
!= SD_ENTRY_SERVICE
&& category
!= SD_ENTRY_EVENTGROUP
) {
565 if (serviceid
== 0xffff) {
566 proto_item_append_text(ti_entry
, " (Service ID ANY");
568 proto_item_append_text(ti_entry
, " (Service ID 0x%04x", serviceid
);
571 if (instanceid
== 0xffff) {
572 proto_item_append_text(ti_entry
, ", Instance ID ANY");
574 proto_item_append_text(ti_entry
, ", Instance ID 0x%04x", instanceid
);
577 if (majorver
== 0xff) {
578 proto_item_append_text(ti_entry
, ", Version ANY");
580 proto_item_append_text(ti_entry
, ", Version %u", majorver
);
584 case SD_ENTRY_SERVICE
:
585 if (minorver
== 0xffffffff) {
586 proto_item_append_text(ti_entry
, ".ANY");
588 proto_item_append_text(ti_entry
, ".%u", minorver
);
592 case SD_ENTRY_EVENTGROUP
:
593 if (eventgroupid
== 0xffff) {
594 proto_item_append_text(ti_entry
, ", Eventgroup ID ANY");
596 proto_item_append_text(ti_entry
, ", Eventgroup ID 0x%04x", eventgroupid
);
601 proto_item_append_text(ti_entry
, ", Options: %s)", buf_opt_ref
);
605 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
) {
606 uint32_t serviceid
= 0;
607 uint32_t instanceid
= 0;
608 uint32_t eventgroupid
= 0;
609 uint32_t majorver
= 0;
610 uint32_t minorver
= 0;
616 uint8_t category
= SD_ENTRY_UNKNOWN
;
618 const char *description
= NULL
;
619 static char buf_opt_ref
[32];
623 uint32_t offset
= offset_orig
;
629 if (length
< SD_ENTRY_LENGTH
|| !tvb_bytes_exist(tvb
, offset
, length
)) {
633 /* lets look ahead and find out the type and ttl */
634 *type
= tvb_get_uint8(tvb
, offset
);
635 *ttl
= tvb_get_ntoh24(tvb
, offset
+ 9);
638 category
= SD_ENTRY_SERVICE
;
639 } else if (*type
>= 4 && *type
< 8) {
640 category
= SD_ENTRY_EVENTGROUP
;
642 *ti_entry
= proto_tree_add_none_format(tree
, hf_someip_sd_entry
, tvb
, offset
, SD_ENTRY_LENGTH
, "Unknown Entry (Type: %d)", *type
);
643 expert_add_info(pinfo
, *ti_entry
, &ei_someipsd_entry_unknown
);
647 description
= val_to_str_const(*type
,
648 (*ttl
== 0) ? sd_entry_type_negative
: sd_entry_type_positive
,
651 *ti_entry
= proto_tree_add_none_format(tree
, hf_someip_sd_entry
, tvb
, offset
, SD_ENTRY_LENGTH
, "%s Entry", description
);
652 tree
= proto_item_add_subtree(*ti_entry
, ett_someip_sd_entry
);
654 proto_tree_add_uint_format_value(tree
, hf_someip_sd_entry_type
, tvb
, offset
, 1, *type
, "0x%02x (%s)", *type
, description
);
657 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_index1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &opt_index1
);
659 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_index2
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &opt_index2
);
662 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_numopt1
, tvb
, offset
, 1, ENC_NA
, &opt_num1
);
663 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_numopt2
, tvb
, offset
, 1, ENC_NA
, &opt_num2
);
666 if (opt_num1
!= 0 && opt_num2
== 0) {
667 snprintf(buf_opt_ref
, 32, "%d-%d", opt_index1
, opt_index1
+ opt_num1
- 1);
668 } else if (opt_num1
== 0 && opt_num2
!= 0) {
669 snprintf(buf_opt_ref
, 32, "%d-%d", opt_index2
, opt_index2
+ opt_num2
- 1);
670 } else if (opt_num1
!= 0 && opt_num2
!= 0) {
671 snprintf(buf_opt_ref
, 32, "%d-%d,%d-%d", opt_index1
, opt_index1
+ opt_num1
- 1, opt_index2
, opt_index2
+ opt_num2
- 1);
673 snprintf(buf_opt_ref
, 32, "None");
676 ti
= proto_tree_add_string(tree
, hf_someip_sd_entry_opts_referenced
, tvb
, offset
- 3, 3, buf_opt_ref
);
677 proto_item_set_generated(ti
);
679 ti
= proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_serviceid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &serviceid
);
680 description
= someip_lookup_service_name((uint16_t)serviceid
);
681 if (description
!= NULL
) {
682 proto_item_append_text(ti
, " (%s)", description
);
683 ti
= proto_tree_add_string(tree
, hf_someip_sd_entry_servicename
, tvb
, offset
, 2, description
);
684 proto_item_set_generated(ti
);
685 proto_item_set_hidden(ti
);
689 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_instanceid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &instanceid
);
692 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_majorver
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &majorver
);
695 proto_tree_add_item(tree
, hf_someip_sd_entry_ttl
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
698 /* Add specific fields - i.e. the last line */
699 if (category
== SD_ENTRY_SERVICE
) {
700 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_minorver
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &minorver
);
701 someip_sd_pdu_entry_append_text(*ti_entry
, category
, serviceid
, instanceid
, majorver
, minorver
, 0, buf_opt_ref
);
702 } else if (category
== SD_ENTRY_EVENTGROUP
) {
703 proto_tree_add_item(tree
, hf_someip_sd_entry_reserved
, tvb
, offset
, 1, ENC_NA
);
706 proto_tree_add_item(tree
, hf_someip_sd_entry_intial_event_flag
, tvb
, offset
, 1, ENC_NA
);
707 proto_tree_add_item(tree
, hf_someip_sd_entry_reserved2
, tvb
, offset
, 1, ENC_NA
);
708 proto_tree_add_item(tree
, hf_someip_sd_entry_counter
, tvb
, offset
, 1, ENC_NA
);
711 ti
= proto_tree_add_item_ret_uint(tree
, hf_someip_sd_entry_eventgroupid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &eventgroupid
);
712 description
= someip_lookup_eventgroup_name((uint16_t)serviceid
, (uint16_t)eventgroupid
);
713 if (description
!= NULL
) {
714 proto_item_append_text(ti
, " (%s)", description
);
715 ti
= proto_tree_add_string(tree
, hf_someip_sd_entry_eventgroupname
, tvb
, offset
, 2, description
);
716 proto_item_set_generated(ti
);
717 proto_item_set_hidden(ti
);
720 someip_sd_pdu_entry_append_text(*ti_entry
, category
, serviceid
, instanceid
, majorver
, 0, eventgroupid
, buf_opt_ref
);
723 /* lets add some combined filtering term */
724 *uniqueid
= (((uint64_t)serviceid
) << 32) | (uint64_t)instanceid
<< 16 | (uint64_t)eventgroupid
;
729 case SD_ENTRY_FIND_SERVICE
:
730 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 case SD_ENTRY_OFFER_SERVICE
:
733 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 case SD_ENTRY_SUBSCRIBE_EVENTGROUP
:
736 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 case SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK
:
739 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
);
744 case SD_ENTRY_STOP_OFFER_SERVICE
:
745 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 case SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP
:
748 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 case SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK
:
751 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
);
756 proto_item_set_hidden(ti
);
758 /* check for Offer Entry without referenced Endpoints */
759 if (opt_num1
== 0 && opt_num2
== 0 && *type
== SD_ENTRY_OFFER_SERVICE
&& *ttl
> 0) {
760 expert_add_info(pinfo
, *ti_entry
, &ei_someipsd_offer_without_endpoint
);
763 /* register ports but we skip 0xfffe because of other-serv */
764 if (serviceid
!= SOMEIP_SD_SERVICE_ID_OTHER_SERVICE
&& !PINFO_FD_VISITED(pinfo
)) {
765 someip_sd_register_ports(opt_index1
, opt_num1
, option_count
, option_ports
);
766 someip_sd_register_ports(opt_index2
, opt_num2
, option_count
, option_ports
);
770 if (have_tap_listener(tap_someip_sd_entries
)) {
771 someip_sd_entries_tap_t
*data
= wmem_alloc(pinfo
->pool
, sizeof(someip_sd_entries_tap_t
));
772 data
->entry_type
= *type
;
773 data
->service_id
= (uint16_t)serviceid
;
774 data
->major_version
= (uint8_t)majorver
;
775 data
->minor_version
= minorver
;
776 data
->instance_id
= (uint16_t)instanceid
;
777 data
->eventgroup_id
= (uint16_t)eventgroupid
;
780 tap_queue_packet(tap_someip_sd_entries
, pinfo
, data
);
785 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
) {
786 proto_item
*ti_entry
;
790 uint32_t entry_flags
= 0;
791 uint32_t stop_entry_flags
= 0;
794 uint64_t last_uniqueid
= 0xffffffffffffffff;
797 while (length
>= SD_ENTRY_LENGTH
) {
798 dissect_someip_sd_pdu_entry(tvb
, pinfo
, tree
, offset
, SD_ENTRY_LENGTH
, &type
, &ttl
, &uniqueid
, option_ports
, option_count
, &ti_entry
);
799 offset
+= SD_ENTRY_LENGTH
;
800 length
-= SD_ENTRY_LENGTH
;
802 /* mark for attaching to info column */
805 stop_entry_flags
= stop_entry_flags
| (1 << type
);
807 entry_flags
= entry_flags
| (1 << type
);
811 if (type
== SD_ENTRY_SUBSCRIBE_EVENTGROUP
&& ttl
== 0) {
812 last_uniqueid
= uniqueid
;
814 if ( (type
== SD_ENTRY_SUBSCRIBE_EVENTGROUP
&& ttl
> 0) && last_uniqueid
== uniqueid
) {
815 expert_add_info(pinfo
, ti_entry
, &ei_someipsd_entry_stopsubsub
);
818 last_uniqueid
= 0xffffffffffffffff;
822 /* Add entry flags */
823 if (stop_entry_flags
!= 0 || entry_flags
!= 0) {
824 col_append_str(pinfo
->cinfo
, COL_INFO
, " ");
827 if (entry_flags
& (1 << SD_ENTRY_FIND_SERVICE
)) {
828 col_append_str(pinfo
->cinfo
, COL_INFO
, "[Find]");
831 if (stop_entry_flags
& (1 << SD_ENTRY_OFFER_SERVICE
)) {
832 col_append_str(pinfo
->cinfo
, COL_INFO
, "[StopOffer]");
835 if (entry_flags
& (1 << SD_ENTRY_OFFER_SERVICE
)) {
836 col_append_str(pinfo
->cinfo
, COL_INFO
, "[Offer]");
839 if (stop_entry_flags
& (1 << SD_ENTRY_SUBSCRIBE_EVENTGROUP
)) {
840 col_append_str(pinfo
->cinfo
, COL_INFO
, "[StopSubscribe]");
843 if (entry_flags
& (1 << SD_ENTRY_SUBSCRIBE_EVENTGROUP
)) {
844 col_append_str(pinfo
->cinfo
, COL_INFO
, "[Subscribe]");
847 if (stop_entry_flags
& (1 << SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK
)) {
848 col_append_str(pinfo
->cinfo
, COL_INFO
, "[SubscribeNack]");
851 if (entry_flags
& (1 << SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK
)) {
852 col_append_str(pinfo
->cinfo
, COL_INFO
, "[SubscribeAck]");
856 expert_add_info(pinfo
, ti
, &ei_someipsd_entry_array_malformed
);
863 dissect_someip_sd_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
865 uint32_t length_entriesarray
= 0;
866 uint32_t length_optionsarray
= 0;
868 proto_item
*ti
= NULL
;
869 proto_item
*ti_sd_entries
= NULL
;
871 proto_tree
*someip_sd_entries_tree
= NULL
;
872 proto_tree
*someip_sd_options_tree
= NULL
;
873 bool stop_parsing_after_entries
= false;
874 uint32_t offset_entriesarray
;
876 /* format for option_ports entries: 1 byte proto | 1 byte reserved | 2 byte port number*/
877 static uint32_t option_ports
[SD_MAX_NUM_OPTIONS
];
878 unsigned option_count
= 0;
880 static int * const someipsd_flags
[] = {
881 &hf_someip_sd_rebootflag
,
882 &hf_someip_sd_unicastflag
,
883 &hf_someip_sd_explicitiniteventflag
,
887 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, SOMEIP_SD_NAME
);
888 col_set_str(pinfo
->cinfo
, COL_INFO
, SOMEIP_SD_NAME
);
890 ti
= proto_tree_add_item(tree
, proto_someip_sd
, tvb
, offset
, -1, ENC_NA
);
891 tree
= proto_item_add_subtree(ti
, ett_someip_sd
);
893 if (!tvb_bytes_exist(tvb
, offset
, SOMEIP_SD_MIN_LENGTH
)) {
894 expert_add_info(pinfo
, ti
, &ei_someipsd_message_truncated
);
895 return tvb_reported_length(tvb
);
899 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_someip_sd_flags
, ett_someip_sd_flags
, someipsd_flags
, ENC_BIG_ENDIAN
);
903 proto_tree_add_item(tree
, hf_someip_sd_reserved
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
906 /* add length of entries */
907 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_length_entriesarray
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &length_entriesarray
);
910 if (!tvb_bytes_exist(tvb
, offset
, length_entriesarray
)) {
911 expert_add_info(pinfo
, ti
, &ei_someipsd_message_truncated
);
912 return tvb_reported_length(tvb
);
915 if (!tvb_bytes_exist(tvb
, offset
, length_entriesarray
)) {
916 /* truncated SD message - need to shorten buffer */
917 length_entriesarray
= tvb_captured_length_remaining(tvb
, offset
);
918 expert_add_info(pinfo
, ti
, &ei_someipsd_message_truncated
);
919 stop_parsing_after_entries
= true;
922 /* preparing entries array but not parsing it yet */
923 ti_sd_entries
= proto_tree_add_item(tree
, hf_someip_sd_entries
, tvb
, offset
, length_entriesarray
, ENC_NA
);
924 someip_sd_entries_tree
= proto_item_add_subtree(ti_sd_entries
, ett_someip_sd_entries
);
925 /* save offset to parse entries later since we need to parse options first */
926 offset_entriesarray
= offset
;
927 offset
+= length_entriesarray
;
929 if (!stop_parsing_after_entries
) {
930 /* make sure we have a length field */
931 if (tvb_bytes_exist(tvb
, offset
, 4)) {
933 /* add options length */
934 proto_tree_add_item_ret_uint(tree
, hf_someip_sd_length_optionsarray
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &length_optionsarray
);
937 if (length_optionsarray
> 0) {
938 if (tvb_bytes_exist(tvb
, offset
, 1)) {
939 ti
= proto_tree_add_item(tree
, hf_someip_sd_options
, tvb
, offset
, -1, ENC_NA
);
940 someip_sd_options_tree
= proto_item_add_subtree(ti
, ett_someip_sd_options
);
942 /* check, if enough bytes are left for optionsarray */
943 if (!tvb_bytes_exist(tvb
, offset
, length_optionsarray
)) {
944 length_optionsarray
= tvb_captured_length_remaining(tvb
, offset
);
945 expert_add_info(pinfo
, ti
, &ei_someipsd_message_truncated
);
946 proto_item_append_text(ti
, " (truncated!)");
949 /* updating to length we will work with */
950 if (length_optionsarray
> 0) {
951 proto_item_set_len(ti
, length_optionsarray
);
954 dissect_someip_sd_pdu_options(tvb
, pinfo
, someip_sd_options_tree
, ti
, offset
, length_optionsarray
, option_ports
, &option_count
);
955 offset
+= length_optionsarray
;
957 expert_add_info(pinfo
, ti
, &ei_someipsd_message_truncated
);
963 if (length_entriesarray
>= SD_ENTRY_LENGTH
) {
964 offset
+= dissect_someip_sd_pdu_entries(tvb
, pinfo
, someip_sd_entries_tree
, ti_sd_entries
, offset_entriesarray
, length_entriesarray
, option_ports
, option_count
);
966 expert_add_info(pinfo
, ti_sd_entries
, &ei_someipsd_entry_array_empty
);
971 /*******************************************
972 **************** Statistics ***************
973 *******************************************/
976 someipsd_entries_stats_tree_init(stats_tree
*st
) {
977 st_node_ip_src
= stats_tree_create_node(st
, st_str_ip_src
, 0, STAT_DT_INT
, true);
978 stat_node_set_flags(st
, st_str_ip_src
, 0, false, ST_FLG_SORT_TOP
);
979 st_node_ip_dst
= stats_tree_create_node(st
, st_str_ip_dst
, 0, STAT_DT_INT
, true);
983 stat_number_to_string_with_any(uint32_t value
, unsigned max
, char *format_string
, char *ret
, size_t size_limit
) {
985 snprintf(ret
, size_limit
, "%s", "MAX");
987 snprintf(ret
, size_limit
, format_string
, value
);
992 stat_create_entry_summary_string(const someip_sd_entries_tap_t
*data
, char *ret
, size_t size_limit
) {
993 char service_str
[128];
994 char instance_str
[128];
995 char majorver_str
[128];
996 char minorver_str
[128];
997 char eventgrp_str
[128];
1000 char *service_name
= someip_lookup_service_name(data
->service_id
);
1001 char *eventgrp_name
= someip_lookup_eventgroup_name(data
->service_id
, data
->eventgroup_id
);
1003 stat_number_to_string_with_any(data
->service_id
, UINT32_MAX
, "0x%04x", service_str
, sizeof(service_str
) - 1);
1004 stat_number_to_string_with_any(data
->instance_id
, UINT32_MAX
, "0x%04x", instance_str
, sizeof(instance_str
) - 1);
1005 stat_number_to_string_with_any(data
->major_version
, UINT8_MAX
, "%d", majorver_str
, sizeof(majorver_str
) - 1);
1007 switch (data
->entry_type
) {
1008 case SD_ENTRY_FIND_SERVICE
:
1009 case SD_ENTRY_OFFER_SERVICE
:
1010 stat_number_to_string_with_any(data
->minor_version
, UINT32_MAX
, "%d", minorver_str
, sizeof(minorver_str
) - 1);
1011 if (service_name
!= NULL
) {
1012 snprintf(ret
, size_limit
, "Service %s (%s) Version %s.%s Instance %s", service_str
, service_name
, majorver_str
, minorver_str
, instance_str
);
1014 snprintf(ret
, size_limit
, "Service %s Version %s.%s Instance %s", service_str
, majorver_str
, minorver_str
, instance_str
);
1018 case SD_ENTRY_SUBSCRIBE_EVENTGROUP
:
1019 case SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK
:
1020 stat_number_to_string_with_any(data
->eventgroup_id
, UINT32_MAX
, "0x%04x", eventgrp_str
, sizeof(eventgrp_str
) - 1);
1021 if (service_name
!= NULL
) {
1022 snprintf(tmp
, sizeof(tmp
) - 1, "Service %s (%s) Version %s Instance %s Eventgroup %s", service_str
, service_name
, majorver_str
, instance_str
, eventgrp_str
);
1024 snprintf(tmp
, sizeof(tmp
) - 1, "Service %s Version %s Instance %s Eventgroup %s", service_str
, majorver_str
, instance_str
, eventgrp_str
);
1026 if (eventgrp_name
!= NULL
) {
1027 snprintf(ret
, size_limit
, "%s (%s)", tmp
, eventgrp_name
);
1033 static tap_packet_status
1034 someipsd_entries_stats_tree_packet(stats_tree
*st
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *p
, tap_flags_t flags _U_
) {
1035 DISSECTOR_ASSERT(p
);
1036 const someip_sd_entries_tap_t
*data
= (const someip_sd_entries_tap_t
*)p
;
1037 static char tmp_addr_str
[256];
1039 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
));
1040 tick_stat_node(st
, st_str_ip_src
, 0, false);
1041 int src_id
= tick_stat_node(st
, tmp_addr_str
, st_node_ip_src
, true);
1043 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
));
1044 tick_stat_node(st
, st_str_ip_dst
, 0, false);
1045 int dst_id
= tick_stat_node(st
, tmp_addr_str
, st_node_ip_dst
, true);
1048 static char tmp_str
[128];
1050 if (data
->ttl
== 0) {
1051 switch (data
->entry_type
) {
1052 case SD_ENTRY_STOP_OFFER_SERVICE
:
1053 stat_create_entry_summary_string(data
, tmp_str
, sizeof(tmp_str
) - 1);
1054 tmp_id
= tick_stat_node(st
, "Stop Offer Service", src_id
, true);
1055 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1056 tmp_id
= tick_stat_node(st
, "Stop Offer Service", dst_id
, true);
1057 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1059 case SD_ENTRY_STOP_SUBSCRIBE_EVENTGROUP
:
1060 stat_create_entry_summary_string(data
, tmp_str
, sizeof(tmp_str
) - 1);
1061 tmp_id
= tick_stat_node(st
, "Stop Subscribe Eventgroup", src_id
, true);
1062 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1063 tmp_id
= tick_stat_node(st
, "Stop Subscribe Eventgroup", dst_id
, true);
1064 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1066 case SD_ENTRY_SUBSCRIBE_EVENTGROUP_NACK
:
1067 stat_create_entry_summary_string(data
, tmp_str
, sizeof(tmp_str
) - 1);
1068 tmp_id
= tick_stat_node(st
, "Subscribe Eventgroup Nack", src_id
, true);
1069 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1070 tmp_id
= tick_stat_node(st
, "Subscribe Eventgroup Nack", dst_id
, true);
1071 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1075 switch (data
->entry_type
) {
1076 case SD_ENTRY_FIND_SERVICE
:
1077 stat_create_entry_summary_string(data
, tmp_str
, sizeof(tmp_str
) - 1);
1078 tmp_id
= tick_stat_node(st
, "Find Service", src_id
, true);
1079 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1080 tmp_id
= tick_stat_node(st
, "Find Service", dst_id
, true);
1081 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1083 case SD_ENTRY_OFFER_SERVICE
:
1084 stat_create_entry_summary_string(data
, tmp_str
, sizeof(tmp_str
) - 1);
1085 tmp_id
= tick_stat_node(st
, "Offer Service", src_id
, true);
1086 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1087 tmp_id
= tick_stat_node(st
, "Offer Service", dst_id
, true);
1088 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1090 case SD_ENTRY_SUBSCRIBE_EVENTGROUP
:
1091 stat_create_entry_summary_string(data
, tmp_str
, sizeof(tmp_str
) - 1);
1092 tmp_id
= tick_stat_node(st
, "Subscribe Eventgroup", src_id
, true);
1093 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1094 tmp_id
= tick_stat_node(st
, "Subscribe Eventgroup", dst_id
, true);
1095 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1097 case SD_ENTRY_SUBSCRIBE_EVENTGROUP_ACK
:
1098 stat_create_entry_summary_string(data
, tmp_str
, sizeof(tmp_str
) - 1);
1099 tmp_id
= tick_stat_node(st
, "Subscribe Eventgroup Ack", src_id
, true);
1100 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1101 tmp_id
= tick_stat_node(st
, "Subscribe Eventgroup Ack", dst_id
, true);
1102 tick_stat_node(st
, tmp_str
, tmp_id
, false);
1107 return TAP_PACKET_REDRAW
;
1111 proto_register_someip_sd(void) {
1112 module_t
*someipsd_module
;
1114 expert_module_t
*expert_module_someip_sd
;
1117 static hf_register_info hf_sd
[] = {
1118 { &hf_someip_sd_flags
,
1119 { "Flags", "someipsd.flags",
1120 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1121 { &hf_someip_sd_rebootflag
,
1122 { "Reboot Flag", "someipsd.flags.reboot",
1123 FT_BOOLEAN
, 8, TFS(&sd_reboot_flag
), SOMEIP_SD_REBOOT_FLAG
, NULL
, HFILL
}},
1124 { &hf_someip_sd_unicastflag
,
1125 { "Unicast Flag", "someipsd.flags.unicast",
1126 FT_BOOLEAN
, 8, TFS(&sd_unicast_flag
), SOMEIP_SD_UNICAST_FLAG
, NULL
, HFILL
}},
1127 { &hf_someip_sd_explicitiniteventflag
,
1128 { "Explicit Initial Events Flag", "someipsd.flags.exp_init_events",
1129 FT_BOOLEAN
, 8, TFS(&sd_eiec_flag
), SOMEIP_SD_EXPL_INIT_EVENT_REQ_FLAG
, NULL
, HFILL
}},
1130 { &hf_someip_sd_reserved
,
1131 { "Reserved", "someipsd.reserved",
1132 FT_UINT24
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1134 { &hf_someip_sd_length_entriesarray
,
1135 { "Length of Entries Array", "someipsd.length_entriesarray",
1136 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1137 { &hf_someip_sd_entries
,
1138 { "Entries Array", "someipsd.entries",
1139 FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1140 { &hf_someip_sd_entry
,
1141 { "Entry", "someipsd.entry",
1142 FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1143 { &hf_someip_sd_entry_type
,
1144 { "Type", "someipsd.entry.type",
1145 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1146 { &hf_someip_sd_entry_index1
,
1147 { "Index 1", "someipsd.entry.index1",
1148 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1149 { &hf_someip_sd_entry_index2
,
1150 { "Index 2", "someipsd.entry.index2",
1151 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1152 { &hf_someip_sd_entry_numopt1
,
1153 { "Number of Opts 1", "someipsd.entry.numopt1",
1154 FT_UINT8
, BASE_HEX
, NULL
, 0xf0, NULL
, HFILL
}},
1155 { &hf_someip_sd_entry_numopt2
,
1156 { "Number of Opts 2", "someipsd.entry.numopt2",
1157 FT_UINT8
, BASE_HEX
, NULL
, 0x0f, NULL
, HFILL
}},
1158 { &hf_someip_sd_entry_opts_referenced
,
1159 { "Options referenced", "someipsd.entry.optionsreferenced",
1160 FT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1162 { &hf_someip_sd_entry_serviceid
,
1163 { "Service ID", "someipsd.entry.serviceid",
1164 FT_UINT16
, BASE_HEX
| BASE_SPECIAL_VALS
, VALS(sd_serviceid_vs
), 0x0, NULL
, HFILL
}},
1165 { &hf_someip_sd_entry_servicename
,
1166 { "Service Name", "someipsd.entry.servicename",
1167 FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1168 { &hf_someip_sd_entry_instanceid
,
1169 { "Instance ID", "someipsd.entry.instanceid",
1170 FT_UINT16
, BASE_HEX
| BASE_SPECIAL_VALS
, VALS(sd_instanceid_vs
), 0x0, NULL
, HFILL
}},
1171 { &hf_someip_sd_entry_majorver
,
1172 { "Major Version", "someipsd.entry.majorver",
1173 FT_UINT8
, BASE_DEC
| BASE_SPECIAL_VALS
, VALS(sd_majorversion_vs
), 0x0, NULL
, HFILL
}},
1174 { &hf_someip_sd_entry_ttl
,
1175 { "TTL", "someipsd.entry.ttl",
1176 FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1177 { &hf_someip_sd_entry_minorver
,
1178 { "Minor Version", "someipsd.entry.minorver",
1179 FT_UINT32
, BASE_DEC
| BASE_SPECIAL_VALS
, VALS(sd_minorversion_vs
), 0x0, NULL
, HFILL
}},
1180 { &hf_someip_sd_entry_eventgroupid
,
1181 { "Eventgroup ID", "someipsd.entry.eventgroupid",
1182 FT_UINT16
, BASE_HEX
| BASE_SPECIAL_VALS
, VALS(sd_eventgroupid_vs
), 0x0, NULL
, HFILL
}},
1183 { &hf_someip_sd_entry_eventgroupname
,
1184 { "Eventgroup Name", "someipsd.entry.eventgroupname",
1185 FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1186 { &hf_someip_sd_entry_reserved
,
1187 { "Reserved", "someipsd.entry.reserved",
1188 FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
} },
1189 { &hf_someip_sd_entry_counter
,
1190 { "Counter", "someipsd.entry.counter",
1191 FT_UINT8
, BASE_HEX
, NULL
, SD_EVENTGROUP_ENTRY_COUNTER_MASK
, NULL
, HFILL
} },
1192 { &hf_someip_sd_entry_reserved2
,
1193 { "Reserved", "someipsd.entry.reserved2",
1194 FT_UINT8
, BASE_HEX
, NULL
, SD_EVENTGROUP_ENTRY_RES2_MASK
, NULL
, HFILL
} },
1195 { &hf_someip_sd_entry_intial_event_flag
,
1196 { "Initial Event Request", "someipsd.entry.initialevents",
1197 FT_BOOLEAN
, 8, NULL
, SD_ENTRY_INIT_EVENT_REQ_MASK
, NULL
, HFILL
} },
1199 { &hf_someip_sd_length_optionsarray
,
1200 { "Length of Options Array", "someipsd.length_optionsarray",
1201 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1202 { &hf_someip_sd_options
,
1203 { "Options Array", "someipsd.options",
1204 FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1206 { &hf_someip_sd_option_type
,
1207 { "Type", "someipsd.option.type",
1208 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1209 { &hf_someip_sd_option_length
,
1210 { "Length", "someipsd.option.length",
1211 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1212 { &hf_someip_sd_option_reserved
,
1213 { "Reserved", "someipsd.option.reserved",
1214 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1215 { &hf_someip_sd_option_ipv4
,
1216 { "IPv4 Address", "someipsd.option.ipv4address",
1217 FT_IPv4
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1218 { &hf_someip_sd_option_ipv6
,
1219 { "IPv6 Address", "someipsd.option.ipv6address",
1220 FT_IPv6
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1221 { &hf_someip_sd_option_port
,
1222 { "Port", "someipsd.option.port",
1223 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1224 { &hf_someip_sd_option_proto
,
1225 { "Protocol", "someipsd.option.proto",
1226 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1227 { &hf_someip_sd_option_reserved2
,
1228 { "Reserved 2", "someipsd.option.reserved2",
1229 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1230 { &hf_someip_sd_option_data
,
1231 { "Unknown Data", "someipsd.option.unknown_data",
1232 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1233 { &hf_someip_sd_option_config_string
,
1234 { "Configuration String", "someipsd.option.config_string",
1235 FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1236 { &hf_someip_sd_option_config_string_element
,
1237 { "Configuration String Element", "someipsd.option.config_string_element",
1238 FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
1239 { &hf_someip_sd_option_lb_priority
,
1240 { "Priority", "someipsd.option.priority",
1241 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1242 { &hf_someip_sd_option_lb_weight
,
1243 { "Weight", "someipsd.option.weight",
1244 FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
1245 { &hf_someip_sd_entry_type_offerservice
,
1246 { "Offer Service", "someipsd.entry.offerservice",
1247 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1248 { &hf_someip_sd_entry_type_stopofferservice
,
1249 { "Stop Offer Service", "someipsd.entry.stopofferservice",
1250 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1251 { &hf_someip_sd_entry_type_findservice
,
1252 { "Find Service", "someipsd.entry.findservice",
1253 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1255 { &hf_someip_sd_entry_type_subscribeeventgroup
,
1256 { "Subscribe Eventgroup", "someipsd.entry.subscribeeventgroup",
1257 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1258 { &hf_someip_sd_entry_type_stopsubscribeeventgroup
,
1259 { "Stop Subscribe Eventgroup", "someipsd.entry.stopsubscribeeventgroup",
1260 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1262 { &hf_someip_sd_entry_type_subscribeeventgroupack
,
1263 { "Subscribe Eventgroup ACK", "someipsd.entry.subscribeeventgroupack",
1264 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1265 { &hf_someip_sd_entry_type_subscribeeventgroupnack
,
1266 { "Subscribe Eventgroup NACK", "someipsd.entry.subscribeeventgroupnack",
1267 FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1270 static int *ett_sd
[] = {
1272 &ett_someip_sd_flags
,
1273 &ett_someip_sd_entries
,
1274 &ett_someip_sd_entry
,
1275 &ett_someip_sd_options
,
1276 &ett_someip_sd_option
,
1277 &ett_someip_sd_config_string
,
1280 static ei_register_info ei_sd
[] = {
1281 { &ei_someipsd_message_truncated
,{ "someipsd.message_truncated", PI_MALFORMED
, PI_ERROR
, "SOME/IP-SD Truncated message!", EXPFILL
} },
1282 { &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
} },
1283 { &ei_someipsd_entry_array_empty
,{ "someipsd.entry_array_empty", PI_MALFORMED
, PI_ERROR
, "SOME/IP-SD Empty Entry Array!", EXPFILL
} },
1284 { &ei_someipsd_entry_unknown
,{ "someipsd.entry_unknown", PI_MALFORMED
, PI_WARN
, "SOME/IP-SD Unknown Entry!", EXPFILL
} },
1285 { &ei_someipsd_offer_without_endpoint
,{ "someipsd.offer_no_endpoints", PI_MALFORMED
, PI_ERROR
, "SOME/IP-SD Offer Service references no endpoints!", EXPFILL
} },
1286 { &ei_someipsd_entry_stopsubsub
,{ "someipsd.stopsub_sub", PI_PROTOCOL
, PI_WARN
, "SOME/IP-SD Subscribe after Stop Subscribe!", EXPFILL
} },
1287 { &ei_someipsd_option_array_truncated
,{ "someipsd.option_array_truncated", PI_MALFORMED
, PI_ERROR
, "SOME/IP-SD Option Array truncated!", EXPFILL
} },
1288 { &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
} },
1289 { &ei_someipsd_option_unknown
,{ "someipsd.option_unknown", PI_MALFORMED
, PI_WARN
, "SOME/IP-SD Unknown Option!", EXPFILL
} },
1290 { &ei_someipsd_option_wrong_length
,{ "someipsd.option_wrong_length", PI_MALFORMED
, PI_ERROR
, "SOME/IP-SD Option length is incorrect!", EXPFILL
} },
1291 { &ei_someipsd_L4_protocol_unsupported
,{ "someipsd.L4_protocol_unsupported", PI_MALFORMED
, PI_ERROR
, "SOME/IP-SD Unsupported Layer 4 Protocol!", EXPFILL
} },
1292 { &ei_someipsd_config_string_malformed
,{ "someipsd.config_string_malformed", PI_MALFORMED
, PI_ERROR
, "SOME/IP-SD Configuration String malformed!", EXPFILL
} },
1295 /* Register Protocol, Fields, ETTs, Expert Info, Taps, Dissector */
1296 proto_someip_sd
= proto_register_protocol(SOMEIP_SD_NAME_LONG
, SOMEIP_SD_NAME
, SOMEIP_SD_NAME_FILTER
);
1297 proto_register_field_array(proto_someip_sd
, hf_sd
, array_length(hf_sd
));
1298 proto_register_subtree_array(ett_sd
, array_length(ett_sd
));
1299 expert_module_someip_sd
= expert_register_protocol(proto_someip_sd
);
1300 expert_register_field_array(expert_module_someip_sd
, ei_sd
, array_length(ei_sd
));
1301 tap_someip_sd_entries
= register_tap("someipsd_entries");
1302 someip_sd_handle
= register_dissector(SOMEIP_SD_NAME_FILTER
, dissect_someip_sd_pdu
, proto_someip_sd
);
1304 /* Register preferences */
1305 someipsd_module
= prefs_register_protocol(proto_someip_sd
, NULL
);
1307 range_convert_str(wmem_epan_scope(), &someip_ignore_ports_udp
, "", 65535);
1308 prefs_register_range_preference(someipsd_module
, "ports.udp.ignore", "UDP Ports ignored",
1309 "SOME/IP Ignore Port Ranges UDP. These ports are not automatically added by the SOME/IP-SD.",
1310 &someip_ignore_ports_udp
, 65535);
1312 range_convert_str(wmem_epan_scope(), &someip_ignore_ports_tcp
, "", 65535);
1313 prefs_register_range_preference(someipsd_module
, "ports.tcp.ignore", "TCP Ports ignored",
1314 "SOME/IP Ignore Port Ranges TCP. These ports are not automatically added by the SOME/IP-SD.",
1315 &someip_ignore_ports_tcp
, 65535);
1319 proto_reg_handoff_someip_sd(void) {
1320 dissector_add_uint("someip.messageid", SOMEIP_SD_MESSAGEID
, someip_sd_handle
);
1321 stats_tree_register("someipsd_entries", "someipsd_entries", "SOME/IP-SD Entries", 0, someipsd_entries_stats_tree_packet
, someipsd_entries_stats_tree_init
, NULL
);
1330 * indent-tabs-mode: nil
1333 * ex: set shiftwidth=4 tabstop=8 expandtab:
1334 * :indentSize=4:tabSize=8:noTabs=true: