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
15 #include <epan/packet.h>
16 #include <epan/prefs.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
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
;
50 static int hf_pdu_name
;
51 static int hf_payload_unparsed
;
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
{
73 uint32_t update_bit_pos
;
74 } ipdum_message_item_t
;
76 typedef struct _ipdum_message_list
{
78 uint32_t num_of_items
;
80 ipdum_message_item_t
*items
;
81 } ipdum_message_list_t
;
83 typedef struct _ipdum_message_list_uat
{
85 uint32_t num_of_params
;
92 uint32_t update_bit_pos
;
93 } ipdum_message_list_uat_t
;
96 typedef struct _ipdum__can_mapping
{
100 } ipdum_can_mapping_t
;
101 typedef ipdum_can_mapping_t ipdum_can_mapping_uat_t
;
103 typedef struct _ipdum_flexray_mapping
{
108 } ipdum_flexray_mapping_t
;
109 typedef ipdum_flexray_mapping_t ipdum_flexray_mapping_uat_t
;
111 typedef struct _ipdum_lin_mapping
{
115 } ipdum_lin_mapping_t
;
116 typedef ipdum_lin_mapping_t ipdum_lin_mapping_uat_t
;
118 typedef struct _ipdum_pdu_transport_mapping
{
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 */
148 ipdum_payload_free_key(void *key
) {
149 wmem_free(wmem_epan_scope(), key
);
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
)
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
;
180 new_rec
->name
= g_strdup(old_rec
->name
);
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
;
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");
201 if (rec
->num_of_params
>= 0xffff) {
202 *err
= ws_strdup_printf("Number of PDUs too big");
206 if (rec
->pos
>= rec
->num_of_params
) {
207 *err
= ws_strdup_printf("Position >= Number of PDUs");
211 if (rec
->name
== NULL
|| rec
->name
[0] == 0) {
212 *err
= ws_strdup_printf("Name cannot be empty");
220 free_ipdum_message_list_cb(void*r
) {
221 ipdum_message_list_uat_t
*rec
= (ipdum_message_list_uat_t
*)r
;
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) {
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
);
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
);
254 /* create new entry ... */
255 g_hash_table_insert(ht
, key
, list
);
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
;
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
) {
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
)
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
;
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
);
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
);
335 post_update_register_can(void) {
336 if (ipdum_handle_can
== NULL
) {
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
);
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
);
354 dissector_add_uint("can.id", id
& CAN_SFF_MASK
, ipdum_handle_can
);
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
) {
377 if (ipdum_can_mapping_num
> 0) {
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
) {
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
);
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
);
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
)
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
;
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
);
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
);
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
) {
461 if (ipdum_flexray_mapping_num
> 0) {
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
) {
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
);
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
)
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
;
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
);
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
);
525 post_update_register_lin(void) {
526 if (ipdum_handle_lin
== NULL
) {
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
);
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
);
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
) {
562 if (ipdum_lin_mapping_num
> 0) {
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
) {
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
);
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
);
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
)
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
;
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
);
625 post_update_register_pdu_transport(void) {
626 if (ipdum_handle_pdu_transport
== NULL
) {
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
);
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
);
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
) {
661 if (ipdum_pdu_transport_mapping_num
> 0) {
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
) {
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 **************************************/
690 dissect_ipdum_payload(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*root_tree
, uint32_t id
) {
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
);
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
);
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
;
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) {
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
));
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. */
756 ipdum_can_mapping_t
*can_mapping
= get_can_mapping(can_info
->id
, can_info
->bus_id
);
757 if (can_mapping
== NULL
) {
761 return dissect_ipdum_payload(tvb
, pinfo
, tree
, can_mapping
->message_id
);
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;
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
) {
780 return dissect_ipdum_payload(tvb
, pinfo
, tree
, flexray_mapping
->message_id
);
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;
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
) {
799 return dissect_ipdum_payload(tvb
, pinfo
, tree
, lin_mapping
->message_id
);
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
) {
813 return dissect_ipdum_payload(tvb
, pinfo
, tree
, pdu_transport_mapping
->message_id
);
817 /**************************************
818 ******** Register Dissector ********
819 **************************************/
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
[] = {
836 { "PDU", "ipdum.pdu", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
838 { "PDU-ID", "ipdum.pdu.id", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
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
[] = {
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)"),
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)"),
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)"),
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)"),
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)"),
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 */
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 */
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 */
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 */
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
);
1006 proto_reg_handoff_autosar_ipdu_multiplexer(void) {
1007 static bool initialized
= false;
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
);
1032 * indent-tabs-mode: nil
1035 * ex: set shiftwidth=4 tabstop=8 expandtab:
1036 * :indentSize=4:tabSize=8:noTabs=true: