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