epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-someip.c
blob4a27ba8b113cfd6a335fd84d1f83d7548e412a0a
1 /* packet-someip.c
2 * SOME/IP dissector.
3 * By Dr. Lars Voelker <lars.voelker@technica-engineering.de> / <lars.voelker@bmw.de>
4 * Copyright 2012-2024 Dr. Lars Voelker
5 * Copyright 2019 Ana Pantar
6 * Copyright 2019 Guenter Ebermann
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <config.h>
17 #include <epan/packet.h>
18 #include <epan/prefs.h>
19 #include <epan/expert.h>
20 #include <epan/to_str.h>
21 #include <epan/uat.h>
22 #include "packet-tcp.h"
23 #include <epan/reassemble.h>
24 #include <epan/addr_resolv.h>
25 #include <epan/stats_tree.h>
26 #include <epan/prefs-int.h>
28 #include "packet-udp.h"
29 #include "packet-dtls.h"
30 #include "packet-someip.h"
31 #include "packet-tls.h"
34 * Dissector for SOME/IP, SOME/IP-TP, and SOME/IP Payloads.
36 * See
37 * http://www.some-ip.com
40 * This dissector also supports the experimental WTLV or TLV extension,
41 * which is not part of the original SOME/IP.
42 * This add-on feature uses a so-called WireType, which is basically
43 * a type of a length field and an ID to each parameter. Since the
44 * WireType is not really a type, we should avoid TLV as name for this.
45 * Only use this, if you know what you are doing since this changes the
46 * serialization methodology of SOME/IP in a incompatible way and might
47 * break the dissection of your messages.
50 #define SOMEIP_NAME "SOME/IP"
51 #define SOMEIP_NAME_LONG "SOME/IP Protocol"
52 #define SOMEIP_NAME_FILTER "someip"
53 #define SOMEIP_NAME_PREFIX "someip.payload"
55 #define SOMEIP_NAME_LONG_MULTIPLE "SOME/IP Protocol (Multiple Payloads)"
56 #define SOMEIP_NAME_LONG_BROKEN "SOME/IP: Incomplete headers!"
57 #define SOMEIP_NAME_LONG_TOO_SHORT "SOME/IP: Incomplete SOME/IP payload!"
59 /*** Configuration ***/
60 #define DATAFILE_SOMEIP_SERVICES "SOMEIP_service_identifiers"
61 #define DATAFILE_SOMEIP_METHODS "SOMEIP_method_event_identifiers"
62 #define DATAFILE_SOMEIP_EVENTGROUPS "SOMEIP_eventgroup_identifiers"
63 #define DATAFILE_SOMEIP_CLIENTS "SOMEIP_client_identifiers"
65 #define DATAFILE_SOMEIP_PARAMETERS "SOMEIP_parameter_list"
66 #define DATAFILE_SOMEIP_BASE_TYPES "SOMEIP_parameter_base_types"
67 #define DATAFILE_SOMEIP_ARRAYS "SOMEIP_parameter_arrays"
68 #define DATAFILE_SOMEIP_STRINGS "SOMEIP_parameter_strings"
69 #define DATAFILE_SOMEIP_TYPEDEFS "SOMEIP_parameter_typedefs"
70 #define DATAFILE_SOMEIP_STRUCTS "SOMEIP_parameter_structs"
71 #define DATAFILE_SOMEIP_UNIONS "SOMEIP_parameter_unions"
72 #define DATAFILE_SOMEIP_ENUMS "SOMEIP_parameter_enums"
74 #define SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_UNKNOWN 0
75 #define SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_BASE_TYPE 1
76 #define SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_STRING 2
77 #define SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ARRAY 3
78 #define SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_STRUCT 4
79 #define SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_UNION 5
80 #define SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_TYPEDEF 6
81 #define SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ENUM 7
83 /*** SOME/IP ***/
84 #define SOMEIP_HDR_LEN 16
85 #define SOMEIP_HDR_PART1_LEN 8
86 #define SOMEIP_HDR_PART2_LEN_INCL_TP 12
87 #define SOMEIP_TP_HDR_LEN 4
88 #define SOMEIP_PROTOCOL_VERSION 1
90 /* Message Types */
91 #define SOMEIP_MSGTYPE_REQUEST 0x00
92 #define SOMEIP_MSGTYPE_REQUEST_NO_RESPONSE 0x01
93 #define SOMEIP_MSGTYPE_NOTIFICATION 0x02
94 #define SOMEIP_MSGTYPE_RESPONSE 0x80
95 #define SOMEIP_MSGTYPE_ERROR 0x81
97 #define SOMEIP_MSGTYPE_ACK_MASK 0x40
98 #define SOMEIP_MSGTYPE_TP_MASK 0x20
99 #define SOMEIP_MSGTYPE_FLAGS_MASK 0x60
100 #define SOMEIP_MSGTYPE_NO_FLAGS_MASK 0x9f
101 #define SOMEIP_MSGTYPE_TP_STRING "SOME/IP-TP segment"
102 #define SOMEIP_MSGTYPE_ACK_STRING "ACK"
104 /* SOME/IP-TP */
105 #define SOMEIP_TP_OFFSET_MASK 0xfffffff0
106 #define SOMEIP_TP_OFFSET_MASK_FLAGS 0x0000000f
107 #define SOMEIP_TP_OFFSET_MASK_RESERVED 0x0000000e
108 #define SOMEIP_TP_OFFSET_MASK_MORE_SEGMENTS 0x00000001
110 /* Return Codes */
111 #define SOMEIP_RETCODE_OK 0x00
112 #define SOMEIP_RETCODE_NOT_OK 0x01
113 #define SOMEIP_RETCODE_UNKNOWN_SERVICE 0x02
114 #define SOMEIP_RETCODE_UNKNOWN_METHOD 0x03
115 #define SOMEIP_RETCODE_NOT_READY 0x04
116 #define SOMEIP_RETCODE_NOT_REACHABLE 0x05
117 #define SOMEIP_RETCODE_TIMEOUT 0x06
118 #define SOMEIP_RETCODE_WRONG_PROTO_VER 0x07
119 #define SOMEIP_RETCODE_WRONG_INTERFACE_VER 0x08
120 #define SOMEIP_RETCODE_MALFORMED_MSG 0x09
121 #define SOMEIP_RETCODE_WRONG_MESSAGE_TYPE 0x0a
123 /* SOME/IP WTLV (experimental "WTLV" extension) */
124 #define SOMEIP_WTLV_MASK_RES 0x8000
125 #define SOMEIP_WTLV_MASK_WIRE_TYPE 0x7000
126 #define SOMEIP_WTLV_MASK_DATA_ID 0x0fff
128 /* ID wireshark identifies the dissector by */
129 static int proto_someip;
130 static module_t *someip_module;
132 static dissector_handle_t someip_handle_udp;
133 static dissector_handle_t someip_handle_tcp;
134 static dissector_handle_t dtls_handle;
136 /* header field */
137 static int hf_someip_messageid;
138 static int hf_someip_serviceid;
139 static int hf_someip_servicename;
140 static int hf_someip_methodid;
141 static int hf_someip_methodname;
142 static int hf_someip_length;
143 static int hf_someip_clientid;
144 static int hf_someip_clientname;
145 static int hf_someip_sessionid;
146 static int hf_someip_protover;
147 static int hf_someip_interface_ver;
148 static int hf_someip_messagetype;
149 static int hf_someip_messagetype_ack_flag;
150 static int hf_someip_messagetype_tp_flag;
151 static int hf_someip_returncode;
153 static int hf_someip_tp;
154 static int hf_someip_tp_offset;
155 static int hf_someip_tp_offset_encoded;
156 static int hf_someip_tp_flags;
157 static int hf_someip_tp_reserved;
158 static int hf_someip_tp_more_segments;
160 static int hf_someip_payload;
162 /* protocol tree items */
163 static int ett_someip;
164 static int ett_someip_msgtype;
165 static int ett_someip_tp;
167 /* dissector handling */
168 static dissector_table_t someip_dissector_table;
170 /* message reassembly for SOME/IP-TP */
171 static int hf_someip_tp_fragments;
172 static int hf_someip_tp_fragment;
173 static int hf_someip_tp_fragment_overlap;
174 static int hf_someip_tp_fragment_overlap_conflicts;
175 static int hf_someip_tp_fragment_multiple_tails;
176 static int hf_someip_tp_fragment_too_long_fragment;
177 static int hf_someip_tp_fragment_error;
178 static int hf_someip_tp_fragment_count;
179 static int hf_someip_tp_reassembled_in;
180 static int hf_someip_tp_reassembled_length;
181 static int hf_someip_tp_reassembled_data;
183 static int hf_payload_unparsed;
184 static int hf_payload_length_field_8bit;
185 static int hf_payload_length_field_16bit;
186 static int hf_payload_length_field_32bit;
187 static int hf_payload_type_field_8bit;
188 static int hf_payload_type_field_16bit;
189 static int hf_payload_type_field_32bit;
190 static int hf_payload_str_base;
191 static int hf_payload_str_string;
192 static int hf_payload_str_struct;
193 static int hf_payload_str_array;
194 static int hf_payload_str_union;
196 static int hf_payload_wtlv_tag;
197 static int hf_payload_wtlv_tag_res;
198 static int hf_payload_wtlv_tag_wire_type;
199 static int hf_payload_wtlv_tag_data_id;
201 static hf_register_info* dynamic_hf_param;
202 static unsigned dynamic_hf_param_size;
203 static hf_register_info* dynamic_hf_array;
204 static unsigned dynamic_hf_array_size;
205 static hf_register_info* dynamic_hf_struct;
206 static unsigned dynamic_hf_struct_size;
207 static hf_register_info* dynamic_hf_union;
208 static unsigned dynamic_hf_union_size;
210 static int ett_someip_tp_fragment;
211 static int ett_someip_tp_fragments;
212 static int ett_someip_payload;
213 static int ett_someip_string;
214 static int ett_someip_array;
215 static int ett_someip_array_dim;
216 static int ett_someip_struct;
217 static int ett_someip_union;
218 static int ett_someip_parameter;
219 static int ett_someip_wtlv_tag;
221 static const fragment_items someip_tp_frag_items = {
222 &ett_someip_tp_fragment,
223 &ett_someip_tp_fragments,
224 &hf_someip_tp_fragments,
225 &hf_someip_tp_fragment,
226 &hf_someip_tp_fragment_overlap,
227 &hf_someip_tp_fragment_overlap_conflicts,
228 &hf_someip_tp_fragment_multiple_tails,
229 &hf_someip_tp_fragment_too_long_fragment,
230 &hf_someip_tp_fragment_error,
231 &hf_someip_tp_fragment_count,
232 &hf_someip_tp_reassembled_in,
233 &hf_someip_tp_reassembled_length,
234 &hf_someip_tp_reassembled_data,
235 "SOME/IP-TP Segments"
238 static bool someip_tp_reassemble = true;
239 static bool someip_deserializer_activated = true;
240 static bool someip_deserializer_wtlv_default;
241 static bool someip_detect_dtls;
243 /* SOME/IP Message Types */
244 static const value_string someip_msg_type[] = {
245 {SOMEIP_MSGTYPE_REQUEST, "Request"},
246 {SOMEIP_MSGTYPE_REQUEST_NO_RESPONSE, "Request no response"},
247 {SOMEIP_MSGTYPE_NOTIFICATION, "Notification"},
248 {SOMEIP_MSGTYPE_RESPONSE, "Response"},
249 {SOMEIP_MSGTYPE_ERROR, "Error"},
250 {SOMEIP_MSGTYPE_REQUEST | SOMEIP_MSGTYPE_ACK_MASK, "Request Ack"},
251 {SOMEIP_MSGTYPE_REQUEST_NO_RESPONSE | SOMEIP_MSGTYPE_ACK_MASK, "Request no response Ack"},
252 {SOMEIP_MSGTYPE_NOTIFICATION | SOMEIP_MSGTYPE_ACK_MASK, "Notification Ack"},
253 {SOMEIP_MSGTYPE_RESPONSE | SOMEIP_MSGTYPE_ACK_MASK, "Response Ack"},
254 {SOMEIP_MSGTYPE_ERROR | SOMEIP_MSGTYPE_ACK_MASK, "Error Ack"},
255 {0, NULL}
258 /* SOME/IP Return Code */
259 static const value_string someip_return_code[] = {
260 {SOMEIP_RETCODE_OK, "Ok"},
261 {SOMEIP_RETCODE_NOT_OK, "Not Ok"},
262 {SOMEIP_RETCODE_UNKNOWN_SERVICE, "Unknown Service"},
263 {SOMEIP_RETCODE_UNKNOWN_METHOD, "Unknown Method/Event"},
264 {SOMEIP_RETCODE_NOT_READY, "Not Ready"},
265 {SOMEIP_RETCODE_NOT_REACHABLE, "Not Reachable (internal)"},
266 {SOMEIP_RETCODE_TIMEOUT, "Timeout (internal)"},
267 {SOMEIP_RETCODE_WRONG_PROTO_VER, "Wrong Protocol Version"},
268 {SOMEIP_RETCODE_WRONG_INTERFACE_VER, "Wrong Interface Version"},
269 {SOMEIP_RETCODE_MALFORMED_MSG, "Malformed Message"},
270 {SOMEIP_RETCODE_WRONG_MESSAGE_TYPE, "Wrong Message Type"},
271 {0, NULL}
274 /*** expert info items ***/
275 static expert_field ei_someip_unknown_version;
276 static expert_field ei_someip_message_truncated;
277 static expert_field ei_someip_incomplete_headers;
279 static expert_field ei_someip_payload_truncated;
280 static expert_field ei_someip_payload_malformed;
281 static expert_field ei_someip_payload_config_error;
282 static expert_field ei_someip_payload_alignment_error;
283 static expert_field ei_someip_payload_static_array_min_not_max;
284 static expert_field ei_someip_payload_dyn_array_not_within_limit;
286 /*** Data Structure for mapping IDs to Names (Services, Methods, ...) ***/
287 static GHashTable *data_someip_services;
288 static GHashTable *data_someip_methods;
289 static GHashTable *data_someip_eventgroups;
290 static GHashTable *data_someip_clients;
292 static GHashTable *data_someip_parameter_list;
293 static GHashTable *data_someip_parameter_base_type_list;
294 static GHashTable *data_someip_parameter_strings;
295 static GHashTable *data_someip_parameter_typedefs;
296 static GHashTable *data_someip_parameter_arrays;
297 static GHashTable *data_someip_parameter_structs;
298 static GHashTable *data_someip_parameter_unions;
299 static GHashTable *data_someip_parameter_enums;
301 /*** Taps ***/
302 static int tap_someip_messages = -1;
304 /*** Stats ***/
305 static const char *st_str_ip_src = "Source Addresses";
306 static const char *st_str_ip_dst = "Destination Addresses";
308 static int st_node_ip_src = -1;
309 static int st_node_ip_dst = -1;
311 /***********************************************
312 ********* Preferences / Configuration *********
313 ***********************************************/
315 typedef struct _someip_payload_parameter_item {
316 uint32_t pos;
317 char *name;
318 uint32_t data_type;
319 uint32_t id_ref;
320 int *hf_id;
321 char *filter_string;
322 } someip_payload_parameter_item_t;
324 #define INIT_SOMEIP_PAYLOAD_PARAMETER_ITEM(NAME) \
325 (NAME)->pos = 0; \
326 (NAME)->name = NULL; \
327 (NAME)->data_type = 0; \
328 (NAME)->id_ref = 0; \
329 (NAME)->hf_id = NULL; \
330 (NAME)->filter_string = NULL;
333 typedef struct _someip_payload_parameter_base_type_list {
334 uint32_t id;
335 char *name;
336 char *data_type;
337 bool big_endian;
338 uint32_t bitlength_base_type;
339 uint32_t bitlength_encoded_type;
340 } someip_payload_parameter_base_type_list_t;
342 #define INIT_COMMON_BASE_TYPE_LIST_ITEM(NAME) \
343 (NAME)->id = 0; \
344 (NAME)->name = NULL; \
345 (NAME)->data_type = NULL ; \
346 (NAME)->big_endian = true; \
347 (NAME)->bitlength_base_type = 0; \
348 (NAME)->bitlength_encoded_type = 0;
351 typedef struct _someip_payload_parameter_string {
352 uint32_t id;
353 char *name;
354 char *encoding;
355 bool dynamic_length;
356 uint32_t max_length;
357 uint32_t length_of_length; /* default: 32 */
358 bool big_endian;
359 uint32_t pad_to;
360 } someip_payload_parameter_string_t;
362 #define INIT_SOMEIP_PAYLOAD_PARAMETER_STRING(NAME) \
363 (NAME)->id = 0; \
364 (NAME)->name = NULL; \
365 (NAME)->encoding = NULL; \
366 (NAME)->dynamic_length = false; \
367 (NAME)->max_length = 0; \
368 (NAME)->length_of_length = 0; \
369 (NAME)->big_endian = true; \
370 (NAME)->pad_to = 0;
373 typedef struct _someip_payload_parameter_typedef {
374 uint32_t id;
375 char* name;
376 uint32_t data_type;
377 uint32_t id_ref;
378 } someip_payload_parameter_typedef_t;
380 #define INIT_SOMEIP_PAYLOAD_PARAMETER_TYPEDEF(NAME) \
381 (NAME)->id = 0; \
382 (NAME)->name = NULL; \
383 (NAME)->data_type = 0; \
384 (NAME)->id_ref = 0;
387 typedef struct _someip_payload_parameter_struct {
388 uint32_t id;
389 char *struct_name;
390 uint32_t length_of_length; /* default: 0 */
391 uint32_t pad_to; /* default: 0 */
392 bool wtlv_encoding;
393 uint32_t num_of_items;
395 /* array of items */
396 someip_payload_parameter_item_t *items;
397 } someip_payload_parameter_struct_t;
399 #define INIT_SOMEIP_PAYLOAD_PARAMETER_STRUCT(NAME) \
400 (NAME)->id = 0; \
401 (NAME)->struct_name = NULL; \
402 (NAME)->length_of_length = 0; \
403 (NAME)->pad_to = 0; \
404 (NAME)->wtlv_encoding = false; \
405 (NAME)->num_of_items = 0;
408 typedef struct _someip_payload_parameter_enum_item {
409 uint64_t value;
410 char *name;
411 } someip_payload_parameter_enum_item_t;
413 #define INIT_SOMEIP_PAYLOAD_PARAMETER_ENUM_ITEM(NAME) \
414 (NAME)->value = 0; \
415 (NAME)->name = NULL;
418 typedef struct _someip_payload_parameter_enum {
419 uint32_t id;
420 char *name;
421 uint32_t data_type;
422 uint32_t id_ref;
423 uint32_t num_of_items;
425 someip_payload_parameter_enum_item_t *items;
426 } someip_payload_parameter_enum_t;
428 #define INIT_SOMEIP_PAYLOAD_PARAMETER_ENUM(NAME) \
429 (NAME)->id = 0; \
430 (NAME)->name = NULL; \
431 (NAME)->data_type = 0; \
432 (NAME)->id_ref = 0; \
433 (NAME)->num_of_items = 0; \
434 (NAME)->items = NULL;
436 typedef struct _someip_parameter_union_item {
437 uint32_t id;
438 char *name;
439 uint32_t data_type;
440 uint32_t id_ref;
441 int *hf_id;
442 char *filter_string;
443 } someip_parameter_union_item_t;
445 typedef struct _someip_parameter_union {
446 uint32_t id;
447 char *name;
448 uint32_t length_of_length; /* default: 32 */
449 uint32_t length_of_type; /* default: 32 */
450 uint32_t pad_to; /* default: 0 */
451 uint32_t num_of_items;
453 someip_parameter_union_item_t *items;
454 } someip_parameter_union_t;
456 typedef struct _someip_parameter_union_uat {
457 uint32_t id;
458 char *name;
459 uint32_t length_of_length;
460 uint32_t length_of_type;
461 uint32_t pad_to;
462 uint32_t num_of_items;
463 uint32_t type_id;
464 char *type_name;
465 uint32_t data_type;
466 uint32_t id_ref;
467 char *filter_string;
468 } someip_parameter_union_uat_t;
470 typedef struct _someip_parameter_enum_uat {
471 uint32_t id;
472 char *name;
473 uint32_t data_type;
474 uint32_t id_ref;
475 uint32_t num_of_items;
476 uint32_t value;
477 char *value_name;
478 } someip_parameter_enum_uat_t;
480 typedef struct _someip_parameter_array_dim {
481 uint32_t num;
482 uint32_t lower_limit;
483 uint32_t upper_limit;
484 uint32_t length_of_length;
485 uint32_t pad_to;
486 } someip_parameter_array_dim_t;
488 typedef struct _someip_parameter_array {
489 uint32_t id;
490 char *name;
491 uint32_t data_type;
492 uint32_t id_ref;
493 uint32_t num_of_dims;
494 int *hf_id;
495 char *filter_string;
497 someip_parameter_array_dim_t *dims;
498 } someip_parameter_array_t;
500 typedef struct _someip_parameter_array_uat {
501 uint32_t id;
502 char *name;
503 uint32_t data_type;
504 uint32_t id_ref;
505 uint32_t num_of_dims;
506 char *filter_string;
508 uint32_t num;
509 uint32_t lower_limit;
510 uint32_t upper_limit;
511 uint32_t length_of_length;
512 uint32_t pad_to;
513 } someip_parameter_array_uat_t;
515 typedef struct _someip_parameter_list {
516 uint32_t service_id;
517 uint32_t method_id;
518 uint32_t version;
519 uint32_t message_type;
520 bool wtlv_encoding;
522 uint32_t num_of_items;
524 someip_payload_parameter_item_t *items;
525 } someip_parameter_list_t;
527 typedef struct _someip_parameter_list_uat {
528 uint32_t service_id;
529 uint32_t method_id;
530 uint32_t version;
531 uint32_t message_type;
532 bool wtlv_encoding;
534 uint32_t num_of_params;
536 uint32_t pos;
537 char *name;
538 uint32_t data_type;
539 uint32_t id_ref;
540 char *filter_string;
541 } someip_parameter_list_uat_t;
543 typedef struct _someip_parameter_struct_uat {
544 uint32_t id;
545 char *struct_name;
546 uint32_t length_of_length; /* default: 0 */
547 uint32_t pad_to; /* default: 0 */
548 bool wtlv_encoding;
550 uint32_t num_of_items;
552 uint32_t pos;
553 char *name;
554 uint32_t data_type;
555 uint32_t id_ref;
556 char *filter_string;
557 } someip_parameter_struct_uat_t;
559 typedef someip_payload_parameter_base_type_list_t someip_parameter_base_type_list_uat_t;
560 typedef someip_payload_parameter_string_t someip_parameter_string_uat_t;
561 typedef someip_payload_parameter_typedef_t someip_parameter_typedef_uat_t;
563 typedef struct _generic_one_id_string {
564 unsigned id;
565 char *name;
566 } generic_one_id_string_t;
568 typedef struct _generic_two_id_string {
569 unsigned id;
570 unsigned id2;
571 char *name;
572 } generic_two_id_string_t;
574 static generic_one_id_string_t *someip_service_ident;
575 static unsigned someip_service_ident_num;
577 static generic_two_id_string_t *someip_method_ident;
578 static unsigned someip_method_ident_num;
580 static generic_two_id_string_t *someip_eventgroup_ident;
581 static unsigned someip_eventgroup_ident_num;
583 static generic_two_id_string_t *someip_client_ident;
584 static unsigned someip_client_ident_num;
586 static someip_parameter_list_uat_t *someip_parameter_list;
587 static unsigned someip_parameter_list_num;
589 static someip_parameter_string_uat_t *someip_parameter_strings;
590 static unsigned someip_parameter_strings_num;
592 static someip_parameter_typedef_uat_t *someip_parameter_typedefs;
593 static unsigned someip_parameter_typedefs_num;
595 static someip_parameter_array_uat_t *someip_parameter_arrays;
596 static unsigned someip_parameter_arrays_num;
598 static someip_parameter_struct_uat_t *someip_parameter_structs;
599 static unsigned someip_parameter_structs_num;
601 static someip_parameter_union_uat_t *someip_parameter_unions;
602 static unsigned someip_parameter_unions_num;
604 static someip_parameter_enum_uat_t *someip_parameter_enums;
605 static unsigned someip_parameter_enums_num;
607 static someip_parameter_base_type_list_uat_t *someip_parameter_base_type_list;
608 static unsigned someip_parameter_base_type_list_num;
610 void proto_register_someip(void);
611 void proto_reg_handoff_someip(void);
613 static void deregister_dynamic_hf_data(hf_register_info **hf_array, unsigned *hf_size);
614 static void update_dynamic_hf_entries_someip_parameter_list(void);
615 static void update_dynamic_hf_entries_someip_parameter_arrays(void);
616 static void update_dynamic_hf_entries_someip_parameter_structs(void);
617 static void update_dynamic_hf_entries_someip_parameter_unions(void);
619 /* Segmentation support
620 * https://gitlab.com/wireshark/wireshark/-/issues/18880
622 typedef struct _someip_segment_key {
623 address src_addr;
624 address dst_addr;
625 uint32_t src_port;
626 uint32_t dst_port;
627 someip_info_t info;
628 } someip_segment_key;
630 static unsigned
631 someip_segment_hash(const void *k)
633 const someip_segment_key *key = (const someip_segment_key *)k;
634 unsigned hash_val;
636 hash_val = (key->info.service_id << 16 | key->info.method_id) ^
637 (key->info.client_id << 16 | key->info.session_id);
639 return hash_val;
642 static int
643 someip_segment_equal(const void *k1, const void *k2)
645 const someip_segment_key *key1 = (someip_segment_key *)k1;
646 const someip_segment_key *key2 = (someip_segment_key *)k2;
648 return (key1->info.session_id == key2->info.session_id) &&
649 (key1->info.service_id == key2->info.service_id) &&
650 (key1->info.client_id == key2->info.client_id) &&
651 (key1->info.method_id == key2->info.method_id) &&
652 (key1->info.message_type == key2->info.message_type) &&
653 (key1->info.major_version == key2->info.major_version) &&
654 (addresses_equal(&key1->src_addr, &key2->src_addr)) &&
655 (addresses_equal(&key1->dst_addr, &key2->dst_addr)) &&
656 (key1->src_port == key2->src_port) &&
657 (key1->dst_port == key2->dst_port);
661 * Create a fragment key for temporary use; it can point to non-
662 * persistent data, and so must only be used to look up and
663 * delete entries, not to add them.
665 static void *
666 someip_segment_temporary_key(const packet_info *pinfo, const uint32_t id _U_,
667 const void *data)
669 const someip_info_t *info = (const someip_info_t *)data;
670 someip_segment_key *key = g_slice_new(someip_segment_key);
672 /* Do a shallow copy of the addresses. */
673 copy_address_shallow(&key->src_addr, &pinfo->src);
674 copy_address_shallow(&key->dst_addr, &pinfo->dst);
675 key->src_port = pinfo->srcport;
676 key->dst_port = pinfo->destport;
677 memcpy(&key->info, info, sizeof(someip_info_t));
679 return (void *)key;
683 * Create a fragment key for permanent use; it must point to persistent
684 * data, so that it can be used to add entries.
686 static void *
687 someip_segment_persistent_key(const packet_info *pinfo,
688 const uint32_t id _U_, const void *data)
690 const someip_info_t *info = (const someip_info_t *)data;
691 someip_segment_key *key = g_slice_new(someip_segment_key);
693 /* Do a deep copy of the addresses. */
694 copy_address(&key->src_addr, &pinfo->src);
695 copy_address(&key->dst_addr, &pinfo->dst);
696 key->src_port = pinfo->srcport;
697 key->dst_port = pinfo->destport;
698 memcpy(&key->info, info, sizeof(someip_info_t));
700 return (void *)key;
703 static void
704 someip_segment_free_temporary_key(void *ptr)
706 someip_segment_key *key = (someip_segment_key *)ptr;
707 if (key) {
708 g_slice_free(someip_segment_key, key);
711 static void
712 someip_segment_free_persistent_key(void *ptr)
714 someip_segment_key *key = (someip_segment_key *)ptr;
715 if (key) {
716 /* Free up the copies of the addresses from the old key. */
717 free_address(&key->src_addr);
718 free_address(&key->dst_addr);
720 g_slice_free(someip_segment_key, key);
724 static const reassembly_table_functions
725 someip_reassembly_table_functions = {
726 someip_segment_hash,
727 someip_segment_equal,
728 someip_segment_temporary_key,
729 someip_segment_persistent_key,
730 someip_segment_free_temporary_key,
731 someip_segment_free_persistent_key
734 static reassembly_table someip_tp_reassembly_table;
737 /* register a UDP SOME/IP port */
738 void
739 register_someip_port_udp(uint32_t portnumber) {
740 dissector_add_uint("udp.port", portnumber, someip_handle_udp);
743 /* register a TCP SOME/IP port */
744 void
745 register_someip_port_tcp(uint32_t portnumber) {
746 dissector_add_uint("tcp.port", portnumber, someip_handle_tcp);
749 /*** UAT Callbacks and Helpers ***/
751 static void
752 set_prefs_changed(void) {
753 /* This ensures that proto_reg_handoff_someip is called, even if SOME/IP is not bound to any port yet. */
754 if (someip_module) {
755 someip_module->prefs_changed_flags |= (PREF_EFFECT_DISSECTION|PREF_EFFECT_FIELDS);
759 static char*
760 check_filter_string(char *filter_string, uint32_t id) {
761 char *err = NULL;
762 unsigned char c;
764 c = proto_check_field_name(filter_string);
765 if (c) {
766 if (c == '.') {
767 err = ws_strdup_printf("Filter String contains illegal chars '.' (ID: %i )", id);
768 } else if (g_ascii_isprint(c)) {
769 err = ws_strdup_printf("Filter String contains illegal chars '%c' (ID: %i)", c, id);
770 } else {
771 err = ws_strdup_printf("Filter String contains invalid byte \\%03o (ID: %i)", c, id);
775 return err;
778 static void
779 someip_free_key(void *key) {
780 wmem_free(wmem_epan_scope(), key);
783 static void
784 simple_free(void *data _U_) {
785 /* we need to free because of the g_strdup in post_update*/
786 g_free(data);
789 /* ID -> Name */
790 static void *
791 copy_generic_one_id_string_cb(void *n, const void *o, size_t size _U_) {
792 generic_one_id_string_t *new_rec = (generic_one_id_string_t *)n;
793 const generic_one_id_string_t *old_rec = (const generic_one_id_string_t *)o;
795 new_rec->name = g_strdup(old_rec->name);
796 new_rec->id = old_rec->id;
797 return new_rec;
800 static bool
801 update_serviceid(void *r, char **err) {
802 generic_one_id_string_t *rec = (generic_one_id_string_t *)r;
804 if (rec->id == 0xffff) {
805 *err = ws_strdup_printf("Service-ID 0xffff is reserved and cannot be used (ID: %i Name: %s)", rec->id, rec->name);
806 return false;
809 if (rec->id > 0xffff) {
810 *err = ws_strdup_printf("Service-IDs have to be 16bit (ID: %i Name: %s)", rec->id, rec->name);
811 return false;
814 if (rec->name == NULL || rec->name[0] == 0) {
815 *err = g_strdup("Name cannot be empty");
816 return false;
819 return true;
822 static void
823 free_generic_one_id_string_cb(void *r) {
824 generic_one_id_string_t *rec = (generic_one_id_string_t *)r;
826 /* freeing result of g_strdup */
827 g_free(rec->name);
828 rec->name = NULL;
831 static void
832 post_update_one_id_string_template_cb(generic_one_id_string_t *data, unsigned data_num, GHashTable *ht) {
833 unsigned i;
834 int *key = NULL;
836 for (i = 0; i < data_num; i++) {
837 key = wmem_new(wmem_epan_scope(), int);
838 *key = data[i].id;
840 g_hash_table_insert(ht, key, g_strdup(data[i].name));
844 /* ID/ID2 -> Name */
846 static void *
847 copy_generic_two_id_string_cb(void *n, const void *o, size_t size _U_) {
848 generic_two_id_string_t *new_rec = (generic_two_id_string_t *)n;
849 const generic_two_id_string_t *old_rec = (const generic_two_id_string_t *)o;
851 new_rec->name = g_strdup(old_rec->name);
852 new_rec->id = old_rec->id;
853 new_rec->id2 = old_rec->id2;
854 return new_rec;
857 static bool
858 update_two_identifier_16bit_check_both(void *r, char **err) {
859 generic_two_id_string_t *rec = (generic_two_id_string_t *)r;
861 if (rec->id == 0xffff) {
862 *err = ws_strdup_printf("Service-ID 0xffff is reserved and cannot be used (ID: %i Name: %s)", rec->id, rec->name);
863 return false;
866 if (rec->id > 0xffff) {
867 *err = ws_strdup_printf("Service-IDs have to be 16bit (ID: %i Name: %s)", rec->id, rec->name);
868 return false;
871 if (rec->id2 == 0xffff) {
872 *err = ws_strdup_printf("0xffff is reserved and cannot be used (ID: %i ID2: %i Name: %s)", rec->id, rec->id2, rec->name);
873 return false;
876 if (rec->id2 > 0xffff) {
877 *err = ws_strdup_printf("We currently only support 16 bit identifiers (ID: %i ID2: %i Name: %s)", rec->id, rec->id2, rec->name);
878 return false;
881 if (rec->name == NULL || rec->name[0] == 0) {
882 *err = g_strdup("Name cannot be empty");
883 return false;
886 return true;
889 static bool
890 update_generic_two_identifier_16bit(void *r, char **err) {
891 generic_two_id_string_t *rec = (generic_two_id_string_t *)r;
893 if (rec->id > 0xffff) {
894 *err = ws_strdup_printf("We currently only support 16 bit identifiers (ID: %i Name: %s)", rec->id, rec->name);
895 return false;
898 if (rec->id2 > 0xffff) {
899 *err = ws_strdup_printf("We currently only support 16 bit identifiers (ID: %i ID2: %i Name: %s)", rec->id, rec->id2, rec->name);
900 return false;
903 if (rec->name == NULL || rec->name[0] == 0) {
904 *err = g_strdup("Name cannot be empty");
905 return false;
908 return true;
911 static void
912 free_generic_two_id_string_cb(void *r) {
913 generic_two_id_string_t *rec = (generic_two_id_string_t *)r;
915 /* freeing result of g_strdup */
916 g_free(rec->name);
917 rec->name = NULL;
920 static void
921 post_update_generic_two_id_string_template_cb(generic_two_id_string_t *data, unsigned data_num, GHashTable *ht) {
922 unsigned i;
923 int *key = NULL;
924 unsigned tmp;
925 unsigned tmp2;
927 for (i = 0; i < data_num; i++) {
928 key = wmem_new(wmem_epan_scope(), int);
929 tmp = (data[i].id & 0xffff) << 16;
930 tmp2 = (data[i].id2 & 0xffff);
932 /* the hash table does not know about uint32, so we use int32 */
933 *key = (int)(tmp + tmp2);
935 g_hash_table_insert(ht, key, g_strdup(data[i].name));
939 char *
940 someip_lookup_service_name(uint16_t serviceid) {
941 uint32_t tmp = (uint32_t)serviceid;
943 if (data_someip_services == NULL) {
944 return NULL;
947 return (char *)g_hash_table_lookup(data_someip_services, &tmp);
950 static char *
951 someip_lookup_method_name(uint16_t serviceid, uint16_t methodid) {
952 uint32_t tmp = (serviceid << 16) + methodid;
954 if (data_someip_methods == NULL) {
955 return NULL;
958 return (char *)g_hash_table_lookup(data_someip_methods, &tmp);
961 char *
962 someip_lookup_eventgroup_name(uint16_t serviceid, uint16_t eventgroupid) {
963 uint32_t tmp = (serviceid << 16) + eventgroupid;
965 if (data_someip_eventgroups == NULL) {
966 return NULL;
969 return (char *)g_hash_table_lookup(data_someip_eventgroups, &tmp);
972 static char *
973 someip_lookup_client_name(uint16_t serviceid, uint16_t clientid) {
974 uint32_t tmp = (serviceid << 16) + clientid;
976 if (data_someip_clients == NULL) {
977 return NULL;
980 return (char *)g_hash_table_lookup(data_someip_clients, &tmp);
984 /*** SOME/IP Services ***/
985 UAT_HEX_CB_DEF (someip_service_ident, id, generic_one_id_string_t)
986 UAT_CSTRING_CB_DEF (someip_service_ident, name, generic_one_id_string_t)
988 static void
989 reset_someip_service_cb(void) {
990 /* destroy old hash table, if it exists */
991 if (data_someip_services) {
992 g_hash_table_destroy(data_someip_services);
993 data_someip_services = NULL;
997 static void
998 post_update_someip_service_cb(void) {
999 reset_someip_service_cb();
1001 /* create new hash table */
1002 data_someip_services = g_hash_table_new_full(g_int_hash, g_int_equal, &someip_free_key, &simple_free);
1003 post_update_one_id_string_template_cb(someip_service_ident, someip_service_ident_num, data_someip_services);
1007 /*** SOME/IP Methods/Events/Fields ***/
1008 UAT_HEX_CB_DEF (someip_method_ident, id, generic_two_id_string_t)
1009 UAT_HEX_CB_DEF (someip_method_ident, id2, generic_two_id_string_t)
1010 UAT_CSTRING_CB_DEF (someip_method_ident, name, generic_two_id_string_t)
1012 static void
1013 reset_someip_method_cb(void) {
1014 /* destroy old hash table, if it exists */
1015 if (data_someip_methods) {
1016 g_hash_table_destroy(data_someip_methods);
1017 data_someip_methods = NULL;
1021 static void
1022 post_update_someip_method_cb(void) {
1023 reset_someip_method_cb();
1025 /* create new hash table */
1026 data_someip_methods = g_hash_table_new_full(g_int_hash, g_int_equal, &someip_free_key, &simple_free);
1027 post_update_generic_two_id_string_template_cb(someip_method_ident, someip_method_ident_num, data_someip_methods);
1031 /*** SOME/IP Eventgroups ***/
1032 UAT_HEX_CB_DEF (someip_eventgroup_ident, id, generic_two_id_string_t)
1033 UAT_HEX_CB_DEF (someip_eventgroup_ident, id2, generic_two_id_string_t)
1034 UAT_CSTRING_CB_DEF (someip_eventgroup_ident, name, generic_two_id_string_t)
1036 static void
1037 reset_someip_eventgroup_cb(void) {
1038 /* destroy old hash table, if it exists */
1039 if (data_someip_eventgroups) {
1040 g_hash_table_destroy(data_someip_eventgroups);
1041 data_someip_eventgroups = NULL;
1045 static void
1046 post_update_someip_eventgroup_cb(void) {
1047 reset_someip_eventgroup_cb();
1049 /* create new hash table */
1050 data_someip_eventgroups = g_hash_table_new_full(g_int_hash, g_int_equal, &someip_free_key, &simple_free);
1051 post_update_generic_two_id_string_template_cb(someip_eventgroup_ident, someip_eventgroup_ident_num, data_someip_eventgroups);
1055 /*** SOME/IP Clients ***/
1056 UAT_HEX_CB_DEF(someip_client_ident, id, generic_two_id_string_t)
1057 UAT_HEX_CB_DEF(someip_client_ident, id2, generic_two_id_string_t)
1058 UAT_CSTRING_CB_DEF(someip_client_ident, name, generic_two_id_string_t)
1060 static void
1061 reset_someip_client_cb(void) {
1062 /* destroy old hash table, if it exists */
1063 if (data_someip_clients) {
1064 g_hash_table_destroy(data_someip_clients);
1065 data_someip_clients = NULL;
1069 static void
1070 post_update_someip_client_cb(void) {
1071 reset_someip_client_cb();
1073 /* create new hash table */
1074 data_someip_clients = g_hash_table_new_full(g_int_hash, g_int_equal, &someip_free_key, &simple_free);
1075 post_update_generic_two_id_string_template_cb(someip_client_ident, someip_client_ident_num, data_someip_clients);
1078 static void
1079 someip_payload_free_key(void *key) {
1080 wmem_free(wmem_epan_scope(), key);
1083 static int64_t
1084 someip_parameter_key(uint16_t serviceid, uint16_t methodid, uint8_t version, uint8_t msgtype) {
1085 int64_t tmp1;
1086 int64_t tmp2;
1087 int64_t tmp3;
1088 int64_t tmp4;
1090 /* key:
1091 Service-ID [16bit] | Method-ID [16bit] | Version [8bit] | Message-Type [8bit]
1094 tmp1 = (int64_t)(serviceid & 0xffff);
1095 tmp2 = (int64_t)(methodid & 0xffff) << 16;
1096 tmp3 = (int64_t)(version & 0xff) << 32;
1097 tmp4 = (int64_t)(msgtype & 0xff) << 40;
1099 return (int64_t)(tmp1 + tmp2 + tmp3 + tmp4);
1102 static someip_parameter_list_t*
1103 get_parameter_config(uint16_t serviceid, uint16_t methodid, uint8_t version, uint8_t msgtype) {
1104 int64_t *key = NULL;
1105 someip_parameter_list_t *tmp = NULL;
1107 if (data_someip_parameter_list == NULL) {
1108 return NULL;
1111 key = wmem_new(wmem_epan_scope(), int64_t);
1112 *key = someip_parameter_key(serviceid, methodid, version, msgtype);
1113 tmp = (someip_parameter_list_t *)g_hash_table_lookup(data_someip_parameter_list, key);
1114 wmem_free(wmem_epan_scope(), key);
1116 return tmp;
1119 static void *
1120 get_generic_config(GHashTable *ht, int64_t id) {
1121 if (ht == NULL) {
1122 return NULL;
1125 return (void *)g_hash_table_lookup(ht, &id);
1128 static someip_payload_parameter_base_type_list_t*
1129 get_base_type_config(uint32_t id) {
1130 return (someip_payload_parameter_base_type_list_t *)get_generic_config(data_someip_parameter_base_type_list, (int64_t)id);
1133 static someip_payload_parameter_string_t*
1134 get_string_config(uint32_t id) {
1135 return (someip_payload_parameter_string_t *)get_generic_config(data_someip_parameter_strings, (int64_t)id);
1138 static someip_payload_parameter_typedef_t*
1139 get_typedef_config(uint32_t id) {
1140 return (someip_payload_parameter_typedef_t *)get_generic_config(data_someip_parameter_typedefs, (int64_t)id);
1143 static someip_parameter_array_t*
1144 get_array_config(uint32_t id) {
1145 return (someip_parameter_array_t *)get_generic_config(data_someip_parameter_arrays, (int64_t)id);
1148 static someip_payload_parameter_struct_t*
1149 get_struct_config(uint32_t id) {
1150 return (someip_payload_parameter_struct_t *)get_generic_config(data_someip_parameter_structs, (int64_t)id);
1153 static someip_parameter_union_t*
1154 get_union_config(uint32_t id) {
1155 return (someip_parameter_union_t *)get_generic_config(data_someip_parameter_unions, (int64_t)id);
1158 static someip_payload_parameter_enum_t*
1159 get_enum_config(uint32_t id) {
1160 return (someip_payload_parameter_enum_t *)get_generic_config(data_someip_parameter_enums, (int64_t)id);
1163 UAT_HEX_CB_DEF(someip_parameter_list, service_id, someip_parameter_list_uat_t)
1164 UAT_HEX_CB_DEF(someip_parameter_list, method_id, someip_parameter_list_uat_t)
1165 UAT_DEC_CB_DEF(someip_parameter_list, version, someip_parameter_list_uat_t)
1166 UAT_HEX_CB_DEF(someip_parameter_list, message_type, someip_parameter_list_uat_t)
1167 UAT_BOOL_CB_DEF(someip_parameter_list, wtlv_encoding, someip_parameter_list_uat_t)
1169 UAT_DEC_CB_DEF(someip_parameter_list, num_of_params, someip_parameter_list_uat_t)
1171 UAT_DEC_CB_DEF(someip_parameter_list, pos, someip_parameter_list_uat_t)
1172 UAT_CSTRING_CB_DEF(someip_parameter_list, name, someip_parameter_list_uat_t)
1173 UAT_DEC_CB_DEF(someip_parameter_list, data_type, someip_parameter_list_uat_t)
1174 UAT_HEX_CB_DEF(someip_parameter_list, id_ref, someip_parameter_list_uat_t)
1175 UAT_CSTRING_CB_DEF(someip_parameter_list, filter_string, someip_parameter_list_uat_t)
1177 static void *
1178 copy_someip_parameter_list_cb(void *n, const void *o, size_t size _U_) {
1179 someip_parameter_list_uat_t *new_rec = (someip_parameter_list_uat_t *)n;
1180 const someip_parameter_list_uat_t *old_rec = (const someip_parameter_list_uat_t *)o;
1182 if (old_rec->name) {
1183 new_rec->name = g_strdup(old_rec->name);
1184 } else {
1185 new_rec->name = NULL;
1188 if (old_rec->filter_string) {
1189 new_rec->filter_string = g_strdup(old_rec->filter_string);
1190 } else {
1191 new_rec->filter_string = NULL;
1194 new_rec->service_id = old_rec->service_id;
1195 new_rec->method_id = old_rec->method_id;
1196 new_rec->version = old_rec->version;
1197 new_rec->message_type = old_rec->message_type;
1198 new_rec->wtlv_encoding = old_rec->wtlv_encoding;
1199 new_rec->num_of_params = old_rec->num_of_params;
1200 new_rec->pos = old_rec->pos;
1201 new_rec->data_type = old_rec->data_type;
1202 new_rec->id_ref = old_rec->id_ref;
1204 return new_rec;
1207 static bool
1208 update_someip_parameter_list(void *r, char **err) {
1209 someip_parameter_list_uat_t *rec = (someip_parameter_list_uat_t *)r;
1210 unsigned char c;
1212 if (rec->service_id > 0xffff) {
1213 *err = ws_strdup_printf("We currently only support 16 bit Service IDs (Service-ID: %i Name: %s)", rec->service_id, rec->name);
1214 return false;
1217 if (rec->method_id > 0xffff) {
1218 *err = ws_strdup_printf("We currently only support 16 bit Method IDs (Service-ID: %i Method-ID: %i Name: %s)", rec->service_id, rec->method_id, rec->name);
1219 return false;
1222 if (rec->version > 0xff) {
1223 *err = ws_strdup_printf("We currently only support 8 bit Version (Service-ID: %i Method-ID: %i Version: %d Name: %s)", rec->service_id, rec->method_id, rec->version, rec->name);
1224 return false;
1227 if (rec->message_type > 0xff) {
1228 *err = ws_strdup_printf("We currently only support 8 bit Message Type (Service-ID: %i Method-ID: %i Version: %d Message Type: %x Name: %s)", rec->service_id, rec->method_id, rec->version, rec->message_type, rec->name);
1229 return false;
1232 if (rec->name == NULL || rec->name[0] == 0) {
1233 *err = ws_strdup_printf("Name cannot be empty");
1234 return false;
1237 if (rec->pos >= rec->num_of_params) {
1238 *err = ws_strdup_printf("Position >= Number of Parameters");
1239 return false;
1242 if (rec->filter_string == NULL || rec->filter_string[0] == 0) {
1243 *err = ws_strdup_printf("Name cannot be empty");
1244 return false;
1247 c = proto_check_field_name(rec->filter_string);
1248 if (c) {
1249 if (c == '.') {
1250 *err = ws_strdup_printf("Filter String contains illegal chars '.' (Service-ID: %i Method-ID: %i)", rec->service_id, rec->method_id);
1251 } else if (g_ascii_isprint(c)) {
1252 *err = ws_strdup_printf("Filter String contains illegal chars '%c' (Service-ID: %i Method-ID: %i)", c, rec->service_id, rec->method_id);
1253 } else {
1254 *err = ws_strdup_printf("Filter String contains invalid byte \\%03o (Service-ID: %i Method-ID: %i)", c, rec->service_id, rec->method_id);
1256 return false;
1259 return true;
1262 static void
1263 free_someip_parameter_list_cb(void *r) {
1264 someip_parameter_list_uat_t *rec = (someip_parameter_list_uat_t *)r;
1266 if (rec->name) {
1267 g_free(rec->name);
1268 rec->name = NULL;
1271 if (rec->filter_string) {
1272 g_free(rec->filter_string);
1273 rec->filter_string = NULL;
1277 static void
1278 free_someip_parameter_list(void *data) {
1279 someip_parameter_list_t *list = (someip_parameter_list_t *)data;
1281 if (list->items != NULL) {
1282 wmem_free(wmem_epan_scope(), (void *)(list->items));
1283 list->items = NULL;
1286 wmem_free(wmem_epan_scope(), (void *)data);
1289 static void
1290 post_update_someip_parameter_list_read_in_data(someip_parameter_list_uat_t *data, unsigned data_num, GHashTable *ht) {
1291 unsigned i = 0;
1292 int64_t *key = NULL;
1293 someip_parameter_list_t *list = NULL;
1294 someip_payload_parameter_item_t *item = NULL;
1295 someip_payload_parameter_item_t *items = NULL;
1297 if (ht == NULL || data == NULL || data_num == 0) {
1298 return;
1301 for (i = 0; i < data_num; i++) {
1302 /* the hash table does not know about uint64, so we use int64*/
1303 key = wmem_new(wmem_epan_scope(), int64_t);
1304 *key = someip_parameter_key((uint16_t)data[i].service_id, (uint16_t)data[i].method_id, (uint8_t)data[i].version, (uint8_t)data[i].message_type);
1306 list = (someip_parameter_list_t *)g_hash_table_lookup(ht, key);
1307 if (list == NULL) {
1309 list = wmem_new(wmem_epan_scope(), someip_parameter_list_t);
1311 list->service_id = data[i].service_id;
1312 list->method_id = data[i].method_id;
1313 list->version = data[i].version;
1314 list->message_type = data[i].message_type;
1315 list->wtlv_encoding = data[i].wtlv_encoding;
1316 list->num_of_items = data[i].num_of_params;
1318 items = (someip_payload_parameter_item_t *)wmem_alloc0_array(wmem_epan_scope(), someip_payload_parameter_item_t, data[i].num_of_params);
1319 list->items = items;
1321 /* create new entry ... */
1322 g_hash_table_insert(ht, key, list);
1323 } else {
1324 /* already present, deleting key */
1325 wmem_free(wmem_epan_scope(), key);
1328 /* and now we add to item array */
1329 if (data[i].num_of_params == list->num_of_items && data[i].pos < list->num_of_items) {
1330 item = &(list->items[data[i].pos]);
1332 /* we do not care if we overwrite param */
1333 item->name = data[i].name;
1334 item->id_ref = data[i].id_ref;
1335 item->pos = data[i].pos;
1336 item->data_type = data[i].data_type;
1337 item->filter_string = data[i].filter_string;
1342 static void
1343 reset_someip_parameter_list_cb(void) {
1344 /* destroy old hash table, if it exists */
1345 if (data_someip_parameter_list) {
1346 deregister_dynamic_hf_data(&dynamic_hf_param, &dynamic_hf_param_size);
1347 g_hash_table_destroy(data_someip_parameter_list);
1348 data_someip_parameter_list = NULL;
1351 set_prefs_changed();
1354 static void
1355 post_update_someip_parameter_list_cb(void) {
1356 reset_someip_parameter_list_cb();
1358 data_someip_parameter_list = g_hash_table_new_full(g_int64_hash, g_int64_equal, &someip_payload_free_key, &free_someip_parameter_list);
1359 post_update_someip_parameter_list_read_in_data(someip_parameter_list, someip_parameter_list_num, data_someip_parameter_list);
1362 UAT_HEX_CB_DEF(someip_parameter_enums, id, someip_parameter_enum_uat_t)
1363 UAT_CSTRING_CB_DEF(someip_parameter_enums, name, someip_parameter_enum_uat_t)
1364 UAT_DEC_CB_DEF(someip_parameter_enums, data_type, someip_parameter_enum_uat_t)
1365 UAT_HEX_CB_DEF(someip_parameter_enums, id_ref, someip_parameter_enum_uat_t)
1366 UAT_DEC_CB_DEF(someip_parameter_enums, num_of_items, someip_parameter_enum_uat_t)
1368 UAT_HEX_CB_DEF(someip_parameter_enums, value, someip_parameter_enum_uat_t)
1369 UAT_CSTRING_CB_DEF(someip_parameter_enums, value_name, someip_parameter_enum_uat_t)
1371 static void *
1372 copy_someip_parameter_enum_cb(void *n, const void *o, size_t size _U_) {
1373 someip_parameter_enum_uat_t *new_rec = (someip_parameter_enum_uat_t *)n;
1374 const someip_parameter_enum_uat_t *old_rec = (const someip_parameter_enum_uat_t *)o;
1376 new_rec->id = old_rec->id;
1377 if (old_rec->name) {
1378 new_rec->name = g_strdup(old_rec->name);
1379 } else {
1380 new_rec->name = NULL;
1382 new_rec->data_type = old_rec->data_type;
1383 new_rec->id_ref = old_rec->id_ref;
1384 new_rec->num_of_items = old_rec->num_of_items;
1386 new_rec->value = old_rec->value;
1387 if (old_rec->value_name) {
1388 new_rec->value_name = g_strdup(old_rec->value_name);
1389 } else {
1390 new_rec->value_name = NULL;
1393 return new_rec;
1396 static bool
1397 update_someip_parameter_enum(void *r, char **err) {
1398 someip_parameter_enum_uat_t *rec = (someip_parameter_enum_uat_t *)r;
1400 /* enum name is not used in a filter yet. */
1402 if (rec->name == NULL || rec->name[0] == 0) {
1403 *err = ws_strdup_printf("Name cannot be empty (ID: 0x%x)!", rec->id);
1404 return false;
1407 if (rec->value_name == NULL || rec->value_name[0] == 0) {
1408 *err = ws_strdup_printf("Value Name cannot be empty (ID: 0x%x)!", rec->id);
1409 return false;
1412 if (rec->num_of_items == 0) {
1413 *err = ws_strdup_printf("Number_of_Items = 0 (ID: 0x%x)!", rec->id);
1414 return false;
1417 if (rec->data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ENUM) {
1418 *err = ws_strdup_printf("An enum cannot reference an enum (ID: 0x%x)!", rec->id);
1419 return false;
1422 return true;
1425 static void
1426 free_someip_parameter_enum_cb(void *r) {
1427 someip_parameter_enum_uat_t *rec = (someip_parameter_enum_uat_t *)r;
1428 if (rec->name) {
1429 g_free(rec->name);
1430 rec->name = NULL;
1433 if (rec->value_name) {
1434 g_free(rec->value_name);
1435 rec->value_name = NULL;
1439 static void
1440 free_someip_parameter_enum(void *data) {
1441 someip_payload_parameter_enum_t *list = (someip_payload_parameter_enum_t *)data;
1443 if (list->items != NULL) {
1444 wmem_free(wmem_epan_scope(), (void *)(list->items));
1445 list->items = NULL;
1448 wmem_free(wmem_epan_scope(), (void *)data);
1451 static void
1452 post_update_someip_parameter_enum_read_in_data(someip_parameter_enum_uat_t *data, unsigned data_num, GHashTable *ht) {
1453 unsigned i = 0;
1454 unsigned j = 0;
1455 int64_t *key = NULL;
1456 someip_payload_parameter_enum_t *list = NULL;
1457 someip_payload_parameter_enum_item_t *item = NULL;
1459 if (ht == NULL || data == NULL || data_num == 0) {
1460 return;
1463 for (i = 0; i < data_num; i++) {
1464 key = wmem_new(wmem_epan_scope(), int64_t);
1465 *key = data[i].id;
1467 list = (someip_payload_parameter_enum_t *)g_hash_table_lookup(ht, key);
1468 if (list == NULL) {
1470 list = wmem_new(wmem_epan_scope(), someip_payload_parameter_enum_t);
1471 INIT_SOMEIP_PAYLOAD_PARAMETER_ENUM(list)
1473 list->id = data[i].id;
1474 list->name = data[i].name;
1475 list->data_type = data[i].data_type;
1476 list->id_ref = data[i].id_ref;
1477 list->num_of_items = data[i].num_of_items;
1479 list->items = (someip_payload_parameter_enum_item_t *)wmem_alloc0_array(wmem_epan_scope(), someip_payload_parameter_enum_item_t, list->num_of_items);
1481 /* create new entry ... */
1482 g_hash_table_insert(ht, key, list);
1483 } else {
1484 /* don't need it anymore */
1485 wmem_free(wmem_epan_scope(), key);
1488 /* and now we add to item array */
1489 if (list->num_of_items > 0 && data[i].num_of_items == list->num_of_items) {
1491 /* find first empty slot */
1492 for (j = 0; j < list->num_of_items && list->items[j].name != NULL; j++);
1494 if (j < list->num_of_items) {
1495 item = &(list->items[j]);
1496 INIT_SOMEIP_PAYLOAD_PARAMETER_ENUM_ITEM(item)
1498 /* we do not care if we overwrite param */
1499 item->value = data[i].value;
1500 item->name = data[i].value_name;
1506 static void
1507 reset_someip_parameter_enum_cb(void) {
1508 /* destroy old hash table, if it exists */
1509 if (data_someip_parameter_enums) {
1510 g_hash_table_destroy(data_someip_parameter_enums);
1511 data_someip_parameter_enums = NULL;
1514 set_prefs_changed();
1517 static void
1518 post_update_someip_parameter_enum_cb(void) {
1519 reset_someip_parameter_enum_cb();
1521 data_someip_parameter_enums = g_hash_table_new_full(g_int64_hash, g_int64_equal, &someip_payload_free_key, &free_someip_parameter_enum);
1522 post_update_someip_parameter_enum_read_in_data(someip_parameter_enums, someip_parameter_enums_num, data_someip_parameter_enums);
1525 UAT_HEX_CB_DEF(someip_parameter_arrays, id, someip_parameter_array_uat_t)
1526 UAT_CSTRING_CB_DEF(someip_parameter_arrays, name, someip_parameter_array_uat_t)
1527 UAT_DEC_CB_DEF(someip_parameter_arrays, data_type, someip_parameter_array_uat_t)
1528 UAT_HEX_CB_DEF(someip_parameter_arrays, id_ref, someip_parameter_array_uat_t)
1529 UAT_DEC_CB_DEF(someip_parameter_arrays, num_of_dims, someip_parameter_array_uat_t)
1530 UAT_CSTRING_CB_DEF(someip_parameter_arrays, filter_string, someip_parameter_array_uat_t)
1532 UAT_DEC_CB_DEF(someip_parameter_arrays, num, someip_parameter_array_uat_t)
1533 UAT_DEC_CB_DEF(someip_parameter_arrays, lower_limit, someip_parameter_array_uat_t)
1534 UAT_DEC_CB_DEF(someip_parameter_arrays, upper_limit, someip_parameter_array_uat_t)
1535 UAT_DEC_CB_DEF(someip_parameter_arrays, length_of_length, someip_parameter_array_uat_t)
1536 UAT_DEC_CB_DEF(someip_parameter_arrays, pad_to, someip_parameter_array_uat_t)
1538 static void *
1539 copy_someip_parameter_array_cb(void *n, const void *o, size_t size _U_) {
1540 someip_parameter_array_uat_t *new_rec = (someip_parameter_array_uat_t *)n;
1541 const someip_parameter_array_uat_t *old_rec = (const someip_parameter_array_uat_t *)o;
1543 new_rec->id = old_rec->id;
1544 if (old_rec->name) {
1545 new_rec->name = g_strdup(old_rec->name);
1546 } else {
1547 new_rec->name = NULL;
1549 new_rec->data_type = old_rec->data_type;
1550 new_rec->id_ref = old_rec->id_ref;
1551 new_rec->num_of_dims = old_rec->num_of_dims;
1552 if (old_rec->filter_string) {
1553 new_rec->filter_string = g_strdup(old_rec->filter_string);
1554 } else {
1555 new_rec->filter_string = NULL;
1558 new_rec->num = old_rec->num;
1559 new_rec->lower_limit = old_rec->lower_limit;
1560 new_rec->upper_limit = old_rec->upper_limit;
1561 new_rec->length_of_length = old_rec->length_of_length;
1562 new_rec->pad_to = old_rec->pad_to;
1564 return new_rec;
1567 static bool
1568 update_someip_parameter_array(void *r, char **err) {
1569 someip_parameter_array_uat_t *rec = (someip_parameter_array_uat_t *)r;
1570 char *tmp;
1572 if (rec->name == NULL || rec->name[0] == 0) {
1573 *err = ws_strdup_printf("Name cannot be empty (ID: 0x%x)!", rec->id);
1574 return false;
1577 if (rec->num >= rec->num_of_dims) {
1578 *err = ws_strdup_printf("Dimension >= Number of Dimensions (ID: 0x%x)!", rec->id);
1579 return false;
1582 if (rec->filter_string == NULL || rec->filter_string[0] == 0) {
1583 *err = ws_strdup_printf("Filter String cannot be empty (ID: 0x%x)!", rec->id);
1584 return false;
1587 tmp = check_filter_string(rec->filter_string, rec->id);
1588 if (tmp != NULL) {
1589 *err = tmp;
1590 return false;
1593 if (rec->data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ARRAY && rec->id == rec->id_ref) {
1594 *err = ws_strdup_printf("An array cannot include itself (ID: 0x%x)!", rec->id);
1595 return false;
1598 return true;
1601 static void
1602 free_someip_parameter_array_cb(void *r) {
1603 someip_parameter_array_uat_t *rec = (someip_parameter_array_uat_t *)r;
1605 if (rec->name) g_free(rec->name);
1606 rec->name = NULL;
1608 if (rec->filter_string) g_free(rec->filter_string);
1609 rec->filter_string = NULL;
1612 static void
1613 free_someip_parameter_array(void *data) {
1614 someip_parameter_array_t *list = (someip_parameter_array_t *)data;
1616 if (list->dims != NULL) {
1617 wmem_free(wmem_epan_scope(), (void *)(list->dims));
1618 list->dims = NULL;
1621 wmem_free(wmem_epan_scope(), (void *)data);
1624 static void
1625 post_update_someip_parameter_array_read_in_data(someip_parameter_array_uat_t *data, unsigned data_num, GHashTable *ht) {
1626 unsigned i = 0;
1627 int64_t *key = NULL;
1628 someip_parameter_array_t *list = NULL;
1629 someip_parameter_array_dim_t *item = NULL;
1630 someip_parameter_array_dim_t *items = NULL;
1632 if (ht == NULL || data == NULL || data_num == 0) {
1633 return;
1636 for (i = 0; i < data_num; i++) {
1637 key = wmem_new(wmem_epan_scope(), int64_t);
1638 *key = data[i].id;
1640 list = (someip_parameter_array_t *)g_hash_table_lookup(ht, key);
1641 if (list == NULL) {
1643 list = wmem_new(wmem_epan_scope(), someip_parameter_array_t);
1645 list->id = data[i].id;
1646 list->name = data[i].name;
1647 list->data_type = data[i].data_type;
1648 list->id_ref = data[i].id_ref;
1649 list->num_of_dims = data[i].num_of_dims;
1650 list->filter_string = data[i].filter_string;
1652 items = (someip_parameter_array_dim_t *)wmem_alloc0_array(wmem_epan_scope(), someip_parameter_array_dim_t, data[i].num_of_dims);
1653 list->dims = items;
1655 /* create new entry ... */
1656 g_hash_table_insert(ht, key, list);
1659 /* and now we add to item array */
1660 if (data[i].num_of_dims == list->num_of_dims && data[i].num < list->num_of_dims) {
1661 item = &(list->dims[data[i].num]);
1663 /* we do not care if we overwrite param */
1664 item->num = data[i].num;
1665 item->lower_limit = data[i].lower_limit;
1666 item->upper_limit = data[i].upper_limit;
1667 item->length_of_length = data[i].length_of_length;
1668 item->pad_to = data[i].pad_to;
1673 static void
1674 reset_someip_parameter_array_cb(void) {
1675 /* destroy old hash table, if it exists */
1676 if (data_someip_parameter_arrays) {
1677 deregister_dynamic_hf_data(&dynamic_hf_array, &dynamic_hf_array_size);
1678 g_hash_table_destroy(data_someip_parameter_arrays);
1679 data_someip_parameter_arrays = NULL;
1682 set_prefs_changed();
1685 static void
1686 post_update_someip_parameter_array_cb(void) {
1687 reset_someip_parameter_array_cb();
1689 data_someip_parameter_arrays = g_hash_table_new_full(g_int64_hash, g_int64_equal, &someip_payload_free_key, &free_someip_parameter_array);
1690 post_update_someip_parameter_array_read_in_data(someip_parameter_arrays, someip_parameter_arrays_num, data_someip_parameter_arrays);
1693 UAT_HEX_CB_DEF(someip_parameter_structs, id, someip_parameter_struct_uat_t)
1694 UAT_CSTRING_CB_DEF(someip_parameter_structs, struct_name, someip_parameter_struct_uat_t)
1695 UAT_DEC_CB_DEF(someip_parameter_structs, length_of_length, someip_parameter_struct_uat_t)
1696 UAT_DEC_CB_DEF(someip_parameter_structs, pad_to, someip_parameter_struct_uat_t)
1697 UAT_BOOL_CB_DEF(someip_parameter_structs, wtlv_encoding, someip_parameter_struct_uat_t)
1698 UAT_DEC_CB_DEF(someip_parameter_structs, num_of_items, someip_parameter_struct_uat_t)
1700 UAT_DEC_CB_DEF(someip_parameter_structs, pos, someip_parameter_struct_uat_t)
1701 UAT_CSTRING_CB_DEF(someip_parameter_structs, name, someip_parameter_struct_uat_t)
1702 UAT_DEC_CB_DEF(someip_parameter_structs, data_type, someip_parameter_struct_uat_t)
1703 UAT_HEX_CB_DEF(someip_parameter_structs, id_ref, someip_parameter_struct_uat_t)
1704 UAT_CSTRING_CB_DEF(someip_parameter_structs, filter_string, someip_parameter_struct_uat_t)
1706 static void *
1707 copy_someip_parameter_struct_cb(void *n, const void *o, size_t size _U_) {
1708 someip_parameter_struct_uat_t *new_rec = (someip_parameter_struct_uat_t *)n;
1709 const someip_parameter_struct_uat_t *old_rec = (const someip_parameter_struct_uat_t *)o;
1711 new_rec->id = old_rec->id;
1713 if (old_rec->struct_name) {
1714 new_rec->struct_name = g_strdup(old_rec->struct_name);
1715 } else {
1716 new_rec->struct_name = NULL;
1719 new_rec->length_of_length = old_rec->length_of_length;
1720 new_rec->pad_to = old_rec->pad_to;
1721 new_rec->wtlv_encoding = old_rec->wtlv_encoding;
1722 new_rec->num_of_items = old_rec->num_of_items;
1724 new_rec->pos = old_rec->pos;
1726 if (old_rec->name) {
1727 new_rec->name = g_strdup(old_rec->name);
1728 } else {
1729 new_rec->name = NULL;
1732 new_rec->data_type = old_rec->data_type;
1733 new_rec->id_ref = old_rec->id_ref;
1735 if (old_rec->filter_string) {
1736 new_rec->filter_string = g_strdup(old_rec->filter_string);
1737 } else {
1738 new_rec->filter_string = NULL;
1741 return new_rec;
1744 static bool
1745 update_someip_parameter_struct(void *r, char **err) {
1746 someip_parameter_struct_uat_t *rec = (someip_parameter_struct_uat_t *)r;
1747 char *tmp = NULL;
1749 if (rec->struct_name == NULL || rec->struct_name[0] == 0) {
1750 *err = ws_strdup_printf("Struct name cannot be empty (ID: 0x%x)!", rec->id);
1751 return false;
1754 if (rec->filter_string == NULL || rec->filter_string[0] == 0) {
1755 *err = ws_strdup_printf("Struct name cannot be empty (ID: 0x%x)!", rec->id);
1756 return false;
1759 tmp = check_filter_string(rec->filter_string, rec->id);
1760 if (tmp != NULL) {
1761 *err = tmp;
1762 return false;
1765 if (rec->name == NULL || rec->name[0] == 0) {
1766 *err = ws_strdup_printf("Name cannot be empty (ID: 0x%x)!", rec->id);
1767 return false;
1770 if (rec->pos >= rec->num_of_items) {
1771 *err = ws_strdup_printf("Position >= Number of Parameters (ID: 0x%x)!", rec->id);
1772 return false;
1775 if (rec->data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_STRUCT && rec->id == rec->id_ref) {
1776 *err = ws_strdup_printf("A struct cannot include itself (ID: 0x%x)!", rec->id);
1777 return false;
1780 return true;
1783 static void
1784 free_someip_parameter_struct_cb(void *r) {
1785 someip_parameter_struct_uat_t *rec = (someip_parameter_struct_uat_t *)r;
1787 if (rec->struct_name) g_free(rec->struct_name);
1788 rec->struct_name = NULL;
1790 if (rec->name) g_free(rec->name);
1791 rec->name = NULL;
1793 if (rec->filter_string) g_free(rec->filter_string);
1794 rec->filter_string = NULL;
1797 static void
1798 free_someip_parameter_struct(void *data) {
1799 someip_payload_parameter_struct_t *list = (someip_payload_parameter_struct_t *)data;
1801 if (list->items != NULL) {
1802 wmem_free(wmem_epan_scope(), (void *)(list->items));
1803 list->items = NULL;
1806 wmem_free(wmem_epan_scope(), (void *)data);
1809 static void
1810 post_update_someip_parameter_struct_read_in_data(someip_parameter_struct_uat_t *data, unsigned data_num, GHashTable *ht) {
1811 unsigned i = 0;
1812 int64_t *key = NULL;
1813 someip_payload_parameter_struct_t *list = NULL;
1814 someip_payload_parameter_item_t *item = NULL;
1815 someip_payload_parameter_item_t *items = NULL;
1817 if (ht == NULL || data == NULL || data_num == 0) {
1818 return;
1821 for (i = 0; i < data_num; i++) {
1822 key = wmem_new(wmem_epan_scope(), int64_t);
1823 *key = data[i].id;
1825 list = (someip_payload_parameter_struct_t *)g_hash_table_lookup(ht, key);
1826 if (list == NULL) {
1827 list = wmem_new(wmem_epan_scope(), someip_payload_parameter_struct_t);
1828 INIT_SOMEIP_PAYLOAD_PARAMETER_STRUCT(list)
1830 list->id = data[i].id;
1831 list->struct_name = data[i].struct_name;
1832 list->length_of_length = data[i].length_of_length;
1833 list->pad_to = data[i].pad_to;
1834 list->wtlv_encoding = data[i].wtlv_encoding;
1835 list->num_of_items = data[i].num_of_items;
1837 items = (someip_payload_parameter_item_t *)wmem_alloc0_array(wmem_epan_scope(), someip_payload_parameter_item_t, data[i].num_of_items);
1838 list->items = items;
1840 /* create new entry ... */
1841 g_hash_table_insert(ht, key, list);
1844 /* and now we add to item array */
1845 if (data[i].num_of_items == list->num_of_items && data[i].pos < list->num_of_items) {
1846 item = &(list->items[data[i].pos]);
1847 INIT_SOMEIP_PAYLOAD_PARAMETER_ITEM(item)
1849 /* we do not care if we overwrite param */
1850 item->name = data[i].name;
1851 item->id_ref = data[i].id_ref;
1852 item->pos = data[i].pos;
1853 item->data_type = data[i].data_type;
1854 item->filter_string = data[i].filter_string;
1859 static void
1860 reset_someip_parameter_struct_cb(void) {
1861 /* destroy old hash table, if it exists */
1862 if (data_someip_parameter_structs) {
1863 deregister_dynamic_hf_data(&dynamic_hf_struct, &dynamic_hf_struct_size);
1864 g_hash_table_destroy(data_someip_parameter_structs);
1865 data_someip_parameter_structs = NULL;
1868 set_prefs_changed();
1871 static void
1872 post_update_someip_parameter_struct_cb(void) {
1873 reset_someip_parameter_struct_cb();
1875 data_someip_parameter_structs = g_hash_table_new_full(g_int64_hash, g_int64_equal, &someip_payload_free_key, &free_someip_parameter_struct);
1876 post_update_someip_parameter_struct_read_in_data(someip_parameter_structs, someip_parameter_structs_num, data_someip_parameter_structs);
1879 UAT_HEX_CB_DEF(someip_parameter_unions, id, someip_parameter_union_uat_t)
1880 UAT_CSTRING_CB_DEF(someip_parameter_unions, name, someip_parameter_union_uat_t)
1881 UAT_DEC_CB_DEF(someip_parameter_unions, length_of_length, someip_parameter_union_uat_t)
1882 UAT_DEC_CB_DEF(someip_parameter_unions, length_of_type, someip_parameter_union_uat_t)
1883 UAT_DEC_CB_DEF(someip_parameter_unions, pad_to, someip_parameter_union_uat_t)
1885 UAT_DEC_CB_DEF(someip_parameter_unions, num_of_items, someip_parameter_union_uat_t)
1887 UAT_DEC_CB_DEF(someip_parameter_unions, type_id, someip_parameter_union_uat_t)
1888 UAT_CSTRING_CB_DEF(someip_parameter_unions, type_name, someip_parameter_union_uat_t)
1889 UAT_DEC_CB_DEF(someip_parameter_unions, data_type, someip_parameter_union_uat_t)
1890 UAT_HEX_CB_DEF(someip_parameter_unions, id_ref, someip_parameter_union_uat_t)
1891 UAT_CSTRING_CB_DEF(someip_parameter_unions, filter_string, someip_parameter_union_uat_t)
1893 static void *
1894 copy_someip_parameter_union_cb(void *n, const void *o, size_t size _U_) {
1895 someip_parameter_union_uat_t *new_rec = (someip_parameter_union_uat_t *)n;
1896 const someip_parameter_union_uat_t *old_rec = (const someip_parameter_union_uat_t *)o;
1898 new_rec->id = old_rec->id;
1900 if (old_rec->name) {
1901 new_rec->name = g_strdup(old_rec->name);
1902 } else {
1903 new_rec->name = NULL;
1906 new_rec->length_of_length = old_rec->length_of_length;
1907 new_rec->length_of_type = old_rec->length_of_type;
1908 new_rec->pad_to = old_rec->pad_to;
1909 new_rec->num_of_items = old_rec->num_of_items;
1910 new_rec->type_id = old_rec->type_id;
1912 if (old_rec->type_name) {
1913 new_rec->type_name = g_strdup(old_rec->type_name);
1914 } else {
1915 new_rec->type_name = NULL;
1918 new_rec->data_type = old_rec->data_type;
1919 new_rec->id_ref = old_rec->id_ref;
1921 if (old_rec->filter_string) {
1922 new_rec->filter_string = g_strdup(old_rec->filter_string);
1923 } else {
1924 new_rec->filter_string = NULL;
1927 return new_rec;
1930 static bool
1931 update_someip_parameter_union(void *r, char **err) {
1932 someip_parameter_union_uat_t *rec = (someip_parameter_union_uat_t *)r;
1933 char *tmp;
1935 if (rec->name == NULL || rec->name[0] == 0) {
1936 *err = ws_strdup_printf("Union name cannot be empty (ID: 0x%x)!", rec->id);
1937 return false;
1940 tmp = check_filter_string(rec->filter_string, rec->id);
1941 if (tmp != NULL) {
1942 *err = tmp;
1943 return false;
1946 if (rec->type_name == NULL || rec->type_name[0] == 0) {
1947 *err = ws_strdup_printf("Type Name cannot be empty (ID: 0x%x)!", rec->id);
1948 return false;
1951 if (rec->data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_UNION && rec->id == rec->id_ref) {
1952 *err = ws_strdup_printf("A union cannot include itself (ID: 0x%x)!", rec->id);
1953 return false;
1956 return true;
1959 static void
1960 free_someip_parameter_union_cb(void *r) {
1961 someip_parameter_union_uat_t *rec = (someip_parameter_union_uat_t *)r;
1963 if (rec->name) {
1964 g_free(rec->name);
1965 rec->name = NULL;
1968 if (rec->type_name) {
1969 g_free(rec->type_name);
1970 rec->type_name = NULL;
1973 if (rec->filter_string) {
1974 g_free(rec->filter_string);
1975 rec->filter_string = NULL;
1979 static void
1980 free_someip_parameter_union(void *data) {
1981 someip_parameter_union_t *list = (someip_parameter_union_t *)data;
1983 if (list->items != NULL) {
1984 wmem_free(wmem_epan_scope(), (void *)(list->items));
1985 list->items = NULL;
1988 wmem_free(wmem_epan_scope(), (void *)data);
1991 static void
1992 post_update_someip_parameter_union_read_in_data(someip_parameter_union_uat_t *data, unsigned data_num, GHashTable *ht) {
1993 unsigned i = 0;
1994 unsigned j = 0;
1995 int64_t *key = NULL;
1996 someip_parameter_union_t *list = NULL;
1997 someip_parameter_union_item_t *item = NULL;
1999 if (ht == NULL || data == NULL || data_num == 0) {
2000 return;
2003 for (i = 0; i < data_num; i++) {
2004 key = wmem_new(wmem_epan_scope(), int64_t);
2005 *key = data[i].id;
2007 list = (someip_parameter_union_t *)g_hash_table_lookup(ht, key);
2008 if (list == NULL) {
2010 list = wmem_new(wmem_epan_scope(), someip_parameter_union_t);
2012 list->id = data[i].id;
2013 list->name = data[i].name;
2014 list->length_of_length = data[i].length_of_length;
2015 list->length_of_type = data[i].length_of_type;
2016 list->pad_to = data[i].pad_to;
2017 list->num_of_items = data[i].num_of_items;
2019 list->items = (someip_parameter_union_item_t *)wmem_alloc0_array(wmem_epan_scope(), someip_parameter_union_item_t, list->num_of_items);
2021 /* create new entry ... */
2022 g_hash_table_insert(ht, key, list);
2023 } else {
2024 /* don't need it anymore */
2025 wmem_free(wmem_epan_scope(), key);
2028 /* and now we add to item array */
2029 if (data[i].num_of_items == list->num_of_items) {
2031 /* find first empty slot */
2032 for (j = 0; j < list->num_of_items && list->items[j].name != NULL; j++);
2034 if (j < list->num_of_items) {
2035 item = &(list->items[j]);
2037 /* we do not care if we overwrite param */
2038 item->id = data[i].type_id;
2039 item->name = data[i].type_name;
2040 item->data_type = data[i].data_type;
2041 item->id_ref = data[i].id_ref;
2042 item->filter_string = data[i].filter_string;
2048 static void
2049 reset_someip_parameter_union_cb(void) {
2050 /* destroy old hash table, if it exists */
2051 if (data_someip_parameter_unions) {
2052 deregister_dynamic_hf_data(&dynamic_hf_union, &dynamic_hf_union_size);
2053 g_hash_table_destroy(data_someip_parameter_unions);
2054 data_someip_parameter_unions = NULL;
2057 set_prefs_changed();
2060 static void
2061 post_update_someip_parameter_union_cb(void) {
2062 reset_someip_parameter_union_cb();
2064 data_someip_parameter_unions = g_hash_table_new_full(g_int64_hash, g_int64_equal, &someip_payload_free_key, &free_someip_parameter_union);
2065 post_update_someip_parameter_union_read_in_data(someip_parameter_unions, someip_parameter_unions_num, data_someip_parameter_unions);
2068 UAT_HEX_CB_DEF(someip_parameter_base_type_list, id, someip_parameter_base_type_list_uat_t)
2069 UAT_CSTRING_CB_DEF(someip_parameter_base_type_list, name, someip_parameter_base_type_list_uat_t)
2070 UAT_CSTRING_CB_DEF(someip_parameter_base_type_list, data_type, someip_parameter_base_type_list_uat_t)
2071 UAT_BOOL_CB_DEF(someip_parameter_base_type_list, big_endian, someip_parameter_base_type_list_uat_t)
2072 UAT_DEC_CB_DEF(someip_parameter_base_type_list, bitlength_base_type, someip_parameter_base_type_list_uat_t)
2073 UAT_DEC_CB_DEF(someip_parameter_base_type_list, bitlength_encoded_type, someip_parameter_base_type_list_uat_t)
2075 static void *
2076 copy_someip_parameter_base_type_list_cb(void *n, const void *o, size_t size _U_) {
2077 someip_parameter_base_type_list_uat_t *new_rec = (someip_parameter_base_type_list_uat_t *)n;
2078 const someip_parameter_base_type_list_uat_t *old_rec = (const someip_parameter_base_type_list_uat_t *)o;
2080 if (old_rec->name) {
2081 new_rec->name = g_strdup(old_rec->name);
2082 } else {
2083 new_rec->name = NULL;
2086 if (old_rec->data_type) {
2087 new_rec->data_type = g_strdup(old_rec->data_type);
2088 } else {
2089 new_rec->data_type = NULL;
2092 new_rec->id = old_rec->id;
2093 new_rec->big_endian = old_rec->big_endian;
2094 new_rec->bitlength_base_type = old_rec->bitlength_base_type;
2095 new_rec->bitlength_encoded_type = old_rec->bitlength_encoded_type;
2097 return new_rec;
2100 static bool
2101 update_someip_parameter_base_type_list(void *r, char **err) {
2102 someip_parameter_base_type_list_uat_t *rec = (someip_parameter_base_type_list_uat_t *)r;
2104 if (rec->name == NULL || rec->name[0] == 0) {
2105 *err = ws_strdup_printf("Name cannot be empty (ID: 0x%x)!", rec->id);
2106 return false;
2109 if (rec->id > 0xffffffff) {
2110 *err = ws_strdup_printf("We currently only support 32 bit IDs (%i) Name: %s", rec->id, rec->name);
2111 return false;
2114 if (rec->bitlength_base_type != 8 && rec->bitlength_base_type != 16 && rec->bitlength_base_type != 32 && rec->bitlength_base_type != 64) {
2115 *err = ws_strdup_printf("Bit length of base type may only be 8, 16, 32, or 64. Affected item: ID (%i) Name (%s).", rec->id, rec->name);
2116 return false;
2119 /* As long as we check that rec->bitlength_base_type equals rec->bitlength_encoded_type, we do not have to check that bitlength_encoded_type is 8, 16, 32, or 64. */
2121 if (rec->bitlength_base_type != rec->bitlength_encoded_type) {
2122 *err = ws_strdup_printf("Bit length of encoded type must be equal to bit length of base type. Affected item: ID (%i) Name (%s). Shortened types supported by Signal-PDU dissector.", rec->id, rec->name);
2123 return false;
2126 return true;
2129 static void
2130 free_someip_parameter_base_type_list_cb(void *r) {
2131 someip_parameter_base_type_list_uat_t *rec = (someip_parameter_base_type_list_uat_t *)r;
2133 if (rec->name) {
2134 g_free(rec->name);
2135 rec->name = NULL;
2138 if (rec->data_type) {
2139 g_free(rec->data_type);
2140 rec->data_type = NULL;
2144 static void
2145 reset_someip_parameter_base_type_list_cb(void) {
2146 /* destroy old hash table, if it exists */
2147 if (data_someip_parameter_base_type_list) {
2148 g_hash_table_destroy(data_someip_parameter_base_type_list);
2149 data_someip_parameter_base_type_list = NULL;
2152 set_prefs_changed();
2155 static void
2156 post_update_someip_parameter_base_type_list_cb(void) {
2157 unsigned i;
2158 int64_t *key = NULL;
2160 reset_someip_parameter_base_type_list_cb();
2162 /* we don't need to free the data as long as we don't alloc it first */
2163 data_someip_parameter_base_type_list = g_hash_table_new_full(g_int64_hash, g_int64_equal, &someip_payload_free_key, NULL);
2165 if (data_someip_parameter_base_type_list == NULL || someip_parameter_base_type_list == NULL || someip_parameter_base_type_list_num == 0) {
2166 return;
2169 if (someip_parameter_base_type_list_num > 0) {
2170 for (i = 0; i < someip_parameter_base_type_list_num; i++) {
2171 key = wmem_new(wmem_epan_scope(), int64_t);
2172 *key = someip_parameter_base_type_list[i].id;
2174 g_hash_table_insert(data_someip_parameter_base_type_list, key, &someip_parameter_base_type_list[i]);
2179 UAT_HEX_CB_DEF(someip_parameter_strings, id, someip_parameter_string_uat_t)
2180 UAT_CSTRING_CB_DEF(someip_parameter_strings, name, someip_parameter_string_uat_t)
2181 UAT_CSTRING_CB_DEF(someip_parameter_strings, encoding, someip_parameter_string_uat_t)
2182 UAT_BOOL_CB_DEF(someip_parameter_strings, dynamic_length, someip_parameter_string_uat_t)
2183 UAT_DEC_CB_DEF(someip_parameter_strings, max_length, someip_parameter_string_uat_t)
2184 UAT_DEC_CB_DEF(someip_parameter_strings, length_of_length, someip_parameter_string_uat_t)
2185 UAT_BOOL_CB_DEF(someip_parameter_strings, big_endian, someip_parameter_string_uat_t)
2186 UAT_DEC_CB_DEF(someip_parameter_strings, pad_to, someip_parameter_string_uat_t)
2188 static void *
2189 copy_someip_parameter_string_list_cb(void *n, const void *o, size_t size _U_) {
2190 someip_parameter_string_uat_t *new_rec = (someip_parameter_string_uat_t *)n;
2191 const someip_parameter_string_uat_t *old_rec = (const someip_parameter_string_uat_t *)o;
2193 if (old_rec->name) {
2194 new_rec->name = g_strdup(old_rec->name);
2195 } else {
2196 new_rec->name = NULL;
2199 if (old_rec->encoding) {
2200 new_rec->encoding = g_strdup(old_rec->encoding);
2201 } else {
2202 new_rec->encoding = NULL;
2205 new_rec->id = old_rec->id;
2206 new_rec->dynamic_length = old_rec->dynamic_length;
2207 new_rec->max_length = old_rec->max_length;
2208 new_rec->length_of_length = old_rec->length_of_length;
2209 new_rec->big_endian = old_rec->big_endian;
2210 new_rec->pad_to = old_rec->pad_to;
2212 return new_rec;
2215 static bool
2216 update_someip_parameter_string_list(void *r, char **err) {
2217 someip_parameter_string_uat_t *rec = (someip_parameter_string_uat_t *)r;
2219 if (rec->name == NULL || rec->name[0] == 0) {
2220 *err = ws_strdup_printf("Name cannot be empty (ID: 0x%x)!", rec->id);
2221 return false;
2224 if (rec->id > 0xffffffff) {
2225 *err = ws_strdup_printf("We currently only support 32 bit IDs (%i) Name: %s", rec->id, rec->name);
2226 return false;
2229 if (rec->max_length > 0xffffffff) {
2230 *err = ws_strdup_printf("We currently only support 32 bit max_length (%i) Name: %s", rec->max_length, rec->name);
2231 return false;
2234 if (rec->length_of_length != 0 && rec->length_of_length != 8 && rec->length_of_length != 16 && rec->length_of_length != 32) {
2235 *err = ws_strdup_printf("length_of_length can be only 0, 8, 16, or 32 but not %d (IDs: %i Name: %s)", rec->length_of_length, rec->id, rec->name);
2236 return false;
2239 return true;
2242 static void
2243 free_someip_parameter_string_list_cb(void *r) {
2244 someip_parameter_string_uat_t *rec = (someip_parameter_string_uat_t *)r;
2246 if (rec->name) {
2247 g_free(rec->name);
2248 rec->name = NULL;
2251 if (rec->encoding) {
2252 g_free(rec->encoding);
2253 rec->encoding = NULL;
2257 static void
2258 reset_someip_parameter_string_list_cb(void) {
2259 /* destroy old hash table, if it exists */
2260 if (data_someip_parameter_strings) {
2261 g_hash_table_destroy(data_someip_parameter_strings);
2262 data_someip_parameter_strings = NULL;
2265 set_prefs_changed();
2268 static void
2269 post_update_someip_parameter_string_list_cb(void) {
2270 unsigned i;
2271 int64_t *key = NULL;
2273 reset_someip_parameter_string_list_cb();
2275 /* we don't need to free the data as long as we don't alloc it first */
2276 data_someip_parameter_strings = g_hash_table_new_full(g_int64_hash, g_int64_equal, &someip_payload_free_key, NULL);
2278 if (data_someip_parameter_strings == NULL || someip_parameter_strings == NULL || someip_parameter_strings_num == 0) {
2279 return;
2282 if (someip_parameter_strings_num > 0) {
2283 for (i = 0; i < someip_parameter_strings_num; i++) {
2284 key = wmem_new(wmem_epan_scope(), int64_t);
2285 *key = someip_parameter_strings[i].id;
2287 g_hash_table_insert(data_someip_parameter_strings, key, &someip_parameter_strings[i]);
2292 UAT_HEX_CB_DEF(someip_parameter_typedefs, id, someip_parameter_typedef_uat_t)
2293 UAT_CSTRING_CB_DEF(someip_parameter_typedefs, name, someip_parameter_typedef_uat_t)
2294 UAT_DEC_CB_DEF(someip_parameter_typedefs, data_type, someip_parameter_typedef_uat_t)
2295 UAT_HEX_CB_DEF(someip_parameter_typedefs, id_ref, someip_parameter_typedef_uat_t)
2297 static void *
2298 copy_someip_parameter_typedef_list_cb(void *n, const void *o, size_t size _U_) {
2299 someip_parameter_typedef_uat_t *new_rec = (someip_parameter_typedef_uat_t *)n;
2300 const someip_parameter_typedef_uat_t *old_rec = (const someip_parameter_typedef_uat_t *)o;
2302 if (old_rec->name) {
2303 new_rec->name = g_strdup(old_rec->name);
2304 } else {
2305 new_rec->name = NULL;
2308 new_rec->id = old_rec->id;
2309 new_rec->data_type = old_rec->data_type;
2310 new_rec->id_ref = old_rec->id_ref;
2312 return new_rec;
2315 static bool
2316 update_someip_parameter_typedef_list(void *r, char **err) {
2317 someip_parameter_typedef_uat_t *rec = (someip_parameter_typedef_uat_t *)r;
2319 if (rec->id > 0xffffffff) {
2320 *err = ws_strdup_printf("We currently only support 32 bit IDs (%i) Name: %s", rec->id, rec->name);
2321 return false;
2324 if (rec->data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_TYPEDEF && rec->id == rec->id_ref) {
2325 *err = ws_strdup_printf("A typedef cannot reference itself (ID: 0x%x)!", rec->id);
2326 return false;
2329 return true;
2332 static void
2333 free_someip_parameter_typedef_list_cb(void *r) {
2334 someip_parameter_typedef_uat_t *rec = (someip_parameter_typedef_uat_t *)r;
2336 if (rec->name) {
2337 g_free(rec->name);
2338 rec->name = NULL;
2342 static void
2343 reset_someip_parameter_typedef_list_cb(void) {
2344 /* destroy old hash table, if it exists */
2345 if (data_someip_parameter_typedefs) {
2346 g_hash_table_destroy(data_someip_parameter_typedefs);
2347 data_someip_parameter_typedefs = NULL;
2350 set_prefs_changed();
2353 static void
2354 post_update_someip_parameter_typedef_list_cb(void) {
2355 unsigned i;
2356 int64_t *key = NULL;
2358 reset_someip_parameter_typedef_list_cb();
2360 /* we don't need to free the data as long as we don't alloc it first */
2361 data_someip_parameter_typedefs = g_hash_table_new_full(g_int64_hash, g_int64_equal, &someip_payload_free_key, NULL);
2363 if (data_someip_parameter_typedefs == NULL || someip_parameter_typedefs == NULL || someip_parameter_typedefs_num == 0) {
2364 return;
2367 if (someip_parameter_typedefs_num > 0) {
2368 for (i = 0; i < someip_parameter_typedefs_num; i++) {
2369 /* key: ID [32bit] */
2370 key = wmem_new(wmem_epan_scope(), int64_t);
2371 *key = someip_parameter_typedefs[i].id;
2372 g_hash_table_insert(data_someip_parameter_typedefs, key, &someip_parameter_typedefs[i]);
2378 static void
2379 deregister_dynamic_hf_data(hf_register_info **hf_array, unsigned *hf_size) {
2380 if (*hf_array) {
2381 /* Unregister all fields used before */
2382 for (unsigned i = 0; i < *hf_size; i++) {
2383 if ((*hf_array)[i].p_id != NULL) {
2384 proto_deregister_field(proto_someip, *((*hf_array)[i].p_id));
2385 g_free((*hf_array)[i].p_id);
2386 (*hf_array)[i].p_id = NULL;
2389 proto_add_deregistered_data(*hf_array);
2390 *hf_array = NULL;
2391 *hf_size = 0;
2395 static void
2396 allocate_dynamic_hf_data(hf_register_info **hf_array, unsigned *hf_size, unsigned new_size) {
2397 *hf_array = g_new0(hf_register_info, new_size);
2398 *hf_size = new_size;
2401 typedef struct _param_return_attibutes_t {
2402 enum ftenum type;
2403 int display_base;
2404 char *base_type_name;
2405 } param_return_attributes_t;
2407 static param_return_attributes_t
2408 get_param_attributes(uint8_t data_type, uint32_t id_ref) {
2409 int count = 10;
2411 param_return_attributes_t ret;
2412 ret.type = FT_NONE;
2413 ret.display_base = BASE_NONE;
2414 ret.base_type_name = NULL;
2416 /* we limit the number of typedef recursion to "count" */
2417 while (data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_TYPEDEF && count > 0) {
2418 someip_payload_parameter_typedef_t *tmp = get_typedef_config(id_ref);
2419 /* this should not be a typedef since we don't support recursion of typedefs */
2420 if (tmp != NULL) {
2421 data_type = tmp->data_type;
2422 id_ref = tmp->id_ref;
2424 count--;
2427 if (data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ENUM) {
2428 someip_payload_parameter_enum_t *tmp = get_enum_config(id_ref);
2429 /* this can only be a base type ... */
2430 if (tmp != NULL) {
2431 data_type = tmp->data_type;
2432 id_ref = tmp->id_ref;
2436 if (data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_STRING) {
2437 someip_payload_parameter_string_t *tmp = get_string_config(id_ref);
2438 ret.type = FT_STRING;
2439 ret.display_base = BASE_NONE;
2440 if (tmp != NULL) {
2441 ret.base_type_name = tmp->name;
2443 return ret;
2446 if (data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_BASE_TYPE) {
2447 someip_payload_parameter_base_type_list_t *tmp = get_base_type_config(id_ref);
2449 ret.display_base = BASE_DEC;
2451 if (tmp != NULL) {
2452 ret.base_type_name = tmp->name;
2454 if (g_strcmp0(tmp->data_type, "uint8") == 0) {
2455 ret.type = FT_UINT8;
2456 } else if (g_strcmp0(tmp->data_type, "uint16") == 0) {
2457 ret.type = FT_UINT16;
2458 } else if (g_strcmp0(tmp->data_type, "uint24") == 0) {
2459 ret.type = FT_UINT24;
2460 } else if (g_strcmp0(tmp->data_type, "uint32") == 0) {
2461 ret.type = FT_UINT32;
2462 } else if (g_strcmp0(tmp->data_type, "uint40") == 0) {
2463 ret.type = FT_UINT40;
2464 } else if (g_strcmp0(tmp->data_type, "uint48") == 0) {
2465 ret.type = FT_UINT48;
2466 } else if (g_strcmp0(tmp->data_type, "uint56") == 0) {
2467 ret.type = FT_UINT56;
2468 } else if (g_strcmp0(tmp->data_type, "uint64") == 0) {
2469 ret.type = FT_UINT64;
2470 } else if (g_strcmp0(tmp->data_type, "int8") == 0) {
2471 ret.type = FT_INT8;
2472 } else if (g_strcmp0(tmp->data_type, "int16") == 0) {
2473 ret.type = FT_INT16;
2474 } else if (g_strcmp0(tmp->data_type, "int24") == 0) {
2475 ret.type = FT_INT24;
2476 } else if (g_strcmp0(tmp->data_type, "int32") == 0) {
2477 ret.type = FT_INT32;
2478 } else if (g_strcmp0(tmp->data_type, "int40") == 0) {
2479 ret.type = FT_INT40;
2480 } else if (g_strcmp0(tmp->data_type, "int48") == 0) {
2481 ret.type = FT_INT48;
2482 } else if (g_strcmp0(tmp->data_type, "int56") == 0) {
2483 ret.type = FT_INT56;
2484 } else if (g_strcmp0(tmp->data_type, "int64") == 0) {
2485 ret.type = FT_INT64;
2486 } else if (g_strcmp0(tmp->data_type, "float32") == 0) {
2487 ret.type = FT_FLOAT;
2488 ret.display_base = BASE_NONE;
2489 } else if (g_strcmp0(tmp->data_type, "float64") == 0) {
2490 ret.type = FT_DOUBLE;
2491 ret.display_base = BASE_NONE;
2492 } else {
2493 ret.type = FT_NONE;
2495 } else {
2496 ret.type = FT_NONE;
2500 /* all other types are handled or don't need a type! */
2501 return ret;
2504 static int*
2505 update_dynamic_hf_entry(hf_register_info *hf_array, int pos, uint32_t data_type, unsigned id_ref, char *param_name, char *filter_string) {
2506 param_return_attributes_t attribs;
2507 int *hf_id;
2509 attribs = get_param_attributes(data_type, id_ref);
2510 if (hf_array == NULL || attribs.type == FT_NONE) {
2511 return NULL;
2514 hf_id = g_new(int, 1);
2515 *hf_id = 0;
2516 hf_array[pos].p_id = hf_id;
2518 hf_array[pos].hfinfo.strings = NULL;
2519 hf_array[pos].hfinfo.bitmask = 0;
2520 hf_array[pos].hfinfo.blurb = NULL;
2522 if (attribs.base_type_name == NULL) {
2523 hf_array[pos].hfinfo.name = g_strdup(param_name);
2524 } else {
2525 hf_array[pos].hfinfo.name = ws_strdup_printf("%s [%s]", param_name, attribs.base_type_name);
2528 hf_array[pos].hfinfo.abbrev = ws_strdup_printf("%s.%s", SOMEIP_NAME_PREFIX, filter_string);
2529 hf_array[pos].hfinfo.type = attribs.type;
2530 hf_array[pos].hfinfo.display = attribs.display_base;
2532 HFILL_INIT(hf_array[pos]);
2534 return hf_id;
2537 static void
2538 update_dynamic_param_hf_entry(void *key _U_, void *value, void *data) {
2539 uint32_t *pos = (uint32_t *)data;
2540 someip_parameter_list_t *list = (someip_parameter_list_t *)value;
2541 unsigned i = 0;
2543 for (i = 0; i < list->num_of_items ; i++) {
2544 if (*pos >= dynamic_hf_param_size) {
2545 return;
2548 someip_payload_parameter_item_t *item = &(list->items[i]);
2550 item->hf_id = update_dynamic_hf_entry(dynamic_hf_param, *pos, item->data_type, item->id_ref, item->name, item->filter_string);
2552 if (item->hf_id != NULL) {
2553 (*pos)++;
2558 static void
2559 update_dynamic_array_hf_entry(void *key _U_, void *value, void *data) {
2560 uint32_t *pos = (uint32_t *)data;
2561 someip_parameter_array_t *item = (someip_parameter_array_t *)value;
2563 if (*pos >= dynamic_hf_array_size) {
2564 return;
2567 item->hf_id = update_dynamic_hf_entry(dynamic_hf_array, *pos, item->data_type, item->id_ref, item->name, item->filter_string);
2569 if (item->hf_id != NULL) {
2570 (*pos)++;
2574 static void
2575 update_dynamic_struct_hf_entry(void *key _U_, void *value, void *data) {
2576 uint32_t *pos = (uint32_t *)data;
2577 someip_payload_parameter_struct_t *list = (someip_payload_parameter_struct_t *)value;
2578 unsigned i = 0;
2580 for (i = 0; i < list->num_of_items; i++) {
2581 if (*pos >= dynamic_hf_struct_size) {
2582 return;
2584 someip_payload_parameter_item_t *item = &(list->items[i]);
2586 item->hf_id = update_dynamic_hf_entry(dynamic_hf_struct, *pos, item->data_type, item->id_ref, item->name, item->filter_string);
2588 if (item->hf_id != NULL) {
2589 (*pos)++;
2594 static void
2595 update_dynamic_union_hf_entry(void *key _U_, void *value, void *data) {
2596 uint32_t *pos = (uint32_t *)data;
2597 someip_parameter_union_t *list = (someip_parameter_union_t *)value;
2598 unsigned i = 0;
2600 for (i = 0; i < list->num_of_items; i++) {
2601 if (*pos >= dynamic_hf_union_size) {
2602 return;
2605 someip_parameter_union_item_t *item = &(list->items[i]);
2607 item->hf_id = update_dynamic_hf_entry(dynamic_hf_union, *pos, item->data_type, item->id_ref, item->name, item->filter_string);
2609 if (item->hf_id != NULL) {
2610 (*pos)++;
2615 static void
2616 update_dynamic_hf_entries_someip_parameter_list(void) {
2617 if (data_someip_parameter_list != NULL) {
2618 deregister_dynamic_hf_data(&dynamic_hf_param, &dynamic_hf_param_size);
2619 allocate_dynamic_hf_data(&dynamic_hf_param, &dynamic_hf_param_size, someip_parameter_list_num);
2620 uint32_t pos = 0;
2621 g_hash_table_foreach(data_someip_parameter_list, update_dynamic_param_hf_entry, &pos);
2622 proto_register_field_array(proto_someip, dynamic_hf_param, pos);
2626 static void
2627 update_dynamic_hf_entries_someip_parameter_arrays(void) {
2628 if (data_someip_parameter_arrays != NULL) {
2629 deregister_dynamic_hf_data(&dynamic_hf_array, &dynamic_hf_array_size);
2630 allocate_dynamic_hf_data(&dynamic_hf_array, &dynamic_hf_array_size, someip_parameter_arrays_num);
2631 uint32_t pos = 0;
2632 g_hash_table_foreach(data_someip_parameter_arrays, update_dynamic_array_hf_entry, &pos);
2633 proto_register_field_array(proto_someip, dynamic_hf_array, pos);
2637 static void
2638 update_dynamic_hf_entries_someip_parameter_structs(void) {
2639 if (data_someip_parameter_structs != NULL) {
2640 deregister_dynamic_hf_data(&dynamic_hf_struct, &dynamic_hf_struct_size);
2641 allocate_dynamic_hf_data(&dynamic_hf_struct, &dynamic_hf_struct_size, someip_parameter_structs_num);
2642 uint32_t pos = 0;
2643 g_hash_table_foreach(data_someip_parameter_structs, update_dynamic_struct_hf_entry, &pos);
2644 proto_register_field_array(proto_someip, dynamic_hf_struct, pos);
2648 static void
2649 update_dynamic_hf_entries_someip_parameter_unions(void) {
2650 if (data_someip_parameter_unions != NULL) {
2651 deregister_dynamic_hf_data(&dynamic_hf_union, &dynamic_hf_union_size);
2652 allocate_dynamic_hf_data(&dynamic_hf_union, &dynamic_hf_union_size, someip_parameter_unions_num);
2653 uint32_t pos = 0;
2654 g_hash_table_foreach(data_someip_parameter_unions, update_dynamic_union_hf_entry, &pos);
2655 proto_register_field_array(proto_someip, dynamic_hf_union, pos);
2659 static void
2660 expert_someip_payload_truncated(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset, int length) {
2661 proto_tree_add_expert(tree, pinfo, &ei_someip_payload_truncated, tvb, offset, length);
2662 col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP Payload: Truncated payload!]");
2665 static void
2666 expert_someip_payload_malformed(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset, int length) {
2667 proto_tree_add_expert(tree, pinfo, &ei_someip_payload_malformed, tvb, offset, length);
2668 col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP Payload: Malformed payload!]");
2671 static void
2672 expert_someip_payload_config_error(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset, int length, const char *message) {
2673 proto_tree_add_expert_format(tree, pinfo, &ei_someip_payload_config_error, tvb, offset, length, "SOME/IP Payload: %s", message);
2674 col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP Payload: Config Error]");
2677 /*******************************************
2678 **************** Statistics ***************
2679 *******************************************/
2681 static void
2682 someip_messages_stats_tree_init(stats_tree *st) {
2683 st_node_ip_src = stats_tree_create_node(st, st_str_ip_src, 0, STAT_DT_INT, true);
2684 stat_node_set_flags(st, st_str_ip_src, 0, false, ST_FLG_SORT_TOP);
2685 st_node_ip_dst = stats_tree_create_node(st, st_str_ip_dst, 0, STAT_DT_INT, true);
2688 static tap_packet_status
2689 someip_messages_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p, tap_flags_t flags _U_) {
2690 static char tmp_srv_str[128];
2691 static char tmp_meth_str[128];
2692 static char tmp_addr_str[128];
2693 int tmp;
2695 DISSECTOR_ASSERT(p);
2696 const someip_messages_tap_t *data = (const someip_messages_tap_t *)p;
2698 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));
2699 tick_stat_node(st, st_str_ip_src, 0, false);
2700 int src_id = tick_stat_node(st, tmp_addr_str, st_node_ip_src, true);
2702 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));
2703 tick_stat_node(st, st_str_ip_dst, 0, false);
2704 int dst_id = tick_stat_node(st, tmp_addr_str, st_node_ip_dst, true);
2706 char *service_name = someip_lookup_service_name(data->service_id);
2707 if (service_name == NULL) {
2708 snprintf(tmp_srv_str, sizeof(tmp_srv_str) - 1, "Service 0x%04x", data->service_id);
2709 } else {
2710 snprintf(tmp_srv_str, sizeof(tmp_srv_str) - 1, "Service 0x%04x (%s)", data->service_id, service_name);
2713 char *method_name = someip_lookup_method_name(data->service_id, data->method_id);
2714 if (method_name == NULL) {
2715 snprintf(tmp_meth_str, sizeof(tmp_meth_str) - 1, "Method 0x%04x %s", data->method_id,
2716 val_to_str(data->message_type, someip_msg_type, "Message-Type: 0x%02x"));
2717 } else {
2718 snprintf(tmp_meth_str, sizeof(tmp_meth_str) - 1, "Method 0x%04x (%s) %s", data->method_id, method_name,
2719 val_to_str(data->message_type, someip_msg_type, "Message-Type: 0x%02x"));
2722 tmp = tick_stat_node(st, tmp_srv_str, src_id, true);
2723 tick_stat_node(st, tmp_meth_str, tmp, false);
2724 tmp = tick_stat_node(st, tmp_srv_str, dst_id, true);
2725 tick_stat_node(st, tmp_meth_str, tmp, false);
2727 return TAP_PACKET_REDRAW;
2730 /*******************************************
2731 ******** SOME/IP Payload Dissector ********
2732 *******************************************/
2734 static int
2735 dissect_someip_payload_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint8_t data_type, uint32_t idref, char *name, int *hf_id_ptr, int wtlv_offset);
2737 static int
2738 dissect_someip_payload_parameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, someip_payload_parameter_item_t *items, uint32_t num_of_items, bool wtlv);
2740 /* add a flexible size length field, -1 for error*/
2741 static int64_t
2742 dissect_someip_payload_length_field(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, int offset, int length_of_length_field) {
2743 proto_item *ti;
2744 uint32_t tmp = 0;
2746 switch (length_of_length_field) {
2747 case 8:
2748 ti = proto_tree_add_item_ret_uint(subtree, hf_payload_length_field_8bit, tvb, offset, length_of_length_field / 8, ENC_NA, &tmp);
2749 proto_item_set_hidden(ti);
2750 break;
2751 case 16:
2752 ti = proto_tree_add_item_ret_uint(subtree, hf_payload_length_field_16bit, tvb, offset, length_of_length_field / 8, ENC_BIG_ENDIAN, &tmp);
2753 proto_item_set_hidden(ti);
2754 break;
2755 case 32:
2756 ti = proto_tree_add_item_ret_uint(subtree, hf_payload_length_field_32bit, tvb, offset, length_of_length_field / 8, ENC_BIG_ENDIAN, &tmp);
2757 proto_item_set_hidden(ti);
2758 break;
2759 default:
2760 proto_tree_add_expert_format(subtree, pinfo, &ei_someip_payload_config_error, tvb, offset, 0,
2761 "SOME/IP: Payload: length of length field does not make sense: %d bits", length_of_length_field);
2762 col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP: Payload Config Error]");
2763 return -1;
2766 return (int64_t)tmp;
2769 /* add a flexible size type field */
2770 static int64_t
2771 dissect_someip_payload_type_field(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, int offset, int length_of_type_field) {
2772 proto_item *ti;
2773 uint32_t tmp = 0;
2775 switch (length_of_type_field) {
2776 case 8:
2777 ti = proto_tree_add_item_ret_uint(subtree, hf_payload_type_field_8bit, tvb, offset, length_of_type_field / 8, ENC_NA, &tmp);
2778 proto_item_set_hidden(ti);
2779 break;
2780 case 16:
2781 ti = proto_tree_add_item_ret_uint(subtree, hf_payload_type_field_16bit, tvb, offset, length_of_type_field / 8, ENC_BIG_ENDIAN, &tmp);
2782 proto_item_set_hidden(ti);
2783 break;
2784 case 32:
2785 ti = proto_tree_add_item_ret_uint(subtree, hf_payload_type_field_32bit, tvb, offset, length_of_type_field / 8, ENC_BIG_ENDIAN, &tmp);
2786 proto_item_set_hidden(ti);
2787 break;
2788 default:
2789 proto_tree_add_expert_format(subtree, pinfo, &ei_someip_payload_config_error, tvb, offset, 0,
2790 "SOME/IP: Payload: length of type field does not make sense: %d bits", length_of_type_field);
2791 col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP: Payload Config Error]");
2792 return -1;
2795 return (int64_t)tmp;
2798 static uint32_t
2799 dissect_someip_payload_add_wtlv_if_needed(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_item *ti_root, proto_tree *parent_tree) {
2800 static int * const tag_bitfield[] = {
2801 &hf_payload_wtlv_tag_res,
2802 &hf_payload_wtlv_tag_wire_type,
2803 &hf_payload_wtlv_tag_data_id,
2804 NULL
2807 if (offset < 0) {
2808 return 0;
2811 proto_tree *tree = parent_tree;
2812 if (tree == NULL) {
2813 tree = proto_item_add_subtree(ti_root, ett_someip_parameter);
2816 uint64_t tagdata = 0;
2817 proto_item *ti = proto_tree_add_bitmask_ret_uint64(tree, tvb, offset, hf_payload_wtlv_tag, ett_someip_wtlv_tag, tag_bitfield, ENC_BIG_ENDIAN, &tagdata);
2818 proto_item_set_hidden(ti);
2820 unsigned wiretype = (unsigned)((tagdata & SOMEIP_WTLV_MASK_WIRE_TYPE) >> 12);
2822 switch (wiretype) {
2823 case 5:
2824 return 8;
2825 case 6:
2826 return 16;
2827 case 7:
2828 return 32;
2829 default:
2830 return 0;
2834 static int
2835 dissect_someip_payload_base_type(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, uint8_t data_type, uint32_t id, char *name, int *hf_id_ptr, int wtlv_offset) {
2836 someip_payload_parameter_base_type_list_t *base_type = NULL;
2837 someip_payload_parameter_enum_t *enum_config = NULL;
2839 uint32_t basetype_id = 0;
2840 uint32_t enum_id = 0;
2842 int param_length = -1;
2844 proto_item *ti = NULL;
2846 uint64_t value = 0;
2847 uint32_t value32 = 0;
2848 bool value_set = false;
2850 uint32_t i = 0;
2851 char *value_name = NULL;
2853 bool big_endian = true;
2855 int hf_id = 0;
2857 if (hf_id_ptr != NULL) {
2858 hf_id = *hf_id_ptr;
2861 switch (data_type) {
2862 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_BASE_TYPE:
2863 basetype_id = id;
2864 break;
2865 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ENUM:
2866 enum_id = id;
2867 enum_config = get_enum_config(enum_id);
2868 if (enum_config == NULL) {
2869 return 0;
2871 basetype_id = enum_config->id_ref;
2872 break;
2873 default:
2874 return 0;
2877 base_type = get_base_type_config(basetype_id);
2878 if (base_type == NULL) {
2879 return 0;
2882 big_endian = base_type->big_endian;
2883 param_length = (int)((base_type->bitlength_base_type) / 8);
2885 if (param_length > tvb_captured_length_remaining(tvb, 0) - offset) {
2886 return 0;
2889 if (hf_id > 0) {
2890 if (strncmp(base_type->data_type, "uint", 4) == 0) {
2891 if (base_type->bitlength_base_type > 32) {
2892 ti = proto_tree_add_item_ret_uint64(tree, hf_id, tvb, offset, param_length, big_endian ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN, &value);
2893 } else {
2894 ti = proto_tree_add_item_ret_uint(tree, hf_id, tvb, offset, param_length, big_endian ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN, &value32);
2895 value = (uint64_t)value32;
2897 value_set = true;
2898 } else {
2899 ti = proto_tree_add_item(tree, hf_id, tvb, offset, param_length, big_endian ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN);
2901 } else {
2902 if (name == NULL) {
2903 ti = proto_tree_add_string_format(tree, hf_payload_str_base, tvb, offset, param_length, base_type->name, "[%s]", base_type->name);
2904 } else {
2905 ti = proto_tree_add_string_format(tree, hf_payload_str_base, tvb, offset, param_length, base_type->name, "%s [%s]", name, base_type->name);
2909 dissect_someip_payload_add_wtlv_if_needed(tvb, pinfo, wtlv_offset, ti, NULL);
2911 if (enum_config != NULL && value_set == true) {
2912 for (i = 0; i < enum_config->num_of_items; i++) {
2913 if (enum_config->items[i].value == value) {
2914 value_name = enum_config->items[i].name;
2915 break;
2918 if (value_name != NULL) {
2919 proto_item_append_text(ti, " (%s)", value_name);
2923 return param_length;
2926 static int
2927 dissect_someip_payload_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint32_t id, char *name, int *hf_id_ptr, int wtlv_offset) {
2928 someip_payload_parameter_string_t *config = NULL;
2930 uint8_t *buf = NULL;
2931 uint32_t i = 0;
2933 proto_item *ti = NULL;
2934 proto_tree *subtree = NULL;
2935 int64_t tmp = 0;
2936 uint32_t length = 0;
2937 int offset_orig = offset;
2939 unsigned str_encoding = 0;
2940 int hf_id = hf_payload_str_string;
2942 if (hf_id_ptr != NULL) {
2943 hf_id = *hf_id_ptr;
2946 config = get_string_config(id);
2948 if (config == NULL) {
2949 return 0;
2952 if (wtlv_offset >= 0) {
2953 ti = proto_tree_add_string_format(tree, hf_id, tvb, wtlv_offset, 0, name, "%s [%s]", name, config->name);
2954 } else {
2955 ti = proto_tree_add_string_format(tree, hf_id, tvb, offset, 0, name, "%s [%s]", name, config->name);
2958 subtree = proto_item_add_subtree(ti, ett_someip_string);
2959 uint32_t length_of_length = dissect_someip_payload_add_wtlv_if_needed(tvb, pinfo, wtlv_offset, ti, NULL);
2961 /* WTLV length overrides configured length */
2962 if (config->length_of_length == 0 && length_of_length == 0) {
2963 length = config->max_length;
2964 } else {
2965 if (length_of_length == 0) {
2966 length_of_length = config->length_of_length;
2969 if (tvb_captured_length_remaining(tvb, offset) < (int)(length_of_length >> 3)) {
2970 expert_someip_payload_malformed(tree, pinfo, tvb, offset, 0);
2971 return 0;
2974 tmp = dissect_someip_payload_length_field(tvb, pinfo, subtree, offset, length_of_length);
2975 if (tmp < 0) {
2976 /* error */
2977 return length_of_length / 8;
2979 length = (uint32_t)tmp;
2980 offset += length_of_length / 8;
2983 if ((uint32_t)tvb_captured_length_remaining(tvb, offset) < length) {
2984 expert_someip_payload_malformed(subtree, pinfo, tvb, offset, 0);
2985 return 0;
2988 if (strcmp(config->encoding, "utf-8") == 0) {
2989 str_encoding = ENC_UTF_8 | ENC_NA;
2990 } else if (strcmp(config->encoding, "utf-16") == 0) {
2991 str_encoding = ENC_UTF_16 | (config->big_endian ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN);
2992 } else {
2993 str_encoding = ENC_ASCII | ENC_NA;
2996 buf = tvb_get_string_enc(pinfo->pool, tvb, offset, length, str_encoding);
2998 /* sanitizing buffer */
2999 if ((str_encoding == (ENC_ASCII | ENC_NA)) || (str_encoding & ENC_UTF_8)) {
3000 for (i = 0; i < length; i++) {
3001 if (buf[i] > 0x00 && buf[i] < 0x20) {
3002 buf[i] = 0x20;
3007 proto_item_append_text(ti, ": %s", buf);
3008 offset += length;
3010 proto_item_set_end(ti, tvb, offset);
3012 return offset - offset_orig;
3015 static int
3016 // NOLINTNEXTLINE(misc-no-recursion)
3017 dissect_someip_payload_struct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset_orig, uint32_t id, char *name, int wtlv_offset) {
3018 someip_payload_parameter_struct_t *config = NULL;
3020 proto_tree *subtree = NULL;
3021 proto_item *ti = NULL;
3022 tvbuff_t *subtvb = tvb;
3024 int64_t length = 0;
3025 int offset = offset_orig;
3027 config = get_struct_config(id);
3029 if (config == NULL || tree == NULL || tvb == NULL) {
3030 return 0;
3033 if (wtlv_offset >= 0) {
3034 ti = proto_tree_add_string_format(tree, hf_payload_str_struct, tvb, wtlv_offset, 0, config->struct_name, "struct %s [%s]", name, config->struct_name);
3035 } else {
3036 ti = proto_tree_add_string_format(tree, hf_payload_str_struct, tvb, offset, 0, config->struct_name, "struct %s [%s]", name, config->struct_name);
3039 subtree = proto_item_add_subtree(ti, ett_someip_struct);
3040 uint32_t length_of_length = dissect_someip_payload_add_wtlv_if_needed(tvb, pinfo, wtlv_offset, ti, subtree);
3042 /* WTLV length overrides configured length */
3043 if (length_of_length == 0) {
3044 length_of_length = config->length_of_length;
3047 if (tvb_captured_length_remaining(tvb, 0) < (int)(length_of_length >> 3)) {
3048 expert_someip_payload_malformed(tree, pinfo, tvb, offset, 0);
3049 return 0;
3052 if (length_of_length != 0) {
3053 length = dissect_someip_payload_length_field(tvb, pinfo, subtree, offset, length_of_length);
3054 if (length < 0) {
3055 /* error */
3056 return length_of_length / 8;
3058 offset += length_of_length / 8;
3059 int endpos = offset_orig + (length_of_length / 8) + (uint32_t)length;
3060 proto_item_set_end(ti, tvb, endpos);
3061 subtvb = tvb_new_subset_length(tvb, 0, endpos);
3064 offset += dissect_someip_payload_parameters(subtvb, pinfo, subtree, offset, config->items, config->num_of_items, config->wtlv_encoding);
3066 if (length_of_length == 0) {
3067 proto_item_set_end(ti, tvb, offset);
3069 return offset - offset_orig;
3070 } else {
3071 return (length_of_length / 8) + (uint32_t)length;
3075 static int
3076 // NOLINTNEXTLINE(misc-no-recursion)
3077 dissect_someip_payload_typedef(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint32_t id, char *name _U_, int *hf_id, int wtlv_offset) {
3078 someip_payload_parameter_typedef_t *config = NULL;
3080 config = get_typedef_config(id);
3082 if (config == NULL) {
3083 return 0;
3086 /* we basically skip over the typedef for now */
3087 return dissect_someip_payload_parameter(tvb, pinfo, tree, offset, (uint8_t)config->data_type, config->id_ref, config->name, hf_id, wtlv_offset);
3090 /* returns bytes parsed, length needs to be int to encode "non-existing" as -1 */
3091 static int
3092 dissect_someip_payload_array_dim_length(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset_orig, int *length, int *lower_limit, int *upper_limit,
3093 someip_parameter_array_t *config, int current_dim, uint32_t length_of_length) {
3094 int offset = offset_orig;
3095 int64_t tmp = 0;
3097 *lower_limit = config->dims[current_dim].lower_limit;
3098 *upper_limit = config->dims[current_dim].upper_limit;
3100 /* length needs to be -1, if we do not have a dynamic length array */
3101 *length = -1;
3103 if (length_of_length == 0) {
3104 length_of_length = config->dims[current_dim].length_of_length;
3106 if (length_of_length > 0) {
3107 /* we are filling the length with number of bytes we found in the packet */
3108 tmp = dissect_someip_payload_length_field(tvb, pinfo, tree, offset, length_of_length);
3109 if (tmp < 0) {
3110 /* leave *length = -1 */
3111 return length_of_length/8;
3113 *length = (int32_t)tmp;
3114 offset += length_of_length/8;
3115 } else {
3116 /* without a length field, the number of elements needs be fixed */
3117 if (config->dims[current_dim].lower_limit != config->dims[current_dim].upper_limit) {
3118 proto_tree_add_expert_format(tree, pinfo, &ei_someip_payload_static_array_min_not_max, tvb, offset_orig, 0,
3119 "Static array config with Min!=Max (%d, %d)", config->dims[current_dim].lower_limit, config->dims[current_dim].upper_limit);
3120 col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP Payload: Static array config with Min!=Max!]");
3122 return 0;
3126 return offset - offset_orig;
3129 /* returns bytes parsed, length needs to be int to encode "non-existing" as -1 */
3130 static int
3131 // NOLINTNEXTLINE(misc-no-recursion)
3132 dissect_someip_payload_array_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset_orig, int length, int lower_limit, int upper_limit,
3133 someip_parameter_array_t *config) {
3134 tvbuff_t *subtvb = NULL;
3135 uint32_t offset = offset_orig;
3136 uint32_t bytes_parsed = 0;
3137 uint32_t ret = 0;
3138 int count = 0;
3140 if (length != -1) {
3141 if (length <= tvb_captured_length_remaining(tvb, offset)) {
3142 subtvb = tvb_new_subset_length(tvb, offset, length);
3143 /* created subtvb. so we set offset=0 */
3144 offset = 0;
3145 } else {
3146 expert_someip_payload_truncated(tree, pinfo, tvb, offset, tvb_captured_length_remaining(tvb, offset));
3147 return tvb_captured_length_remaining(tvb, offset);
3149 } else {
3150 subtvb = tvb;
3153 while ((length == -1 && count < upper_limit) || ((int)offset < length)) {
3154 bytes_parsed = dissect_someip_payload_parameter(subtvb, pinfo, tree, offset, (uint8_t)config->data_type, config->id_ref, config->name, config->hf_id, -1);
3155 if (bytes_parsed == 0) {
3156 /* does this make sense? */
3157 return 1;
3159 offset += bytes_parsed;
3160 count++;
3163 if (count<lower_limit && count>upper_limit) {
3164 proto_tree_add_expert_format(tree, pinfo, &ei_someip_payload_dyn_array_not_within_limit, tvb, offset_orig, length,
3165 "Number of items (%d) outside limit %d-%d", count, lower_limit, upper_limit);
3166 col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP Payload: Dynamic array does not stay between Min and Max values]");
3169 if (length != -1) {
3170 /* we created subtvb first and set offset to 0 */
3171 ret = offset;
3172 } else {
3173 ret = offset - offset_orig;
3176 return ret;
3179 static int
3180 // NOLINTNEXTLINE(misc-no-recursion)
3181 dissect_someip_payload_array_dim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset_orig, int length, int lower_limit, int upper_limit, someip_parameter_array_t *config, unsigned current_dim, char *name, uint32_t length_of_length) {
3182 proto_item *ti = NULL;
3183 proto_tree *subtree = NULL;
3184 int sub_length = 0;
3185 int sub_lower_limit = 0;
3186 int sub_upper_limit = 0;
3187 int i = 0;
3189 int sub_offset = 0;
3190 int offset = offset_orig;
3192 if (config->num_of_dims == current_dim + 1) {
3193 /* only payload left. :) */
3194 offset += dissect_someip_payload_array_payload(tvb, pinfo, tree, offset, length, lower_limit, upper_limit, config);
3195 } else {
3196 if (length != -1) {
3197 while (offset < offset_orig + (int)length) {
3198 sub_offset = offset;
3200 ti = proto_tree_add_string_format(tree, hf_payload_str_array, tvb, sub_offset, 0, name, "subarray (dim: %d, limit %d-%d)", current_dim + 1, sub_lower_limit, sub_upper_limit);
3201 subtree = proto_item_add_subtree(ti, ett_someip_array_dim);
3203 offset += dissect_someip_payload_array_dim_length(tvb, pinfo, subtree, offset, &sub_length, &sub_lower_limit, &sub_upper_limit, config, current_dim + 1, length_of_length);
3205 if (tvb_captured_length_remaining(tvb, offset) < (int)sub_length) {
3206 expert_someip_payload_truncated(subtree, pinfo, tvb, offset, tvb_captured_length_remaining(tvb, offset));
3207 return 0;
3210 offset += dissect_someip_payload_array_dim(tvb, pinfo, subtree, offset, sub_length, sub_lower_limit, sub_upper_limit, config, current_dim + 1, name, length_of_length);
3212 proto_item_set_end(ti, tvb, offset);
3214 } else {
3215 /* Multi-dim static array */
3216 sub_lower_limit = config->dims[current_dim].lower_limit;
3217 sub_upper_limit = config->dims[current_dim].upper_limit;
3219 for (i = 0; i < upper_limit; i++) {
3220 offset += dissect_someip_payload_array_dim(tvb, pinfo, tree, offset, -1, sub_lower_limit, sub_upper_limit, config, current_dim + 1, name, length_of_length);
3225 return offset - offset_orig;
3228 static int
3229 // NOLINTNEXTLINE(misc-no-recursion)
3230 dissect_someip_payload_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset_orig, uint32_t id, char *name, int wtlv_offset) {
3231 someip_parameter_array_t *config = NULL;
3233 proto_tree *subtree;
3234 proto_item *ti = NULL;
3236 int offset = offset_orig;
3238 int length = 0;
3239 int size_of_length = 0;
3240 int lower_limit = 0;
3241 int upper_limit = 0;
3243 config = get_array_config(id);
3245 if (config == NULL) {
3246 return 0;
3249 if (config->num_of_dims == 0 || config->dims == NULL) {
3250 expert_someip_payload_config_error(tree, pinfo, tvb, offset, 0, "Array config has not enough dimensions for this array!");
3251 return 0;
3254 ti = proto_tree_add_string_format(tree, hf_payload_str_array, tvb, offset, 0, config->name, "array %s", name);
3255 subtree = proto_item_add_subtree(ti, ett_someip_array);
3256 uint32_t length_of_length = dissect_someip_payload_add_wtlv_if_needed(tvb, pinfo, wtlv_offset, ti, subtree);
3258 offset += dissect_someip_payload_array_dim_length(tvb, pinfo, subtree, offset_orig, &length, &lower_limit, &upper_limit, config, 0, length_of_length);
3259 size_of_length = offset - offset_orig;
3261 if (length != -1) {
3262 proto_item_append_text(ti, " (elements limit: %d-%d)", lower_limit, upper_limit);
3263 } else {
3264 proto_item_append_text(ti, " (elements limit: %d)", upper_limit);
3267 offset += dissect_someip_payload_array_dim(tvb, pinfo, subtree, offset, length, lower_limit, upper_limit, config, 0, name, length_of_length);
3269 proto_item_set_end(ti, tvb, offset);
3271 if (length >= 0) {
3272 /* length field present */
3273 return size_of_length + length;
3274 } else {
3275 /* We have no length field, so we return what has been parsed! */
3276 return offset - offset_orig;
3280 static int
3281 // NOLINTNEXTLINE(misc-no-recursion)
3282 dissect_someip_payload_union(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset_orig, uint32_t id, char *name, int wtlv_offset) {
3283 someip_parameter_union_t *config = NULL;
3284 someip_parameter_union_item_t *item = NULL;
3286 proto_item *ti = NULL;
3287 proto_tree *subtree = NULL;
3289 tvbuff_t *subtvb;
3290 int buf_length = -1;
3292 int64_t tmp = 0;
3293 uint32_t length = 0;
3294 uint32_t type = 0;
3296 uint32_t i = 0;
3298 int offset = offset_orig;
3300 config = get_union_config(id);
3301 buf_length = tvb_captured_length_remaining(tvb, 0);
3303 if (config == NULL) {
3304 expert_someip_payload_config_error(tree, pinfo, tvb, offset, 0, "Union ID not configured");
3305 return 0;
3308 if (wtlv_offset >= 0) {
3309 ti = proto_tree_add_string_format(tree, hf_payload_str_union, tvb, wtlv_offset, 0, name, "union %s [%s]", name, config->name);
3310 } else {
3311 ti = proto_tree_add_string_format(tree, hf_payload_str_union, tvb, offset_orig, 0, name, "union %s [%s]", name, config->name);
3314 subtree = proto_item_add_subtree(ti, ett_someip_union);
3315 uint32_t length_of_length = dissect_someip_payload_add_wtlv_if_needed(tvb, pinfo, wtlv_offset, ti, subtree);
3317 if (length_of_length == 0) {
3318 length_of_length = config->length_of_length;
3321 if ((length_of_length + config->length_of_type) / 8 > (unsigned)buf_length - offset) {
3322 expert_someip_payload_truncated(tree, pinfo, tvb, offset, tvb_captured_length_remaining(tvb, offset));
3323 return 0;
3326 tmp = dissect_someip_payload_length_field(tvb, pinfo, subtree, offset_orig, length_of_length);
3327 if (tmp == -1) {
3328 return offset - offset_orig;
3329 } else {
3330 length = (uint32_t)tmp;
3333 tmp = dissect_someip_payload_type_field(tvb, pinfo, subtree, offset_orig + length_of_length / 8, config->length_of_type);
3334 if (tmp == -1) {
3335 return offset - offset_orig;
3336 } else {
3337 type = (uint32_t)tmp;
3340 offset += (length_of_length + config->length_of_type) / 8;
3341 proto_item_set_end(ti, tvb, offset + length);
3343 item = NULL;
3344 for (i = 0; i < config->num_of_items; i++) {
3345 if (config->items[i].id == type && config->items[i].name != NULL) {
3346 item = &(config->items[i]);
3350 if (item != NULL) {
3351 subtvb = tvb_new_subset_length(tvb, offset, length);
3352 dissect_someip_payload_parameter(subtvb, pinfo, subtree, 0, (uint8_t)item->data_type, item->id_ref, item->name, item->hf_id, -1);
3353 } else {
3354 expert_someip_payload_config_error(tree, pinfo, tvb, offset, 0, "Union type not configured");
3357 return length + (config->length_of_type + length_of_length) / 8;
3360 static int
3361 // NOLINTNEXTLINE(misc-no-recursion)
3362 dissect_someip_payload_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint8_t data_type, uint32_t idref, char *name, int *hf_id_ptr, int wtlv_offset) {
3363 int bytes_parsed = 0;
3365 increment_dissection_depth(pinfo);
3366 switch (data_type) {
3367 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_TYPEDEF:
3368 bytes_parsed = dissect_someip_payload_typedef(tvb, pinfo, tree, offset, idref, name, hf_id_ptr, wtlv_offset);
3369 break;
3370 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_BASE_TYPE:
3371 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ENUM:
3372 bytes_parsed = dissect_someip_payload_base_type(tvb, pinfo, tree, offset, data_type, idref, name, hf_id_ptr, wtlv_offset);
3373 break;
3374 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_STRING:
3375 bytes_parsed = dissect_someip_payload_string(tvb, pinfo, tree, offset, idref, name, hf_id_ptr, wtlv_offset);
3376 break;
3377 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ARRAY:
3378 bytes_parsed = dissect_someip_payload_array(tvb, pinfo, tree, offset, idref, name, wtlv_offset);
3379 break;
3380 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_STRUCT:
3381 bytes_parsed = dissect_someip_payload_struct(tvb, pinfo, tree, offset, idref, name, wtlv_offset);
3382 break;
3383 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_UNION:
3384 bytes_parsed = dissect_someip_payload_union(tvb, pinfo, tree, offset, idref, name, wtlv_offset);
3385 break;
3386 default:
3387 proto_tree_add_expert_format(tree, pinfo, &ei_someip_payload_config_error, tvb, offset, 0,
3388 "SOME/IP: Payload: item->data_type (0x%x) unknown/not implemented yet! name: %s, id_ref: 0x%x",
3389 data_type, name, idref);
3390 col_append_str(pinfo->cinfo, COL_INFO, " [SOME/IP: Payload Config Error]");
3391 break;
3393 decrement_dissection_depth(pinfo);
3395 return bytes_parsed;
3399 * returns <0 for errors
3401 static int dissect_someip_payload_peek_length_of_length(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset, int length, someip_payload_parameter_item_t *item) {
3402 if (item == NULL) {
3403 return -1;
3406 uint32_t data_type = item->data_type;
3407 uint32_t id_ref = item->id_ref;
3409 /* a config error could cause an endless loop, so we limit the number of indirections with loop_limit */
3410 int loop_limit = 255;
3411 while (data_type == SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_TYPEDEF && loop_limit > 0) {
3412 someip_payload_parameter_typedef_t *tmp = get_typedef_config(id_ref);
3413 data_type = tmp->data_type;
3414 id_ref = tmp->id_ref;
3415 loop_limit--;
3418 someip_payload_parameter_string_t *tmp_string_config;
3419 someip_parameter_array_t *tmp_array_config;
3420 someip_payload_parameter_struct_t *tmp_struct_config;
3421 someip_parameter_union_t *tmp_union_config;
3423 switch (data_type) {
3424 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_STRING:
3425 tmp_string_config = get_string_config(id_ref);
3426 if (tmp_string_config == NULL) {
3427 return -1;
3430 return tmp_string_config->length_of_length;
3432 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ARRAY:
3433 tmp_array_config = get_array_config(id_ref);
3434 if (tmp_array_config == NULL) {
3435 return -1;
3438 if (tmp_array_config->num_of_dims < 1 || tmp_array_config->dims == NULL) {
3439 expert_someip_payload_config_error(tree, pinfo, tvb, offset, length, "array configuration does not support WTLV");
3440 return -1;
3443 return tmp_array_config->dims[0].length_of_length;
3445 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_STRUCT:
3446 tmp_struct_config = get_struct_config(id_ref);
3447 if (tmp_struct_config == NULL) {
3448 return -1;
3451 return tmp_struct_config->length_of_length;
3453 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_UNION:
3454 tmp_union_config = get_union_config(id_ref);
3455 if (tmp_union_config == NULL) {
3456 return -1;
3459 return tmp_union_config->length_of_length;
3461 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_TYPEDEF:
3462 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_BASE_TYPE:
3463 case SOMEIP_PAYLOAD_PARAMETER_DATA_TYPE_ENUM:
3464 default:
3465 /* This happens only if configuration or message are buggy. */
3466 return -2;
3470 static int
3471 // NOLINTNEXTLINE(misc-no-recursion)
3472 dissect_someip_payload_parameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, someip_payload_parameter_item_t *items, uint32_t num_of_items, bool wtlv) {
3473 someip_payload_parameter_item_t *item;
3475 int offset_orig = offset;
3477 if (items == NULL && !someip_deserializer_wtlv_default) {
3478 return 0;
3481 if (wtlv) {
3482 while (tvb_captured_length_remaining(tvb, offset) >= 2) {
3483 uint64_t tagdata = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
3484 unsigned wiretype = (tagdata & SOMEIP_WTLV_MASK_WIRE_TYPE) >> 12;
3485 unsigned param_id = tagdata & SOMEIP_WTLV_MASK_DATA_ID;
3486 offset += 2;
3488 if (param_id < num_of_items && items != NULL) {
3489 item = &(items[param_id]);
3490 } else {
3491 item = NULL;
3494 unsigned param_length = 0;
3495 switch (wiretype) {
3497 /* fixed length type with just 1, 2, 4, or 8 byte length */
3498 case 0:
3499 case 1:
3500 case 2:
3501 case 3:
3502 param_length = 1 << wiretype;
3503 break;
3505 /* var length types like structs, strings, arrays, and unions */
3506 case 4:
3507 /* this type is deprecated and should not be used*/
3509 switch (dissect_someip_payload_peek_length_of_length(tree, pinfo, tvb, offset - 2, 0, item)) {
3510 case 8:
3511 param_length = 1 + tvb_get_uint8(tvb, offset);
3512 break;
3513 case 16:
3514 param_length = 2 + tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
3515 break;
3516 case 32:
3517 param_length = 4 + tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
3518 break;
3519 default:
3520 expert_someip_payload_config_error(tree, pinfo, tvb, offset - 2, 2, "WTLV type 4 but datatype has not an appropriate length field configured");
3521 return 8 * (offset - offset_orig);
3523 break;
3525 case 5:
3526 param_length = 1 + tvb_get_uint8(tvb, offset);
3527 break;
3528 case 6:
3529 param_length = 2 + tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
3530 break;
3531 case 7:
3532 param_length = 4 + tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
3533 break;
3535 default:
3536 /* unsupported Wire Type!*/
3537 expert_someip_payload_malformed(tree, pinfo, tvb, offset - 2, 2);
3538 break;
3541 tvbuff_t *subtvb = tvb_new_subset_length(tvb, offset - 2, param_length + 2);
3542 if (item != NULL) {
3543 dissect_someip_payload_parameter(subtvb, pinfo, tree, 2, (uint8_t)item->data_type, item->id_ref, item->name, item->hf_id, 0);
3544 } else {
3545 proto_item *ti = proto_tree_add_item(tree, hf_payload_unparsed, subtvb, 2, param_length, ENC_NA);
3546 dissect_someip_payload_add_wtlv_if_needed(tvb, pinfo, offset - 2, ti, NULL);
3548 offset += param_length;
3550 } else {
3551 if (items == NULL) {
3552 return 0;
3554 uint32_t i;
3555 for (i = 0; i < num_of_items; i++) {
3556 item = &(items[i]);
3557 offset += dissect_someip_payload_parameter(tvb, pinfo, tree, offset, (uint8_t)item->data_type, item->id_ref, item->name, item->hf_id, -1);
3561 return offset - offset_orig;
3564 static void
3565 dissect_someip_payload(tvbuff_t* tvb, packet_info* pinfo, proto_item *ti, uint16_t serviceid, uint16_t methodid, uint8_t version, uint8_t msgtype) {
3566 someip_parameter_list_t* paramlist = NULL;
3568 int length = -1;
3569 int offset = 0;
3571 proto_tree *tree = NULL;
3573 length = tvb_captured_length_remaining(tvb, 0);
3574 tree = proto_item_add_subtree(ti, ett_someip_payload);
3575 paramlist = get_parameter_config(serviceid, methodid, version, msgtype);
3577 if (paramlist == NULL) {
3578 if (someip_deserializer_wtlv_default) {
3579 offset += dissect_someip_payload_parameters(tvb, pinfo, tree, offset, NULL, 0, true);
3580 } else {
3581 return;
3583 } else {
3584 offset += dissect_someip_payload_parameters(tvb, pinfo, tree, offset, paramlist->items, paramlist->num_of_items, paramlist->wtlv_encoding);
3587 if (length > offset) {
3588 proto_tree_add_item(tree, hf_payload_unparsed, tvb, offset, length - (offset), ENC_NA);
3592 /***********************************
3593 ******** SOME/IP Dissector ********
3594 ***********************************/
3596 static int
3597 dissect_someip_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
3598 uint32_t offset = 0;
3599 uint32_t someip_messageid = 0;
3600 uint32_t someip_serviceid = 0;
3601 uint32_t someip_methodid = 0;
3602 uint32_t someip_clientid = 0;
3603 uint32_t someip_sessionid = 0;
3604 uint32_t someip_length = 0;
3605 const char *service_description = NULL;
3606 const char *method_description = NULL;
3607 const char *client_description = NULL;
3608 someip_info_t someip_data = SOMEIP_INFO_T_INIT;
3610 uint32_t someip_payload_length = 0;
3611 tvbuff_t *subtvb = NULL;
3613 proto_item *ti = NULL;
3614 proto_item *ti_someip = NULL;
3615 proto_tree *someip_tree = NULL;
3616 proto_tree *msgtype_tree = NULL;
3618 uint32_t protocol_version = 0;
3619 uint32_t version = 0;
3620 uint32_t msgtype = 0;
3621 bool msgtype_ack = false;
3622 bool msgtype_tp = false;
3623 uint32_t retcode = 0;
3624 int tmp = 0;
3626 int tvb_length = tvb_captured_length_remaining(tvb, offset);
3628 col_set_str(pinfo->cinfo, COL_PROTOCOL, SOMEIP_NAME);
3629 col_set_str(pinfo->cinfo, COL_INFO, SOMEIP_NAME_LONG);
3630 ti_someip = proto_tree_add_item(tree, proto_someip, tvb, offset, -1, ENC_NA);
3631 someip_tree = proto_item_add_subtree(ti_someip, ett_someip);
3633 /* we should never get called with less than 8 bytes */
3634 if (tvb_length < 8) {
3635 return tvb_length;
3638 /* Message ID = Service ID + Method ID*/
3639 someip_messageid = tvb_get_ntohl(tvb, 0);
3640 ti = proto_tree_add_uint_format_value(someip_tree, hf_someip_messageid, tvb, offset, 4, someip_messageid, "0x%08x", someip_messageid);
3641 proto_item_set_hidden(ti);
3643 /* Service ID */
3644 ti = proto_tree_add_item_ret_uint(someip_tree, hf_someip_serviceid, tvb, offset, 2, ENC_BIG_ENDIAN, &someip_serviceid);
3645 someip_data.service_id = someip_serviceid;
3646 service_description = someip_lookup_service_name(someip_serviceid);
3647 if (service_description != NULL) {
3648 proto_item_append_text(ti, " (%s)", service_description);
3649 ti = proto_tree_add_string(someip_tree, hf_someip_servicename, tvb, offset, 2, service_description);
3650 proto_item_set_generated(ti);
3651 proto_item_set_hidden(ti);
3653 offset += 2;
3655 /* Method ID */
3656 ti = proto_tree_add_item_ret_uint(someip_tree, hf_someip_methodid, tvb, offset, 2, ENC_BIG_ENDIAN, &someip_methodid);
3657 someip_data.method_id = someip_methodid;
3658 method_description = someip_lookup_method_name(someip_serviceid, someip_methodid);
3659 if (method_description != NULL) {
3660 proto_item_append_text(ti, " (%s)", method_description);
3661 ti = proto_tree_add_string(someip_tree, hf_someip_methodname , tvb, offset, 2, method_description);
3662 proto_item_set_generated(ti);
3663 proto_item_set_hidden(ti);
3665 offset += 2;
3667 /* Length */
3668 proto_tree_add_item_ret_uint(someip_tree, hf_someip_length, tvb, offset, 4, ENC_BIG_ENDIAN, &someip_length);
3669 offset += 4;
3671 /* this checks if value of the header field */
3672 if (someip_length < 8) {
3673 expert_add_info_format(pinfo, ti_someip, &ei_someip_incomplete_headers, "%s", "SOME/IP length too short (<8 Bytes)!");
3674 return tvb_length;
3677 /* Add some additional info to the Protocol line and the Info Column*/
3678 if (service_description == NULL) {
3679 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (Service ID: 0x%04x, Method ID: 0x%04x, Length: %i)",
3680 SOMEIP_NAME_LONG, someip_serviceid, someip_methodid, someip_length);
3681 } else if (method_description == NULL) {
3682 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (Service ID: 0x%04x (%s), Method ID: 0x%04x, Length: %i)",
3683 SOMEIP_NAME_LONG, someip_serviceid, service_description, someip_methodid, someip_length);
3684 } else {
3685 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (Service ID: 0x%04x (%s), Method ID: 0x%04x (%s), Length: %i)",
3686 SOMEIP_NAME_LONG, someip_serviceid, service_description, someip_methodid, method_description, someip_length);
3688 proto_item_append_text(ti_someip, " (Service ID: 0x%04x, Method ID: 0x%04x, Length: %i)", someip_serviceid, someip_methodid, someip_length);
3690 /* check if we have bytes for the rest of the header */
3691 if (tvb_length < 0 || offset + 8 > (uint32_t)tvb_length) {
3692 expert_add_info_format(pinfo, ti_someip, &ei_someip_incomplete_headers, "%s", "SOME/IP not enough buffer bytes for header!");
3693 return tvb_length;
3696 /* Client ID */
3697 ti = proto_tree_add_item_ret_uint(someip_tree, hf_someip_clientid, tvb, offset, 2, ENC_BIG_ENDIAN, &someip_clientid);
3698 someip_data.client_id = someip_clientid;
3699 client_description = someip_lookup_client_name(someip_serviceid, someip_clientid);
3700 if (client_description != NULL) {
3701 proto_item_append_text(ti, " (%s)", client_description);
3702 ti = proto_tree_add_string(someip_tree, hf_someip_clientname, tvb, offset, 2, client_description);
3703 proto_item_set_generated(ti);
3704 proto_item_set_hidden(ti);
3706 offset += 2;
3708 /* Session ID */
3709 proto_tree_add_item_ret_uint(someip_tree, hf_someip_sessionid, tvb, offset, 2, ENC_BIG_ENDIAN, &someip_sessionid);
3710 someip_data.session_id = someip_sessionid;
3711 offset += 2;
3713 /* Protocol Version*/
3714 ti = proto_tree_add_item_ret_uint(someip_tree, hf_someip_protover, tvb, offset, 1, ENC_BIG_ENDIAN, &protocol_version);
3715 if (protocol_version!=SOMEIP_PROTOCOL_VERSION) {
3716 expert_add_info(pinfo, ti, &ei_someip_unknown_version);
3718 offset += 1;
3720 /* Major Version of Service Interface */
3721 proto_tree_add_item_ret_uint(someip_tree, hf_someip_interface_ver, tvb, offset, 1, ENC_BIG_ENDIAN, &version);
3722 someip_data.major_version = version;
3723 offset += 1;
3725 /* Message Type */
3726 ti = proto_tree_add_item_ret_uint(someip_tree, hf_someip_messagetype, tvb, offset, 1, ENC_BIG_ENDIAN, &msgtype);
3727 someip_data.message_type = msgtype;
3728 msgtype_tree = proto_item_add_subtree(ti, ett_someip_msgtype);
3729 proto_tree_add_item_ret_boolean(msgtype_tree, hf_someip_messagetype_ack_flag, tvb, offset, 1, ENC_BIG_ENDIAN, &msgtype_ack);
3730 proto_tree_add_item_ret_boolean(msgtype_tree, hf_someip_messagetype_tp_flag, tvb, offset, 1, ENC_BIG_ENDIAN, &msgtype_tp);
3732 proto_item_append_text(ti, " (%s)", val_to_str_const((~SOMEIP_MSGTYPE_TP_MASK)&msgtype, someip_msg_type, "Unknown Message Type"));
3733 if (msgtype_tp) {
3734 proto_item_append_text(ti, " (%s)", SOMEIP_MSGTYPE_TP_STRING);
3736 offset += 1;
3738 /* Return Code */
3739 ti = proto_tree_add_item_ret_uint(someip_tree, hf_someip_returncode, tvb, offset, 1, ENC_BIG_ENDIAN, &retcode);
3740 proto_item_append_text(ti, " (%s)", val_to_str_const(retcode, someip_return_code, "Unknown Return Code"));
3741 offset += 1;
3743 /* lets figure out what we have for the rest */
3744 if (((uint32_t)tvb_length >= (someip_length + 8)) ) {
3745 someip_payload_length = someip_length - SOMEIP_HDR_PART1_LEN;
3746 } else {
3747 someip_payload_length = tvb_length - SOMEIP_HDR_LEN;
3748 expert_add_info(pinfo, ti_someip, &ei_someip_message_truncated);
3751 /* Is this a SOME/IP-TP segment? */
3752 if (msgtype_tp) {
3753 uint32_t tp_offset = 0;
3754 bool tp_more_segments = false;
3755 bool update_col_info = true;
3756 fragment_head *someip_tp_head = NULL;
3757 proto_tree *tp_tree = NULL;
3759 ti = proto_tree_add_item(someip_tree, hf_someip_tp, tvb, offset, someip_payload_length, ENC_NA);
3760 tp_tree = proto_item_add_subtree(ti, ett_someip_tp);
3762 /* Unfortunately, with a bitmask set the value is always shifted and cannot be set directly. */
3763 proto_tree_add_item_ret_uint(tp_tree, hf_someip_tp_offset_encoded, tvb, offset, 4, ENC_BIG_ENDIAN, &tp_offset);
3764 tp_offset <<= 4;
3765 proto_tree_add_item(tp_tree, hf_someip_tp_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
3766 proto_tree_add_item_ret_boolean(tp_tree, hf_someip_tp_more_segments, tvb, offset, 4, ENC_BIG_ENDIAN, &tp_more_segments);
3767 ti = proto_tree_add_uint(tp_tree, hf_someip_tp_offset, tvb, offset, 4, tp_offset);
3768 PROTO_ITEM_SET_GENERATED(ti);
3769 offset += 4;
3771 proto_tree_add_item(tp_tree, hf_someip_payload, tvb, offset, someip_payload_length - SOMEIP_TP_HDR_LEN, ENC_NA);
3773 if (someip_tp_reassemble && tvb_bytes_exist(tvb, offset, someip_payload_length - SOMEIP_TP_HDR_LEN)) {
3774 someip_tp_head = fragment_add_check(&someip_tp_reassembly_table, tvb, offset, pinfo, 0,
3775 &someip_data, tp_offset, someip_payload_length - SOMEIP_TP_HDR_LEN, tp_more_segments);
3776 subtvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled SOME/IP-TP Segment",
3777 someip_tp_head, &someip_tp_frag_items, &update_col_info, someip_tree);
3779 } else {
3780 subtvb = tvb_new_subset_length(tvb, SOMEIP_HDR_LEN, someip_payload_length);
3783 if (subtvb != NULL) {
3784 /* TAP */
3785 if (have_tap_listener(tap_someip_messages)) {
3786 someip_messages_tap_t *stats_data = wmem_alloc(pinfo->pool, sizeof(someip_messages_tap_t));
3787 stats_data->service_id = (uint16_t)someip_serviceid;
3788 stats_data->method_id = (uint16_t)someip_methodid;
3789 stats_data->interface_version = (uint8_t)version;
3790 stats_data->message_type = (uint8_t)(~SOMEIP_MSGTYPE_TP_MASK) & msgtype;
3792 tap_queue_packet(tap_someip_messages, pinfo, stats_data);
3795 tvb_length = tvb_captured_length_remaining(subtvb, 0);
3796 if (tvb_length > 0) {
3797 tmp = dissector_try_uint_new(someip_dissector_table, someip_messageid, subtvb, pinfo, tree, false, &someip_data);
3799 /* if no subdissector was found, the generic payload dissector takes over. */
3800 if (tmp==0) {
3801 ti = proto_tree_add_item(someip_tree, hf_someip_payload, subtvb, 0, tvb_length, ENC_NA);
3803 if (someip_deserializer_activated) {
3804 dissect_someip_payload(subtvb, pinfo, ti, (uint16_t)someip_serviceid, (uint16_t)someip_methodid, (uint8_t)version, (uint8_t)(~SOMEIP_MSGTYPE_TP_MASK)&msgtype);
3805 } else {
3806 proto_tree* payload_dissection_disabled_info_sub_tree = proto_item_add_subtree(ti, ett_someip_payload);
3807 proto_tree_add_text_internal(payload_dissection_disabled_info_sub_tree, subtvb, 0, tvb_length, "Dissection of payload is disabled. It can be enabled via protocol preferences.");
3813 return SOMEIP_HDR_LEN + someip_payload_length;
3816 static unsigned
3817 get_someip_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) {
3818 return SOMEIP_HDR_PART1_LEN + (unsigned)tvb_get_ntohl(tvb, offset + 4);
3821 static int
3822 dissect_someip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
3823 tcp_dissect_pdus(tvb, pinfo, tree, true, SOMEIP_HDR_PART1_LEN, get_someip_message_len, dissect_someip_message, data);
3824 return tvb_reported_length(tvb);
3827 static bool
3828 could_this_be_dtls(tvbuff_t *tvb) {
3829 /* Headers compared
3831 * Byte | SOME/IP | DTLS
3832 * --------------------------------
3833 * 00 | Service ID | Content Type
3834 * 01 | Service ID | Version
3835 * 02 | Method ID | Version
3836 * 03 | Method ID | Epoch
3837 * 04 | Length | Epoch
3838 * 05 | Length | Sequence Counter
3839 * 06 | Length | Sequence Counter
3840 * 07 | Length | Sequence Counter
3841 * 08 | Client ID | Sequence Counter
3842 * 09 | Client ID | Sequence Counter
3843 * 10 | Session ID | Sequence Counter
3844 * 11 | Session ID | Length
3845 * 12 | SOME/IP Ver | Length
3846 * 13 | Iface Ver | ...
3847 * 14 | Msg Type | ...
3848 * 15 | Return Code | ...
3849 * 16 | ... | ...
3851 int length = tvb_captured_length_remaining(tvb, 0);
3853 /* DTLS header is 13 bytes. */
3854 if (length < 13) {
3855 /* not sure what we have here ... */
3856 return false;
3859 uint8_t dtls_content_type = tvb_get_uint8(tvb, 0);
3860 uint16_t dtls_version = tvb_get_uint16(tvb, 1, ENC_BIG_ENDIAN);
3861 uint16_t dtls_length = tvb_get_uint16(tvb, 11, ENC_BIG_ENDIAN);
3863 bool dtls_possible = (20 <= dtls_content_type) && (dtls_content_type <= 63) &&
3864 (0xfefc <= dtls_version) && (dtls_version <= 0xfeff) &&
3865 ((uint32_t)length == (uint32_t)dtls_length + 13);
3867 if (dtls_possible && length < SOMEIP_HDR_LEN) {
3868 return true;
3871 uint32_t someip_length = tvb_get_uint32(tvb, 4, ENC_BIG_ENDIAN);
3872 uint8_t someip_version = tvb_get_uint8(tvb, 12);
3874 /* typically this is 1500 bytes or less on UDP but being conservative */
3875 bool someip_possible = (someip_version == 1) && (8 <= someip_length) && (someip_length <= 65535) &&
3876 ((uint32_t)length == someip_length + 8);
3878 return dtls_possible && !someip_possible;
3881 static int
3882 dissect_someip_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
3883 if (someip_detect_dtls && could_this_be_dtls(tvb)) {
3884 if (!PINFO_FD_VISITED(pinfo)) {
3885 dissector_add_uint("dtls.port", (uint16_t)pinfo->destport, someip_handle_udp);
3888 if (dtls_handle != 0) {
3889 return call_dissector_with_data(dtls_handle, tvb, pinfo, tree, data);
3893 return udp_dissect_pdus(tvb, pinfo, tree, SOMEIP_HDR_PART1_LEN, NULL, get_someip_message_len, dissect_someip_message, data);
3896 static bool
3897 test_someip(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_, void *data _U_) {
3898 if (tvb_captured_length(tvb) < SOMEIP_HDR_LEN) {
3899 return false;
3902 if (tvb_get_uint32(tvb, 4, ENC_BIG_ENDIAN) < 8) {
3903 return false;
3906 if ((tvb_get_uint8(tvb, 12)) != SOMEIP_PROTOCOL_VERSION) {
3907 return false;
3910 if (!try_val_to_str((tvb_get_uint8(tvb, 14) & ~SOMEIP_MSGTYPE_TP_MASK), someip_msg_type)) {
3911 return false;
3914 return true;
3917 static bool
3918 dissect_some_ip_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
3919 if (test_someip(pinfo, tvb, 0, data)) {
3920 tcp_dissect_pdus(tvb, pinfo, tree, true, SOMEIP_HDR_PART1_LEN, get_someip_message_len, dissect_someip_message, data);
3921 return true;
3923 return false;
3926 static bool
3927 dissect_some_ip_heur_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
3928 return (udp_dissect_pdus(tvb, pinfo, tree, SOMEIP_HDR_PART1_LEN, test_someip, get_someip_message_len, dissect_someip_message, data) != 0);
3931 void
3932 proto_register_someip(void) {
3933 expert_module_t *expert_module_someip;
3935 uat_t *someip_service_uat;
3936 uat_t *someip_method_uat;
3937 uat_t *someip_eventgroup_uat;
3938 uat_t *someip_client_uat;
3940 uat_t *someip_parameter_base_type_list_uat;
3941 uat_t *someip_parameter_strings_uat;
3942 uat_t *someip_parameter_typedefs_uat;
3943 uat_t *someip_parameter_list_uat;
3944 uat_t *someip_parameter_arrays_uat;
3945 uat_t *someip_parameter_structs_uat;
3946 uat_t *someip_parameter_unions_uat;
3947 uat_t *someip_parameter_enums_uat;
3949 /* data fields */
3950 static hf_register_info hf[] = {
3951 { &hf_someip_serviceid,
3952 { "Service ID", "someip.serviceid",
3953 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3954 { &hf_someip_servicename,
3955 { "Service Name", "someip.servicename",
3956 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3957 { &hf_someip_methodid,
3958 { "Method ID", "someip.methodid",
3959 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3960 { &hf_someip_methodname,
3961 { "Method Name", "someip.methodname",
3962 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3963 { &hf_someip_messageid,
3964 { "Message ID", "someip.messageid",
3965 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3966 { &hf_someip_length,
3967 { "Length", "someip.length",
3968 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3969 { &hf_someip_clientid,
3970 { "Client ID", "someip.clientid",
3971 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3972 { &hf_someip_clientname,
3973 { "Client Name", "someip.clientname",
3974 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3975 { &hf_someip_sessionid,
3976 { "Session ID", "someip.sessionid",
3977 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3978 { &hf_someip_protover,
3979 { "SOME/IP Version", "someip.protoversion",
3980 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3981 { &hf_someip_interface_ver,
3982 { "Interface Version", "someip.interfaceversion",
3983 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3984 { &hf_someip_messagetype,
3985 { "Message Type", "someip.messagetype",
3986 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3987 { &hf_someip_messagetype_ack_flag,
3988 { "Message Type Ack Flag", "someip.messagetype.ack",
3989 FT_BOOLEAN, 8, NULL, SOMEIP_MSGTYPE_ACK_MASK, NULL, HFILL }},
3990 { &hf_someip_messagetype_tp_flag,
3991 { "Message Type TP Flag", "someip.messagetype.tp",
3992 FT_BOOLEAN, 8, NULL, SOMEIP_MSGTYPE_TP_MASK, NULL, HFILL }},
3993 { &hf_someip_returncode,
3994 { "Return Code", "someip.returncode",
3995 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3997 { &hf_someip_payload,
3998 { "Payload", "someip.payload",
3999 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4001 { &hf_someip_tp,
4002 { "SOME/IP-TP", "someip.tp",
4003 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4004 { &hf_someip_tp_offset,
4005 { "Offset", "someip.tp.offset",
4006 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4007 { &hf_someip_tp_offset_encoded,
4008 { "Encoded Offset", "someip.tp.offset_encoded",
4009 FT_UINT32, BASE_HEX, NULL, SOMEIP_TP_OFFSET_MASK, NULL, HFILL }},
4010 { &hf_someip_tp_flags,
4011 { "Flags", "someip.tp.flags",
4012 FT_UINT32, BASE_HEX, NULL, SOMEIP_TP_OFFSET_MASK_FLAGS, NULL, HFILL }},
4013 { &hf_someip_tp_reserved,
4014 { "Reserved", "someip.tp.flags.reserved",
4015 FT_UINT32, BASE_HEX, NULL, SOMEIP_TP_OFFSET_MASK_RESERVED, NULL, HFILL }},
4016 { &hf_someip_tp_more_segments,
4017 { "More Segments", "someip.tp.flags.more_segments",
4018 FT_BOOLEAN, 32, NULL, SOMEIP_TP_OFFSET_MASK_MORE_SEGMENTS, NULL, HFILL }},
4020 {&hf_someip_tp_fragments,
4021 {"SOME/IP-TP segments", "someip.tp.fragments",
4022 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
4023 {&hf_someip_tp_fragment,
4024 {"SOME/IP-TP segment", "someip.tp.fragment",
4025 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
4026 {&hf_someip_tp_fragment_overlap,
4027 {"SOME/IP-TP segment overlap", "someip.tp.fragment.overlap",
4028 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
4029 {&hf_someip_tp_fragment_overlap_conflicts,
4030 {"SOME/IP-TP segment overlapping with conflicting data", "someip.tp.fragment.overlap.conflicts",
4031 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
4032 {&hf_someip_tp_fragment_multiple_tails,
4033 {"SOME/IP-TP Message has multiple tail fragments", "someip.tp.fragment.multiple_tails",
4034 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
4035 {&hf_someip_tp_fragment_too_long_fragment,
4036 {"SOME/IP-TP segment too long", "someip.tp.fragment.too_long_fragment",
4037 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
4038 {&hf_someip_tp_fragment_error,
4039 {"SOME/IP-TP Message defragmentation error", "someip.tp.fragment.error",
4040 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
4041 {&hf_someip_tp_fragment_count,
4042 {"SOME/IP-TP segment count", "someip.tp.fragment.count",
4043 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
4044 {&hf_someip_tp_reassembled_in,
4045 {"Reassembled in", "someip.tp.reassembled.in",
4046 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
4047 {&hf_someip_tp_reassembled_length,
4048 {"Reassembled length", "someip.tp.reassembled.length",
4049 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
4051 {&hf_someip_tp_reassembled_data,
4052 {"Reassembled data", "someip.tp.reassembled.data",
4053 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4055 { &hf_payload_unparsed,
4056 { "Unparsed Payload", "someip.payload.unparsed",
4057 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4058 { &hf_payload_length_field_8bit,
4059 { "Length", "someip.payload.length",
4060 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4061 { &hf_payload_length_field_16bit,
4062 { "Length", "someip.payload.length",
4063 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4064 { &hf_payload_length_field_32bit,
4065 { "Length", "someip.payload.length",
4066 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4067 { &hf_payload_type_field_8bit,
4068 { "Type", "someip.payload.type",
4069 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4070 { &hf_payload_type_field_16bit,
4071 { "Type", "someip.payload.type",
4072 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4073 { &hf_payload_type_field_32bit,
4074 { "Type", "someip.payload.type",
4075 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4077 { &hf_payload_str_base, {
4078 "(base)", "someip.payload.base",
4079 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4080 { &hf_payload_str_string, {
4081 "(string)", "someip.payload.string",
4082 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4083 { &hf_payload_str_struct, {
4084 "(struct)", "someip.payload.struct",
4085 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4086 { &hf_payload_str_array, {
4087 "(array)", "someip.payload.array",
4088 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4089 { &hf_payload_str_union, {
4090 "(array)", "someip.payload.union",
4091 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4093 { &hf_payload_wtlv_tag, {
4094 "WTLV-TAG", "someip.payload.wtlvtag",
4095 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
4096 { &hf_payload_wtlv_tag_res, {
4097 "Reserved", "someip.payload.wtlvtag.res",
4098 FT_UINT16, BASE_DEC, NULL, SOMEIP_WTLV_MASK_RES, NULL, HFILL } },
4099 { &hf_payload_wtlv_tag_wire_type, {
4100 "Wire Type", "someip.payload.wtlvtag.wire_type",
4101 FT_UINT16, BASE_DEC, NULL, SOMEIP_WTLV_MASK_WIRE_TYPE, NULL, HFILL } },
4102 { &hf_payload_wtlv_tag_data_id, {
4103 "Data ID", "someip.payload.wtlvtag.data_id",
4104 FT_UINT16, BASE_DEC, NULL, SOMEIP_WTLV_MASK_DATA_ID, NULL, HFILL } },
4107 static int *ett[] = {
4108 &ett_someip,
4109 &ett_someip_msgtype,
4110 &ett_someip_tp,
4111 &ett_someip_tp_fragment,
4112 &ett_someip_tp_fragments,
4114 &ett_someip_payload,
4115 &ett_someip_string,
4116 &ett_someip_array,
4117 &ett_someip_array_dim,
4118 &ett_someip_struct,
4119 &ett_someip_union,
4121 &ett_someip_parameter,
4122 &ett_someip_wtlv_tag,
4126 /* UATs for user_data fields */
4127 static uat_field_t someip_service_uat_fields[] = {
4128 UAT_FLD_HEX(someip_service_ident, id, "Service ID", "ID of the SOME/IP Service (16bit hex without leading 0x)"),
4129 UAT_FLD_CSTRING(someip_service_ident, name, "Service Name", "Name of the SOME/IP Service (string)"),
4130 UAT_END_FIELDS
4133 static uat_field_t someip_method_uat_fields[] = {
4134 UAT_FLD_HEX(someip_method_ident, id, "Service ID", "ID of the SOME/IP Service (16bit hex without leading 0x)"),
4135 UAT_FLD_HEX(someip_method_ident, id2, "Methods ID", "ID of the SOME/IP Method/Event/Notifier (16bit hex without leading 0x)"),
4136 UAT_FLD_CSTRING(someip_method_ident, name, "Method Name", "Name of the SOME/IP Method/Event/Notifier (string)"),
4137 UAT_END_FIELDS
4140 static uat_field_t someip_eventgroup_uat_fields[] = {
4141 UAT_FLD_HEX(someip_eventgroup_ident, id, "Service ID", "ID of the SOME/IP Service (16bit hex without leading 0x)"),
4142 UAT_FLD_HEX(someip_eventgroup_ident, id2, "Eventgroup ID", "ID of the SOME/IP Eventgroup (16bit hex without leading 0x)"),
4143 UAT_FLD_CSTRING(someip_eventgroup_ident, name, "Eventgroup Name", "Name of the SOME/IP Service (string)"),
4144 UAT_END_FIELDS
4147 static uat_field_t someip_client_uat_fields[] = {
4148 UAT_FLD_HEX(someip_client_ident, id, "Service ID", "ID of the SOME/IP Service (16bit hex without leading 0x)"),
4149 UAT_FLD_HEX(someip_client_ident, id2, "Client ID", "ID of the SOME/IP Client (16bit hex without leading 0x)"),
4150 UAT_FLD_CSTRING(someip_client_ident, name, "Client Name", "Name of the SOME/IP Client (string)"),
4151 UAT_END_FIELDS
4154 static uat_field_t someip_parameter_list_uat_fields[] = {
4155 UAT_FLD_HEX(someip_parameter_list, service_id, "Service ID", "ID of the SOME/IP Service (16bit hex without leading 0x)"),
4156 UAT_FLD_HEX(someip_parameter_list, method_id, "Method ID", "ID of the SOME/IP Method/Event/Notifier (16bit hex without leading 0x)"),
4157 UAT_FLD_DEC(someip_parameter_list, version, "Version", "Version of the SOME/IP Service (8bit dec)"),
4158 UAT_FLD_HEX(someip_parameter_list, message_type, "Message Type", "Message Type (8bit hex without leading 0x)"),
4159 UAT_FLD_BOOL(someip_parameter_list, wtlv_encoding, "WTLV Extension?", "SOME/IP is extended by Wiretag-Length-Value encoding for this parameter list (not pure SOME/IP)"),
4161 UAT_FLD_DEC(someip_parameter_list, num_of_params, "Number of Parameters", "Number of Parameters (16bit dec), needs to be larger than greatest Parameter Position/ID"),
4163 UAT_FLD_DEC(someip_parameter_list, pos, "Parameter Position/ID", "Position or ID of parameter (16bit dec, starting with 0)"),
4164 UAT_FLD_CSTRING(someip_parameter_list, name, "Parameter Name", "Name of parameter (string)"),
4165 UAT_FLD_DEC(someip_parameter_list, data_type, "Parameter Type", "Type of parameter (1: base, 2: string, 3: array, 4: struct, 5: union, 6: typedef, 7: enum)"),
4166 UAT_FLD_HEX(someip_parameter_list, id_ref, "ID Reference", "ID Reference (32bit hex)"),
4167 UAT_FLD_CSTRING(someip_parameter_list, filter_string, "Filter String", "Unique filter string that will be prepended with someip.payload. (string)"),
4168 UAT_END_FIELDS
4171 static uat_field_t someip_parameter_array_uat_fields[] = {
4172 UAT_FLD_HEX(someip_parameter_arrays, id, "ID", "ID of SOME/IP array (32bit hex without leading 0x)"),
4173 UAT_FLD_CSTRING(someip_parameter_arrays, name, "Array Name", "Name of array"),
4174 UAT_FLD_DEC(someip_parameter_arrays, data_type, "Parameter Type", "Type of parameter (1: base, 2: string, 3: array, 4: struct, 5: union, 6: typedef, 7: enum)"),
4175 UAT_FLD_HEX(someip_parameter_arrays, id_ref, "ID Reference", "ID Reference (32bit hex)"),
4176 UAT_FLD_DEC(someip_parameter_arrays, num_of_dims, "Number of Items", "Number of Dimensions (16bit dec)"),
4177 UAT_FLD_CSTRING(someip_parameter_arrays, filter_string, "Filter String", "Unique filter string that will be prepended with someip.payload. (string)"),
4179 UAT_FLD_DEC(someip_parameter_arrays, num, "Dimension", "Dimension (16bit dec, starting with 0)"),
4180 UAT_FLD_DEC(someip_parameter_arrays, lower_limit, "Lower Limit", "Dimension (32bit dec)"),
4181 UAT_FLD_DEC(someip_parameter_arrays, upper_limit, "Upper Limit", "Dimension (32bit dec)"),
4182 UAT_FLD_DEC(someip_parameter_arrays, length_of_length, "Length of Length Field", "Length of the arrays length field in bits (8bit dec)"),
4183 UAT_FLD_DEC(someip_parameter_arrays, pad_to, "Pad to", "Padding pads to reach alignment (8bit dec)"),
4184 UAT_END_FIELDS
4187 static uat_field_t someip_parameter_struct_uat_fields[] = {
4188 UAT_FLD_HEX(someip_parameter_structs, id, "ID", "ID of SOME/IP struct (32bit hex without leading 0x)"),
4189 UAT_FLD_CSTRING(someip_parameter_structs, struct_name, "Struct Name", "Name of struct"),
4190 UAT_FLD_DEC(someip_parameter_structs, length_of_length, "Length of Length Field", "Length of the structs length field in bits (8bit dec)"),
4191 UAT_FLD_DEC(someip_parameter_structs, pad_to, "Pad to", "Padding pads to reach alignment (8bit dec)"),
4192 UAT_FLD_BOOL(someip_parameter_structs, wtlv_encoding, "WTLV Extension?", "SOME/IP is extended by Wiretag-Length-Value encoding for this struct (not pure SOME/IP)"),
4193 UAT_FLD_DEC(someip_parameter_structs, num_of_items, "Number of Items", "Number of Items (16bit dec)"),
4195 UAT_FLD_DEC(someip_parameter_structs, pos, "Parameter Position/ID", "Position or ID of parameter (16bit dec, starting with 0)"),
4196 UAT_FLD_CSTRING(someip_parameter_structs, name, "Parameter Name", "Name of parameter (string)"),
4197 UAT_FLD_DEC(someip_parameter_structs, data_type, "Parameter Type", "Type of parameter (1: base, 2: string, 3: array, 4: struct, 5: union, 6: typedef, 7: enum)"),
4198 UAT_FLD_HEX(someip_parameter_structs, id_ref, "ID Reference", "ID Reference (32bit hex)"),
4199 UAT_FLD_CSTRING(someip_parameter_structs, filter_string, "Filter String", "Unique filter string that will be prepended with someip.payload. (string)"),
4200 UAT_END_FIELDS
4203 static uat_field_t someip_parameter_union_uat_fields[] = {
4204 UAT_FLD_HEX(someip_parameter_unions, id, "ID", "ID of SOME/IP union (32bit hex without leading 0x)"),
4205 UAT_FLD_CSTRING(someip_parameter_unions, name, "Union Name", "Name of union"),
4206 UAT_FLD_DEC(someip_parameter_unions, length_of_length, "Length of Length Field", "Length of the unions length field in bits (uint8 dec)"),
4207 UAT_FLD_DEC(someip_parameter_unions, length_of_type, "Length of Type Field", "Length of the unions type field in bits (8bit dec)"),
4208 UAT_FLD_DEC(someip_parameter_unions, pad_to, "Pad to", "Padding pads to reach alignment (8bit dec)"),
4210 UAT_FLD_DEC(someip_parameter_unions, num_of_items, "Number of Items", "Number of Items (32bit dec)"),
4212 UAT_FLD_DEC(someip_parameter_unions, type_id, "Type ID", "ID of Type (32bit dec, starting with 0)"),
4213 UAT_FLD_CSTRING(someip_parameter_unions, type_name, "Type Name", "Name of Type (string)"),
4214 UAT_FLD_DEC(someip_parameter_unions, data_type, "Data Type", "Type of payload (1: base, 2: string, 3: array, 4: struct, 5: union, 6: typedef, 7: enum)"),
4215 UAT_FLD_HEX(someip_parameter_unions, id_ref, "ID Reference", "ID Reference (32bit hex)"),
4216 UAT_FLD_CSTRING(someip_parameter_unions, filter_string, "Filter String", "Unique filter string that will be prepended with someip.payload. (string)"),
4217 UAT_END_FIELDS
4220 static uat_field_t someip_parameter_enum_uat_fields[] = {
4221 UAT_FLD_HEX(someip_parameter_enums, id, "ID", "ID of SOME/IP enum (32bit hex without leading 0x)"),
4222 UAT_FLD_CSTRING(someip_parameter_enums, name, "Name", "Name of Enumeration (string)"),
4223 UAT_FLD_DEC(someip_parameter_enums, data_type, "Parameter Type", "Type of parameter (1: base, 2: string, 3: array, 4: struct, 5: union, 6: typedef, 7: enum)"),
4224 UAT_FLD_HEX(someip_parameter_enums, id_ref, "ID Reference", "ID Reference (32bit hex)"),
4225 UAT_FLD_DEC(someip_parameter_enums, num_of_items, "Number of Items", "Number of Items (32bit dec)"),
4227 UAT_FLD_HEX(someip_parameter_enums, value, "Value", "Value (64bit uint hex)"),
4228 UAT_FLD_CSTRING(someip_parameter_enums, value_name, "Value Name", "Name (string)"),
4229 UAT_END_FIELDS
4232 static uat_field_t someip_parameter_base_type_list_uat_fields[] = {
4233 UAT_FLD_HEX(someip_parameter_base_type_list, id, "ID ", "ID (32bit hex)"),
4234 UAT_FLD_CSTRING(someip_parameter_base_type_list, name, "Name", "Name of type (string)"),
4235 UAT_FLD_CSTRING(someip_parameter_base_type_list, data_type, "Data Type", "Data type (string)"),
4236 UAT_FLD_BOOL(someip_parameter_base_type_list, big_endian, "Big Endian", "Encoded Big Endian"),
4237 UAT_FLD_DEC(someip_parameter_base_type_list, bitlength_base_type, "Bitlength base type", "Bitlength base type (uint32 dec)"),
4238 UAT_FLD_DEC(someip_parameter_base_type_list, bitlength_encoded_type, "Bitlength enc. type", "Bitlength encoded type (uint32 dec)"),
4239 UAT_END_FIELDS
4242 static uat_field_t someip_parameter_string_list_uat_fields[] = {
4243 UAT_FLD_HEX(someip_parameter_strings, id, "ID ", "ID (32bit hex)"),
4244 UAT_FLD_CSTRING(someip_parameter_strings, name, "Name", "Name of string (string)"),
4245 UAT_FLD_CSTRING(someip_parameter_strings, encoding, "Encoding", "String Encoding (ascii, utf-8, utf-16)"),
4246 UAT_FLD_BOOL(someip_parameter_strings, dynamic_length, "Dynamic Length", "Dynamic length of string"),
4247 UAT_FLD_DEC(someip_parameter_strings, max_length, "Max. Length", "Maximum length/Length (uint32 dec)"),
4248 UAT_FLD_DEC(someip_parameter_strings, length_of_length, "Length of Len Field", "Length of the length field in bits (uint8 dec)"),
4249 UAT_FLD_BOOL(someip_parameter_strings, big_endian, "Big Endian", "Encoded Big Endian"),
4250 UAT_FLD_DEC(someip_parameter_strings, pad_to, "Pad to", "Padding pads to reach alignment (8bit dec)"),
4251 UAT_END_FIELDS
4254 static uat_field_t someip_parameter_typedef_list_uat_fields[] = {
4255 UAT_FLD_HEX(someip_parameter_typedefs, id, "ID ", "ID (32bit hex)"),
4256 UAT_FLD_CSTRING(someip_parameter_typedefs, name, "Name", "Name of typedef (string)"),
4257 UAT_FLD_DEC(someip_parameter_typedefs, data_type, "Data Type", "Type referenced item (1: base, 2: string, 3: array, 4: struct, 5: union, 6: typedef, 7: enum)"),
4258 UAT_FLD_HEX(someip_parameter_typedefs, id_ref, "ID Reference", "ID Reference (32bit hex)"),
4259 UAT_END_FIELDS
4262 static ei_register_info ei[] = {
4263 { &ei_someip_unknown_version,{ "someip.unknown_protocol_version",
4264 PI_PROTOCOL, PI_WARN, "SOME/IP Unknown Protocol Version!", EXPFILL } },
4265 { &ei_someip_message_truncated,{ "someip.message_truncated",
4266 PI_MALFORMED, PI_ERROR, "SOME/IP Truncated message!", EXPFILL } },
4267 { &ei_someip_incomplete_headers,{ "someip.incomplete_headers",
4268 PI_MALFORMED, PI_ERROR, "SOME/IP Incomplete headers or some bytes left over!", EXPFILL } },
4270 { &ei_someip_payload_truncated, {"someip.payload.expert_truncated",
4271 PI_MALFORMED, PI_ERROR, "SOME/IP Payload: Truncated payload!", EXPFILL} },
4272 { &ei_someip_payload_malformed, {"someip.payload.expert_malformed",
4273 PI_MALFORMED, PI_ERROR, "SOME/IP Payload: Malformed payload!", EXPFILL} },
4274 { &ei_someip_payload_config_error, {"someip.payload.expert_config_error",
4275 PI_MALFORMED, PI_ERROR, "SOME/IP Payload: Config Error!", EXPFILL} },
4276 { &ei_someip_payload_alignment_error, {"someip.payload.expert_alignment_error",
4277 PI_MALFORMED, PI_ERROR, "SOME/IP Payload: SOME/IP datatype must be align to a byte!", EXPFILL} },
4278 { &ei_someip_payload_static_array_min_not_max, {"someip.payload.expert_static_array_min_max",
4279 PI_MALFORMED, PI_ERROR, "SOME/IP Payload: Static array with min!=max!", EXPFILL} },
4280 { &ei_someip_payload_dyn_array_not_within_limit, {"someip.payload.expert_dyn_array_not_within_limit",
4281 PI_MALFORMED, PI_WARN, "SOME/IP Payload: Dynamic array does not stay between Min and Max values!", EXPFILL} },
4284 /* Register Protocol, Handles, Fields, ETTs, Expert Info, Dissector Table, Taps */
4285 proto_someip = proto_register_protocol(SOMEIP_NAME_LONG, SOMEIP_NAME, SOMEIP_NAME_FILTER);
4286 someip_handle_udp = register_dissector("someip_udp", dissect_someip_udp, proto_someip);
4287 someip_handle_tcp = register_dissector("someip_tcp", dissect_someip_tcp, proto_someip);
4289 proto_register_field_array(proto_someip, hf, array_length(hf));
4290 proto_register_subtree_array(ett, array_length(ett));
4291 expert_module_someip = expert_register_protocol(proto_someip);
4292 expert_register_field_array(expert_module_someip, ei, array_length(ei));
4294 someip_dissector_table = register_dissector_table("someip.messageid", "SOME/IP Message ID", proto_someip, FT_UINT32, BASE_HEX);
4296 tap_someip_messages = register_tap("someip_messages");
4298 /* init for SOME/IP-TP */
4299 reassembly_table_init(&someip_tp_reassembly_table, &someip_reassembly_table_functions);
4301 /* Register preferences */
4302 someip_module = prefs_register_protocol(proto_someip, &proto_reg_handoff_someip);
4304 /* UATs */
4305 someip_service_uat = uat_new("SOME/IP Services",
4306 sizeof(generic_one_id_string_t), /* record size */
4307 DATAFILE_SOMEIP_SERVICES, /* filename */
4308 true, /* from profile */
4309 (void **) &someip_service_ident, /* data_ptr */
4310 &someip_service_ident_num, /* numitems_ptr */
4311 UAT_AFFECTS_DISSECTION, /* but not fields */
4312 NULL, /* help */
4313 copy_generic_one_id_string_cb, /* copy callback */
4314 update_serviceid, /* update callback */
4315 free_generic_one_id_string_cb, /* free callback */
4316 post_update_someip_service_cb, /* post update callback */
4317 reset_someip_service_cb, /* reset callback */
4318 someip_service_uat_fields /* UAT field definitions */
4321 prefs_register_uat_preference(someip_module, "services", "SOME/IP Services",
4322 "A table to define names of SOME/IP services", someip_service_uat);
4324 someip_method_uat = uat_new("SOME/IP Methods/Events/Fields",
4325 sizeof(generic_two_id_string_t), /* record size */
4326 DATAFILE_SOMEIP_METHODS, /* filename */
4327 true, /* from profile */
4328 (void **) &someip_method_ident, /* data_ptr */
4329 &someip_method_ident_num, /* numitems_ptr */
4330 UAT_AFFECTS_DISSECTION, /* but not fields */
4331 NULL, /* help */
4332 copy_generic_two_id_string_cb, /* copy callback */
4333 update_two_identifier_16bit_check_both, /* update callback */
4334 free_generic_two_id_string_cb, /* free callback */
4335 post_update_someip_method_cb, /* post update callback */
4336 reset_someip_method_cb, /* reset callback */
4337 someip_method_uat_fields /* UAT field definitions */
4340 prefs_register_uat_preference(someip_module, "methods", "SOME/IP Methods",
4341 "A table to define names of SOME/IP methods", someip_method_uat);
4343 someip_eventgroup_uat = uat_new("SOME/IP Eventgroups",
4344 sizeof(generic_two_id_string_t), /* record size */
4345 DATAFILE_SOMEIP_EVENTGROUPS, /* filename */
4346 true, /* from profile */
4347 (void **) &someip_eventgroup_ident, /* data_ptr */
4348 &someip_eventgroup_ident_num, /* numitems_ptr */
4349 UAT_AFFECTS_DISSECTION, /* but not fields */
4350 NULL, /* help */
4351 copy_generic_two_id_string_cb, /* copy callback */
4352 update_two_identifier_16bit_check_both, /* update callback */
4353 free_generic_two_id_string_cb, /* free callback */
4354 post_update_someip_eventgroup_cb, /* post update callback */
4355 reset_someip_eventgroup_cb, /* reset callback */
4356 someip_eventgroup_uat_fields /* UAT field definitions */
4359 prefs_register_uat_preference(someip_module, "eventgroups", "SOME/IP Eventgroups",
4360 "A table to define names of SOME/IP eventgroups", someip_eventgroup_uat);
4362 someip_client_uat = uat_new("SOME/IP Clients",
4363 sizeof(generic_two_id_string_t), /* record size */
4364 DATAFILE_SOMEIP_CLIENTS, /* filename */
4365 true, /* from profile */
4366 (void **)&someip_client_ident, /* data_ptr */
4367 &someip_client_ident_num, /* numitems_ptr */
4368 UAT_AFFECTS_DISSECTION, /* but not fields */
4369 NULL, /* help */
4370 copy_generic_two_id_string_cb, /* copy callback */
4371 update_generic_two_identifier_16bit, /* update callback */
4372 free_generic_two_id_string_cb, /* free callback */
4373 post_update_someip_client_cb, /* post update callback */
4374 reset_someip_client_cb, /* reset callback */
4375 someip_client_uat_fields /* UAT field definitions */
4378 prefs_register_uat_preference(someip_module, "clients", "SOME/IP Clients",
4379 "A table to define names of SOME/IP clients", someip_client_uat);
4381 someip_parameter_list_uat = uat_new("SOME/IP Parameter List",
4382 sizeof(someip_parameter_list_uat_t), /* record size */
4383 DATAFILE_SOMEIP_PARAMETERS, /* filename */
4384 true, /* from profile */
4385 (void **)&someip_parameter_list, /* data_ptr */
4386 &someip_parameter_list_num, /* numitems_ptr */
4387 UAT_AFFECTS_DISSECTION | UAT_AFFECTS_FIELDS,
4388 NULL, /* help */
4389 copy_someip_parameter_list_cb, /* copy callback */
4390 update_someip_parameter_list, /* update callback */
4391 free_someip_parameter_list_cb, /* free callback */
4392 post_update_someip_parameter_list_cb, /* post update callback */
4393 reset_someip_parameter_list_cb, /* reset callback */
4394 someip_parameter_list_uat_fields /* UAT field definitions */
4397 prefs_register_bool_preference(someip_module, "reassemble_tp", "Reassemble SOME/IP-TP",
4398 "Reassemble SOME/IP-TP segments", &someip_tp_reassemble);
4400 prefs_register_bool_preference(someip_module, "payload_dissector_activated",
4401 "Dissect Payload",
4402 "Should the SOME/IP Dissector use the payload dissector?",
4403 &someip_deserializer_activated);
4405 prefs_register_bool_preference(someip_module, "detect_dtls_and_hand_off",
4406 "Try to automatically detect DTLS",
4407 "Should the SOME/IP Dissector automatically detect DTLS and hand off to it?",
4408 &someip_detect_dtls);
4410 prefs_register_bool_preference(someip_module, "payload_dissector_wtlv_default",
4411 "Try WTLV payload dissection for unconfigured messages (not pure SOME/IP)",
4412 "Should the SOME/IP Dissector use the payload dissector with the experimental WTLV encoding for unconfigured messages?",
4413 &someip_deserializer_wtlv_default);
4415 prefs_register_uat_preference(someip_module, "_someip_parameter_list", "SOME/IP Parameter List",
4416 "A table to define names of SOME/IP parameters", someip_parameter_list_uat);
4418 someip_parameter_arrays_uat = uat_new("SOME/IP Parameter Arrays",
4419 sizeof(someip_parameter_array_uat_t), /* record size */
4420 DATAFILE_SOMEIP_ARRAYS, /* filename */
4421 true, /* from profile */
4422 (void **)&someip_parameter_arrays, /* data_ptr */
4423 &someip_parameter_arrays_num, /* numitems_ptr */
4424 UAT_AFFECTS_DISSECTION | UAT_AFFECTS_FIELDS,
4425 NULL, /* help */
4426 copy_someip_parameter_array_cb, /* copy callback */
4427 update_someip_parameter_array, /* update callback */
4428 free_someip_parameter_array_cb, /* free callback */
4429 post_update_someip_parameter_array_cb, /* post update callback */
4430 reset_someip_parameter_array_cb, /* reset callback */
4431 someip_parameter_array_uat_fields /* UAT field definitions */
4434 prefs_register_uat_preference(someip_module, "_someip_parameter_arrays", "SOME/IP Parameter Arrays",
4435 "A table to define arrays used by SOME/IP", someip_parameter_arrays_uat);
4437 someip_parameter_structs_uat = uat_new("SOME/IP Parameter Structs",
4438 sizeof(someip_parameter_struct_uat_t), /* record size */
4439 DATAFILE_SOMEIP_STRUCTS, /* filename */
4440 true, /* from profile */
4441 (void **)&someip_parameter_structs, /* data_ptr */
4442 &someip_parameter_structs_num, /* numitems_ptr */
4443 UAT_AFFECTS_DISSECTION | UAT_AFFECTS_FIELDS,
4444 NULL, /* help */
4445 copy_someip_parameter_struct_cb, /* copy callback */
4446 update_someip_parameter_struct, /* update callback */
4447 free_someip_parameter_struct_cb, /* free callback */
4448 post_update_someip_parameter_struct_cb, /* post update callback */
4449 reset_someip_parameter_struct_cb, /* reset callback */
4450 someip_parameter_struct_uat_fields /* UAT field definitions */
4453 prefs_register_uat_preference(someip_module, "_someip_parameter_structs", "SOME/IP Parameter Structs",
4454 "A table to define structs used by SOME/IP", someip_parameter_structs_uat);
4456 someip_parameter_unions_uat = uat_new("SOME/IP Parameter Unions",
4457 sizeof(someip_parameter_union_uat_t), /* record size */
4458 DATAFILE_SOMEIP_UNIONS, /* filename */
4459 true, /* from profile */
4460 (void **)&someip_parameter_unions, /* data_ptr */
4461 &someip_parameter_unions_num, /* numitems_ptr */
4462 UAT_AFFECTS_DISSECTION | UAT_AFFECTS_FIELDS,
4463 NULL, /* help */
4464 copy_someip_parameter_union_cb, /* copy callback */
4465 update_someip_parameter_union, /* update callback */
4466 free_someip_parameter_union_cb, /* free callback */
4467 post_update_someip_parameter_union_cb, /* post update callback */
4468 reset_someip_parameter_union_cb, /* reset callback */
4469 someip_parameter_union_uat_fields /* UAT field definitions */
4472 prefs_register_uat_preference(someip_module, "_someip_parameter_unions", "SOME/IP Parameter Unions",
4473 "A table to define unions used by SOME/IP", someip_parameter_unions_uat);
4475 someip_parameter_enums_uat = uat_new("SOME/IP Parameter Enums",
4476 sizeof(someip_parameter_enum_uat_t), /* record size */
4477 DATAFILE_SOMEIP_ENUMS, /* filename */
4478 true, /* from profile */
4479 (void **)&someip_parameter_enums, /* data_ptr */
4480 &someip_parameter_enums_num, /* numitems_ptr */
4481 UAT_AFFECTS_DISSECTION, /* but not fields */
4482 NULL, /* help */
4483 copy_someip_parameter_enum_cb, /* copy callback */
4484 update_someip_parameter_enum, /* update callback */
4485 free_someip_parameter_enum_cb, /* free callback */
4486 post_update_someip_parameter_enum_cb, /* post update callback */
4487 reset_someip_parameter_enum_cb, /* reset callback */
4488 someip_parameter_enum_uat_fields /* UAT field definitions */
4491 prefs_register_uat_preference(someip_module, "_someip_parameter_enums", "SOME/IP Parameter Enums",
4492 "A table to define enumerations used by SOME/IP", someip_parameter_enums_uat);
4494 someip_parameter_base_type_list_uat = uat_new("SOME/IP Parameter Base Type List",
4495 sizeof(someip_parameter_base_type_list_uat_t), /* record size */
4496 DATAFILE_SOMEIP_BASE_TYPES, /* filename */
4497 true, /* from profile */
4498 (void **)&someip_parameter_base_type_list, /* data_ptr */
4499 &someip_parameter_base_type_list_num, /* numitems_ptr */
4500 UAT_AFFECTS_DISSECTION, /* but not fields */
4501 NULL, /* help */
4502 copy_someip_parameter_base_type_list_cb, /* copy callback */
4503 update_someip_parameter_base_type_list, /* update callback */
4504 free_someip_parameter_base_type_list_cb, /* free callback */
4505 post_update_someip_parameter_base_type_list_cb, /* post update callback */
4506 reset_someip_parameter_base_type_list_cb, /* reset callback */
4507 someip_parameter_base_type_list_uat_fields /* UAT field definitions */
4510 prefs_register_uat_preference(someip_module, "_someip_parameter_base_type_list", "SOME/IP Parameter Base Type List",
4511 "A table to define base types of SOME/IP parameters", someip_parameter_base_type_list_uat);
4513 someip_parameter_strings_uat = uat_new("SOME/IP Parameter String List",
4514 sizeof(someip_parameter_string_uat_t), /* record size */
4515 DATAFILE_SOMEIP_STRINGS, /* filename */
4516 true, /* from profile */
4517 (void **)&someip_parameter_strings, /* data_ptr */
4518 &someip_parameter_strings_num, /* numitems_ptr */
4519 UAT_AFFECTS_DISSECTION, /* but not fields */
4520 NULL, /* help */
4521 copy_someip_parameter_string_list_cb, /* copy callback */
4522 update_someip_parameter_string_list, /* update callback */
4523 free_someip_parameter_string_list_cb, /* free callback */
4524 post_update_someip_parameter_string_list_cb, /* post update callback */
4525 reset_someip_parameter_string_list_cb, /* reset callback */
4526 someip_parameter_string_list_uat_fields /* UAT field definitions */
4529 prefs_register_uat_preference(someip_module, "_someip_parameter_string_list", "SOME/IP Parameter String List",
4530 "A table to define strings parameters", someip_parameter_strings_uat);
4532 someip_parameter_typedefs_uat = uat_new("SOME/IP Parameter Typedef List",
4533 sizeof(someip_parameter_typedef_uat_t), /* record size */
4534 DATAFILE_SOMEIP_TYPEDEFS, /* filename */
4535 true, /* from profile */
4536 (void **)&someip_parameter_typedefs, /* data_ptr */
4537 &someip_parameter_typedefs_num, /* numitems_ptr */
4538 UAT_AFFECTS_DISSECTION, /* but not fields */
4539 NULL, /* help */
4540 copy_someip_parameter_typedef_list_cb, /* copy callback */
4541 update_someip_parameter_typedef_list, /* update callback */
4542 free_someip_parameter_typedef_list_cb, /* free callback */
4543 post_update_someip_parameter_typedef_list_cb, /* post update callback */
4544 reset_someip_parameter_typedef_list_cb, /* reset callback */
4545 someip_parameter_typedef_list_uat_fields /* UAT field definitions */
4548 prefs_register_uat_preference(someip_module, "_someip_parameter_typedef_list", "SOME/IP Parameter Typedef List",
4549 "A table to define typedefs", someip_parameter_typedefs_uat);
4552 static void
4553 clean_all_hashtables_with_empty_uat(void) {
4554 /* On config change, we delete all hashtables which should have 0 entries! */
4555 /* Usually this is already done in the post update cb of the uat.*/
4556 /* Unfortunately, Wireshark does not call the post_update_cb on config errors. :( */
4557 if (data_someip_services && someip_service_ident_num==0) {
4558 g_hash_table_destroy(data_someip_services);
4559 data_someip_services = NULL;
4561 if (data_someip_methods && someip_method_ident_num==0) {
4562 g_hash_table_destroy(data_someip_methods);
4563 data_someip_methods = NULL;
4565 if (data_someip_eventgroups && someip_eventgroup_ident_num==0) {
4566 g_hash_table_destroy(data_someip_eventgroups);
4567 data_someip_eventgroups = NULL;
4569 if (data_someip_clients && someip_client_ident_num == 0) {
4570 g_hash_table_destroy(data_someip_clients);
4571 data_someip_clients = NULL;
4573 if (data_someip_parameter_list && someip_parameter_list_num==0) {
4574 g_hash_table_destroy(data_someip_parameter_list);
4575 data_someip_parameter_list = NULL;
4577 if (data_someip_parameter_arrays && someip_parameter_arrays_num==0) {
4578 g_hash_table_destroy(data_someip_parameter_arrays);
4579 data_someip_parameter_arrays = NULL;
4581 if (data_someip_parameter_structs && someip_parameter_structs_num==0) {
4582 g_hash_table_destroy(data_someip_parameter_structs);
4583 data_someip_parameter_structs = NULL;
4585 if (data_someip_parameter_unions && someip_parameter_unions_num==0) {
4586 g_hash_table_destroy(data_someip_parameter_unions);
4587 data_someip_parameter_unions = NULL;
4589 if (data_someip_parameter_enums && someip_parameter_enums_num == 0) {
4590 g_hash_table_destroy(data_someip_parameter_enums);
4591 data_someip_parameter_enums = NULL;
4593 if (data_someip_parameter_base_type_list && someip_parameter_base_type_list_num==0) {
4594 g_hash_table_destroy(data_someip_parameter_base_type_list);
4595 data_someip_parameter_base_type_list = NULL;
4597 if (data_someip_parameter_strings && someip_parameter_strings_num==0) {
4598 g_hash_table_destroy(data_someip_parameter_strings);
4599 data_someip_parameter_strings = NULL;
4601 if (data_someip_parameter_typedefs && someip_parameter_typedefs_num==0) {
4602 g_hash_table_destroy(data_someip_parameter_typedefs);
4603 data_someip_parameter_typedefs = NULL;
4607 void
4608 proto_reg_handoff_someip(void) {
4609 static bool initialized = false;
4611 if (!initialized) {
4612 /* add support for (D)TLS decode as */
4613 dtls_dissector_add(0, someip_handle_udp);
4614 ssl_dissector_add(0, someip_handle_tcp);
4616 heur_dissector_add("udp", dissect_some_ip_heur_udp, "SOME/IP over UDP", "someip_udp_heur", proto_someip, HEURISTIC_DISABLE);
4617 heur_dissector_add("tcp", dissect_some_ip_heur_tcp, "SOME/IP over TCP", "someip_tcp_heur", proto_someip, HEURISTIC_DISABLE);
4619 stats_tree_register("someip_messages", "someip_messages", "SOME/IP Messages", 0, someip_messages_stats_tree_packet, someip_messages_stats_tree_init, NULL);
4621 dissector_add_uint_range_with_preference("udp.port", "", someip_handle_udp);
4622 dissector_add_uint_range_with_preference("tcp.port", "", someip_handle_tcp);
4624 dtls_handle = find_dissector("dtls");
4626 initialized = true;
4627 } else {
4628 clean_all_hashtables_with_empty_uat();
4631 update_dynamic_hf_entries_someip_parameter_list();
4632 update_dynamic_hf_entries_someip_parameter_arrays();
4633 update_dynamic_hf_entries_someip_parameter_structs();
4634 update_dynamic_hf_entries_someip_parameter_unions();
4638 * Editor modelines
4640 * Local Variables:
4641 * c-basic-offset: 4
4642 * tab-width: 8
4643 * indent-tabs-mode: nil
4644 * End:
4646 * ex: set shiftwidth=4 tabstop=8 expandtab:
4647 * :indentSize=4:tabSize=8:noTabs=true: