4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * TTX Logger (TTL) file format from TTTech Computertechnik AG decoder
7 * for the Wiretap library.
8 * You can find the PDF with the documentation of the format at
9 * https://servicearea.tttech-auto.com/ (registration and approval required).
11 * Copyright (c) 2024 by Giovanni Musto <giovanni.musto@partner.italdesign.it>
13 * SPDX-License-Identifier: GPL-2.0-or-later
17 #define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP
22 #include <epan/dissectors/packet-socketcan.h>
23 #include <wsutil/wslog.h>
24 #include <wsutil/report_message.h>
25 #include <wsutil/filesystem.h>
26 #include <wsutil/strtoi.h>
28 #include <libxml/tree.h>
29 #include <libxml/parser.h>
30 #include <libxml/xpath.h>
32 #include "file_wrappers.h"
35 static const uint8_t ttl_magic
[] = { 'T', 'T', 'L', ' ' };
37 static int ttl_file_type_subtype
= -1;
39 #define TTL_ADDRESS_NAME_PREFS "file_format_ttl_names"
40 #define TTL_ADDRESS_MASTER_PREFS "file_format_ttl_masters"
42 void register_ttl(void);
43 static bool ttl_read(wtap
* wth
, wtap_rec
* rec
, int* err
, char** err_info
, int64_t* data_offset
);
44 static bool ttl_seek_read(wtap
* wth
, int64_t seek_off
, wtap_rec
* rec
, int* err
, char** err_info
);
45 static void ttl_close(wtap
* wth
);
47 typedef struct ttl_data
{
50 uint32_t next_interface_id
;
52 GHashTable
* address_to_iface_ht
;
53 GHashTable
* address_to_master_ht
;
54 GHashTable
* address_to_name_ht
;
55 GHashTable
* segmented_frames_ht
;
56 GHashTable
* reassembled_frames_ht
;
59 typedef enum ttl_read_validity
{
62 } ttl_read_validity_t
;
65 * Usually, 'fh' is valid and is used by ttl_read_bytes, but in case of
66 * segmented entries, 'buf' will be set to the reassembled nested entry.
68 typedef struct ttl_read
{
77 ttl_read_validity_t validity
;
81 * Values smaller than 0 indicate errors, 0 means OK, 1 means everything is
82 * good, but the entry is unsupported. 2 means that the file looks corrupted
83 * or unaliged and our caller should try to fix the situation.
92 static ttl_result_t
ttl_read_entry(wtap
* wth
, wtap_rec
* rec
, int* err
, char** err_info
, ttl_read_t
* in
, int64_t offset
, int64_t end
);
95 * This struct is used to map the source address of an entry to an actual
98 * The field 'channelB' has meaning only for FlexRay and it means that the
99 * packet belongs to FlexRay's Channel B.
101 typedef struct ttl_addr_to_iface_entry
{
105 uint32_t interface_id
;
106 } ttl_addr_to_iface_entry_t
;
108 typedef struct ttl_segmented_entry
{
110 uint32_t size
; /* Full size of the reassembled entry */
111 uint32_t type
; /* Type of the entry */
113 uint32_t size_so_far
;
114 uint8_t next_segment
;
116 } ttl_segmented_entry_t
;
118 typedef struct ttl_reassembled_entry
{
122 } ttl_reassembled_entry_t
;
125 ttl_free_segmented_entry(void* data
) {
126 ttl_segmented_entry_t
* item
;
128 item
= (ttl_segmented_entry_t
*)data
;
129 if (item
->buf
!= NULL
) {
137 ttl_free_reassembled_entry(void* data
) {
138 ttl_reassembled_entry_t
* item
;
140 item
= (ttl_reassembled_entry_t
*)data
;
141 if (item
->buf
!= NULL
) {
148 #ifndef OPT_EPB_FLAGS
149 #define OPT_EPB_FLAGS 0x0002 /* Copied from pcapng.c */
152 #ifndef FLEXRAY_FRAME
153 #define FLEXRAY_FRAME 0x01 /* Copied from packet-flexray.c */
156 #ifndef FLEXRAY_SYMBOL
157 #define FLEXRAY_SYMBOL 0x02 /* Copied from packet-flexray.c */
161 fix_endianness_ttl_fileheader(ttl_fileheader_t
* header
) {
162 header
->version
= GUINT32_FROM_LE(header
->version
);
163 header
->block_size
= GUINT32_FROM_LE(header
->block_size
);
164 header
->header_size
= GUINT32_FROM_LE(header
->header_size
);
168 fix_endianness_ttl_entryheader(ttl_entryheader_t
* header
) {
169 header
->size_type
= GUINT16_FROM_LE(header
->size_type
);
170 header
->dest_addr
= GUINT16_FROM_LE(header
->dest_addr
);
171 header
->src_addr
= GUINT16_FROM_LE(header
->src_addr
);
172 header
->status_info
= GUINT16_FROM_LE(header
->status_info
);
176 * This function returns the "master" address of coupled addresses.
178 * The output is different from the input in two cases:
179 * 1. Coupled Ethernet channel, such as the slave side of a tap
180 * 2. FlexRay Channel B, in order to couple it to Channel A
182 * In both cases, the returned address is the one of the "main" channel, so
183 * that both addresses can be mapped to the same interface.
185 * If a hash table is passed as input, and an entry is present for addr,
186 * then the stored result is returned. If there's no match, or no hash table
187 * is passed as input, then the default behaviour applies:
188 * - For FlexRay, always return corresponding Channel A if addr is Channel B.
190 * - Return the same address if cascade is 0 (i.e. the channel belongs to
192 * - Return the address of the master if addr belongs to a tap (cascade != 0)
194 uint16_t ttl_get_master_address(GHashTable
* ht
, uint16_t addr
) {
195 uint8_t function
= ttl_addr_get_function(addr
);
199 if (g_hash_table_lookup_extended(ht
, GUINT_TO_POINTER(addr
), NULL
, &master
)) {
200 return (uint16_t)GPOINTER_TO_UINT(master
);
204 if (ttl_addr_get_cascade(addr
) == 0) { /* The address refers to the logger itself */
205 switch (ttl_addr_get_device(addr
))
207 case TTL_LOGGER_DEVICE_FPGA
:
209 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH2
:
210 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH2
:
212 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH3
:
213 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH3
:
215 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B
:
216 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B
:
217 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B
:
223 case TTL_LOGGER_DEVICE_TRICORE1
:
224 case TTL_LOGGER_DEVICE_TRICORE2
:
225 case TTL_LOGGER_DEVICE_TRICORE3
:
226 if (function
== TTL_LOGGER_TRICORE_FUNCTION_FLEXRAYB
) {
230 case TTL_LOGGER_DEVICE_FPGAA
:
231 if (function
== TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B
) {
235 case TTL_LOGGER_DEVICE_FPGAB
:
237 case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH2
:
238 case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH2
:
239 case TTL_LOGGER_FPGAB_FUNCTION_AETHA_CH2
:
240 case TTL_LOGGER_FPGAB_FUNCTION_AETHB_CH2
:
241 case TTL_LOGGER_FPGAB_FUNCTION_AETHC_CH2
:
242 case TTL_LOGGER_FPGAB_FUNCTION_AETHD_CH2
:
243 case TTL_LOGGER_FPGAB_FUNCTION_AETHE_CH2
:
244 case TTL_LOGGER_FPGAB_FUNCTION_AETHF_CH2
:
245 case TTL_LOGGER_FPGAB_FUNCTION_AETHG_CH2
:
246 case TTL_LOGGER_FPGAB_FUNCTION_AETHH_CH2
:
247 case TTL_LOGGER_FPGAB_FUNCTION_AETHI_CH2
:
248 case TTL_LOGGER_FPGAB_FUNCTION_AETHJ_CH2
:
249 case TTL_LOGGER_FPGAB_FUNCTION_AETHK_CH2
:
250 case TTL_LOGGER_FPGAB_FUNCTION_AETHL_CH2
:
260 else { /* The address refers to a TAP */
261 switch (ttl_addr_get_device(addr
)) {
262 case TTL_TAP_DEVICE_PT15_FPGA
:
264 case TTL_PT15_FPGA_FUNCTION_BrdR1b
:
265 case TTL_PT15_FPGA_FUNCTION_BrdR2b
:
266 case TTL_PT15_FPGA_FUNCTION_BrdR3b
:
267 case TTL_PT15_FPGA_FUNCTION_BrdR4b
:
268 case TTL_PT15_FPGA_FUNCTION_BrdR5b
:
269 case TTL_PT15_FPGA_FUNCTION_BrdR6b
:
275 case TTL_TAP_DEVICE_PT20_FPGA
:
277 case TTL_PT20_FPGA_FUNCTION_GbEth1b
:
278 case TTL_PT20_FPGA_FUNCTION_GbEth2b
:
279 case TTL_PT20_FPGA_FUNCTION_GbEth3b
:
285 case TTL_TAP_DEVICE_PC3_FPGA
:
286 if (function
== TTL_PC3_FPGA_FUNCTION_BrdR1b
) {
290 case TTL_TAP_DEVICE_PC3_AURIX
:
292 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B
:
293 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B
:
307 bool ttl_is_chb_addr(uint16_t addr
) {
308 uint8_t function
= ttl_addr_get_function(addr
);
310 if (ttl_addr_get_cascade(addr
) == 0) { /* The address refers to the logger itself */
311 switch (ttl_addr_get_device(addr
))
313 case TTL_LOGGER_DEVICE_FPGA
:
315 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B
:
316 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B
:
317 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B
:
323 case TTL_LOGGER_DEVICE_TRICORE1
:
324 case TTL_LOGGER_DEVICE_TRICORE2
:
325 case TTL_LOGGER_DEVICE_TRICORE3
:
326 if (function
== TTL_LOGGER_TRICORE_FUNCTION_FLEXRAYB
) {
330 case TTL_LOGGER_DEVICE_FPGAA
:
331 if (function
== TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B
) {
339 else { /* The address refers to a TAP */
340 switch (ttl_addr_get_device(addr
)) {
341 case TTL_TAP_DEVICE_PC3_AURIX
:
343 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B
:
344 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B
:
358 int ttl_get_address_iface_type(uint16_t addr
) {
359 uint8_t function
= ttl_addr_get_function(addr
);
361 if (ttl_addr_get_cascade(addr
) == 0) { /* The address refers to the logger itself */
362 switch (ttl_addr_get_device(addr
))
364 case TTL_LOGGER_DEVICE_FPGA
:
366 case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST25
:
367 case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST150
:
368 case TTL_LOGGER_FPGA_FUNCTION_EXT1_MOST25
:
369 return WTAP_ENCAP_MOST
;
370 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH1
:
371 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH1
:
372 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH2
:
373 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH2
:
374 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH3
:
375 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH3
:
376 return WTAP_ENCAP_ETHERNET
;
377 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1A
:
378 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B
:
379 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2A
:
380 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B
:
381 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3A
:
382 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B
:
383 return WTAP_ENCAP_FLEXRAY
;
384 case TTL_LOGGER_FPGA_FUNCTION_CAN1
:
385 case TTL_LOGGER_FPGA_FUNCTION_CAN2
:
386 case TTL_LOGGER_FPGA_FUNCTION_CAN3
:
387 case TTL_LOGGER_FPGA_FUNCTION_CAN4
:
388 case TTL_LOGGER_FPGA_FUNCTION_CAN5
:
389 case TTL_LOGGER_FPGA_FUNCTION_CAN6
:
390 case TTL_LOGGER_FPGA_FUNCTION_CAN7
:
391 case TTL_LOGGER_FPGA_FUNCTION_CAN8
:
392 case TTL_LOGGER_FPGA_FUNCTION_CAN9
:
393 case TTL_LOGGER_FPGA_FUNCTION_CAN10
:
394 case TTL_LOGGER_FPGA_FUNCTION_CAN11
:
395 case TTL_LOGGER_FPGA_FUNCTION_CAN12
:
396 case TTL_LOGGER_FPGA_FUNCTION_CAN13
:
397 case TTL_LOGGER_FPGA_FUNCTION_CAN14
:
398 case TTL_LOGGER_FPGA_FUNCTION_CAN15
:
399 case TTL_LOGGER_FPGA_FUNCTION_CAN16
:
400 case TTL_LOGGER_FPGA_FUNCTION_CAN17
:
401 case TTL_LOGGER_FPGA_FUNCTION_CAN18
:
402 case TTL_LOGGER_FPGA_FUNCTION_CAN19
:
403 case TTL_LOGGER_FPGA_FUNCTION_CAN20
:
404 case TTL_LOGGER_FPGA_FUNCTION_CAN21
:
405 case TTL_LOGGER_FPGA_FUNCTION_CAN22
:
406 case TTL_LOGGER_FPGA_FUNCTION_CAN23
:
407 case TTL_LOGGER_FPGA_FUNCTION_CAN24
:
408 return WTAP_ENCAP_SOCKETCAN
;
409 case TTL_LOGGER_FPGA_FUNCTION_LIN1
:
410 case TTL_LOGGER_FPGA_FUNCTION_LIN2
:
411 case TTL_LOGGER_FPGA_FUNCTION_LIN3
:
412 case TTL_LOGGER_FPGA_FUNCTION_LIN4
:
413 case TTL_LOGGER_FPGA_FUNCTION_LIN5
:
414 case TTL_LOGGER_FPGA_FUNCTION_LIN6
:
415 case TTL_LOGGER_FPGA_FUNCTION_LIN7
:
416 case TTL_LOGGER_FPGA_FUNCTION_LIN8
:
417 case TTL_LOGGER_FPGA_FUNCTION_LIN9
:
418 case TTL_LOGGER_FPGA_FUNCTION_LIN10
:
419 case TTL_LOGGER_FPGA_FUNCTION_LIN11
:
420 case TTL_LOGGER_FPGA_FUNCTION_LIN12
:
421 return WTAP_ENCAP_LIN
;
427 case TTL_LOGGER_DEVICE_ATOM
:
429 case TTL_LOGGER_ATOM_FUNCTION_ETHA
:
430 case TTL_LOGGER_ATOM_FUNCTION_ETHB
:
431 return WTAP_ENCAP_ETHERNET
;
437 case TTL_LOGGER_DEVICE_TRICORE1
:
439 case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1A
:
440 case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1B
:
441 case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1
:
442 case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1AB
:
443 return WTAP_ENCAP_FLEXRAY
;
444 case TTL_LOGGER_TRICORE1_FUNCTION_CAN1
:
445 case TTL_LOGGER_TRICORE1_FUNCTION_CAN2
:
446 case TTL_LOGGER_TRICORE1_FUNCTION_CAN3
:
447 case TTL_LOGGER_TRICORE1_FUNCTION_CAN4
:
448 return WTAP_ENCAP_SOCKETCAN
;
454 case TTL_LOGGER_DEVICE_TRICORE2
:
456 case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2A
:
457 case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2B
:
458 case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2
:
459 case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2AB
:
460 return WTAP_ENCAP_FLEXRAY
;
461 case TTL_LOGGER_TRICORE2_FUNCTION_CAN6
:
462 case TTL_LOGGER_TRICORE2_FUNCTION_CAN7
:
463 case TTL_LOGGER_TRICORE2_FUNCTION_CAN10
:
464 case TTL_LOGGER_TRICORE2_FUNCTION_CAN12
:
465 return WTAP_ENCAP_SOCKETCAN
;
471 case TTL_LOGGER_DEVICE_TRICORE3
:
473 case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3A
:
474 case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3B
:
475 case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3
:
476 case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3AB
:
477 return WTAP_ENCAP_FLEXRAY
;
478 case TTL_LOGGER_TRICORE3_FUNCTION_CAN5
:
479 case TTL_LOGGER_TRICORE3_FUNCTION_CAN8
:
480 case TTL_LOGGER_TRICORE3_FUNCTION_CAN9
:
481 case TTL_LOGGER_TRICORE3_FUNCTION_CAN11
:
482 return WTAP_ENCAP_SOCKETCAN
;
488 case TTL_LOGGER_DEVICE_TDA4x
:
490 case TTL_LOGGER_TDA4x_FUNCTION_CAN1
:
491 case TTL_LOGGER_TDA4x_FUNCTION_CAN2
:
492 case TTL_LOGGER_TDA4x_FUNCTION_CAN3
:
493 case TTL_LOGGER_TDA4x_FUNCTION_CAN4
:
494 case TTL_LOGGER_TDA4x_FUNCTION_CAN5
:
495 case TTL_LOGGER_TDA4x_FUNCTION_CAN6
:
496 case TTL_LOGGER_TDA4x_FUNCTION_CAN7
:
497 case TTL_LOGGER_TDA4x_FUNCTION_CAN8
:
498 case TTL_LOGGER_TDA4x_FUNCTION_CAN9
:
499 case TTL_LOGGER_TDA4x_FUNCTION_CAN10
:
500 case TTL_LOGGER_TDA4x_FUNCTION_CAN11
:
501 return WTAP_ENCAP_SOCKETCAN
;
507 case TTL_LOGGER_DEVICE_FPGAA
:
509 case TTL_LOGGER_FPGAA_FUNCTION_CAN1
:
510 case TTL_LOGGER_FPGAA_FUNCTION_CAN2
:
511 case TTL_LOGGER_FPGAA_FUNCTION_CAN3
:
512 case TTL_LOGGER_FPGAA_FUNCTION_CAN4
:
513 case TTL_LOGGER_FPGAA_FUNCTION_CAN5
:
514 case TTL_LOGGER_FPGAA_FUNCTION_CAN6
:
515 case TTL_LOGGER_FPGAA_FUNCTION_CAN7
:
516 case TTL_LOGGER_FPGAA_FUNCTION_CAN8
:
517 case TTL_LOGGER_FPGAA_FUNCTION_CAN9
:
518 case TTL_LOGGER_FPGAA_FUNCTION_CAN10
:
519 case TTL_LOGGER_FPGAA_FUNCTION_CAN11
:
520 return WTAP_ENCAP_SOCKETCAN
;
521 case TTL_LOGGER_FPGAA_FUNCTION_LIN1
:
522 case TTL_LOGGER_FPGAA_FUNCTION_LIN2
:
523 case TTL_LOGGER_FPGAA_FUNCTION_LIN3
:
524 case TTL_LOGGER_FPGAA_FUNCTION_LIN4
:
525 case TTL_LOGGER_FPGAA_FUNCTION_LIN5
:
526 case TTL_LOGGER_FPGAA_FUNCTION_LIN6
:
527 case TTL_LOGGER_FPGAA_FUNCTION_LIN7
:
528 case TTL_LOGGER_FPGAA_FUNCTION_LIN8
:
529 case TTL_LOGGER_FPGAA_FUNCTION_LIN9
:
530 case TTL_LOGGER_FPGAA_FUNCTION_LIN10
:
531 case TTL_LOGGER_FPGAA_FUNCTION_LIN11
:
532 case TTL_LOGGER_FPGAA_FUNCTION_LIN12
:
533 case TTL_LOGGER_FPGAA_FUNCTION_LIN13
:
534 case TTL_LOGGER_FPGAA_FUNCTION_LIN14
:
535 case TTL_LOGGER_FPGAA_FUNCTION_LIN15
:
536 case TTL_LOGGER_FPGAA_FUNCTION_LIN16
:
537 return WTAP_ENCAP_LIN
;
538 case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1A
:
539 case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B
:
540 return WTAP_ENCAP_FLEXRAY
;
546 case TTL_LOGGER_DEVICE_FPGAB
:
548 case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH1
:
549 case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH1
:
550 case TTL_LOGGER_FPGAB_FUNCTION_AETHA_CH1
:
551 case TTL_LOGGER_FPGAB_FUNCTION_AETHB_CH1
:
552 case TTL_LOGGER_FPGAB_FUNCTION_AETHC_CH1
:
553 case TTL_LOGGER_FPGAB_FUNCTION_AETHD_CH1
:
554 case TTL_LOGGER_FPGAB_FUNCTION_AETHE_CH1
:
555 case TTL_LOGGER_FPGAB_FUNCTION_AETHF_CH1
:
556 case TTL_LOGGER_FPGAB_FUNCTION_AETHG_CH1
:
557 case TTL_LOGGER_FPGAB_FUNCTION_AETHH_CH1
:
558 case TTL_LOGGER_FPGAB_FUNCTION_AETHI_CH1
:
559 case TTL_LOGGER_FPGAB_FUNCTION_AETHJ_CH1
:
560 case TTL_LOGGER_FPGAB_FUNCTION_AETHK_CH1
:
561 case TTL_LOGGER_FPGAB_FUNCTION_AETHL_CH1
:
562 case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH2
:
563 case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH2
:
564 case TTL_LOGGER_FPGAB_FUNCTION_AETHA_CH2
:
565 case TTL_LOGGER_FPGAB_FUNCTION_AETHB_CH2
:
566 case TTL_LOGGER_FPGAB_FUNCTION_AETHC_CH2
:
567 case TTL_LOGGER_FPGAB_FUNCTION_AETHD_CH2
:
568 case TTL_LOGGER_FPGAB_FUNCTION_AETHE_CH2
:
569 case TTL_LOGGER_FPGAB_FUNCTION_AETHF_CH2
:
570 case TTL_LOGGER_FPGAB_FUNCTION_AETHG_CH2
:
571 case TTL_LOGGER_FPGAB_FUNCTION_AETHH_CH2
:
572 case TTL_LOGGER_FPGAB_FUNCTION_AETHI_CH2
:
573 case TTL_LOGGER_FPGAB_FUNCTION_AETHJ_CH2
:
574 case TTL_LOGGER_FPGAB_FUNCTION_AETHK_CH2
:
575 case TTL_LOGGER_FPGAB_FUNCTION_AETHL_CH2
:
576 return WTAP_ENCAP_ETHERNET
;
586 else { /* The address refers to a TAP */
587 switch (ttl_addr_get_device(addr
)) {
588 case TTL_TAP_DEVICE_PT15_FPGA
:
590 case TTL_PT15_FPGA_FUNCTION_CAN1
:
591 case TTL_PT15_FPGA_FUNCTION_CAN2
:
592 return WTAP_ENCAP_SOCKETCAN
;
593 case TTL_PT15_FPGA_FUNCTION_BrdR1a
:
594 case TTL_PT15_FPGA_FUNCTION_BrdR1b
:
595 case TTL_PT15_FPGA_FUNCTION_BrdR2a
:
596 case TTL_PT15_FPGA_FUNCTION_BrdR2b
:
597 case TTL_PT15_FPGA_FUNCTION_BrdR3a
:
598 case TTL_PT15_FPGA_FUNCTION_BrdR3b
:
599 case TTL_PT15_FPGA_FUNCTION_BrdR4a
:
600 case TTL_PT15_FPGA_FUNCTION_BrdR4b
:
601 case TTL_PT15_FPGA_FUNCTION_BrdR5a
:
602 case TTL_PT15_FPGA_FUNCTION_BrdR5b
:
603 case TTL_PT15_FPGA_FUNCTION_BrdR6a
:
604 case TTL_PT15_FPGA_FUNCTION_BrdR6b
:
605 return WTAP_ENCAP_ETHERNET
;
606 case TTL_PT15_FPGA_FUNCTION_MDIO
: /* TODO: Support this */
612 case TTL_TAP_DEVICE_PT20_FPGA
:
614 case TTL_PT20_FPGA_FUNCTION_CAN1
:
615 case TTL_PT20_FPGA_FUNCTION_CAN2
:
616 case TTL_PT20_FPGA_FUNCTION_CAN3
:
617 case TTL_PT20_FPGA_FUNCTION_CAN4
:
618 case TTL_PT20_FPGA_FUNCTION_CAN5
:
619 return WTAP_ENCAP_SOCKETCAN
;
620 case TTL_PT20_FPGA_FUNCTION_GbEth1a
:
621 case TTL_PT20_FPGA_FUNCTION_GbEth1b
:
622 case TTL_PT20_FPGA_FUNCTION_GbEth2a
:
623 case TTL_PT20_FPGA_FUNCTION_GbEth2b
:
624 case TTL_PT20_FPGA_FUNCTION_GbEth3a
:
625 case TTL_PT20_FPGA_FUNCTION_GbEth3b
:
626 return WTAP_ENCAP_ETHERNET
;
627 case TTL_PT20_FPGA_FUNCTION_MDIO
: /* TODO: Support this */
633 case TTL_TAP_DEVICE_PC3_FPGA
:
635 case TTL_PC3_FPGA_FUNCTION_BrdR1a
:
636 case TTL_PC3_FPGA_FUNCTION_BrdR1b
:
637 return WTAP_ENCAP_ETHERNET
;
643 case TTL_TAP_DEVICE_PC3_AURIX
:
645 case TTL_PC3_AURIX_FUNCTION_CAN1
:
646 case TTL_PC3_AURIX_FUNCTION_CAN2
:
647 case TTL_PC3_AURIX_FUNCTION_CAN3
:
648 case TTL_PC3_AURIX_FUNCTION_CAN4
:
649 return WTAP_ENCAP_SOCKETCAN
;
650 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1A
:
651 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B
:
652 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2A
:
653 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B
:
654 return WTAP_ENCAP_FLEXRAY
;
660 case TTL_TAP_DEVICE_ZELDA_CANFD
:
662 case TTL_TAP_DEVICE_ZELDA_CANFD1
:
663 case TTL_TAP_DEVICE_ZELDA_CANFD2
:
664 case TTL_TAP_DEVICE_ZELDA_CANFD3
:
665 case TTL_TAP_DEVICE_ZELDA_CANFD4
:
666 case TTL_TAP_DEVICE_ZELDA_CANFD5
:
667 case TTL_TAP_DEVICE_ZELDA_CANFD6
:
668 case TTL_TAP_DEVICE_ZELDA_CANFD7
:
669 case TTL_TAP_DEVICE_ZELDA_CANFD8
:
670 case TTL_TAP_DEVICE_ZELDA_CANFD9
:
671 case TTL_TAP_DEVICE_ZELDA_CANFD10
:
672 case TTL_TAP_DEVICE_ZELDA_CANFD11
:
673 case TTL_TAP_DEVICE_ZELDA_CANFD12
:
674 case TTL_TAP_DEVICE_ZELDA_CANFD13
:
675 case TTL_TAP_DEVICE_ZELDA_CANFD14
:
676 case TTL_TAP_DEVICE_ZELDA_CANFD15
:
677 return WTAP_ENCAP_SOCKETCAN
;
683 case TTL_TAP_DEVICE_ZELDA_LIN
:
685 case TTL_TAP_DEVICE_ZELDA_LIN1
:
686 case TTL_TAP_DEVICE_ZELDA_LIN2
:
687 case TTL_TAP_DEVICE_ZELDA_LIN3
:
688 case TTL_TAP_DEVICE_ZELDA_LIN4
:
689 case TTL_TAP_DEVICE_ZELDA_LIN5
:
690 case TTL_TAP_DEVICE_ZELDA_LIN6
:
691 case TTL_TAP_DEVICE_ZELDA_LIN7
:
692 case TTL_TAP_DEVICE_ZELDA_LIN8
:
693 case TTL_TAP_DEVICE_ZELDA_LIN9
:
694 case TTL_TAP_DEVICE_ZELDA_LIN10
:
695 case TTL_TAP_DEVICE_ZELDA_LIN11
:
696 case TTL_TAP_DEVICE_ZELDA_LIN12
:
697 case TTL_TAP_DEVICE_ZELDA_LIN13
:
698 case TTL_TAP_DEVICE_ZELDA_LIN14
:
699 case TTL_TAP_DEVICE_ZELDA_LIN15
:
700 case TTL_TAP_DEVICE_ZELDA_LIN16
:
701 case TTL_TAP_DEVICE_ZELDA_LIN17
:
702 case TTL_TAP_DEVICE_ZELDA_LIN18
:
703 case TTL_TAP_DEVICE_ZELDA_LIN19
:
704 case TTL_TAP_DEVICE_ZELDA_LIN20
:
705 case TTL_TAP_DEVICE_ZELDA_LIN21
:
706 case TTL_TAP_DEVICE_ZELDA_LIN22
:
707 case TTL_TAP_DEVICE_ZELDA_LIN23
:
708 case TTL_TAP_DEVICE_ZELDA_LIN24
:
709 return WTAP_ENCAP_LIN
;
720 return WTAP_ENCAP_UNKNOWN
;
723 static const char* const ttl_cascade_names
[] = { "Logger", "Tap1", "Tap2", "Tap3", "Tap4", "Tap5", "Tap6", "Tap7" };
725 const char* ttl_get_cascade_name(uint16_t addr
) {
726 return ttl_cascade_names
[ttl_addr_get_cascade(addr
)];
729 const char* ttl_get_device_name(uint16_t addr
) {
730 if (ttl_addr_get_cascade(addr
) == 0) {
731 switch (ttl_addr_get_device(addr
)) {
732 case TTL_LOGGER_DEVICE_FPGA
:
733 case TTL_LOGGER_DEVICE_FPGAA
:
734 case TTL_LOGGER_DEVICE_FPGAB
:
736 case TTL_LOGGER_DEVICE_ATOM
:
738 case TTL_LOGGER_DEVICE_TRICORE1
:
739 case TTL_LOGGER_DEVICE_TRICORE2
:
740 case TTL_LOGGER_DEVICE_TRICORE3
:
742 case TTL_LOGGER_DEVICE_TDA4x
:
749 switch (ttl_addr_get_device(addr
)) {
750 case TTL_TAP_DEVICE_PT15_FPGA
:
751 case TTL_TAP_DEVICE_PT15_HPS_LINUX
:
753 case TTL_TAP_DEVICE_PT20_FPGA
:
754 case TTL_TAP_DEVICE_PT20_HPS_LINUX
:
756 case TTL_TAP_DEVICE_PC3_FPGA
:
757 case TTL_TAP_DEVICE_PC3_HPS_LINUX
:
758 case TTL_TAP_DEVICE_PC3_AURIX
:
760 case TTL_TAP_DEVICE_ZELDA_CANFD
:
761 case TTL_TAP_DEVICE_ZELDA_LIN
:
771 const char* ttl_get_function_name(uint16_t addr
) {
772 uint8_t function
= ttl_addr_get_function(addr
);
774 if (ttl_addr_get_cascade(addr
) == 0) {
775 switch (ttl_addr_get_device(addr
)) {
776 case TTL_LOGGER_DEVICE_FPGA
:
778 case TTL_LOGGER_FPGA_FUNCTION_CORE
:
780 case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST25
:
781 return "Ext0_MOST25";
782 case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST150
:
784 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH1
:
785 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH2
:
786 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH3
:
788 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH1
:
789 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH2
:
790 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH3
:
792 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1A
:
793 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B
:
795 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2A
:
796 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B
:
798 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3A
:
799 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B
:
801 case TTL_LOGGER_FPGA_FUNCTION_CAN1
:
803 case TTL_LOGGER_FPGA_FUNCTION_CAN2
:
805 case TTL_LOGGER_FPGA_FUNCTION_CAN3
:
807 case TTL_LOGGER_FPGA_FUNCTION_CAN4
:
809 case TTL_LOGGER_FPGA_FUNCTION_CAN5
:
811 case TTL_LOGGER_FPGA_FUNCTION_CAN6
:
813 case TTL_LOGGER_FPGA_FUNCTION_CAN7
:
815 case TTL_LOGGER_FPGA_FUNCTION_CAN8
:
817 case TTL_LOGGER_FPGA_FUNCTION_CAN9
:
819 case TTL_LOGGER_FPGA_FUNCTION_CAN10
:
821 case TTL_LOGGER_FPGA_FUNCTION_CAN11
:
823 case TTL_LOGGER_FPGA_FUNCTION_CAN12
:
825 case TTL_LOGGER_FPGA_FUNCTION_CAN13
:
827 case TTL_LOGGER_FPGA_FUNCTION_CAN14
:
829 case TTL_LOGGER_FPGA_FUNCTION_CAN15
:
831 case TTL_LOGGER_FPGA_FUNCTION_CAN16
:
833 case TTL_LOGGER_FPGA_FUNCTION_CAN17
:
835 case TTL_LOGGER_FPGA_FUNCTION_CAN18
:
837 case TTL_LOGGER_FPGA_FUNCTION_CAN19
:
839 case TTL_LOGGER_FPGA_FUNCTION_CAN20
:
841 case TTL_LOGGER_FPGA_FUNCTION_CAN21
:
843 case TTL_LOGGER_FPGA_FUNCTION_CAN22
:
845 case TTL_LOGGER_FPGA_FUNCTION_CAN23
:
847 case TTL_LOGGER_FPGA_FUNCTION_CAN24
:
849 case TTL_LOGGER_FPGA_FUNCTION_EXT1_MOST25
:
851 case TTL_LOGGER_FPGA_FUNCTION_LIN1
:
853 case TTL_LOGGER_FPGA_FUNCTION_LIN2
:
855 case TTL_LOGGER_FPGA_FUNCTION_LIN3
:
857 case TTL_LOGGER_FPGA_FUNCTION_LIN4
:
859 case TTL_LOGGER_FPGA_FUNCTION_LIN5
:
861 case TTL_LOGGER_FPGA_FUNCTION_LIN6
:
863 case TTL_LOGGER_FPGA_FUNCTION_LIN7
:
865 case TTL_LOGGER_FPGA_FUNCTION_LIN8
:
867 case TTL_LOGGER_FPGA_FUNCTION_LIN9
:
869 case TTL_LOGGER_FPGA_FUNCTION_LIN10
:
871 case TTL_LOGGER_FPGA_FUNCTION_LIN11
:
873 case TTL_LOGGER_FPGA_FUNCTION_LIN12
:
879 case TTL_LOGGER_DEVICE_ATOM
:
881 case TTL_LOGGER_ATOM_FUNCTION_ETHA
:
883 case TTL_LOGGER_ATOM_FUNCTION_ETHB
:
889 case TTL_LOGGER_DEVICE_TRICORE1
:
891 case TTL_LOGGER_TRICORE1_FUNCTION_CORE
:
893 case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1A
:
894 case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1B
:
895 case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1
:
896 case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1AB
:
898 case TTL_LOGGER_TRICORE1_FUNCTION_CAN1
:
900 case TTL_LOGGER_TRICORE1_FUNCTION_CAN2
:
902 case TTL_LOGGER_TRICORE1_FUNCTION_CAN3
:
904 case TTL_LOGGER_TRICORE1_FUNCTION_CAN4
:
906 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGOUT1
:
908 case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALOUT5
:
909 return "DigitalOut5";
910 case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALOUT6
:
911 return "DigitalOut6";
912 case TTL_LOGGER_TRICORE1_FUNCTION_SERIAL1
:
914 case TTL_LOGGER_TRICORE1_FUNCTION_SERIAL2
:
916 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN6
:
918 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN8
:
920 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN11
:
922 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN14
:
924 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN15
:
926 case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN8
:
928 case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN10
:
929 return "DigitalIn10";
930 case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN11
:
931 return "DigitalIn11";
932 case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN12
:
933 return "DigitalIn12";
934 case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN13
:
935 return "DigitalIn13";
936 case TTL_LOGGER_TRICORE1_FUNCTION_KL15IN
:
938 case TTL_LOGGER_TRICORE1_FUNCTION_KL30IN
:
944 case TTL_LOGGER_DEVICE_TRICORE2
:
946 case TTL_LOGGER_TRICORE2_FUNCTION_CORE
:
948 case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2A
:
949 case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2B
:
950 case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2
:
951 case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2AB
:
953 case TTL_LOGGER_TRICORE2_FUNCTION_CAN6
:
955 case TTL_LOGGER_TRICORE2_FUNCTION_CAN7
:
957 case TTL_LOGGER_TRICORE2_FUNCTION_CAN10
:
959 case TTL_LOGGER_TRICORE2_FUNCTION_CAN12
:
961 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGOUT2
:
963 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALOUT3
:
964 return "DigitalOut3";
965 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALOUT4
:
966 return "DigitalOut4";
967 case TTL_LOGGER_TRICORE2_FUNCTION_SERIAL3
:
969 case TTL_LOGGER_TRICORE2_FUNCTION_SERIAL4
:
971 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN3
:
973 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN4
:
975 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN5
:
977 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN7
:
979 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN9
:
981 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN6
:
983 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN7
:
985 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN9
:
987 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN14
:
988 return "DigitalIn14";
989 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN15
:
990 return "DigitalIn15";
995 case TTL_LOGGER_DEVICE_TRICORE3
:
997 case TTL_LOGGER_TRICORE3_FUNCTION_CORE
:
999 case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3A
:
1000 case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3B
:
1001 case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3
:
1002 case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3AB
:
1004 case TTL_LOGGER_TRICORE3_FUNCTION_CAN5
:
1006 case TTL_LOGGER_TRICORE3_FUNCTION_CAN8
:
1008 case TTL_LOGGER_TRICORE3_FUNCTION_CAN9
:
1010 case TTL_LOGGER_TRICORE3_FUNCTION_CAN11
:
1012 case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGOUT3
:
1013 return "AnalogOut3";
1014 case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALOUT1
:
1015 return "DigitalOut1";
1016 case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALOUT2
:
1017 return "DigitalOut2";
1018 case TTL_LOGGER_TRICORE3_FUNCTION_SERIAL5
:
1020 case TTL_LOGGER_TRICORE3_FUNCTION_SERIAL6
:
1022 case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN1
:
1024 case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN2
:
1026 case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN10
:
1027 return "AnalogIn10";
1028 case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN12
:
1029 return "AnalogIn12";
1030 case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN13
:
1031 return "AnalogIn13";
1032 case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN1
:
1033 return "DigitalIn1";
1034 case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN2
:
1035 return "DigitalIn2";
1036 case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN3
:
1037 return "DigitalIn3";
1038 case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN4
:
1039 return "DigitalIn4";
1040 case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN5
:
1041 return "DigitalIn5";
1046 case TTL_LOGGER_DEVICE_TDA4x
:
1048 case TTL_LOGGER_TDA4x_FUNCTION_CORE
:
1050 case TTL_LOGGER_TDA4x_FUNCTION_CAN1
:
1052 case TTL_LOGGER_TDA4x_FUNCTION_CAN2
:
1054 case TTL_LOGGER_TDA4x_FUNCTION_CAN3
:
1056 case TTL_LOGGER_TDA4x_FUNCTION_CAN4
:
1058 case TTL_LOGGER_TDA4x_FUNCTION_CAN5
:
1060 case TTL_LOGGER_TDA4x_FUNCTION_CAN6
:
1062 case TTL_LOGGER_TDA4x_FUNCTION_CAN7
:
1064 case TTL_LOGGER_TDA4x_FUNCTION_CAN8
:
1066 case TTL_LOGGER_TDA4x_FUNCTION_CAN9
:
1068 case TTL_LOGGER_TDA4x_FUNCTION_CAN10
:
1070 case TTL_LOGGER_TDA4x_FUNCTION_CAN11
:
1072 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL1
:
1074 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL2
:
1076 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL3
:
1078 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL4
:
1080 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL5
:
1082 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL6
:
1084 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN1
:
1086 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN2
:
1088 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN3
:
1090 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN4
:
1092 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN5
:
1094 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN6
:
1096 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGOUT1
:
1097 return "AnalogOut1";
1098 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGOUT2
:
1099 return "AnalogOut2";
1100 case TTL_LOGGER_TDA4x_FUNCTION_KL15IN
:
1102 case TTL_LOGGER_TDA4x_FUNCTION_KL30IN
:
1108 case TTL_LOGGER_DEVICE_FPGAA
:
1110 case TTL_LOGGER_FPGAA_FUNCTION_CORE
:
1112 case TTL_LOGGER_FPGAA_FUNCTION_CAN1
:
1114 case TTL_LOGGER_FPGAA_FUNCTION_CAN2
:
1116 case TTL_LOGGER_FPGAA_FUNCTION_CAN3
:
1118 case TTL_LOGGER_FPGAA_FUNCTION_CAN4
:
1120 case TTL_LOGGER_FPGAA_FUNCTION_CAN5
:
1122 case TTL_LOGGER_FPGAA_FUNCTION_CAN6
:
1124 case TTL_LOGGER_FPGAA_FUNCTION_CAN7
:
1126 case TTL_LOGGER_FPGAA_FUNCTION_CAN8
:
1128 case TTL_LOGGER_FPGAA_FUNCTION_CAN9
:
1130 case TTL_LOGGER_FPGAA_FUNCTION_CAN10
:
1132 case TTL_LOGGER_FPGAA_FUNCTION_CAN11
:
1134 case TTL_LOGGER_FPGAA_FUNCTION_LIN1
:
1136 case TTL_LOGGER_FPGAA_FUNCTION_LIN2
:
1138 case TTL_LOGGER_FPGAA_FUNCTION_LIN3
:
1140 case TTL_LOGGER_FPGAA_FUNCTION_LIN4
:
1142 case TTL_LOGGER_FPGAA_FUNCTION_LIN5
:
1144 case TTL_LOGGER_FPGAA_FUNCTION_LIN6
:
1146 case TTL_LOGGER_FPGAA_FUNCTION_LIN7
:
1148 case TTL_LOGGER_FPGAA_FUNCTION_LIN8
:
1150 case TTL_LOGGER_FPGAA_FUNCTION_LIN9
:
1152 case TTL_LOGGER_FPGAA_FUNCTION_LIN10
:
1154 case TTL_LOGGER_FPGAA_FUNCTION_LIN11
:
1156 case TTL_LOGGER_FPGAA_FUNCTION_LIN12
:
1158 case TTL_LOGGER_FPGAA_FUNCTION_LIN13
:
1160 case TTL_LOGGER_FPGAA_FUNCTION_LIN14
:
1162 case TTL_LOGGER_FPGAA_FUNCTION_LIN15
:
1164 case TTL_LOGGER_FPGAA_FUNCTION_LIN16
:
1166 case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1A
:
1167 case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B
:
1169 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL1
:
1171 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL2
:
1173 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL3
:
1175 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL4
:
1177 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL5
:
1179 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL6
:
1185 case TTL_LOGGER_DEVICE_FPGAB
:
1187 case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH1
:
1188 case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH2
:
1190 case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH1
:
1191 case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH2
:
1193 case TTL_LOGGER_FPGAB_FUNCTION_AETHA_CH1
:
1194 case TTL_LOGGER_FPGAB_FUNCTION_AETHA_CH2
:
1195 return "AutomotiveEthernetA";
1196 case TTL_LOGGER_FPGAB_FUNCTION_AETHB_CH1
:
1197 case TTL_LOGGER_FPGAB_FUNCTION_AETHB_CH2
:
1198 return "AutomotiveEthernetB";
1199 case TTL_LOGGER_FPGAB_FUNCTION_AETHC_CH1
:
1200 case TTL_LOGGER_FPGAB_FUNCTION_AETHC_CH2
:
1201 return "AutomotiveEthernetC";
1202 case TTL_LOGGER_FPGAB_FUNCTION_AETHD_CH1
:
1203 case TTL_LOGGER_FPGAB_FUNCTION_AETHD_CH2
:
1204 return "AutomotiveEthernetD";
1205 case TTL_LOGGER_FPGAB_FUNCTION_AETHE_CH1
:
1206 case TTL_LOGGER_FPGAB_FUNCTION_AETHE_CH2
:
1207 return "AutomotiveEthernetE";
1208 case TTL_LOGGER_FPGAB_FUNCTION_AETHF_CH1
:
1209 case TTL_LOGGER_FPGAB_FUNCTION_AETHF_CH2
:
1210 return "AutomotiveEthernetF";
1211 case TTL_LOGGER_FPGAB_FUNCTION_AETHG_CH1
:
1212 case TTL_LOGGER_FPGAB_FUNCTION_AETHG_CH2
:
1213 return "AutomotiveEthernetG";
1214 case TTL_LOGGER_FPGAB_FUNCTION_AETHH_CH1
:
1215 case TTL_LOGGER_FPGAB_FUNCTION_AETHH_CH2
:
1216 return "AutomotiveEthernetH";
1217 case TTL_LOGGER_FPGAB_FUNCTION_AETHI_CH1
:
1218 case TTL_LOGGER_FPGAB_FUNCTION_AETHI_CH2
:
1219 return "AutomotiveEthernetI";
1220 case TTL_LOGGER_FPGAB_FUNCTION_AETHJ_CH1
:
1221 case TTL_LOGGER_FPGAB_FUNCTION_AETHJ_CH2
:
1222 return "AutomotiveEthernetJ";
1223 case TTL_LOGGER_FPGAB_FUNCTION_AETHK_CH1
:
1224 case TTL_LOGGER_FPGAB_FUNCTION_AETHK_CH2
:
1225 return "AutomotiveEthernetK";
1226 case TTL_LOGGER_FPGAB_FUNCTION_AETHL_CH1
:
1227 case TTL_LOGGER_FPGAB_FUNCTION_AETHL_CH2
:
1228 return "AutomotiveEthernetL";
1238 switch (ttl_addr_get_device(addr
)) {
1239 case TTL_TAP_DEVICE_PT15_FPGA
:
1241 case TTL_PT15_FPGA_FUNCTION_CORE
:
1243 case TTL_PT15_FPGA_FUNCTION_CAN1
:
1245 case TTL_PT15_FPGA_FUNCTION_CAN2
:
1247 case TTL_PT15_FPGA_FUNCTION_BrdR1a
:
1249 case TTL_PT15_FPGA_FUNCTION_BrdR1b
:
1251 case TTL_PT15_FPGA_FUNCTION_BrdR2a
:
1253 case TTL_PT15_FPGA_FUNCTION_BrdR2b
:
1255 case TTL_PT15_FPGA_FUNCTION_BrdR3a
:
1257 case TTL_PT15_FPGA_FUNCTION_BrdR3b
:
1259 case TTL_PT15_FPGA_FUNCTION_BrdR4a
:
1261 case TTL_PT15_FPGA_FUNCTION_BrdR4b
:
1263 case TTL_PT15_FPGA_FUNCTION_BrdR5a
:
1265 case TTL_PT15_FPGA_FUNCTION_BrdR5b
:
1267 case TTL_PT15_FPGA_FUNCTION_BrdR6a
:
1269 case TTL_PT15_FPGA_FUNCTION_BrdR6b
:
1271 case TTL_PT15_FPGA_FUNCTION_MDIO
:
1277 case TTL_TAP_DEVICE_PT20_FPGA
:
1279 case TTL_PT20_FPGA_FUNCTION_CORE
:
1281 case TTL_PT20_FPGA_FUNCTION_CAN1
:
1283 case TTL_PT20_FPGA_FUNCTION_CAN2
:
1285 case TTL_PT20_FPGA_FUNCTION_CAN3
:
1287 case TTL_PT20_FPGA_FUNCTION_CAN4
:
1289 case TTL_PT20_FPGA_FUNCTION_CAN5
:
1291 case TTL_PT20_FPGA_FUNCTION_GbEth1a
:
1293 case TTL_PT20_FPGA_FUNCTION_GbEth1b
:
1295 case TTL_PT20_FPGA_FUNCTION_GbEth2a
:
1297 case TTL_PT20_FPGA_FUNCTION_GbEth2b
:
1299 case TTL_PT20_FPGA_FUNCTION_GbEth3a
:
1301 case TTL_PT20_FPGA_FUNCTION_GbEth3b
:
1303 case TTL_PT20_FPGA_FUNCTION_MDIO
:
1309 case TTL_TAP_DEVICE_PC3_FPGA
:
1311 case TTL_PC3_FPGA_FUNCTION_CORE
:
1313 case TTL_PC3_FPGA_FUNCTION_BrdR1a
:
1315 case TTL_PC3_FPGA_FUNCTION_BrdR1b
:
1321 case TTL_TAP_DEVICE_PC3_AURIX
:
1323 case TTL_PC3_AURIX_FUNCTION_CORE
:
1324 return "Aurix_Core";
1325 case TTL_PC3_AURIX_FUNCTION_CAN1
:
1327 case TTL_PC3_AURIX_FUNCTION_CAN2
:
1329 case TTL_PC3_AURIX_FUNCTION_CAN3
:
1331 case TTL_PC3_AURIX_FUNCTION_CAN4
:
1333 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1A
:
1334 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B
:
1336 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2A
:
1337 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B
:
1339 case TTL_PC3_AURIX_FUNCTION_DIGITALIN1
:
1340 return "DigitalIn1";
1341 case TTL_PC3_AURIX_FUNCTION_DIGITALIN2
:
1342 return "DigitalIn2";
1343 case TTL_PC3_AURIX_FUNCTION_DIGITALOUT1
:
1344 return "DigitalOut1";
1345 case TTL_PC3_AURIX_FUNCTION_DIGITALOUT2
:
1346 return "DigitalOut2";
1351 case TTL_TAP_DEVICE_ZELDA_CANFD
:
1353 case TTL_TAP_DEVICE_ZELDA_CORE
:
1354 return "CANFD_Core";
1355 case TTL_TAP_DEVICE_ZELDA_CANFD1
:
1357 case TTL_TAP_DEVICE_ZELDA_CANFD2
:
1359 case TTL_TAP_DEVICE_ZELDA_CANFD3
:
1361 case TTL_TAP_DEVICE_ZELDA_CANFD4
:
1363 case TTL_TAP_DEVICE_ZELDA_CANFD5
:
1365 case TTL_TAP_DEVICE_ZELDA_CANFD6
:
1367 case TTL_TAP_DEVICE_ZELDA_CANFD7
:
1369 case TTL_TAP_DEVICE_ZELDA_CANFD8
:
1371 case TTL_TAP_DEVICE_ZELDA_CANFD9
:
1373 case TTL_TAP_DEVICE_ZELDA_CANFD10
:
1375 case TTL_TAP_DEVICE_ZELDA_CANFD11
:
1377 case TTL_TAP_DEVICE_ZELDA_CANFD12
:
1379 case TTL_TAP_DEVICE_ZELDA_CANFD13
:
1381 case TTL_TAP_DEVICE_ZELDA_CANFD14
:
1383 case TTL_TAP_DEVICE_ZELDA_CANFD15
:
1389 case TTL_TAP_DEVICE_ZELDA_LIN
:
1391 case TTL_TAP_DEVICE_ZELDA_CORE
:
1393 case TTL_TAP_DEVICE_ZELDA_LIN1
:
1395 case TTL_TAP_DEVICE_ZELDA_LIN2
:
1397 case TTL_TAP_DEVICE_ZELDA_LIN3
:
1399 case TTL_TAP_DEVICE_ZELDA_LIN4
:
1401 case TTL_TAP_DEVICE_ZELDA_LIN5
:
1403 case TTL_TAP_DEVICE_ZELDA_LIN6
:
1405 case TTL_TAP_DEVICE_ZELDA_LIN7
:
1407 case TTL_TAP_DEVICE_ZELDA_LIN8
:
1409 case TTL_TAP_DEVICE_ZELDA_LIN9
:
1411 case TTL_TAP_DEVICE_ZELDA_LIN10
:
1413 case TTL_TAP_DEVICE_ZELDA_LIN11
:
1415 case TTL_TAP_DEVICE_ZELDA_LIN12
:
1417 case TTL_TAP_DEVICE_ZELDA_LIN13
:
1419 case TTL_TAP_DEVICE_ZELDA_LIN14
:
1421 case TTL_TAP_DEVICE_ZELDA_LIN15
:
1423 case TTL_TAP_DEVICE_ZELDA_LIN16
:
1425 case TTL_TAP_DEVICE_ZELDA_LIN17
:
1427 case TTL_TAP_DEVICE_ZELDA_LIN18
:
1429 case TTL_TAP_DEVICE_ZELDA_LIN19
:
1431 case TTL_TAP_DEVICE_ZELDA_LIN20
:
1433 case TTL_TAP_DEVICE_ZELDA_LIN21
:
1435 case TTL_TAP_DEVICE_ZELDA_LIN22
:
1437 case TTL_TAP_DEVICE_ZELDA_LIN23
:
1439 case TTL_TAP_DEVICE_ZELDA_LIN24
:
1453 static wtap_opttype_return_val
1454 ttl_add_interface_name(wtap_block_t int_data
, uint16_t addr
, const char* name
) {
1456 return wtap_block_add_string_option(int_data
, OPT_IDB_NAME
, name
, strlen(name
));
1459 return wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "%s::%s::%s",
1460 ttl_get_cascade_name(addr
),
1461 ttl_get_device_name(addr
),
1462 ttl_get_function_name(addr
));
1466 * This function will create the interface and populate the
1467 * 'address_to_iface_ht' hash table.
1470 ttl_create_interface(wtap
* wth
, int pkt_encap
, uint16_t addr
, const char* name
) {
1471 wtap_block_t int_data
;
1472 wtapng_if_descr_mandatory_t
* if_descr_mand
;
1478 int_data
= wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO
);
1479 if_descr_mand
= wtap_block_get_mandatory_data(int_data
);
1481 if_descr_mand
->wtap_encap
= pkt_encap
;
1482 ttl_add_interface_name(int_data
, addr
, name
);
1484 if_descr_mand
->time_units_per_second
= 1000 * 1000;
1485 if_descr_mand
->tsprecision
= WTAP_TSPREC_USEC
;
1486 wtap_block_add_uint8_option(int_data
, OPT_IDB_TSRESOL
, 9);
1487 if_descr_mand
->snap_len
= WTAP_MAX_PACKET_SIZE_STANDARD
;
1488 if_descr_mand
->num_stat_entries
= 0;
1489 if_descr_mand
->interface_statistics
= NULL
;
1490 wtap_add_idb(wth
, int_data
);
1492 if (wth
->file_encap
== WTAP_ENCAP_NONE
) {
1493 wth
->file_encap
= if_descr_mand
->wtap_encap
;
1495 else if (wth
->file_encap
!= if_descr_mand
->wtap_encap
) {
1496 wth
->file_encap
= WTAP_ENCAP_PER_PACKET
;
1502 #define TTL_LOOKUP_INTERFACE_MAX_ITERATIONS 2
1503 #define ttl_lookup_interface(...) ttl_lookup_interface_int(__VA_ARGS__, 0)
1505 // NOLINTNEXTLINE(misc-no-recursion)
1506 static const ttl_addr_to_iface_entry_t
* ttl_lookup_interface_int(wtap
* wth
, uint16_t addr
, int* err
, char** err_info
, int iteration
) {
1507 ttl_addr_to_iface_entry_t
* item
;
1510 uint16_t master_addr
;
1517 ttl
= (ttl_t
*)wth
->priv
;
1518 if (ttl
== NULL
|| ttl
->address_to_iface_ht
== NULL
) {
1522 /* Recursion limit to avoid coding errors. */
1523 if (iteration
> TTL_LOOKUP_INTERFACE_MAX_ITERATIONS
) {
1524 *err
= WTAP_ERR_INTERNAL
;
1525 *err_info
= ws_strdup_printf("ttl_lookup_interface(): more iterations than allowed: %d (max. %d)", iteration
, TTL_LOOKUP_INTERFACE_MAX_ITERATIONS
);
1529 item
= g_hash_table_lookup(ttl
->address_to_iface_ht
, GUINT_TO_POINTER(addr
));
1534 pkt_encap
= ttl_get_address_iface_type(addr
);
1535 if (pkt_encap
<= WTAP_ENCAP_UNKNOWN
) {
1539 master_addr
= ttl_get_master_address(ttl
->address_to_master_ht
, addr
);
1540 if (addr
!= master_addr
) { /* The interface ID is the "slave" one */
1541 const ttl_addr_to_iface_entry_t
* master_item
= ttl_lookup_interface_int(wth
, master_addr
, err
, err_info
, iteration
+ 1);
1542 if (master_item
== NULL
) {
1546 iface_id
= master_item
->interface_id
;
1548 else { /* Create a new interface */
1549 const char* saved_name
= g_hash_table_lookup(ttl
->address_to_name_ht
, GUINT_TO_POINTER(addr
));
1550 bool ret
= ttl_create_interface(wth
, pkt_encap
, addr
, saved_name
);
1552 if (saved_name
!= NULL
) {
1553 g_hash_table_remove(ttl
->address_to_name_ht
, GUINT_TO_POINTER(addr
));
1560 iface_id
= ttl
->next_interface_id
++;
1563 /* Create the entry */
1564 item
= g_new(ttl_addr_to_iface_entry_t
, 1);
1565 item
->interface_id
= iface_id
;
1566 item
->pkt_encap
= pkt_encap
;
1567 item
->channelB
= ttl_is_chb_addr(addr
);
1568 g_hash_table_insert(ttl
->address_to_iface_ht
, GUINT_TO_POINTER(addr
), item
);
1574 ttl_init_rec(wtap_rec
* rec
, uint64_t timestamp
, uint16_t addr
, int pkt_encap
, uint32_t iface_id
, uint32_t caplen
, uint32_t len
) {
1575 rec
->rec_type
= REC_TYPE_PACKET
;
1576 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
1577 rec
->presence_flags
= WTAP_HAS_CAP_LEN
| WTAP_HAS_INTERFACE_ID
| WTAP_HAS_TS
;
1578 rec
->tsprec
= WTAP_TSPREC_USEC
;
1579 rec
->ts
.secs
= timestamp
/ (1000 * 1000);
1580 rec
->ts
.nsecs
= 1000 * (timestamp
% (1000 * 1000));
1581 rec
->rec_header
.packet_header
.caplen
= caplen
;
1582 rec
->rec_header
.packet_header
.len
= len
;
1584 rec
->ts_rel_cap_valid
= false;
1586 rec
->rec_header
.packet_header
.pkt_encap
= pkt_encap
;
1587 rec
->rec_header
.packet_header
.interface_id
= iface_id
;
1589 wtap_block_add_uint32_option(rec
->block
, OPT_PKT_QUEUE
, addr
);
1593 ttl_read_bytes(ttl_read_t
* in
, void* out
, uint16_t size
, int* err
, char** err_info
) {
1594 switch (in
->validity
) {
1596 if (!wtap_read_bytes_or_eof(in
->fh
, out
, size
, err
, err_info
)) {
1597 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err
);
1603 if ((in
->cur_pos
+ size
) > in
->size
) {
1604 *err
= WTAP_ERR_SHORT_READ
;
1605 *err_info
= ws_strdup("ttl_read_bytes(): Attempt to read beyond buffer end");
1609 memcpy(out
, in
->buf
+ in
->cur_pos
, size
);
1611 in
->cur_pos
+= size
;
1615 *err
= WTAP_ERR_INTERNAL
;
1616 *err_info
= ws_strdup_printf("ttl_read_bytes(): ttl_read_t unknown validity flags: %d", in
->validity
);
1624 ttl_read_bytes_buffer(ttl_read_t
* in
, Buffer
* buf
, uint16_t size
, int* err
, char** err_info
) {
1625 ws_buffer_assure_space(buf
, size
);
1626 if (!ttl_read_bytes(in
, ws_buffer_end_ptr(buf
), size
, err
, err_info
)) {
1629 ws_buffer_increase_length(buf
, size
);
1634 ttl_skip_bytes(ttl_read_t
* in
, uint16_t size
, int* err
, char** err_info
) {
1635 return ttl_read_bytes(in
, NULL
, size
, err
, err_info
);
1639 ttl_add_eth_dir_option(wtap_rec
* rec
, uint16_t status
) {
1640 uint32_t opt
= PACK_FLAGS_DIRECTION_UNKNOWN
;
1643 case TTL_ETH_STATUS_VALID_FRAME
:
1644 case TTL_ETH_STATUS_CRC_ERROR_FRAME
:
1645 case TTL_ETH_STATUS_LENGTH_ERROR_FRAME
:
1646 case TTL_ETH_STATUS_PHY_ERROR_FRAME
:
1647 opt
= PACK_FLAGS_DIRECTION_INBOUND
;
1649 case TTL_ETH_STATUS_TX_ERROR_FRAME
:
1650 case TTL_ETH_STATUS_TX_FREEMEM_INFO_FRAME
:
1651 case TTL_ETH_STATUS_TX_FRAME
:
1652 opt
= PACK_FLAGS_DIRECTION_OUTBOUND
;
1658 wtap_block_add_uint32_option(rec
->block
, OPT_EPB_FLAGS
, opt
);
1662 ttl_read_eth_data_entry(wtap_rec
* rec
, int* err
, char** err_info
, ttl_read_t
* in
, uint16_t size
, uint16_t addr
,
1663 const ttl_addr_to_iface_entry_t
* item
, uint16_t status
, uint64_t timestamp
) {
1665 *err
= WTAP_ERR_INTERNAL
;
1666 *err_info
= ws_strdup("ttl_read_eth_data_entry called with NULL item");
1670 if (status
== TTL_ETH_STATUS_PHY_STATUS
) { /* TODO */
1671 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
1674 return TTL_UNSUPPORTED
;
1677 if (size
< 2) { /* 2 unused bytes */
1678 return TTL_CORRUPTED
;
1680 if (!ttl_skip_bytes(in
, 2, err
, err_info
)) {
1685 if (size
!= 0 && !ttl_read_bytes_buffer(in
, &rec
->data
, size
, err
, err_info
)) {
1689 ttl_init_rec(rec
, timestamp
, addr
, item
->pkt_encap
, item
->interface_id
, size
, size
);
1690 ttl_add_eth_dir_option(rec
, status
);
1692 return TTL_NO_ERROR
;
1696 ttl_add_can_dir_option(wtap_rec
* rec
) {
1697 uint32_t opt
= PACK_FLAGS_DIRECTION_INBOUND
; /* For the moment, we only support this */
1699 wtap_block_add_uint32_option(rec
->block
, OPT_EPB_FLAGS
, opt
);
1702 static const uint8_t canfd_dlc_to_length
[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64 };
1705 ttl_read_can_data_entry(wtap_rec
* rec
, int* err
, char** err_info
, ttl_read_t
* in
, uint16_t size
, uint16_t addr
,
1706 const ttl_addr_to_iface_entry_t
* item
, uint16_t status
, uint64_t timestamp
) {
1707 uint32_t can_id
= 0;
1708 uint8_t dlc
, error_code
, len
, canfd_flags
= 0;
1709 uint8_t can_header
[8], can_error_payload
[CAN_ERR_DLC
] = {0};
1712 *err
= WTAP_ERR_INTERNAL
;
1713 *err_info
= ws_strdup("ttl_read_can_data_entry called with NULL item");
1717 dlc
= (status
& TTL_CAN_STATUS_DLC_MASK
) >> TTL_CAN_STATUS_DLC_POS
;
1718 error_code
= (status
& TTL_CAN_STATUS_ERROR_CODE_MASK
) >> TTL_CAN_STATUS_ERROR_CODE_POS
;
1720 if (status
& TTL_CAN_STATUS_VALID_BIT_MASK
) { /* DLC, ID and Payload are valid */
1721 if (size
< sizeof(uint32_t)) { /* No more data */
1722 return TTL_CORRUPTED
;
1725 if (!ttl_read_bytes(in
, &can_id
, sizeof(uint32_t), err
, err_info
)) {
1728 can_id
= GUINT32_FROM_LE(can_id
);
1729 size
-= sizeof(uint32_t);
1731 if (size
== 0 && !(status
& TTL_CAN_STATUS_RTR_BIT_MASK
)) {
1732 /* No more data, and it's not a remote transmission frame */
1733 return TTL_CORRUPTED
;
1738 can_id
= CAN_ERR_FLAG
;
1739 if (status
& TTL_CAN_STATUS_BUSOFF_MASK
) can_id
|= CAN_ERR_BUSOFF
;
1742 switch (error_code
) {
1743 case TTL_CAN_ERROR_STUFF_ERROR
:
1744 can_id
|= CAN_ERR_PROT
;
1745 can_error_payload
[2] = CAN_ERR_PROT_STUFF
;
1747 case TTL_CAN_ERROR_FORM_ERROR
:
1748 can_id
|= CAN_ERR_PROT
;
1749 can_error_payload
[2] = CAN_ERR_PROT_FORM
;
1751 case TTL_CAN_ERROR_ACK_ERROR
:
1752 can_id
|= CAN_ERR_ACK
;
1754 case TTL_CAN_ERROR_BIT1_ERROR
:
1755 can_id
|= CAN_ERR_PROT
;
1756 can_error_payload
[2] = CAN_ERR_PROT_BIT1
;
1758 case TTL_CAN_ERROR_BIT0_ERROR
:
1759 can_id
|= CAN_ERR_PROT
;
1760 can_error_payload
[2] = CAN_ERR_PROT_BIT0
;
1762 case TTL_CAN_ERROR_CRC_ERROR
:
1763 can_id
|= CAN_ERR_PROT
;
1764 can_error_payload
[3] = CAN_ERR_PROT_LOC_CRC_SEQ
;
1766 case TTL_CAN_ERROR_INVALID_DLC
:
1767 can_id
|= CAN_ERR_PROT
;
1768 can_error_payload
[3] = CAN_ERR_PROT_LOC_DLC
;
1773 if (status
& TTL_CAN_STATUS_RTR_BIT_MASK
) can_id
|= CAN_RTR_FLAG
;
1774 if (status
& TTL_CAN_STATUS_IDE_BIT_MASK
) can_id
|= CAN_EFF_FLAG
;
1775 if (status
& TTL_CAN_STATUS_EDL_BIT_MASK
) {
1776 canfd_flags
|= CANFD_FDF
;
1777 len
= canfd_dlc_to_length
[dlc
];
1782 if (status
& TTL_CAN_STATUS_BRS_BIT_MASK
) canfd_flags
|= CANFD_BRS
;
1783 if (status
& TTL_CAN_STATUS_ESI_BIT_MASK
) canfd_flags
|= CANFD_ESI
;
1786 can_header
[0] = (can_id
& 0xff000000) >> 24;
1787 can_header
[1] = (can_id
& 0x00ff0000) >> 16;
1788 can_header
[2] = (can_id
& 0x0000ff00) >> 8;
1789 can_header
[3] = (can_id
& 0x000000ff);
1790 can_header
[4] = len
;
1791 can_header
[5] = canfd_flags
;
1795 ws_buffer_append(&rec
->data
, can_header
, sizeof(can_header
));
1798 ws_buffer_append(&rec
->data
, can_error_payload
, sizeof(can_error_payload
));
1799 if (size
!= 0 && !ttl_skip_bytes(in
, size
, err
, err_info
)) {
1802 ttl_init_rec(rec
, timestamp
, addr
, item
->pkt_encap
, item
->interface_id
,
1803 sizeof(can_header
) + sizeof(can_error_payload
), sizeof(can_header
) + sizeof(can_error_payload
));
1806 if (size
!= 0 && !ttl_read_bytes_buffer(in
, &rec
->data
, size
, err
, err_info
)) {
1809 ttl_init_rec(rec
, timestamp
, addr
, item
->pkt_encap
, item
->interface_id
, size
+ sizeof(can_header
), len
+ sizeof(can_header
));
1812 ttl_add_can_dir_option(rec
);
1814 return TTL_NO_ERROR
;
1818 ttl_add_lin_dir_option(wtap_rec
* rec
) {
1819 uint32_t opt
= PACK_FLAGS_DIRECTION_INBOUND
; /* For the moment, we only support this */
1821 wtap_block_add_uint32_option(rec
->block
, OPT_EPB_FLAGS
, opt
);
1825 ttl_read_lin_data_entry(wtap_rec
* rec
, int* err
, char** err_info
, ttl_read_t
* in
, uint16_t size
, uint16_t addr
,
1826 const ttl_addr_to_iface_entry_t
* item
, uint16_t status
, uint64_t timestamp
) {
1827 uint8_t lin_header
[8], lin_payload
[8];
1831 *err
= WTAP_ERR_INTERNAL
;
1832 *err_info
= ws_strdup("ttl_read_lin_data_entry called with NULL item");
1836 dlc
= size
!= 0 ? MIN((size
- 1), 8) : 0;
1838 lin_header
[0] = 1; /* message format rev = 1 */
1839 lin_header
[1] = 0; /* reserved */
1840 lin_header
[2] = 0; /* reserved */
1841 lin_header
[3] = 0; /* reserved */
1842 lin_header
[4] = dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
1843 lin_header
[5] = status
& TTL_LIN_STATUS_PID_MASK
; /* parity (2bit) | id (6bit) */
1844 lin_header
[6] = 0; /* checksum */
1845 lin_header
[7] = 0; /* errors */
1847 if (status
& TTL_LIN_ERROR_PARITY_ERROR
) lin_header
[7] |= 0x04;
1848 if (status
& TTL_LIN_ERROR_SYNC_ERROR
) lin_header
[7] |= 0x02; /* Is this correct? */
1849 if (status
& TTL_LIN_ERROR_NO_DATA_ERROR
) lin_header
[7] |= 0x01;
1850 if (status
& TTL_LIN_ERROR_ABORT_ERROR
) lin_header
[7] |= 0x02; /* Is this correct? */
1851 /* Set the checksum error if the checksum is wrong with respect to both types */
1852 if ((status
& TTL_LIN_ERROR_ANY_CHECKSUM
) == TTL_LIN_ERROR_ANY_CHECKSUM
) lin_header
[7] |= 0x08;
1855 if (!ttl_read_bytes(in
, &lin_payload
[0], dlc
, err
, err_info
)) {
1862 if (!ttl_read_bytes(in
, &lin_header
[6], 1, err
, err_info
)) {
1868 if (size
!= 0) { /* Skip any extra byte */
1869 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
1874 ws_buffer_append(&rec
->data
, lin_header
, sizeof(lin_header
));
1877 ws_buffer_append(&rec
->data
, lin_payload
, dlc
);
1880 ttl_init_rec(rec
, timestamp
, addr
, item
->pkt_encap
, item
->interface_id
, dlc
+ sizeof(lin_header
), dlc
+ sizeof(lin_header
));
1881 ttl_add_lin_dir_option(rec
);
1883 return TTL_NO_ERROR
;
1887 ttl_add_flexray_dir_option(wtap_rec
* rec
) {
1888 uint32_t opt
= PACK_FLAGS_DIRECTION_INBOUND
; /* For the moment, we only support this */
1890 wtap_block_add_uint32_option(rec
->block
, OPT_EPB_FLAGS
, opt
);
1894 ttl_read_flexray_data_entry(wtap_rec
* rec
, int* err
, char** err_info
, ttl_read_t
* in
, uint16_t size
, uint16_t addr
,
1895 const ttl_addr_to_iface_entry_t
* item
, uint16_t status
, uint64_t timestamp
) {
1897 uint8_t fr_header
[2];
1900 *err
= WTAP_ERR_INTERNAL
;
1901 *err_info
= ws_strdup("ttl_read_flexray_data_entry called with NULL item");
1905 fr_item
= status
& TTL_FLEXRAY_ITEM_MASK
;
1907 if (fr_item
!= TTL_FLEXRAY_ITEM_REGULAR_FRAME
&& fr_item
!= TTL_FLEXRAY_ITEM_ABORTED_FRAME
) { /* TODO */
1908 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
1911 return TTL_UNSUPPORTED
;
1914 fr_header
[0] = FLEXRAY_FRAME
;
1915 fr_header
[1] = 0; /* Errors */
1917 if (item
->channelB
) fr_header
[0] |= 0x80;
1919 if (status
& (TTL_FLEXRAY_FSS_ERROR_MASK
| TTL_FLEXRAY_BSS_ERROR_MASK
)) fr_header
[1] |= 0x02;
1920 if (status
& TTL_FLEXRAY_FES_ERROR_MASK
) fr_header
[1] |= 0x04;
1921 if (status
& TTL_FLEXRAY_FRAME_CRC_ERROR_MASK
) fr_header
[1] |= 0x10;
1922 if (status
& TTL_FLEXRAY_HEADER_CRC_ERROR_MASK
) fr_header
[1] |= 0x08;
1924 ws_buffer_append(&rec
->data
, fr_header
, sizeof(fr_header
));
1926 if (size
!= 0 && !ttl_read_bytes_buffer(in
, &rec
->data
, size
, err
, err_info
)) {
1930 ttl_init_rec(rec
, timestamp
, addr
, item
->pkt_encap
, item
->interface_id
, size
+ sizeof(fr_header
), size
+ sizeof(fr_header
));
1931 ttl_add_flexray_dir_option(rec
);
1933 return TTL_NO_ERROR
;
1937 ttl_read_data_entry(wtap
* wth
, wtap_rec
* rec
, int* err
, char** err_info
, ttl_read_t
* in
, uint16_t size
, uint16_t src
, uint16_t status
) {
1938 const ttl_addr_to_iface_entry_t
* item
;
1939 int pkt_encap
= ttl_get_address_iface_type(src
);
1942 if (pkt_encap
<= WTAP_ENCAP_UNKNOWN
) {
1943 ws_debug("ttl_read_data_entry: Unsupported source address found in TTL_BUS_DATA_ENTRY: 0x%X", src
);
1944 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
1947 return TTL_UNSUPPORTED
;
1951 item
= ttl_lookup_interface(wth
, src
, err
, err_info
);
1956 if (size
< sizeof(uint64_t)) {
1957 return TTL_CORRUPTED
;
1959 if (!ttl_read_bytes(in
, ×tamp
, sizeof(uint64_t), err
, err_info
)) {
1962 timestamp
= GUINT64_FROM_LE(timestamp
);
1963 size
-= sizeof(uint64_t);
1965 switch (pkt_encap
) {
1966 case WTAP_ENCAP_ETHERNET
:
1967 return ttl_read_eth_data_entry(rec
, err
, err_info
, in
, size
, src
, item
, status
, timestamp
);
1968 case WTAP_ENCAP_SOCKETCAN
:
1969 return ttl_read_can_data_entry(rec
, err
, err_info
, in
, size
, src
, item
, status
, timestamp
);
1970 case WTAP_ENCAP_LIN
:
1971 return ttl_read_lin_data_entry(rec
, err
, err_info
, in
, size
, src
, item
, status
, timestamp
);
1972 case WTAP_ENCAP_FLEXRAY
:
1973 return ttl_read_flexray_data_entry(rec
, err
, err_info
, in
, size
, src
, item
, status
, timestamp
);
1975 ws_debug("ttl_read_data_entry: Unsupported packet type found in TTL_BUS_DATA_ENTRY: %d", pkt_encap
);
1976 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
1979 return TTL_UNSUPPORTED
;
1985 ttl_check_segmented_message_recursion(const ttl_read_t
* in
, int* err
, char** err_info
) {
1986 ttl_entryheader_t header
;
1988 if (in
->validity
!= VALIDITY_BUF
) {
1989 *err
= WTAP_ERR_INTERNAL
;
1990 *err_info
= ws_strdup("tt_fix_segmented_message_entry_payload: input buffer is not valid");
1994 memcpy(&header
, in
->buf
+ in
->cur_pos
, sizeof(ttl_entryheader_t
));
1995 fix_endianness_ttl_entryheader(&header
);
1997 if ((header
.size_type
>> 12) == TTL_SEGMENTED_MESSAGE_ENTRY
) {
2005 * For some reason, the timestamp of the nested frame is garbage.
2006 * Copy the timestamp of the first segment in its place.
2009 ttl_fix_segmented_message_entry_timestamp(const ttl_read_t
* in
, uint64_t timestamp
, int* err
, char** err_info
) {
2010 ttl_entryheader_t header
;
2012 if (in
->validity
!= VALIDITY_BUF
) {
2013 *err
= WTAP_ERR_INTERNAL
;
2014 *err_info
= ws_strdup("tt_fix_segmented_message_entry_payload: input buffer is not valid");
2018 memcpy(&header
, in
->buf
+ in
->cur_pos
, sizeof(ttl_entryheader_t
));
2019 fix_endianness_ttl_entryheader(&header
);
2021 if ((header
.size_type
>> 12) == TTL_BUS_DATA_ENTRY
) {
2022 timestamp
= GUINT64_TO_LE(timestamp
);
2023 memcpy(in
->buf
+ in
->cur_pos
+ sizeof(ttl_entryheader_t
), ×tamp
, sizeof(uint64_t));
2029 // NOLINTNEXTLINE(misc-no-recursion)
2030 static ttl_result_t
ttl_read_segmented_message_entry(wtap
* wth
, wtap_rec
* rec
, int* err
, char** err_info
, ttl_read_t
* in
,
2031 uint16_t size
, uint16_t src
, uint16_t status
, int64_t offset
) {
2032 ttl_segmented_entry_t
* item
;
2033 ttl_reassembled_entry_t
* reassembled_item
;
2034 ttl_t
* ttl
= (ttl_t
*)wth
->priv
;
2036 uint8_t frame_num
= status
& 0x000f;
2037 uint8_t seg_frame_id
= (status
>> 4) & 0x000f;
2038 uint32_t key
= ((uint32_t)seg_frame_id
<< 16) | src
;
2041 if (status
== 0xFFFF) { /* Reserved for future use */
2042 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
2045 return TTL_UNSUPPORTED
;
2048 reassembled_item
= g_hash_table_lookup(ttl
->reassembled_frames_ht
, &offset
);
2050 if (reassembled_item
== NULL
) {
2051 if (size
< sizeof(uint64_t)) {
2052 return TTL_CORRUPTED
;
2054 if (!ttl_read_bytes(in
, ×tamp
, sizeof(uint64_t), err
, err_info
)) {
2057 timestamp
= GUINT64_FROM_LE(timestamp
);
2058 size
-= sizeof(uint64_t);
2060 item
= g_hash_table_lookup(ttl
->segmented_frames_ht
, GUINT_TO_POINTER(key
));
2062 if (frame_num
== 0) { /* This is the first segment */
2063 if (item
!= NULL
) { /* New header with reassemble in progress */
2064 ws_debug("ttl_read_segmented_message_entry: Found new header while reassembly was in progress for SRC %d, FRAME ID %d", src
, seg_frame_id
);
2065 g_hash_table_remove(ttl
->segmented_frames_ht
, GUINT_TO_POINTER(key
));
2068 if (size
< (2 * sizeof(uint32_t))) { /* Size and type below */
2069 return TTL_CORRUPTED
;
2072 item
= (ttl_segmented_entry_t
*)g_new0(ttl_segmented_entry_t
, 1);
2073 item
->timestamp
= timestamp
;
2075 if (!ttl_read_bytes(in
, &item
->size
, sizeof(uint32_t), err
, err_info
)) {
2079 item
->size
= GUINT32_FROM_LE(item
->size
);
2080 size
-= sizeof(uint32_t);
2082 if (!ttl_read_bytes(in
, &item
->type
, sizeof(uint32_t), err
, err_info
)) {
2086 item
->type
= GUINT32_FROM_LE(item
->type
);
2087 size
-= sizeof(uint32_t);
2089 /* If the reassebled size is too big, we go on as usual, but without a buffer.
2090 * This way we avoid problems with segments later.
2092 if (item
->size
<= WTAP_MAX_PACKET_SIZE_STANDARD
) {
2093 item
->buf
= g_try_malloc(item
->size
);
2094 if (item
->buf
== NULL
) {
2095 *err
= WTAP_ERR_INTERNAL
;
2096 *err_info
= ws_strdup("ttl_read_segmented_message_entry: cannot allocate memory");
2101 g_hash_table_insert(ttl
->segmented_frames_ht
, GUINT_TO_POINTER(key
), item
);
2105 ws_debug("ttl_read_segmented_message_entry: Found frame number %d without header for SRC %d, FRAME ID %d", frame_num
, src
, seg_frame_id
);
2106 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
2109 return TTL_UNSUPPORTED
;
2112 if (item
->next_segment
!= frame_num
) {
2113 ws_debug("ttl_read_segmented_message_entry: Found out of order segment (expected %d, found %d) for SRC %d, FRAME ID %d",
2114 item
->next_segment
, frame_num
, src
, seg_frame_id
);
2115 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
2118 return TTL_UNSUPPORTED
;
2122 if ((item
->size_so_far
+ size
) > item
->size
) {
2123 g_hash_table_remove(ttl
->segmented_frames_ht
, GUINT_TO_POINTER(key
));
2124 return TTL_CORRUPTED
;
2127 void* dest_buf
= item
->buf
!= NULL
? item
->buf
+ item
->size_so_far
: NULL
;
2128 if (!ttl_read_bytes(in
, dest_buf
, size
, err
, err_info
)) {
2129 g_hash_table_remove(ttl
->segmented_frames_ht
, GUINT_TO_POINTER(key
));
2132 item
->size_so_far
+= size
;
2133 item
->next_segment
++;
2135 if (item
->size_so_far
>= item
->size
) { /* Reassemble complete */
2136 if (item
->buf
== NULL
) {
2137 /* Silently discard packets we reassembled without data */
2138 g_hash_table_remove(ttl
->segmented_frames_ht
, GUINT_TO_POINTER(key
));
2139 return TTL_UNSUPPORTED
;
2142 if (item
->type
!= TTL_SEGMENTED_MESSAGE_ENTRY_TYPE_NESTED_FRAME
) {
2143 ws_debug("ttl_read_segmented_message_entry: Unsupported type found: %d", item
->type
);
2144 g_hash_table_remove(ttl
->segmented_frames_ht
, GUINT_TO_POINTER(key
));
2145 return TTL_UNSUPPORTED
;
2148 reassembled_item
= (ttl_reassembled_entry_t
*)g_new(ttl_reassembled_entry_t
, 1);
2149 reassembled_item
->timestamp
= item
->timestamp
;
2150 reassembled_item
->size
= item
->size
;
2151 reassembled_item
->buf
= item
->buf
;
2153 item
->buf
= NULL
; /* Dereference it so that it doesn't get destroyed */
2154 g_hash_table_remove(ttl
->segmented_frames_ht
, GUINT_TO_POINTER(key
));
2155 int64_t* new_off
= g_new(int64_t, 1);
2157 g_hash_table_insert(ttl
->reassembled_frames_ht
, new_off
, reassembled_item
);
2159 else { /* Reassemble not complete, wait for the rest */
2160 return TTL_UNSUPPORTED
;
2164 /* We already have the reassembled item, maybe we're re-visiting this entry. Simply skip to the end. */
2165 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
2170 /* If we're here, we have our reassembled entry */
2171 new_in
.buf
= reassembled_item
->buf
;
2172 new_in
.size
= reassembled_item
->size
;
2174 new_in
.validity
= VALIDITY_BUF
;
2176 /* Avoid recursion by not supporting nested segmented entries */
2178 if (!ttl_check_segmented_message_recursion(&new_in
, err
, err_info
)) {
2179 g_hash_table_remove(ttl
->reassembled_frames_ht
, &offset
);
2184 return TTL_UNSUPPORTED
;
2187 if (!ttl_fix_segmented_message_entry_timestamp(&new_in
, reassembled_item
->timestamp
, err
, err_info
)) {
2188 g_hash_table_remove(ttl
->reassembled_frames_ht
, &offset
);
2192 /* Read it as if it was a normal entry, but passing the buffer
2193 * as input insted of the file handler.
2195 return ttl_read_entry(wth
, rec
, err
, err_info
, &new_in
, 0, new_in
.size
);
2199 ttl_read_padding_entry(int* err
, char** err_info
, ttl_read_t
* in
, uint16_t size
) {
2200 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
2203 return TTL_UNSUPPORTED
;
2206 // NOLINTNEXTLINE(misc-no-recursion)
2207 static ttl_result_t
ttl_read_entry(wtap
* wth
, wtap_rec
* rec
, int* err
, char** err_info
, ttl_read_t
* in
, int64_t offset
, int64_t end
) {
2208 ttl_entryheader_t header
;
2213 if ((end
- offset
) < (int64_t)sizeof(ttl_entryheader_t
)) {
2215 * We probably have a corrupted file, try to recover our alignment
2216 * by skipping to the next block.
2218 return TTL_CORRUPTED
;
2221 /* Try to read the (next) entry header */
2222 if (!ttl_read_bytes(in
, &header
, sizeof(ttl_entryheader_t
), err
, err_info
)) {
2225 fix_endianness_ttl_entryheader(&header
);
2227 type
= header
.size_type
>> 12;
2228 size
= header
.size_type
& TTL_SIZE_MASK
;
2229 src_addr
= header
.src_addr
& TTL_ADDRESS_MASK
;
2231 if (size
< sizeof(ttl_entryheader_t
) || size
> (end
- offset
)) {
2233 * Hope the file is simply unaligned and skipping to the next block
2234 * will fix everything. This could also be the sign of a malformed
2235 * file; in that case, this error will repeat itself many times.
2237 return TTL_CORRUPTED
;
2240 size
-= sizeof(ttl_entryheader_t
);
2242 if (header
.dest_addr
& TTL_META1_COMPRESSED_FORMAT_MASK
) {
2243 /* We do not support this kind of entries yet. */
2244 ws_debug("ttl_read_entry: Skipping entry with compressed timestamp");
2245 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
2248 return TTL_UNSUPPORTED
;
2252 case TTL_BUS_DATA_ENTRY
:
2253 return ttl_read_data_entry(wth
, rec
, err
, err_info
, in
, size
, src_addr
, header
.status_info
);
2254 case TTL_SEGMENTED_MESSAGE_ENTRY
:
2255 /* Recursion is avoided inside ttl_read_segmented_message_entry() */
2256 return ttl_read_segmented_message_entry(wth
, rec
, err
, err_info
, in
, size
, src_addr
, header
.status_info
, offset
);
2257 case TTL_PADDING_ENTRY
:
2258 return ttl_read_padding_entry(err
, err_info
, in
, size
);
2260 ws_debug("ttl_read_entry: Unknown Entry type: %u", type
);
2261 if (!ttl_skip_bytes(in
, size
, err
, err_info
)) {
2264 return TTL_UNSUPPORTED
;
2271 ttl_xml_node_get_number(xmlNodePtr node
, xmlXPathContextPtr ctx
, double *ret
) {
2272 xmlXPathObjectPtr result
;
2279 result
= xmlXPathNodeEval(node
, "./Number[1]/text()", ctx
);
2280 if (result
&& result
->type
== XPATH_NODESET
&& !xmlXPathNodeSetIsEmpty(result
->nodesetval
)) {
2281 val
= xmlXPathCastToNumber(result
);
2282 if (!xmlXPathIsNaN(val
)) {
2284 xmlXPathFreeObject(result
);
2293 ttl_xml_node_get_string(xmlNodePtr node
, xmlXPathContextPtr ctx
, const char* name
, char** ret
) {
2294 xmlXPathObjectPtr result
;
2297 if (name
== NULL
|| ret
== NULL
) {
2301 str
= ws_strdup_printf("./%s[1]/text()", name
);
2303 result
= xmlXPathNodeEval(node
, str
, ctx
);
2305 if (result
&& result
->type
== XPATH_NODESET
&& !xmlXPathNodeSetIsEmpty(result
->nodesetval
)) {
2306 str
= xmlXPathCastToString(result
);
2307 *ret
= ws_strdup(str
);
2316 ttl_process_xml_config(ttl_t
* ttl
, const char* text
, int size
) {
2318 xmlXPathContextPtr ctx
;
2319 xmlXPathObjectPtr cascades
, devices
, functions
;
2322 uint16_t cascade
, device
, function
, addr
;
2323 char* user_defined_name
= NULL
;
2325 doc
= xmlParseMemory(text
, size
);
2330 if (xmlDocGetRootElement(doc
) == NULL
) {
2332 return false; /* Empty XML */
2335 ctx
= xmlXPathNewContext(doc
);
2336 cascades
= xmlXPathEvalExpression("/LoggerConfiguration/HWList/Cascades/Cascade", ctx
);
2337 if (cascades
&& cascades
->type
== XPATH_NODESET
&& !xmlXPathNodeSetIsEmpty(cascades
->nodesetval
)) {
2338 for (i
= 0; i
< cascades
->nodesetval
->nodeNr
; i
++) {
2339 if (ttl_xml_node_get_number(cascades
->nodesetval
->nodeTab
[i
], ctx
, &val
) && val
>= 0 && val
<= 7) {
2340 cascade
= (uint16_t)val
;
2341 if (val
== 0) { /* Only the configuration of the logger is inside the TTL file. The TAPs have their own configuration */
2343 devices
= xmlXPathNodeEval(cascades
->nodesetval
->nodeTab
[i
], "./Devices/Device", ctx
);
2344 if (devices
&& devices
->type
== XPATH_NODESET
&& !xmlXPathNodeSetIsEmpty(devices
->nodesetval
)) {
2345 for (j
= 0; j
< devices
->nodesetval
->nodeNr
; j
++) {
2346 if (ttl_xml_node_get_number(devices
->nodesetval
->nodeTab
[j
], ctx
, &val
) && val
>= 0 && val
<= 15) {
2347 device
= (uint16_t)val
;
2349 functions
= xmlXPathNodeEval(devices
->nodesetval
->nodeTab
[j
], "./Functions/Function", ctx
);
2350 if (functions
&& functions
->type
== XPATH_NODESET
&& !xmlXPathNodeSetIsEmpty(functions
->nodesetval
)) {
2351 for (k
= 0; k
< functions
->nodesetval
->nodeNr
; k
++) {
2352 if (ttl_xml_node_get_number(functions
->nodesetval
->nodeTab
[k
], ctx
, &val
) && val
>= 0 && val
<= 63) {
2353 function
= (uint16_t)val
;
2354 addr
= cascade
<< 10 | device
<< 6 | function
;
2356 if (g_hash_table_lookup(ttl
->address_to_name_ht
, GUINT_TO_POINTER(addr
)) == NULL
) {
2357 /* Get the name only if we don't already have it */
2358 if (ttl_xml_node_get_string(functions
->nodesetval
->nodeTab
[k
], ctx
, "UserDefinedName", &user_defined_name
)) {
2359 g_hash_table_insert(ttl
->address_to_name_ht
, GUINT_TO_POINTER(addr
), user_defined_name
);
2360 /* XXX - At this point, we should check if the interface (in case of Ethernet)
2361 * is a standalone interface or it's a coupled interface. Since getting this
2362 * information from the XML is a pain, and the configuration will never be
2363 * exhaustive, give up and rely on the user setting the mapping themself.
2371 xmlXPathFreeObject(functions
);
2375 xmlXPathFreeObject(devices
);
2380 xmlXPathFreeObject(cascades
);
2382 xmlXPathFreeContext(ctx
);
2386 #endif /* HAVE_LIBXML2 */
2388 /* Maximum supported line length of preference files */
2389 #define MAX_LINELEN 1024
2391 /** Read a line without trailing (CR)LF. Returns -1 on failure. */
2393 fgetline(char* buf
, int size
, FILE* fp
)
2395 if (fgets(buf
, size
, fp
)) {
2396 int len
= (int)strcspn(buf
, "\r\n");
2405 ttl_is_master_slave_relation_correct(uint16_t master
, uint16_t slave
) {
2406 uint8_t function
= ttl_addr_get_function(master
);
2408 if (ttl_addr_get_cascade(master
) == 0) {
2409 switch (ttl_addr_get_device(master
)) {
2410 case TTL_LOGGER_DEVICE_FPGA
:
2411 if (function
== TTL_LOGGER_FPGA_FUNCTION_ETHA_CH1
) {
2412 return (slave
== (master
+ 1));
2415 case TTL_LOGGER_DEVICE_ATOM
:
2416 if (function
== TTL_LOGGER_ATOM_FUNCTION_ETHA
) {
2417 return (slave
== (master
+ 1));
2420 case TTL_LOGGER_DEVICE_FPGAB
:
2422 case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH1
:
2423 case TTL_LOGGER_FPGAB_FUNCTION_AETHA_CH1
:
2424 case TTL_LOGGER_FPGAB_FUNCTION_AETHC_CH1
:
2425 case TTL_LOGGER_FPGAB_FUNCTION_AETHE_CH1
:
2426 case TTL_LOGGER_FPGAB_FUNCTION_AETHG_CH1
:
2427 case TTL_LOGGER_FPGAB_FUNCTION_AETHI_CH1
:
2428 case TTL_LOGGER_FPGAB_FUNCTION_AETHK_CH1
:
2429 return (slave
== (master
+ 1));
2439 switch (ttl_addr_get_device(master
)) {
2440 case TTL_TAP_DEVICE_PT15_FPGA
:
2442 case TTL_PT15_FPGA_FUNCTION_BrdR1a
:
2443 case TTL_PT15_FPGA_FUNCTION_BrdR2a
:
2444 case TTL_PT15_FPGA_FUNCTION_BrdR3a
:
2445 case TTL_PT15_FPGA_FUNCTION_BrdR4a
:
2446 case TTL_PT15_FPGA_FUNCTION_BrdR5a
:
2447 case TTL_PT15_FPGA_FUNCTION_BrdR6a
:
2448 return (slave
== (master
+ 1));
2453 case TTL_TAP_DEVICE_PT20_FPGA
:
2455 case TTL_PT20_FPGA_FUNCTION_GbEth1a
:
2456 case TTL_PT20_FPGA_FUNCTION_GbEth2a
:
2457 case TTL_PT20_FPGA_FUNCTION_GbEth3a
:
2458 return (slave
== (master
+ 1));
2463 case TTL_TAP_DEVICE_PC3_FPGA
:
2464 if (function
== TTL_PC3_FPGA_FUNCTION_BrdR1a
) {
2465 return (slave
== (master
+ 1));
2477 ttl_parse_masters_pref_file(ttl_t
* ttl
, const char* path
) {
2479 char line
[MAX_LINELEN
];
2487 fp
= ws_fopen(path
, "r");
2492 while (fgetline(line
, sizeof(line
), fp
) >= 0) {
2493 if ((cp
= strchr(line
, '#')))
2496 cp
= strtok(line
, " \t");
2497 if (cp
== NULL
|| !ws_strtou16(cp
, NULL
, &tmp
) || tmp
> 7) {
2498 continue; /* Invalid cascade */
2502 cp
= strtok(NULL
, " \t");
2503 if (cp
== NULL
|| !ws_strtou16(cp
, NULL
, &tmp
) || tmp
> 15) {
2504 continue; /* Invalid device */
2508 cp
= strtok(NULL
, " \t");
2509 if (cp
== NULL
|| !ws_strtou16(cp
, NULL
, &tmp
) || tmp
> 63) {
2510 continue; /* Invalid function */
2514 cp
= strtok(NULL
, " \t");
2515 if (cp
== NULL
|| !ws_strtou16(cp
, NULL
, &tmp
) || tmp
> 1) {
2516 continue; /* Invalid flag */
2519 if (tmp
) { /* The address is coupled to the master */
2520 if (addr
!= 0 && ttl_is_master_slave_relation_correct(addr
- 1, addr
)) {
2521 g_hash_table_insert(ttl
->address_to_master_ht
, GUINT_TO_POINTER(addr
), GUINT_TO_POINTER(addr
- 1));
2524 else { /* The address is independent from the master */
2525 g_hash_table_insert(ttl
->address_to_master_ht
, GUINT_TO_POINTER(addr
), GUINT_TO_POINTER(addr
));
2534 * This function gets the working mode of the Ethernet interfaces from a
2535 * configuration file. This only applies to the interfaces that can be
2536 * configured both as the second side of a tap and independent interfaces.
2537 * The entry format is the following: Cascade Device Function Flag
2538 * A flag value of 0 means independent interface, while 1 means coupled with
2539 * its master. If an entry is not present, the interface will be treated
2540 * by ttl_lookup_interface() according to the default behaviour (currently,
2541 * independent interface for the logger and coupled interface for the taps).
2544 ttl_init_masters_from_pref_file(ttl_t
* ttl
) {
2548 pref_file
= get_persconffile_path(TTL_ADDRESS_MASTER_PREFS
, true);
2549 ret
= ttl_parse_masters_pref_file(ttl
, pref_file
);
2552 pref_file
= get_persconffile_path(TTL_ADDRESS_MASTER_PREFS
, false);
2553 ret
= ttl_parse_masters_pref_file(ttl
, pref_file
);
2561 ttl_parse_names_pref_file(ttl_t
* ttl
, const char* path
) {
2563 char line
[MAX_LINELEN
];
2572 fp
= ws_fopen(path
, "r");
2577 while (fgetline(line
, sizeof(line
), fp
) >= 0) {
2578 if ((cp
= strchr(line
, '#')))
2581 cp
= strtok(line
, " \t");
2582 if (cp
== NULL
|| !ws_strtou16(cp
, NULL
, &tmp
) || tmp
> 7) {
2583 continue; /* Invalid cascade */
2587 cp
= strtok(NULL
, " \t");
2588 if (cp
== NULL
|| !ws_strtou16(cp
, NULL
, &tmp
) || tmp
> 15) {
2589 continue; /* Invalid device */
2593 cp
= strtok(NULL
, " \t");
2594 if (cp
== NULL
|| !ws_strtou16(cp
, NULL
, &tmp
) || tmp
> 63) {
2595 continue; /* Invalid function */
2599 cp
= strtok(NULL
, " \t");
2600 if (cp
!= NULL
&& strlen(cp
) != 0) {
2601 name
= ws_strdup(cp
);
2602 g_hash_table_insert(ttl
->address_to_name_ht
, GUINT_TO_POINTER(addr
), name
);
2611 * This function gets the names of the interfaces from a configuration file.
2612 * The entry format is the following: Cascade Device Function Name
2613 * If an entry is not present, the value from the configuration XML in the file
2614 * is used. If also that is not present, a meaningful name is generated in
2615 * ttl_add_interface_name() starting from the interface address.
2618 ttl_init_names_from_pref_file(ttl_t
* ttl
) {
2622 pref_file
= get_persconffile_path(TTL_ADDRESS_NAME_PREFS
, true);
2623 ret
= ttl_parse_names_pref_file(ttl
, pref_file
);
2626 pref_file
= get_persconffile_path(TTL_ADDRESS_NAME_PREFS
, false);
2627 ret
= ttl_parse_names_pref_file(ttl
, pref_file
);
2635 ttl_cleanup(ttl_t
* ttl
) {
2637 if (ttl
->address_to_iface_ht
!= NULL
) {
2638 g_hash_table_destroy(ttl
->address_to_iface_ht
);
2640 if (ttl
->address_to_master_ht
!= NULL
) {
2641 g_hash_table_destroy(ttl
->address_to_master_ht
);
2643 if (ttl
->address_to_name_ht
!= NULL
) {
2644 g_hash_table_destroy(ttl
->address_to_name_ht
);
2646 if (ttl
->segmented_frames_ht
!= NULL
) {
2647 g_hash_table_destroy(ttl
->segmented_frames_ht
);
2649 if (ttl
->reassembled_frames_ht
!= NULL
) {
2650 g_hash_table_destroy(ttl
->reassembled_frames_ht
);
2656 wtap_open_return_val
2657 ttl_open(wtap
* wth
, int* err
, char** err_info
) {
2658 ttl_fileheader_t header
;
2660 unsigned int offset
;
2662 ws_debug("opening file");
2664 if (!wtap_read_bytes_or_eof(wth
->fh
, &header
, sizeof(ttl_fileheader_t
), err
, err_info
)) {
2666 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err
);
2667 if (*err
== 0 || *err
== WTAP_ERR_SHORT_READ
) {
2669 * Short read or EOF.
2671 * We're reading this as part of an open, so
2672 * the file is too short to be a ttl file.
2677 return WTAP_OPEN_NOT_MINE
;
2679 return WTAP_OPEN_ERROR
;
2682 fix_endianness_ttl_fileheader(&header
);
2684 if (memcmp(header
.magic
, ttl_magic
, sizeof(ttl_magic
))) {
2685 return WTAP_OPEN_NOT_MINE
;
2688 /* This seems to be a TLL! */
2689 /* Check for a valid header length */
2690 if (header
.header_size
< sizeof(ttl_fileheader_t
)) {
2691 *err
= WTAP_ERR_BAD_FILE
;
2692 *err_info
= ws_strdup("ttl: file header length too short");
2693 return WTAP_OPEN_ERROR
;
2696 offset
= (unsigned int)sizeof(ttl_fileheader_t
);
2698 /* Prepare our private context. */
2699 ttl
= g_new(ttl_t
, 1);
2700 ttl
->next_interface_id
= 0;
2701 ttl
->block_size
= header
.block_size
;
2702 ttl
->header_size
= header
.header_size
;
2703 ttl
->address_to_iface_ht
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
, g_free
);
2704 ttl
->address_to_master_ht
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
, NULL
);
2705 ttl
->address_to_name_ht
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
, g_free
);
2706 ttl
->segmented_frames_ht
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
, NULL
, ttl_free_segmented_entry
);
2707 ttl
->reassembled_frames_ht
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, g_free
, ttl_free_reassembled_entry
);
2709 if (header
.version
>= 10) {
2710 if (header
.header_size
< (offset
+ TTL_LOGFILE_INFO_SIZE
)) {
2711 report_warning("Found TTL file version %u with shorter header length than expected.", header
.version
);
2714 /* TODO: Extract needed info from the rest of the header. */
2715 if (!wtap_read_bytes(wth
->fh
, NULL
, TTL_LOGFILE_INFO_SIZE
, err
, err_info
)) {
2717 return WTAP_OPEN_ERROR
;
2719 offset
+= TTL_LOGFILE_INFO_SIZE
;
2721 unsigned int xml_len
= header
.header_size
- offset
;
2723 unsigned char* xml
= g_try_malloc(xml_len
);
2725 *err
= WTAP_ERR_INTERNAL
;
2726 *err_info
= ws_strdup("ttl: cannot allocate memory");
2730 if (!wtap_read_bytes(wth
->fh
, xml
, xml_len
, err
, err_info
)) {
2733 return WTAP_OPEN_ERROR
;
2735 if (!ttl_process_xml_config(ttl
, xml
, xml_len
)) {
2736 report_warning("Cannot extract information from TTL XML.");
2741 #endif /* HAVE_LIBXML2 */
2745 if ((header
.header_size
- offset
) != 0) {
2746 if (!wtap_read_bytes(wth
->fh
, NULL
, header
.header_size
- offset
, err
, err_info
)) {
2748 return WTAP_OPEN_ERROR
;
2752 ttl_init_masters_from_pref_file(ttl
);
2753 ttl_init_names_from_pref_file(ttl
);
2755 wth
->priv
= (void*)ttl
;
2756 wth
->file_encap
= WTAP_ENCAP_NONE
;
2757 wth
->snapshot_length
= 0;
2758 wth
->file_tsprec
= WTAP_TSPREC_UNKNOWN
;
2759 wth
->subtype_read
= ttl_read
;
2760 wth
->subtype_seek_read
= ttl_seek_read
;
2761 wth
->subtype_close
= ttl_close
;
2762 wth
->file_type_subtype
= ttl_file_type_subtype
;
2764 return WTAP_OPEN_MINE
;
2767 static inline int64_t
2768 ttl_next_block(const ttl_t
* ttl
, int64_t pos
) {
2769 if (ttl
== NULL
|| pos
< 0 || pos
< ttl
->header_size
) {
2773 return pos
+ ttl
->block_size
- ((pos
- ttl
->header_size
) % ttl
->block_size
);
2776 static bool ttl_read(wtap
* wth
, wtap_rec
* rec
, int* err
, char** err_info
, int64_t* data_offset
) {
2782 input
.validity
= VALIDITY_FH
;
2785 pos
= file_tell(wth
->fh
);
2786 end
= ttl_next_block((ttl_t
*)wth
->priv
, pos
);
2788 res
= ttl_read_entry(wth
, rec
, err
, err_info
, &input
, pos
, end
);
2789 if (G_UNLIKELY(res
== TTL_CORRUPTED
)) {
2790 ws_warning("ttl_read(): Unaligned block found, skipping to next block offset: 0x%" PRIx64
, end
);
2791 report_warning("Found unaligned TTL block. Skipping to the next one.");
2792 if (file_seek(wth
->fh
, end
, SEEK_SET
, err
) < 0) {
2793 return false; /* Seek error */
2797 * XXX - For now we simply skip over any entry we don't understand,
2798 * but in the future we might want an easy way to report warnings
2799 * without spamming the user with dialog boxes.
2801 } while (res
> TTL_NO_ERROR
);
2803 if (G_LIKELY(res
== TTL_NO_ERROR
)) {
2811 static bool ttl_seek_read(wtap
* wth
, int64_t seek_off
, wtap_rec
* rec
, int* err
, char** err_info
) {
2815 input
.fh
= wth
->random_fh
;
2816 input
.validity
= VALIDITY_FH
;
2818 /* seek to the right file position */
2819 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) < 0) {
2820 return false; /* Seek error */
2823 res
= ttl_read_entry(wth
, rec
, err
, err_info
, &input
, seek_off
, ttl_next_block((ttl_t
*)wth
->priv
, seek_off
));
2824 if (G_LIKELY(res
== TTL_NO_ERROR
)) {
2828 if (res
> TTL_NO_ERROR
) {
2830 * If we're here, there has been an error during the first pass and we
2831 * returned true on an unsupported or unaligned entry.
2833 *err
= WTAP_ERR_INTERNAL
;
2834 *err_info
= ws_strdup_printf("ttl_seek_read called with invalid offset: 0x%" PRIx64
, seek_off
);
2840 static void ttl_close(wtap
* wth
) {
2842 ttl_cleanup((ttl_t
*)wth
->priv
);
2847 /* Options for interface blocks. */
2848 static const struct supported_option_type interface_block_options_supported
[] = {
2849 /* No comments, just an interface name. */
2850 { OPT_IDB_NAME
, ONE_OPTION_SUPPORTED
}
2853 static const struct supported_block_type ttl_blocks_supported
[] = {
2854 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
},
2855 { WTAP_BLOCK_IF_ID_AND_INFO
, MULTIPLE_BLOCKS_SUPPORTED
, OPTION_TYPES_SUPPORTED(interface_block_options_supported
) },
2858 static const struct file_type_subtype_info ttl_info
= {
2859 "TTTech Computertechnik TTX Logger (TTL) logfile", "ttl", "ttl", NULL
,
2860 false, BLOCKS_SUPPORTED(ttl_blocks_supported
),
2864 void register_ttl(void)
2866 ttl_file_type_subtype
= wtap_register_file_type_subtype(&ttl_info
);
2869 * Register name for backwards compatibility with the
2870 * wtap_filetypes table in Lua.
2872 wtap_register_backwards_compatibility_lua_name("TTL", ttl_file_type_subtype
);
2877 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2882 * indent-tabs-mode: nil
2885 * vi: set shiftwidth=4 tabstop=8 expandtab:
2886 * :indentSize=4:tabSize=8:noTabs=true: