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