Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-autosar-ipdu-multiplexer.c
blobdeff4478b43a8b30eb6bb4a264b3e9eb9258d34e
1 /* packet-autosar-ipdu-multiplexer.c
2 * Dissector for AUTOSAR I-PDU Multiplexer.
3 * By Dr. Lars Voelker <lars.voelker@technica-engineering.de>
4 * Copyright 2021-2022 Dr. Lars Voelker
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <config.h>
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/uat.h>
18 #include "packet-autosar-ipdu-multiplexer.h"
20 #include "packet-socketcan.h"
21 #include "packet-flexray.h"
22 #include "packet-pdu-transport.h"
23 #include "packet-lin.h"
25 void proto_register_autosar_ipdu_multiplexer(void);
26 void proto_reg_handoff_autosar_ipdu_multiplexer(void);
29 * Dissector for AUTOSAR I-PDU Multiplexer
31 * See https ://www.autosar.org/fileadmin/user_upload/standards/classic/20-11/AUTOSAR_SWS_IPDUMultiplexer.pdf
34 /* this protocol */
35 static int proto_ipdu_multiplexer;
36 #define IPDUM_NAME "AUTOSAR I-PduM"
38 /* dissector handles - incoming messages */
39 static dissector_handle_t ipdum_handle_can;
40 static dissector_handle_t ipdum_handle_flexray;
41 static dissector_handle_t ipdum_handle_lin;
42 static dissector_handle_t ipdum_handle_pdu_transport;
44 /* subdissectors - outgoing messages */
45 static dissector_table_t subdissector_table;
47 /* header field */
48 static int hf_pdu;
49 static int hf_pdu_id;
50 static int hf_pdu_name;
51 static int hf_payload_unparsed;
53 /* etts */
54 static int ett_ipdum;
55 static int ett_ipdum_pdu;
57 /**************************************
58 ******** UAT configs ********
59 **************************************/
60 #define DATAFILE_IPDUM_MESSAGES "AUTOSAR_IPDUM_Messages"
61 #define DATAFILE_IPDUM_CAN_MAPPING "AUTOSAR_IPDUM_Binding_CAN"
62 #define DATAFILE_IPDUM_FLEXRAY_MAPPING "AUTOSAR_IPDUM_Binding_FlexRay"
63 #define DATAFILE_IPDUM_LIN_MAPPING "AUTOSAR_IPDUM_Binding_LIN"
64 #define DATAFILE_IPDUM_PDU_TRANSPORT_MAPPING "AUTOSAR_IPDUM_Binding_PDU_Transport"
67 typedef struct _ipdum_message_item {
68 uint32_t pos;
69 uint32_t pdu_id;
70 char *name;
71 uint32_t start_pos;
72 uint32_t bit_length;
73 uint32_t update_bit_pos;
74 } ipdum_message_item_t;
76 typedef struct _ipdum_message_list {
77 uint32_t id;
78 uint32_t num_of_items;
80 ipdum_message_item_t *items;
81 } ipdum_message_list_t;
83 typedef struct _ipdum_message_list_uat {
84 uint32_t id;
85 uint32_t num_of_params;
87 uint32_t pos;
88 uint32_t pdu_id;
89 char *name;
90 uint32_t start_pos;
91 uint32_t bit_length;
92 uint32_t update_bit_pos;
93 } ipdum_message_list_uat_t;
96 typedef struct _ipdum__can_mapping {
97 uint32_t can_id;
98 uint32_t bus_id;
99 uint32_t message_id;
100 } ipdum_can_mapping_t;
101 typedef ipdum_can_mapping_t ipdum_can_mapping_uat_t;
103 typedef struct _ipdum_flexray_mapping {
104 uint32_t channel;
105 uint32_t cycle;
106 uint32_t frame_id;
107 uint32_t message_id;
108 } ipdum_flexray_mapping_t;
109 typedef ipdum_flexray_mapping_t ipdum_flexray_mapping_uat_t;
111 typedef struct _ipdum_lin_mapping {
112 uint32_t frame_id;
113 uint32_t bus_id;
114 uint32_t message_id;
115 } ipdum_lin_mapping_t;
116 typedef ipdum_lin_mapping_t ipdum_lin_mapping_uat_t;
118 typedef struct _ipdum_pdu_transport_mapping {
119 uint32_t pdu_id;
120 uint32_t message_id;
121 } ipdum_pdu_transport_mapping_t;
122 typedef ipdum_pdu_transport_mapping_t ipdum_pdu_transport_mapping_uat_t;
124 static ipdum_message_list_uat_t *ipdum_message_list;
125 static unsigned ipdum_message_list_num;
126 static GHashTable *data_ipdum_messages;
128 static ipdum_can_mapping_t *ipdum_can_mapping;
129 static unsigned ipdum_can_mapping_num;
130 static GHashTable *data_ipdum_can_mappings;
132 static ipdum_flexray_mapping_t *ipdum_flexray_mapping;
133 static unsigned ipdum_flexray_mapping_num;
134 static GHashTable *data_ipdum_flexray_mappings;
136 static ipdum_lin_mapping_t *ipdum_lin_mapping;
137 static unsigned ipdum_lin_mapping_num;
138 static GHashTable *data_ipdum_lin_mappings;
140 static ipdum_pdu_transport_mapping_t *ipdum_pdu_transport_mapping;
141 static unsigned ipdum_pdu_transport_mapping_num;
142 static GHashTable *data_ipdum_pdu_transport_mappings;
145 /* UAT Callbacks and Helpers */
147 static void
148 ipdum_payload_free_key(void *key) {
149 wmem_free(wmem_epan_scope(), key);
152 static void
153 ipdum_payload_free_generic_data(void *data _U_) {
154 /* currently nothing to be free */
158 /* UAT: I-PduM Message Config */
159 UAT_HEX_CB_DEF(ipdum_message_list, id, ipdum_message_list_uat_t)
160 UAT_DEC_CB_DEF(ipdum_message_list, num_of_params, ipdum_message_list_uat_t)
161 UAT_DEC_CB_DEF(ipdum_message_list, pos, ipdum_message_list_uat_t)
162 UAT_HEX_CB_DEF(ipdum_message_list, pdu_id, ipdum_message_list_uat_t)
163 UAT_CSTRING_CB_DEF(ipdum_message_list, name, ipdum_message_list_uat_t)
164 UAT_DEC_CB_DEF(ipdum_message_list, start_pos, ipdum_message_list_uat_t)
165 UAT_DEC_CB_DEF(ipdum_message_list, bit_length, ipdum_message_list_uat_t)
166 UAT_DEC_CB_DEF(ipdum_message_list, update_bit_pos, ipdum_message_list_uat_t)
168 static void *
169 copy_ipdum_message_list_cb(void *n, const void *o, size_t size _U_) {
170 ipdum_message_list_uat_t *new_rec = (ipdum_message_list_uat_t *)n;
171 const ipdum_message_list_uat_t *old_rec = (const ipdum_message_list_uat_t *)o;
173 new_rec->id = old_rec->id;
174 new_rec->num_of_params = old_rec->num_of_params;
176 new_rec->pos = old_rec->pos;
177 new_rec->pdu_id = old_rec->pdu_id;
179 if (old_rec->name) {
180 new_rec->name = g_strdup(old_rec->name);
181 } else {
182 new_rec->name = NULL;
185 new_rec->start_pos = old_rec->start_pos;
186 new_rec->bit_length = old_rec->bit_length;
187 new_rec->update_bit_pos = old_rec->update_bit_pos;
189 return new_rec;
192 static bool
193 update_ipdum_message_list(void *r, char **err) {
194 ipdum_message_list_uat_t *rec = (ipdum_message_list_uat_t *)r;
196 if (rec->pos >= 0xffff) {
197 *err = ws_strdup_printf("Position too big");
198 return false;
201 if (rec->num_of_params >= 0xffff) {
202 *err = ws_strdup_printf("Number of PDUs too big");
203 return false;
206 if (rec->pos >= rec->num_of_params) {
207 *err = ws_strdup_printf("Position >= Number of PDUs");
208 return false;
211 if (rec->name == NULL || rec->name[0] == 0) {
212 *err = ws_strdup_printf("Name cannot be empty");
213 return false;
216 return true;
219 static void
220 free_ipdum_message_list_cb(void*r) {
221 ipdum_message_list_uat_t *rec = (ipdum_message_list_uat_t *)r;
222 if (rec->name) {
223 g_free(rec->name);
224 rec->name = NULL;
228 static void
229 post_update_ipdum_message_list_read_in_data(ipdum_message_list_uat_t *data, unsigned data_num, GHashTable *ht) {
230 if (ht == NULL || data == NULL || data_num == 0) {
231 return;
234 if (data_num) {
235 unsigned i = 0;
236 for (i = 0; i < data_num; i++) {
238 /* the hash table does not know about uint64, so we use int64*/
239 int64_t *key = wmem_new(wmem_epan_scope(), int64_t);
240 *key = (uint32_t)data[i].id;
242 ipdum_message_list_t *list = (ipdum_message_list_t *)g_hash_table_lookup(ht, key);
243 if (list == NULL) {
245 list = wmem_new(wmem_epan_scope(), ipdum_message_list_t);
247 list->id = data[i].id;
248 list->num_of_items = data[i].num_of_params;
250 ipdum_message_item_t *items = (ipdum_message_item_t *)wmem_alloc0_array(wmem_epan_scope(), ipdum_message_item_t, data[i].num_of_params);
252 list->items = items;
254 /* create new entry ... */
255 g_hash_table_insert(ht, key, list);
256 } else {
257 /* already present, deleting key */
258 wmem_free(wmem_epan_scope(), key);
261 /* and now we add to item array */
262 if (data[i].num_of_params == list->num_of_items && data[i].pos < list->num_of_items) {
263 ipdum_message_item_t *item = &(list->items[data[i].pos]);
265 /* we do not care if we overwrite param */
266 item->pos = data[i].pos;
267 item->pdu_id = data[i].pdu_id;
268 item->name = g_strdup(data[i].name);
269 item->start_pos = data[i].start_pos;
270 item->bit_length = data[i].bit_length;
271 item->update_bit_pos = data[i].update_bit_pos;
277 static void
278 post_update_ipdum_message_list_cb(void) {
279 /* destroy old hash table, if it exists */
280 if (data_ipdum_messages) {
281 g_hash_table_destroy(data_ipdum_messages);
282 data_ipdum_messages = NULL;
285 data_ipdum_messages = g_hash_table_new_full(g_int64_hash, g_int64_equal, &ipdum_payload_free_key, &ipdum_payload_free_generic_data);
286 post_update_ipdum_message_list_read_in_data(ipdum_message_list, ipdum_message_list_num, data_ipdum_messages);
289 static ipdum_message_list_t *
290 get_message_config(uint32_t id) {
291 if (data_ipdum_messages == NULL) {
292 return NULL;
295 int64_t key = (int64_t)id;
296 return (ipdum_message_list_t *)g_hash_table_lookup(data_ipdum_messages, &key);
300 /* UAT: CAN Binding Config */
301 UAT_HEX_CB_DEF(ipdum_can_mapping, can_id, ipdum_can_mapping_uat_t)
302 UAT_HEX_CB_DEF(ipdum_can_mapping, bus_id, ipdum_can_mapping_uat_t)
303 UAT_HEX_CB_DEF(ipdum_can_mapping, message_id, ipdum_can_mapping_uat_t)
305 static void *
306 copy_ipdum_can_mapping_cb(void *n, const void *o, size_t size _U_) {
307 ipdum_can_mapping_uat_t *new_rec = (ipdum_can_mapping_uat_t *)n;
308 const ipdum_can_mapping_uat_t *old_rec = (const ipdum_can_mapping_uat_t *)o;
310 new_rec->can_id = old_rec->can_id;
311 new_rec->bus_id = old_rec->bus_id;
312 new_rec->message_id = old_rec->message_id;
314 return new_rec;
317 static bool
318 update_ipdum_can_mapping(void *r, char **err) {
319 ipdum_can_mapping_uat_t *rec = (ipdum_can_mapping_uat_t *)r;
321 if ((rec->can_id & (CAN_RTR_FLAG | CAN_ERR_FLAG)) != 0) {
322 *err = g_strdup_printf("We currently do not support CAN IDs with RTR or Error Flag set (CAN_ID: 0x%x)", rec->can_id);
323 return false;
326 if ((rec->can_id & CAN_EFF_FLAG) == 0 && rec->can_id > CAN_SFF_MASK) {
327 *err = g_strdup_printf("Standard CAN ID (EFF flag not set) cannot be bigger than 0x7ff (CAN_ID: 0x%x)", rec->can_id);
328 return false;
331 return true;
334 static void
335 post_update_register_can(void) {
336 if (ipdum_handle_can == NULL) {
337 return;
340 dissector_delete_all("can.id", ipdum_handle_can);
341 dissector_delete_all("can.extended_id", ipdum_handle_can);
343 /* CAN: loop over all frame IDs in HT */
344 if (data_ipdum_can_mappings != NULL) {
345 GList *keys = g_hash_table_get_keys(data_ipdum_can_mappings);
347 GList *tmp;
348 for (tmp = keys; tmp != NULL; tmp = tmp->next) {
349 int32_t id = (*(int32_t*)tmp->data);
351 if ((id & CAN_EFF_FLAG) == CAN_EFF_FLAG) {
352 dissector_add_uint("can.extended_id", id & CAN_EFF_MASK, ipdum_handle_can);
353 } else {
354 dissector_add_uint("can.id", id & CAN_SFF_MASK, ipdum_handle_can);
358 g_list_free(keys);
362 static void
363 post_update_ipdum_can_mapping_cb(void) {
364 /* destroy old hash table, if it exists */
365 if (data_ipdum_can_mappings) {
366 g_hash_table_destroy(data_ipdum_can_mappings);
367 data_ipdum_can_mappings = NULL;
370 /* we don't need to free the data as long as we don't alloc it first */
371 data_ipdum_can_mappings = g_hash_table_new_full(g_int64_hash, g_int64_equal, &ipdum_payload_free_key, NULL);
373 if (data_ipdum_can_mappings == NULL || ipdum_can_mapping == NULL) {
374 return;
377 if (ipdum_can_mapping_num > 0) {
378 unsigned i;
379 for (i = 0; i < ipdum_can_mapping_num; i++) {
380 int64_t *key = wmem_new(wmem_epan_scope(), int64_t);
381 *key = ipdum_can_mapping[i].can_id;
382 *key |= ((int64_t)(ipdum_can_mapping[i].bus_id & 0xffff)) << 32;
384 g_hash_table_insert(data_ipdum_can_mappings, key, &ipdum_can_mapping[i]);
388 /* we need to make sure we register again */
389 post_update_register_can();
392 static ipdum_can_mapping_t *
393 get_can_mapping(uint32_t id, uint16_t bus_id) {
394 if (data_ipdum_can_mappings == NULL) {
395 return NULL;
398 int64_t key = ((int64_t)id & (CAN_EFF_MASK | CAN_EFF_FLAG)) | ((int64_t)bus_id << 32);
399 ipdum_can_mapping_t *tmp = (ipdum_can_mapping_t *)g_hash_table_lookup(data_ipdum_can_mappings, &key);
400 if (tmp == NULL) {
401 /* try again without Bus ID set */
402 key = id & (CAN_EFF_MASK | CAN_EFF_FLAG);
403 tmp = (ipdum_can_mapping_t *)g_hash_table_lookup(data_ipdum_can_mappings, &key);
406 return tmp;
410 /* UAT: FlexRay Binding Config */
411 UAT_HEX_CB_DEF(ipdum_flexray_mapping, channel, ipdum_flexray_mapping_uat_t)
412 UAT_HEX_CB_DEF(ipdum_flexray_mapping, cycle, ipdum_flexray_mapping_uat_t)
413 UAT_HEX_CB_DEF(ipdum_flexray_mapping, frame_id, ipdum_flexray_mapping_uat_t)
414 UAT_HEX_CB_DEF(ipdum_flexray_mapping, message_id, ipdum_flexray_mapping_uat_t)
416 static void *
417 copy_ipdum_flexray_mapping_cb(void *n, const void *o, size_t size _U_) {
418 ipdum_flexray_mapping_uat_t *new_rec = (ipdum_flexray_mapping_uat_t *)n;
419 const ipdum_flexray_mapping_uat_t *old_rec = (const ipdum_flexray_mapping_uat_t *)o;
421 new_rec->channel = old_rec->channel;
422 new_rec->cycle = old_rec->cycle;
423 new_rec->frame_id = old_rec->frame_id;
424 new_rec->message_id = old_rec->message_id;
426 return new_rec;
429 static bool
430 update_ipdum_flexray_mapping(void *r, char **err) {
431 ipdum_flexray_mapping_uat_t *rec = (ipdum_flexray_mapping_uat_t *)r;
433 if (rec->cycle > 0xff) {
434 *err = ws_strdup_printf("We currently only support 8 bit Cycles (Cycle: %i Frame ID: %i)", rec->cycle, rec->frame_id);
435 return false;
438 if (rec->frame_id > 0xffff) {
439 *err = ws_strdup_printf("We currently only support 16 bit Frame IDs (Cycle: %i Frame ID: %i)", rec->cycle, rec->frame_id);
440 return false;
443 return true;
446 static void
447 post_update_ipdum_flexray_mapping_cb(void) {
448 /* destroy old hash table, if it exists */
449 if (data_ipdum_flexray_mappings) {
450 g_hash_table_destroy(data_ipdum_flexray_mappings);
451 data_ipdum_flexray_mappings = NULL;
454 /* we don't need to free the data as long as we don't alloc it first */
455 data_ipdum_flexray_mappings = g_hash_table_new_full(g_int64_hash, g_int64_equal, &ipdum_payload_free_key, NULL);
457 if (data_ipdum_flexray_mappings == NULL || ipdum_flexray_mapping == NULL) {
458 return;
461 if (ipdum_flexray_mapping_num > 0) {
462 unsigned i;
463 for (i = 0; i < ipdum_flexray_mapping_num; i++) {
464 int64_t *key = wmem_new(wmem_epan_scope(), int64_t);
465 *key = ipdum_flexray_mapping[i].frame_id & 0xffff;
466 *key |= ((int64_t)ipdum_flexray_mapping[i].cycle & 0xff) << 16;
467 *key |= ((int64_t)ipdum_flexray_mapping[i].channel & 0xff) << 24;
469 g_hash_table_insert(data_ipdum_flexray_mappings, key, &ipdum_flexray_mapping[i]);
474 static ipdum_flexray_mapping_t *
475 get_flexray_mapping(uint8_t channel, uint8_t cycle, uint16_t flexray_id) {
476 if (data_ipdum_flexray_mappings == NULL) {
477 return NULL;
480 int64_t *key = wmem_new(wmem_epan_scope(), int64_t);
481 *key = (channel << 24) | (cycle << 16) | flexray_id;
483 ipdum_flexray_mapping_t *tmp = (ipdum_flexray_mapping_t*)g_hash_table_lookup(data_ipdum_flexray_mappings, key);
484 wmem_free(wmem_epan_scope(), key);
486 return tmp;
490 /* UAT: LIN Binding Config */
491 UAT_HEX_CB_DEF(ipdum_lin_mapping, frame_id, ipdum_lin_mapping_uat_t)
492 UAT_HEX_CB_DEF(ipdum_lin_mapping, bus_id, ipdum_lin_mapping_uat_t)
493 UAT_HEX_CB_DEF(ipdum_lin_mapping, message_id, ipdum_lin_mapping_uat_t)
495 static void *
496 copy_ipdum_lin_mapping_cb(void *n, const void *o, size_t size _U_) {
497 ipdum_lin_mapping_uat_t *new_rec = (ipdum_lin_mapping_uat_t *)n;
498 const ipdum_lin_mapping_uat_t *old_rec = (const ipdum_lin_mapping_uat_t*)o;
500 new_rec->frame_id = old_rec->frame_id;
501 new_rec->bus_id = old_rec->bus_id;
502 new_rec->message_id = old_rec->message_id;
504 return new_rec;
507 static bool
508 update_ipdum_lin_mapping(void *r, char **err) {
509 ipdum_lin_mapping_uat_t *rec = (ipdum_lin_mapping_uat_t *)r;
511 if (rec->frame_id > LIN_ID_MASK) {
512 *err = ws_strdup_printf("LIN Frame IDs are only uint with 6 bits (ID: %i)", rec->frame_id);
513 return false;
516 if (rec->bus_id > 0xffff) {
517 *err = ws_strdup_printf("LIN Bus IDs are only uint with 16 bits (ID: 0x%x, Bus ID: 0x%x)", rec->frame_id, rec->bus_id);
518 return false;
521 return true;
524 static void
525 post_update_register_lin(void) {
526 if (ipdum_handle_lin == NULL) {
527 return;
530 dissector_delete_all("lin.frame_id", ipdum_handle_lin);
532 /* LIN: loop over all frame IDs in HT */
533 if (data_ipdum_lin_mappings != NULL) {
534 GList *keys = g_hash_table_get_keys(data_ipdum_lin_mappings);
536 GList *tmp;
537 for (tmp = keys; tmp != NULL; tmp = tmp->next) {
538 int32_t *id = (int32_t*)tmp->data;
539 /* we register the combination of bus and frame id */
540 dissector_add_uint("lin.frame_id", *id, ipdum_handle_lin);
543 g_list_free(keys);
547 static void
548 post_update_ipdum_lin_mapping_cb(void) {
549 /* destroy old hash table, if it exists */
550 if (data_ipdum_lin_mappings) {
551 g_hash_table_destroy(data_ipdum_lin_mappings);
552 data_ipdum_lin_mappings = NULL;
555 /* we don't need to free the data as long as we don't alloc it first */
556 data_ipdum_lin_mappings = g_hash_table_new_full(g_int_hash, g_int_equal, &ipdum_payload_free_key, NULL);
558 if (data_ipdum_lin_mappings == NULL || ipdum_lin_mapping == NULL) {
559 return;
562 if (ipdum_lin_mapping_num > 0) {
563 unsigned i;
564 for (i = 0; i < ipdum_lin_mapping_num; i++) {
565 int *key = wmem_new(wmem_epan_scope(), int);
566 *key = (ipdum_lin_mapping[i].frame_id) & LIN_ID_MASK;
567 *key |= ((ipdum_lin_mapping[i].bus_id) & 0xffff) << 16;
569 g_hash_table_insert(data_ipdum_lin_mappings, key, &ipdum_lin_mapping[i]);
573 /* we need to make sure we register again */
574 post_update_register_lin();
577 static ipdum_lin_mapping_t*
578 get_lin_mapping(lin_info_t *lininfo) {
579 if (data_ipdum_lin_mappings == NULL) {
580 return NULL;
583 int32_t key = ((lininfo->id) & LIN_ID_MASK) | (((lininfo->bus_id) & 0xffff) << 16);
585 ipdum_lin_mapping_t *tmp = (ipdum_lin_mapping_t *)g_hash_table_lookup(data_ipdum_lin_mappings, &key);
587 if (tmp == NULL) {
588 /* try again without Bus ID set */
589 key = (lininfo->id) & LIN_ID_MASK;
590 tmp = (ipdum_lin_mapping_t *)g_hash_table_lookup(data_ipdum_lin_mappings, &key);
593 return tmp;
597 /* UAT: PDU Transport Binding Config */
598 UAT_HEX_CB_DEF(ipdum_pdu_transport_mapping, pdu_id, ipdum_pdu_transport_mapping_uat_t)
599 UAT_HEX_CB_DEF(ipdum_pdu_transport_mapping, message_id, ipdum_pdu_transport_mapping_uat_t)
601 static void *
602 copy_ipdum_pdu_transport_mapping_cb(void *n, const void *o, size_t size _U_) {
603 ipdum_pdu_transport_mapping_uat_t *new_rec = (ipdum_pdu_transport_mapping_uat_t*)n;
604 const ipdum_pdu_transport_mapping_uat_t *old_rec = (const ipdum_pdu_transport_mapping_uat_t*)o;
606 new_rec->pdu_id = old_rec->pdu_id;
607 new_rec->message_id = old_rec->message_id;
609 return new_rec;
612 static bool
613 update_ipdum_pdu_transport_mapping(void *r, char **err) {
614 ipdum_pdu_transport_mapping_uat_t *rec = (ipdum_pdu_transport_mapping_uat_t *)r;
616 if (rec->pdu_id > 0xffffffff) {
617 *err = ws_strdup_printf("PDU-Transport IDs are only uint32 (ID: %i)", rec->pdu_id);
618 return false;
621 return true;
624 static void
625 post_update_register_pdu_transport(void) {
626 if (ipdum_handle_pdu_transport == NULL) {
627 return;
630 dissector_delete_all("pdu_transport.id", ipdum_handle_pdu_transport);
632 /* PDU Transport: loop over all messages IDs in HT */
633 if (data_ipdum_pdu_transport_mappings != NULL) {
634 GList *keys = g_hash_table_get_keys(data_ipdum_pdu_transport_mappings);
636 GList *tmp;
637 for (tmp = keys; tmp != NULL; tmp = tmp->next) {
638 int64_t *id = (int64_t*)tmp->data;
639 dissector_add_uint("pdu_transport.id", ((uint32_t)((uint64_t)(*id)) & 0xffffffff), ipdum_handle_pdu_transport);
642 g_list_free(keys);
646 static void
647 post_update_ipdum_pdu_transport_mapping_cb(void) {
648 /* destroy old hash table, if it exists */
649 if (data_ipdum_pdu_transport_mappings) {
650 g_hash_table_destroy(data_ipdum_pdu_transport_mappings);
651 data_ipdum_pdu_transport_mappings = NULL;
654 /* we don't need to free the data as long as we don't alloc it first */
655 data_ipdum_pdu_transport_mappings = g_hash_table_new_full(g_int64_hash, g_int64_equal, &ipdum_payload_free_key, NULL);
657 if (data_ipdum_pdu_transport_mappings == NULL || ipdum_pdu_transport_mapping == NULL) {
658 return;
661 if (ipdum_pdu_transport_mapping_num > 0) {
662 unsigned i;
663 for (i = 0; i < ipdum_pdu_transport_mapping_num; i++) {
664 int64_t *key = wmem_new(wmem_epan_scope(), int64_t);
665 *key = ipdum_pdu_transport_mapping[i].pdu_id;
667 g_hash_table_insert(data_ipdum_pdu_transport_mappings, key, &ipdum_pdu_transport_mapping[i]);
671 /* we need to make sure we register again */
672 post_update_register_pdu_transport();
675 static ipdum_pdu_transport_mapping_t *
676 get_pdu_transport_mapping(uint32_t pdu_transport_id) {
677 if (data_ipdum_pdu_transport_mappings == NULL) {
678 return NULL;
681 int64_t key = (int64_t)pdu_transport_id;
682 return (ipdum_pdu_transport_mapping_t *)g_hash_table_lookup(data_ipdum_pdu_transport_mappings, &key);
685 /**************************************
686 ******** Dissection ********
687 **************************************/
689 static int
690 dissect_ipdum_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *root_tree, uint32_t id) {
691 int offset = 0;
692 int length = tvb_captured_length_remaining(tvb, 0);
694 proto_item *ti = proto_tree_add_item(root_tree, proto_ipdu_multiplexer, tvb, offset, -1, ENC_NA);
695 proto_tree *tree = proto_item_add_subtree(ti, ett_ipdum);
697 ipdum_message_list_t *config = get_message_config(id);
698 unsigned i;
700 col_set_str(pinfo->cinfo, COL_PROTOCOL, IPDUM_NAME);
701 col_set_str(pinfo->cinfo, COL_INFO, IPDUM_NAME);
703 if (config == NULL || config->num_of_items == 0) {
704 proto_tree_add_item(tree, hf_payload_unparsed, tvb, offset, length, ENC_NA);
705 } else {
706 for (i = 0; i < config->num_of_items; i++) {
707 bool update_bit_ok = true;
709 if (config->items[i].update_bit_pos != 0xffff) {
710 int update_byte = config->items[i].update_bit_pos / 8;
711 int update_bit_mask = 1 << (config->items[i].update_bit_pos % 8);
712 uint8_t tmp = tvb_get_uint8(tvb, update_byte);
713 update_bit_ok = (tmp & update_bit_mask) == update_bit_mask;
716 if (update_bit_ok) {
717 int start_byte = config->items[i].start_pos / 8;
718 int end_byte = (config->items[i].start_pos + config->items[i].bit_length) / 8;
719 if ((config->items[i].start_pos + config->items[i].bit_length) % 8 != 0) {
720 end_byte++;
723 int pdu_len = end_byte - start_byte;
724 if (pdu_len > tvb_captured_length_remaining(tvb, offset + start_byte)) {
725 pdu_len = tvb_captured_length_remaining(tvb, offset + start_byte);
728 ti = proto_tree_add_item(tree, hf_pdu, tvb, offset + start_byte, pdu_len, ENC_NA);
729 proto_tree *pdu_tree = proto_item_add_subtree(ti, ett_ipdum_pdu);
730 proto_tree_add_string(pdu_tree, hf_pdu_name, tvb, offset + start_byte, pdu_len, config->items[i].name);
731 proto_tree_add_uint(pdu_tree, hf_pdu_id, tvb, offset + start_byte, pdu_len, config->items[i].pdu_id);
733 tvbuff_t *subtvb = tvb_new_subset_length(tvb, offset + start_byte, pdu_len);
734 if (subtvb != NULL) {
735 autosar_ipdu_multiplexer_info_t pdu_t_info;
736 pdu_t_info.pdu_id = config->items[i].pdu_id;
738 dissector_try_uint_with_data(subdissector_table, config->items[i].pdu_id, subtvb, pinfo, root_tree, false, (void *)(&pdu_t_info));
743 return length;
746 static int
747 dissect_ipdum_message_can(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
748 struct can_info *can_info = (struct can_info *)data;
749 DISSECTOR_ASSERT(can_info);
751 if (can_info->id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) {
752 /* Error and RTR frames are not for us. */
753 return 0;
756 ipdum_can_mapping_t *can_mapping = get_can_mapping(can_info->id, can_info->bus_id);
757 if (can_mapping == NULL) {
758 return 0;
761 return dissect_ipdum_payload(tvb, pinfo, tree, can_mapping->message_id);
764 static bool
765 dissect_ipdum_message_can_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
766 return dissect_ipdum_message_can(tvb, pinfo, tree, data) != 0;
769 static int
770 dissect_ipdum_message_flexray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
771 struct flexray_info *flexray_data = (struct flexray_info*)data;
772 DISSECTOR_ASSERT(flexray_data);
774 ipdum_flexray_mapping_t *flexray_mapping = get_flexray_mapping(flexray_data->ch, flexray_data->cc, flexray_data->id);
776 if (flexray_mapping == NULL) {
777 return 0;
780 return dissect_ipdum_payload(tvb, pinfo, tree, flexray_mapping->message_id);
783 static bool
784 dissect_ipdum_message_flexray_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
785 return dissect_ipdum_message_flexray(tvb, pinfo, tree, data) != 0;
788 static int
789 dissect_ipdum_message_lin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
790 lin_info_t *lininfo = (lin_info_t *)data;
791 DISSECTOR_ASSERT(lininfo);
793 ipdum_lin_mapping_t *lin_mapping = get_lin_mapping(lininfo);
795 if (lin_mapping == NULL) {
796 return 0;
799 return dissect_ipdum_payload(tvb, pinfo, tree, lin_mapping->message_id);
802 static int
803 dissect_ipdum_message_pdu_transport(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
804 pdu_transport_info_t *pdu_info = (pdu_transport_info_t*)data;
805 DISSECTOR_ASSERT(pdu_info);
807 ipdum_pdu_transport_mapping_t *pdu_transport_mapping = get_pdu_transport_mapping(pdu_info->id);
809 if (pdu_transport_mapping == NULL) {
810 return 0;
813 return dissect_ipdum_payload(tvb, pinfo, tree, pdu_transport_mapping->message_id);
817 /**************************************
818 ******** Register Dissector ********
819 **************************************/
821 void
822 proto_register_autosar_ipdu_multiplexer(void) {
823 module_t *ipdum_module;
825 /* UAT for parsing the message */
826 uat_t *ipdum_message_uat;
828 /* UATs for binding to protocol */
829 uat_t *ipdum_can_mapping_uat;
830 uat_t *ipdum_flexray_mapping_uat;
831 uat_t *ipdum_lin_mapping_uat;
832 uat_t *ipdum_pdu_transport_mapping_uat;
834 static hf_register_info hf[] = {
835 { &hf_pdu,
836 { "PDU", "ipdum.pdu", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
837 { &hf_pdu_id,
838 { "PDU-ID", "ipdum.pdu.id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
839 { &hf_pdu_name,
840 { "Name", "ipdum.pdu.name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
841 { &hf_payload_unparsed,
842 { "Unparsed Payload", "ipdum.unparsed", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
845 static int *ett[] = {
846 &ett_ipdum,
847 &ett_ipdum_pdu,
850 static uat_field_t ipdum_message_list_uat_fields[] = {
851 UAT_FLD_HEX(ipdum_message_list, id, "I-PduM Message ID", "ID of the I-PduM Message (32bit hex without leading 0x)"),
852 UAT_FLD_DEC(ipdum_message_list, num_of_params, "Number of PDUs", "Number of PDUs (16bit dec)"),
854 UAT_FLD_DEC(ipdum_message_list, pos, "PDU Position", "Position of PDU (16bit dec, starting with 0)"),
855 UAT_FLD_HEX(ipdum_message_list, pdu_id, "PDU ID", "ID of the PDU (32bit hex without leading 0x)"),
856 UAT_FLD_CSTRING(ipdum_message_list, name, "PDU Name", "Name of PDU (string)"),
857 UAT_FLD_DEC(ipdum_message_list, start_pos, "PDU Start Pos (bits)", "Start Position of PDU in bits (16bit dec, starting with 0)"),
858 UAT_FLD_DEC(ipdum_message_list, bit_length, "PDU Length (bits)", "Length of PDU in bits (16bit dec, starting with 0)"),
859 UAT_FLD_DEC(ipdum_message_list, update_bit_pos, "PDU Update Bit", "Position of Update bit (16bit dec, starting with 0, 65535 disabled)"),
860 UAT_END_FIELDS
863 static uat_field_t ipdum_can_mapping_uat_fields[] = {
864 UAT_FLD_HEX(ipdum_can_mapping, can_id, "CAN ID", "CAN ID (32bit hex without leading 0x, highest bit 1 for extended, 0 for standard ID)"),
865 UAT_FLD_HEX(ipdum_can_mapping, bus_id, "Bus ID", "Bus ID on which frame was recorded with 0=any (16bit hex without leading 0x)"),
866 UAT_FLD_HEX(ipdum_can_mapping, message_id, "Message ID", "ID of the I-PduM Config (32bit hex without leading 0x)"),
867 UAT_END_FIELDS
870 static uat_field_t ipdum_flexray_mapping_uat_fields[] = {
871 UAT_FLD_HEX(ipdum_flexray_mapping, channel, "Channel", "Channel (8bit hex without leading 0x)"),
872 UAT_FLD_HEX(ipdum_flexray_mapping, frame_id, "Frame ID", "Frame ID (16bit hex without leading 0x)"),
873 UAT_FLD_HEX(ipdum_flexray_mapping, cycle, "Cycle", "Cycle (8bit hex without leading 0x)"),
874 UAT_FLD_HEX(ipdum_flexray_mapping, message_id, "Message ID", "ID of the I-PduM Config (32bit hex without leading 0x)"),
875 UAT_END_FIELDS
878 static uat_field_t ipdum_lin_mapping_uat_fields[] = {
879 UAT_FLD_HEX(ipdum_lin_mapping, frame_id, "Frame ID", "LIN Frame ID (6bit hex without leading 0x)"),
880 UAT_FLD_HEX(ipdum_lin_mapping, bus_id, "Bus ID", "Bus ID on which frame was recorded with 0=any (16bit hex without leading 0x)"),
881 UAT_FLD_HEX(ipdum_lin_mapping, message_id, "Message ID", "ID of the I-PduM Config (32bit hex without leading 0x)"),
882 UAT_END_FIELDS
885 static uat_field_t ipdum_pdu_transport_mapping_uat_fields[] = {
886 UAT_FLD_HEX(ipdum_pdu_transport_mapping, pdu_id, "PDU ID", "PDU ID (32bit hex without leading 0x)"),
887 UAT_FLD_HEX(ipdum_pdu_transport_mapping, message_id, "Message ID", "ID of the I-PduM Config (32bit hex without leading 0x)"),
888 UAT_END_FIELDS
892 proto_ipdu_multiplexer = proto_register_protocol("AUTOSAR I-PDU Multiplexer", IPDUM_NAME, "ipdum");
893 ipdum_module = prefs_register_protocol(proto_ipdu_multiplexer, NULL);
895 proto_register_field_array(proto_ipdu_multiplexer, hf, array_length(hf));
896 proto_register_subtree_array(ett, array_length(ett));
898 subdissector_table = register_dissector_table("ipdum.pdu.id", "I-PduM PDU ID", proto_ipdu_multiplexer, FT_UINT32, BASE_HEX);
901 ipdum_message_uat = uat_new("I-PduM Message List",
902 sizeof(ipdum_message_list_uat_t), /* record size */
903 DATAFILE_IPDUM_MESSAGES, /* filename */
904 true, /* from profile */
905 (void**)&ipdum_message_list, /* data_ptr */
906 &ipdum_message_list_num, /* numitems_ptr */
907 UAT_AFFECTS_DISSECTION, /* but not fields */
908 NULL, /* help */
909 copy_ipdum_message_list_cb, /* copy callback */
910 update_ipdum_message_list, /* update callback */
911 free_ipdum_message_list_cb, /* free callback */
912 post_update_ipdum_message_list_cb, /* post update callback */
913 NULL, /* reset callback */
914 ipdum_message_list_uat_fields /* UAT field definitions */
917 prefs_register_uat_preference(ipdum_module, "_ipdum_message_list", "Message List",
918 "A table to define messages and PDUs", ipdum_message_uat);
921 prefs_register_static_text_preference(ipdum_module, "empty1", "", NULL);
922 prefs_register_static_text_preference(ipdum_module, "map", "Protocol Mappings:", NULL);
925 ipdum_can_mapping_uat = uat_new("CAN",
926 sizeof(ipdum_can_mapping_uat_t), /* record size */
927 DATAFILE_IPDUM_CAN_MAPPING, /* filename */
928 true, /* from profile */
929 (void**)&ipdum_can_mapping, /* data_ptr */
930 &ipdum_can_mapping_num, /* numitems_ptr */
931 UAT_AFFECTS_DISSECTION, /* but not fields */
932 NULL, /* help */ /* help */
933 copy_ipdum_can_mapping_cb, /* copy callback */
934 update_ipdum_can_mapping, /* update callback */
935 NULL, /* free callback */
936 post_update_ipdum_can_mapping_cb, /* post update callback */
937 NULL, /* reset */ /* reset callback */
938 ipdum_can_mapping_uat_fields /* UAT field definitions */
941 prefs_register_uat_preference(ipdum_module, "_ipdum_can_mapping", "CAN Mappings",
942 "A table to map CAN payloads to I-PduM Message configuration", ipdum_can_mapping_uat);
945 ipdum_flexray_mapping_uat = uat_new("FlexRay",
946 sizeof(ipdum_flexray_mapping_uat_t), /* record size */
947 DATAFILE_IPDUM_FLEXRAY_MAPPING, /* filename */
948 true, /* from profile */
949 (void**)&ipdum_flexray_mapping, /* data_ptr */
950 &ipdum_flexray_mapping_num, /* numitems_ptr */
951 UAT_AFFECTS_DISSECTION, /* but not fields */
952 NULL, /* help */
953 copy_ipdum_flexray_mapping_cb, /* copy callback */
954 update_ipdum_flexray_mapping, /* update callback */
955 NULL, /* free callback */
956 post_update_ipdum_flexray_mapping_cb, /* post update callback */
957 NULL, /* reset callback */
958 ipdum_flexray_mapping_uat_fields /* UAT field definitions */
961 prefs_register_uat_preference(ipdum_module, "_ipdum_flexray_mapping", "FlexRay Mappings",
962 "A table to map FlexRay payloads to I-PduM Message configuration", ipdum_flexray_mapping_uat);
965 ipdum_lin_mapping_uat = uat_new("LIN",
966 sizeof(ipdum_lin_mapping_uat_t), /* record size */
967 DATAFILE_IPDUM_LIN_MAPPING, /* filename */
968 true, /* from profile */
969 (void**)&ipdum_lin_mapping, /* data_ptr */
970 &ipdum_lin_mapping_num, /* numitems_ptr */
971 UAT_AFFECTS_DISSECTION, /* but not fields */
972 NULL, /* help */
973 copy_ipdum_lin_mapping_cb, /* copy callback */
974 update_ipdum_lin_mapping, /* update callback */
975 NULL, /* free callback */
976 post_update_ipdum_lin_mapping_cb, /* post update callback */
977 NULL, /* reset callback */
978 ipdum_lin_mapping_uat_fields /* UAT field definitions */
981 prefs_register_uat_preference(ipdum_module, "_ipdum_lin_mapping", "LIN Mappings",
982 "A table to map LIN payloads to I-PduM Message configuration", ipdum_lin_mapping_uat);
985 ipdum_pdu_transport_mapping_uat = uat_new("PDU Transport",
986 sizeof(ipdum_pdu_transport_mapping_uat_t), /* record size */
987 DATAFILE_IPDUM_PDU_TRANSPORT_MAPPING, /* filename */
988 true, /* from profile */
989 (void**)&ipdum_pdu_transport_mapping, /* data_ptr */
990 &ipdum_pdu_transport_mapping_num, /* numitems_ptr */
991 UAT_AFFECTS_DISSECTION, /* but not fields */
992 NULL, /* help */
993 copy_ipdum_pdu_transport_mapping_cb, /* copy callback */
994 update_ipdum_pdu_transport_mapping, /* update callback */
995 NULL, /* free callback */
996 post_update_ipdum_pdu_transport_mapping_cb, /* post update callback */
997 NULL, /* reset callback */
998 ipdum_pdu_transport_mapping_uat_fields /* UAT field definitions */
1001 prefs_register_uat_preference(ipdum_module, "_ipdum_pdu_transport_mapping", "PDU Transport Mappings",
1002 "A table to map PDU Transport payloads to I-PduM Message configuration", ipdum_pdu_transport_mapping_uat);
1005 void
1006 proto_reg_handoff_autosar_ipdu_multiplexer(void) {
1007 static bool initialized = false;
1009 if (!initialized) {
1010 ipdum_handle_can = register_dissector("ipdu_multiplexer_over_can", dissect_ipdum_message_can, proto_ipdu_multiplexer);
1011 dissector_add_for_decode_as("can.subdissector", ipdum_handle_can);
1012 heur_dissector_add("can", dissect_ipdum_message_can_heur, "IPDU Multiplexer over CAN", "ipdu_multiplexer_can_heur", proto_ipdu_multiplexer, HEURISTIC_ENABLE);
1014 ipdum_handle_flexray = register_dissector("ipdu_multiplexer_over_flexray", dissect_ipdum_message_flexray, proto_ipdu_multiplexer);
1015 dissector_add_for_decode_as("flexray.subdissector", ipdum_handle_flexray);
1016 heur_dissector_add("flexray", dissect_ipdum_message_flexray_heur, "IPDU Multiplexer over FlexRay", "ipdu_multiplexer_flexray_heur", proto_ipdu_multiplexer, HEURISTIC_ENABLE);
1018 ipdum_handle_lin = register_dissector("ipdu_multiplexer_over_lin", dissect_ipdum_message_lin, proto_ipdu_multiplexer);
1020 ipdum_handle_pdu_transport = register_dissector("ipdu_multiplexer_over_pdu_transport", dissect_ipdum_message_pdu_transport, proto_ipdu_multiplexer);
1022 initialized = true;
1027 * Editor modelines
1029 * Local Variables:
1030 * c-basic-offset: 4
1031 * tab-width: 8
1032 * indent-tabs-mode: nil
1033 * End:
1035 * ex: set shiftwidth=4 tabstop=8 expandtab:
1036 * :indentSize=4:tabSize=8:noTabs=true: