TODO netlogon_user_flags_ntlmv2_enabled
[wireshark-sm.git] / wiretap / ttl.c
blob00d8d7d6d51404982c50b80737bffcca9ad39cfc
1 /* ttl.c
3 * Wiretap Library
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
16 #include <config.h>
17 #define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP
19 #include "ttl.h"
21 #include <string.h>
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>
27 #ifdef HAVE_LIBXML2
28 #include <libxml/tree.h>
29 #include <libxml/parser.h>
30 #include <libxml/xpath.h>
31 #endif
32 #include "file_wrappers.h"
33 #include "wtap-int.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 {
48 uint32_t block_size;
49 uint32_t header_size;
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;
57 } ttl_t;
59 typedef enum ttl_read_validity {
60 VALIDITY_FH = 1,
61 VALIDITY_BUF = 2
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 {
69 union {
70 FILE_T fh;
71 struct {
72 uint8_t* buf;
73 uint32_t size;
74 uint32_t cur_pos;
77 ttl_read_validity_t validity;
78 } ttl_read_t;
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.
85 typedef enum {
86 TTL_ERROR = -1,
87 TTL_NO_ERROR = 0,
88 TTL_UNSUPPORTED = 1,
89 TTL_CORRUPTED = 2
90 } ttl_result_t;
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
96 * interface.
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 {
102 int pkt_encap;
103 bool channelB;
105 uint32_t interface_id;
106 } ttl_addr_to_iface_entry_t;
108 typedef struct ttl_segmented_entry {
109 uint64_t timestamp;
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;
115 unsigned char* buf;
116 } ttl_segmented_entry_t;
118 typedef struct ttl_reassembled_entry {
119 uint64_t timestamp;
120 uint32_t size;
121 unsigned char* buf;
122 } ttl_reassembled_entry_t;
124 void
125 ttl_free_segmented_entry(void* data) {
126 ttl_segmented_entry_t* item;
127 if (data != NULL) {
128 item = (ttl_segmented_entry_t*)data;
129 if (item->buf != NULL) {
130 g_free(item->buf);
132 g_free(data);
136 void
137 ttl_free_reassembled_entry(void* data) {
138 ttl_reassembled_entry_t* item;
139 if (data != NULL) {
140 item = (ttl_reassembled_entry_t*)data;
141 if (item->buf != NULL) {
142 g_free(item->buf);
144 g_free(data);
148 #ifndef OPT_EPB_FLAGS
149 #define OPT_EPB_FLAGS 0x0002 /* Copied from pcapng.c */
150 #endif
152 #ifndef FLEXRAY_FRAME
153 #define FLEXRAY_FRAME 0x01 /* Copied from packet-flexray.c */
154 #endif
156 #ifndef FLEXRAY_SYMBOL
157 #define FLEXRAY_SYMBOL 0x02 /* Copied from packet-flexray.c */
158 #endif
160 static void
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);
167 static void
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.
189 * - For Ethernet:
190 * - Return the same address if cascade is 0 (i.e. the channel belongs to
191 * the logger).
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);
197 if (ht != NULL) {
198 void* master;
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:
208 switch (function) {
209 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH2:
210 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH2:
211 return (addr - 45);
212 case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH3:
213 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH3:
214 return (addr - 47);
215 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B:
216 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B:
217 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B:
218 return (addr - 1);
219 default:
220 break;
222 break;
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) {
227 return (addr - 1);
229 break;
230 case TTL_LOGGER_DEVICE_FPGAA:
231 if (function == TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B) {
232 return (addr - 1);
234 break;
235 case TTL_LOGGER_DEVICE_FPGAB:
236 switch (function) {
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:
251 return (addr - 14);
252 default:
253 break;
255 break;
256 default:
257 break;
260 else { /* The address refers to a TAP */
261 switch (ttl_addr_get_device(addr)) {
262 case TTL_TAP_DEVICE_PT15_FPGA:
263 switch (function) {
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:
270 return (addr - 1);
271 default:
272 break;
274 break;
275 case TTL_TAP_DEVICE_PT20_FPGA:
276 switch (function) {
277 case TTL_PT20_FPGA_FUNCTION_GbEth1b:
278 case TTL_PT20_FPGA_FUNCTION_GbEth2b:
279 case TTL_PT20_FPGA_FUNCTION_GbEth3b:
280 return (addr - 1);
281 default:
282 break;
284 break;
285 case TTL_TAP_DEVICE_PC3_FPGA:
286 if (function == TTL_PC3_FPGA_FUNCTION_BrdR1b) {
287 return (addr - 1);
289 break;
290 case TTL_TAP_DEVICE_PC3_AURIX:
291 switch (function) {
292 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B:
293 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B:
294 return (addr - 1);
295 default:
296 break;
298 break;
299 default:
300 break;
304 return addr;
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:
314 switch (function) {
315 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B:
316 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B:
317 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B:
318 return true;
319 default:
320 break;
322 break;
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) {
327 return true;
329 break;
330 case TTL_LOGGER_DEVICE_FPGAA:
331 if (function == TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B) {
332 return true;
334 break;
335 default:
336 break;
339 else { /* The address refers to a TAP */
340 switch (ttl_addr_get_device(addr)) {
341 case TTL_TAP_DEVICE_PC3_AURIX:
342 switch (function) {
343 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B:
344 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B:
345 return true;
346 default:
347 break;
349 break;
350 default:
351 break;
355 return false;
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:
365 switch (function) {
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;
422 default:
423 break;
426 break;
427 case TTL_LOGGER_DEVICE_ATOM:
428 switch (function) {
429 case TTL_LOGGER_ATOM_FUNCTION_ETHA:
430 case TTL_LOGGER_ATOM_FUNCTION_ETHB:
431 return WTAP_ENCAP_ETHERNET;
432 default:
433 break;
436 break;
437 case TTL_LOGGER_DEVICE_TRICORE1:
438 switch (function) {
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;
449 default:
450 break;
453 break;
454 case TTL_LOGGER_DEVICE_TRICORE2:
455 switch (function) {
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;
466 default:
467 break;
470 break;
471 case TTL_LOGGER_DEVICE_TRICORE3:
472 switch (function) {
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;
483 default:
484 break;
487 break;
488 case TTL_LOGGER_DEVICE_TDA4x:
489 switch (function) {
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;
502 default:
503 break;
506 break;
507 case TTL_LOGGER_DEVICE_FPGAA:
508 switch (function) {
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;
541 default:
542 break;
545 break;
546 case TTL_LOGGER_DEVICE_FPGAB:
547 switch (function) {
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;
577 default:
578 break;
581 break;
582 default:
583 break;
586 else { /* The address refers to a TAP */
587 switch (ttl_addr_get_device(addr)) {
588 case TTL_TAP_DEVICE_PT15_FPGA:
589 switch (function) {
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 */
607 default:
608 break;
611 break;
612 case TTL_TAP_DEVICE_PT20_FPGA:
613 switch (function) {
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 */
628 default:
629 break;
632 break;
633 case TTL_TAP_DEVICE_PC3_FPGA:
634 switch (function) {
635 case TTL_PC3_FPGA_FUNCTION_BrdR1a:
636 case TTL_PC3_FPGA_FUNCTION_BrdR1b:
637 return WTAP_ENCAP_ETHERNET;
638 default:
639 break;
642 break;
643 case TTL_TAP_DEVICE_PC3_AURIX:
644 switch (function) {
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;
655 default:
656 break;
659 break;
660 case TTL_TAP_DEVICE_ZELDA_CANFD:
661 switch (function) {
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;
678 default:
679 break;
682 break;
683 case TTL_TAP_DEVICE_ZELDA_LIN:
684 switch (function) {
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;
710 default:
711 break;
714 break;
715 default:
716 break;
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:
735 return "FPGA";
736 case TTL_LOGGER_DEVICE_ATOM:
737 return "Atom";
738 case TTL_LOGGER_DEVICE_TRICORE1:
739 case TTL_LOGGER_DEVICE_TRICORE2:
740 case TTL_LOGGER_DEVICE_TRICORE3:
741 return "Tricore";
742 case TTL_LOGGER_DEVICE_TDA4x:
743 return "TDA4x";
744 default:
745 break;
748 else {
749 switch (ttl_addr_get_device(addr)) {
750 case TTL_TAP_DEVICE_PT15_FPGA:
751 case TTL_TAP_DEVICE_PT15_HPS_LINUX:
752 return "PT15";
753 case TTL_TAP_DEVICE_PT20_FPGA:
754 case TTL_TAP_DEVICE_PT20_HPS_LINUX:
755 return "PT20";
756 case TTL_TAP_DEVICE_PC3_FPGA:
757 case TTL_TAP_DEVICE_PC3_HPS_LINUX:
758 case TTL_TAP_DEVICE_PC3_AURIX:
759 return "PC3";
760 case TTL_TAP_DEVICE_ZELDA_CANFD:
761 case TTL_TAP_DEVICE_ZELDA_LIN:
762 return "Zelda";
763 default:
764 break;
768 return "Unknown";
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:
777 switch (function) {
778 case TTL_LOGGER_FPGA_FUNCTION_CORE:
779 return "Core";
780 case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST25:
781 return "Ext0_MOST25";
782 case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST150:
783 return "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:
787 return "EthernetA";
788 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH1:
789 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH2:
790 case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH3:
791 return "EthernetB";
792 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1A:
793 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B:
794 return "FlexRay1";
795 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2A:
796 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B:
797 return "FlexRay2";
798 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3A:
799 case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B:
800 return "FlexRay3";
801 case TTL_LOGGER_FPGA_FUNCTION_CAN1:
802 return "CAN1";
803 case TTL_LOGGER_FPGA_FUNCTION_CAN2:
804 return "CAN2";
805 case TTL_LOGGER_FPGA_FUNCTION_CAN3:
806 return "CAN3";
807 case TTL_LOGGER_FPGA_FUNCTION_CAN4:
808 return "CAN4";
809 case TTL_LOGGER_FPGA_FUNCTION_CAN5:
810 return "CAN5";
811 case TTL_LOGGER_FPGA_FUNCTION_CAN6:
812 return "CAN6";
813 case TTL_LOGGER_FPGA_FUNCTION_CAN7:
814 return "CAN7";
815 case TTL_LOGGER_FPGA_FUNCTION_CAN8:
816 return "CAN8";
817 case TTL_LOGGER_FPGA_FUNCTION_CAN9:
818 return "CAN9";
819 case TTL_LOGGER_FPGA_FUNCTION_CAN10:
820 return "CAN10";
821 case TTL_LOGGER_FPGA_FUNCTION_CAN11:
822 return "CAN11";
823 case TTL_LOGGER_FPGA_FUNCTION_CAN12:
824 return "CAN12";
825 case TTL_LOGGER_FPGA_FUNCTION_CAN13:
826 return "CAN13";
827 case TTL_LOGGER_FPGA_FUNCTION_CAN14:
828 return "CAN14";
829 case TTL_LOGGER_FPGA_FUNCTION_CAN15:
830 return "CAN15";
831 case TTL_LOGGER_FPGA_FUNCTION_CAN16:
832 return "CAN16";
833 case TTL_LOGGER_FPGA_FUNCTION_CAN17:
834 return "CAN17";
835 case TTL_LOGGER_FPGA_FUNCTION_CAN18:
836 return "CAN18";
837 case TTL_LOGGER_FPGA_FUNCTION_CAN19:
838 return "CAN19";
839 case TTL_LOGGER_FPGA_FUNCTION_CAN20:
840 return "CAN20";
841 case TTL_LOGGER_FPGA_FUNCTION_CAN21:
842 return "CAN21";
843 case TTL_LOGGER_FPGA_FUNCTION_CAN22:
844 return "CAN22";
845 case TTL_LOGGER_FPGA_FUNCTION_CAN23:
846 return "CAN23";
847 case TTL_LOGGER_FPGA_FUNCTION_CAN24:
848 return "CAN24";
849 case TTL_LOGGER_FPGA_FUNCTION_EXT1_MOST25:
850 return "MOST25";
851 case TTL_LOGGER_FPGA_FUNCTION_LIN1:
852 return "LIN1";
853 case TTL_LOGGER_FPGA_FUNCTION_LIN2:
854 return "LIN2";
855 case TTL_LOGGER_FPGA_FUNCTION_LIN3:
856 return "LIN3";
857 case TTL_LOGGER_FPGA_FUNCTION_LIN4:
858 return "LIN4";
859 case TTL_LOGGER_FPGA_FUNCTION_LIN5:
860 return "LIN5";
861 case TTL_LOGGER_FPGA_FUNCTION_LIN6:
862 return "LIN6";
863 case TTL_LOGGER_FPGA_FUNCTION_LIN7:
864 return "LIN7";
865 case TTL_LOGGER_FPGA_FUNCTION_LIN8:
866 return "LIN8";
867 case TTL_LOGGER_FPGA_FUNCTION_LIN9:
868 return "LIN9";
869 case TTL_LOGGER_FPGA_FUNCTION_LIN10:
870 return "LIN10";
871 case TTL_LOGGER_FPGA_FUNCTION_LIN11:
872 return "LIN11";
873 case TTL_LOGGER_FPGA_FUNCTION_LIN12:
874 return "LIN12";
875 default:
876 break;
878 break;
879 case TTL_LOGGER_DEVICE_ATOM:
880 switch (function) {
881 case TTL_LOGGER_ATOM_FUNCTION_ETHA:
882 return "EthernetA";
883 case TTL_LOGGER_ATOM_FUNCTION_ETHB:
884 return "EthernetB";
885 default:
886 break;
888 break;
889 case TTL_LOGGER_DEVICE_TRICORE1:
890 switch (function) {
891 case TTL_LOGGER_TRICORE1_FUNCTION_CORE:
892 return "Core1";
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:
897 return "FlexRay1";
898 case TTL_LOGGER_TRICORE1_FUNCTION_CAN1:
899 return "CAN1";
900 case TTL_LOGGER_TRICORE1_FUNCTION_CAN2:
901 return "CAN2";
902 case TTL_LOGGER_TRICORE1_FUNCTION_CAN3:
903 return "CAN3";
904 case TTL_LOGGER_TRICORE1_FUNCTION_CAN4:
905 return "CAN4";
906 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGOUT1:
907 return "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:
913 return "Serial1";
914 case TTL_LOGGER_TRICORE1_FUNCTION_SERIAL2:
915 return "Serial2";
916 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN6:
917 return "AnalogIn6";
918 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN8:
919 return "AnalogIn8";
920 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN11:
921 return "AnalogIn11";
922 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN14:
923 return "AnalogIn14";
924 case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN15:
925 return "AnalogIn15";
926 case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN8:
927 return "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:
937 return "KL15";
938 case TTL_LOGGER_TRICORE1_FUNCTION_KL30IN:
939 return "KL30";
940 default:
941 break;
943 break;
944 case TTL_LOGGER_DEVICE_TRICORE2:
945 switch (function) {
946 case TTL_LOGGER_TRICORE2_FUNCTION_CORE:
947 return "Core2";
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:
952 return "FlexRay2";
953 case TTL_LOGGER_TRICORE2_FUNCTION_CAN6:
954 return "CAN6";
955 case TTL_LOGGER_TRICORE2_FUNCTION_CAN7:
956 return "CAN7";
957 case TTL_LOGGER_TRICORE2_FUNCTION_CAN10:
958 return "CAN10";
959 case TTL_LOGGER_TRICORE2_FUNCTION_CAN12:
960 return "CAN12";
961 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGOUT2:
962 return "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:
968 return "Serial3";
969 case TTL_LOGGER_TRICORE2_FUNCTION_SERIAL4:
970 return "Serial4";
971 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN3:
972 return "AnalogIn3";
973 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN4:
974 return "AnalogIn4";
975 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN5:
976 return "AnalogIn5";
977 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN7:
978 return "AnalogIn7";
979 case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN9:
980 return "AnalogIn9";
981 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN6:
982 return "DigitalIn6";
983 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN7:
984 return "DigitalIn7";
985 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN9:
986 return "DigitalIn9";
987 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN14:
988 return "DigitalIn14";
989 case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN15:
990 return "DigitalIn15";
991 default:
992 break;
994 break;
995 case TTL_LOGGER_DEVICE_TRICORE3:
996 switch (function) {
997 case TTL_LOGGER_TRICORE3_FUNCTION_CORE:
998 return "Core3";
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:
1003 return "FlexRay3";
1004 case TTL_LOGGER_TRICORE3_FUNCTION_CAN5:
1005 return "CAN5";
1006 case TTL_LOGGER_TRICORE3_FUNCTION_CAN8:
1007 return "CAN8";
1008 case TTL_LOGGER_TRICORE3_FUNCTION_CAN9:
1009 return "CAN9";
1010 case TTL_LOGGER_TRICORE3_FUNCTION_CAN11:
1011 return "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:
1019 return "Serial5";
1020 case TTL_LOGGER_TRICORE3_FUNCTION_SERIAL6:
1021 return "Serial6";
1022 case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN1:
1023 return "AnalogIn1";
1024 case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN2:
1025 return "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";
1042 default:
1043 break;
1045 break;
1046 case TTL_LOGGER_DEVICE_TDA4x:
1047 switch (function) {
1048 case TTL_LOGGER_TDA4x_FUNCTION_CORE:
1049 return "Core";
1050 case TTL_LOGGER_TDA4x_FUNCTION_CAN1:
1051 return "CAN1";
1052 case TTL_LOGGER_TDA4x_FUNCTION_CAN2:
1053 return "CAN2";
1054 case TTL_LOGGER_TDA4x_FUNCTION_CAN3:
1055 return "CAN3";
1056 case TTL_LOGGER_TDA4x_FUNCTION_CAN4:
1057 return "CAN4";
1058 case TTL_LOGGER_TDA4x_FUNCTION_CAN5:
1059 return "CAN5";
1060 case TTL_LOGGER_TDA4x_FUNCTION_CAN6:
1061 return "CAN6";
1062 case TTL_LOGGER_TDA4x_FUNCTION_CAN7:
1063 return "CAN7";
1064 case TTL_LOGGER_TDA4x_FUNCTION_CAN8:
1065 return "CAN8";
1066 case TTL_LOGGER_TDA4x_FUNCTION_CAN9:
1067 return "CAN9";
1068 case TTL_LOGGER_TDA4x_FUNCTION_CAN10:
1069 return "CAN10";
1070 case TTL_LOGGER_TDA4x_FUNCTION_CAN11:
1071 return "CAN11";
1072 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL1:
1073 return "Serial1";
1074 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL2:
1075 return "Serial2";
1076 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL3:
1077 return "Serial3";
1078 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL4:
1079 return "Serial4";
1080 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL5:
1081 return "Serial5";
1082 case TTL_LOGGER_TDA4x_FUNCTION_SERIAL6:
1083 return "Serial6";
1084 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN1:
1085 return "AnalogIn1";
1086 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN2:
1087 return "AnalogIn2";
1088 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN3:
1089 return "AnalogIn3";
1090 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN4:
1091 return "AnalogIn4";
1092 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN5:
1093 return "AnalogIn5";
1094 case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN6:
1095 return "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:
1101 return "KL15";
1102 case TTL_LOGGER_TDA4x_FUNCTION_KL30IN:
1103 return "KL30";
1104 default:
1105 break;
1107 break;
1108 case TTL_LOGGER_DEVICE_FPGAA:
1109 switch (function) {
1110 case TTL_LOGGER_FPGAA_FUNCTION_CORE:
1111 return "Core";
1112 case TTL_LOGGER_FPGAA_FUNCTION_CAN1:
1113 return "CAN1";
1114 case TTL_LOGGER_FPGAA_FUNCTION_CAN2:
1115 return "CAN2";
1116 case TTL_LOGGER_FPGAA_FUNCTION_CAN3:
1117 return "CAN3";
1118 case TTL_LOGGER_FPGAA_FUNCTION_CAN4:
1119 return "CAN4";
1120 case TTL_LOGGER_FPGAA_FUNCTION_CAN5:
1121 return "CAN5";
1122 case TTL_LOGGER_FPGAA_FUNCTION_CAN6:
1123 return "CAN6";
1124 case TTL_LOGGER_FPGAA_FUNCTION_CAN7:
1125 return "CAN7";
1126 case TTL_LOGGER_FPGAA_FUNCTION_CAN8:
1127 return "CAN8";
1128 case TTL_LOGGER_FPGAA_FUNCTION_CAN9:
1129 return "CAN9";
1130 case TTL_LOGGER_FPGAA_FUNCTION_CAN10:
1131 return "CAN10";
1132 case TTL_LOGGER_FPGAA_FUNCTION_CAN11:
1133 return "CAN11";
1134 case TTL_LOGGER_FPGAA_FUNCTION_LIN1:
1135 return "LIN1";
1136 case TTL_LOGGER_FPGAA_FUNCTION_LIN2:
1137 return "LIN2";
1138 case TTL_LOGGER_FPGAA_FUNCTION_LIN3:
1139 return "LIN3";
1140 case TTL_LOGGER_FPGAA_FUNCTION_LIN4:
1141 return "LIN4";
1142 case TTL_LOGGER_FPGAA_FUNCTION_LIN5:
1143 return "LIN5";
1144 case TTL_LOGGER_FPGAA_FUNCTION_LIN6:
1145 return "LIN6";
1146 case TTL_LOGGER_FPGAA_FUNCTION_LIN7:
1147 return "LIN7";
1148 case TTL_LOGGER_FPGAA_FUNCTION_LIN8:
1149 return "LIN8";
1150 case TTL_LOGGER_FPGAA_FUNCTION_LIN9:
1151 return "LIN9";
1152 case TTL_LOGGER_FPGAA_FUNCTION_LIN10:
1153 return "LIN10";
1154 case TTL_LOGGER_FPGAA_FUNCTION_LIN11:
1155 return "LIN11";
1156 case TTL_LOGGER_FPGAA_FUNCTION_LIN12:
1157 return "LIN12";
1158 case TTL_LOGGER_FPGAA_FUNCTION_LIN13:
1159 return "LIN13";
1160 case TTL_LOGGER_FPGAA_FUNCTION_LIN14:
1161 return "LIN14";
1162 case TTL_LOGGER_FPGAA_FUNCTION_LIN15:
1163 return "LIN15";
1164 case TTL_LOGGER_FPGAA_FUNCTION_LIN16:
1165 return "LIN16";
1166 case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1A:
1167 case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B:
1168 return "FlexRay1";
1169 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL1:
1170 return "Serial1";
1171 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL2:
1172 return "Serial2";
1173 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL3:
1174 return "Serial3";
1175 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL4:
1176 return "Serial4";
1177 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL5:
1178 return "Serial5";
1179 case TTL_LOGGER_FPGAA_FUNCTION_SERIAL6:
1180 return "Serial6";
1181 default:
1182 break;
1184 break;
1185 case TTL_LOGGER_DEVICE_FPGAB:
1186 switch (function) {
1187 case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH1:
1188 case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH2:
1189 return "EthernetA";
1190 case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH1:
1191 case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH2:
1192 return "EthernetB";
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";
1229 default:
1230 break;
1232 break;
1233 default:
1234 break;
1237 else {
1238 switch (ttl_addr_get_device(addr)) {
1239 case TTL_TAP_DEVICE_PT15_FPGA:
1240 switch (function) {
1241 case TTL_PT15_FPGA_FUNCTION_CORE:
1242 return "Core";
1243 case TTL_PT15_FPGA_FUNCTION_CAN1:
1244 return "CAN1";
1245 case TTL_PT15_FPGA_FUNCTION_CAN2:
1246 return "CAN2";
1247 case TTL_PT15_FPGA_FUNCTION_BrdR1a:
1248 return "BR1a";
1249 case TTL_PT15_FPGA_FUNCTION_BrdR1b:
1250 return "BR1b";
1251 case TTL_PT15_FPGA_FUNCTION_BrdR2a:
1252 return "BR2a";
1253 case TTL_PT15_FPGA_FUNCTION_BrdR2b:
1254 return "BR2b";
1255 case TTL_PT15_FPGA_FUNCTION_BrdR3a:
1256 return "BR3a";
1257 case TTL_PT15_FPGA_FUNCTION_BrdR3b:
1258 return "BR3b";
1259 case TTL_PT15_FPGA_FUNCTION_BrdR4a:
1260 return "BR4a";
1261 case TTL_PT15_FPGA_FUNCTION_BrdR4b:
1262 return "BR4b";
1263 case TTL_PT15_FPGA_FUNCTION_BrdR5a:
1264 return "BR5a";
1265 case TTL_PT15_FPGA_FUNCTION_BrdR5b:
1266 return "BR5b";
1267 case TTL_PT15_FPGA_FUNCTION_BrdR6a:
1268 return "BR6a";
1269 case TTL_PT15_FPGA_FUNCTION_BrdR6b:
1270 return "BR6b";
1271 case TTL_PT15_FPGA_FUNCTION_MDIO:
1272 return "MDIO";
1273 default:
1274 break;
1276 break;
1277 case TTL_TAP_DEVICE_PT20_FPGA:
1278 switch (function) {
1279 case TTL_PT20_FPGA_FUNCTION_CORE:
1280 return "Core";
1281 case TTL_PT20_FPGA_FUNCTION_CAN1:
1282 return "CAN1";
1283 case TTL_PT20_FPGA_FUNCTION_CAN2:
1284 return "CAN2";
1285 case TTL_PT20_FPGA_FUNCTION_CAN3:
1286 return "CAN3";
1287 case TTL_PT20_FPGA_FUNCTION_CAN4:
1288 return "CAN4";
1289 case TTL_PT20_FPGA_FUNCTION_CAN5:
1290 return "CAN5";
1291 case TTL_PT20_FPGA_FUNCTION_GbEth1a:
1292 return "GbEth1a";
1293 case TTL_PT20_FPGA_FUNCTION_GbEth1b:
1294 return "GbEth1b";
1295 case TTL_PT20_FPGA_FUNCTION_GbEth2a:
1296 return "GbEth2a";
1297 case TTL_PT20_FPGA_FUNCTION_GbEth2b:
1298 return "GbEth2b";
1299 case TTL_PT20_FPGA_FUNCTION_GbEth3a:
1300 return "GbEth3a";
1301 case TTL_PT20_FPGA_FUNCTION_GbEth3b:
1302 return "GbEth3b";
1303 case TTL_PT20_FPGA_FUNCTION_MDIO:
1304 return "MDIO";
1305 default:
1306 break;
1308 break;
1309 case TTL_TAP_DEVICE_PC3_FPGA:
1310 switch (function) {
1311 case TTL_PC3_FPGA_FUNCTION_CORE:
1312 return "FPGA_Core";
1313 case TTL_PC3_FPGA_FUNCTION_BrdR1a:
1314 return "BR1a";
1315 case TTL_PC3_FPGA_FUNCTION_BrdR1b:
1316 return "BR1b";
1317 default:
1318 break;
1320 break;
1321 case TTL_TAP_DEVICE_PC3_AURIX:
1322 switch (function) {
1323 case TTL_PC3_AURIX_FUNCTION_CORE:
1324 return "Aurix_Core";
1325 case TTL_PC3_AURIX_FUNCTION_CAN1:
1326 return "CAN1";
1327 case TTL_PC3_AURIX_FUNCTION_CAN2:
1328 return "CAN2";
1329 case TTL_PC3_AURIX_FUNCTION_CAN3:
1330 return "CAN3";
1331 case TTL_PC3_AURIX_FUNCTION_CAN4:
1332 return "CAN4";
1333 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1A:
1334 case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B:
1335 return "FlexRay1";
1336 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2A:
1337 case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B:
1338 return "FlexRay2";
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";
1347 default:
1348 break;
1350 break;
1351 case TTL_TAP_DEVICE_ZELDA_CANFD:
1352 switch (function) {
1353 case TTL_TAP_DEVICE_ZELDA_CORE:
1354 return "CANFD_Core";
1355 case TTL_TAP_DEVICE_ZELDA_CANFD1:
1356 return "CANFD1";
1357 case TTL_TAP_DEVICE_ZELDA_CANFD2:
1358 return "CANFD2";
1359 case TTL_TAP_DEVICE_ZELDA_CANFD3:
1360 return "CANFD3";
1361 case TTL_TAP_DEVICE_ZELDA_CANFD4:
1362 return "CANFD4";
1363 case TTL_TAP_DEVICE_ZELDA_CANFD5:
1364 return "CANFD5";
1365 case TTL_TAP_DEVICE_ZELDA_CANFD6:
1366 return "CANFD6";
1367 case TTL_TAP_DEVICE_ZELDA_CANFD7:
1368 return "CANFD7";
1369 case TTL_TAP_DEVICE_ZELDA_CANFD8:
1370 return "CANFD8";
1371 case TTL_TAP_DEVICE_ZELDA_CANFD9:
1372 return "CANFD9";
1373 case TTL_TAP_DEVICE_ZELDA_CANFD10:
1374 return "CANFD10";
1375 case TTL_TAP_DEVICE_ZELDA_CANFD11:
1376 return "CANFD11";
1377 case TTL_TAP_DEVICE_ZELDA_CANFD12:
1378 return "CANFD12";
1379 case TTL_TAP_DEVICE_ZELDA_CANFD13:
1380 return "CANFD13";
1381 case TTL_TAP_DEVICE_ZELDA_CANFD14:
1382 return "CANFD14";
1383 case TTL_TAP_DEVICE_ZELDA_CANFD15:
1384 return "CANFD15";
1385 default:
1386 break;
1388 break;
1389 case TTL_TAP_DEVICE_ZELDA_LIN:
1390 switch (function) {
1391 case TTL_TAP_DEVICE_ZELDA_CORE:
1392 return "LIN_Core";
1393 case TTL_TAP_DEVICE_ZELDA_LIN1:
1394 return "LIN1";
1395 case TTL_TAP_DEVICE_ZELDA_LIN2:
1396 return "LIN2";
1397 case TTL_TAP_DEVICE_ZELDA_LIN3:
1398 return "LIN3";
1399 case TTL_TAP_DEVICE_ZELDA_LIN4:
1400 return "LIN4";
1401 case TTL_TAP_DEVICE_ZELDA_LIN5:
1402 return "LIN5";
1403 case TTL_TAP_DEVICE_ZELDA_LIN6:
1404 return "LIN6";
1405 case TTL_TAP_DEVICE_ZELDA_LIN7:
1406 return "LIN7";
1407 case TTL_TAP_DEVICE_ZELDA_LIN8:
1408 return "LIN8";
1409 case TTL_TAP_DEVICE_ZELDA_LIN9:
1410 return "LIN9";
1411 case TTL_TAP_DEVICE_ZELDA_LIN10:
1412 return "LIN10";
1413 case TTL_TAP_DEVICE_ZELDA_LIN11:
1414 return "LIN11";
1415 case TTL_TAP_DEVICE_ZELDA_LIN12:
1416 return "LIN12";
1417 case TTL_TAP_DEVICE_ZELDA_LIN13:
1418 return "LIN13";
1419 case TTL_TAP_DEVICE_ZELDA_LIN14:
1420 return "LIN14";
1421 case TTL_TAP_DEVICE_ZELDA_LIN15:
1422 return "LIN15";
1423 case TTL_TAP_DEVICE_ZELDA_LIN16:
1424 return "LIN16";
1425 case TTL_TAP_DEVICE_ZELDA_LIN17:
1426 return "LIN17";
1427 case TTL_TAP_DEVICE_ZELDA_LIN18:
1428 return "LIN18";
1429 case TTL_TAP_DEVICE_ZELDA_LIN19:
1430 return "LIN19";
1431 case TTL_TAP_DEVICE_ZELDA_LIN20:
1432 return "LIN20";
1433 case TTL_TAP_DEVICE_ZELDA_LIN21:
1434 return "LIN21";
1435 case TTL_TAP_DEVICE_ZELDA_LIN22:
1436 return "LIN22";
1437 case TTL_TAP_DEVICE_ZELDA_LIN23:
1438 return "LIN23";
1439 case TTL_TAP_DEVICE_ZELDA_LIN24:
1440 return "LIN24";
1441 default:
1442 break;
1444 break;
1445 default:
1446 break;
1450 return "Unknown";
1453 static wtap_opttype_return_val
1454 ttl_add_interface_name(wtap_block_t int_data, uint16_t addr, const char* name) {
1455 if (name != NULL) {
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.
1469 static bool
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;
1474 if (wth == NULL) {
1475 return false;
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;
1499 return true;
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;
1508 ttl_t* ttl;
1509 uint32_t iface_id;
1510 uint16_t master_addr;
1511 int pkt_encap;
1513 if (wth == NULL) {
1514 return NULL;
1517 ttl = (ttl_t*)wth->priv;
1518 if (ttl == NULL || ttl->address_to_iface_ht == NULL) {
1519 return 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);
1526 return NULL;
1529 item = g_hash_table_lookup(ttl->address_to_iface_ht, GUINT_TO_POINTER(addr));
1530 if (item != NULL) {
1531 return item;
1534 pkt_encap = ttl_get_address_iface_type(addr);
1535 if (pkt_encap <= WTAP_ENCAP_UNKNOWN) {
1536 return NULL;
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) {
1543 return 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));
1556 if (!ret) {
1557 return NULL;
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);
1570 return item;
1573 static void
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);
1592 static bool
1593 ttl_read_bytes(ttl_read_t* in, void* out, uint16_t size, int* err, char** err_info) {
1594 switch (in->validity) {
1595 case VALIDITY_FH:
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);
1598 return false;
1600 break;
1601 case VALIDITY_BUF:
1602 if (size != 0) {
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");
1606 return false;
1608 if (out != NULL) {
1609 memcpy(out, in->buf + in->cur_pos, size);
1611 in->cur_pos += size;
1613 break;
1614 default:
1615 *err = WTAP_ERR_INTERNAL;
1616 *err_info = ws_strdup_printf("ttl_read_bytes(): ttl_read_t unknown validity flags: %d", in->validity);
1617 return false;
1620 return true;
1623 static bool
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)) {
1627 return false;
1629 ws_buffer_increase_length(buf, size);
1630 return true;
1633 static bool
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);
1638 static void
1639 ttl_add_eth_dir_option(wtap_rec* rec, uint16_t status) {
1640 uint32_t opt = PACK_FLAGS_DIRECTION_UNKNOWN;
1642 switch (status) {
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;
1648 break;
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;
1653 break;
1654 default:
1655 break;
1658 wtap_block_add_uint32_option(rec->block, OPT_EPB_FLAGS, opt);
1661 static ttl_result_t
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) {
1664 if (item == NULL) {
1665 *err = WTAP_ERR_INTERNAL;
1666 *err_info = ws_strdup("ttl_read_eth_data_entry called with NULL item");
1667 return TTL_ERROR;
1670 if (status == TTL_ETH_STATUS_PHY_STATUS) { /* TODO */
1671 if (!ttl_skip_bytes(in, size, err, err_info)) {
1672 return TTL_ERROR;
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)) {
1681 return TTL_ERROR;
1683 size -= 2;
1685 if (size != 0 && !ttl_read_bytes_buffer(in, &rec->data, size, err, err_info)) {
1686 return TTL_ERROR;
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;
1695 static void
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 };
1704 static ttl_result_t
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};
1711 if (item == NULL) {
1712 *err = WTAP_ERR_INTERNAL;
1713 *err_info = ws_strdup("ttl_read_can_data_entry called with NULL item");
1714 return TTL_ERROR;
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)) {
1726 return TTL_ERROR;
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;
1737 if (error_code) {
1738 can_id = CAN_ERR_FLAG;
1739 if (status & TTL_CAN_STATUS_BUSOFF_MASK) can_id |= CAN_ERR_BUSOFF;
1740 len = CAN_ERR_DLC;
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;
1746 break;
1747 case TTL_CAN_ERROR_FORM_ERROR:
1748 can_id |= CAN_ERR_PROT;
1749 can_error_payload[2] = CAN_ERR_PROT_FORM;
1750 break;
1751 case TTL_CAN_ERROR_ACK_ERROR:
1752 can_id |= CAN_ERR_ACK;
1753 break;
1754 case TTL_CAN_ERROR_BIT1_ERROR:
1755 can_id |= CAN_ERR_PROT;
1756 can_error_payload[2] = CAN_ERR_PROT_BIT1;
1757 break;
1758 case TTL_CAN_ERROR_BIT0_ERROR:
1759 can_id |= CAN_ERR_PROT;
1760 can_error_payload[2] = CAN_ERR_PROT_BIT0;
1761 break;
1762 case TTL_CAN_ERROR_CRC_ERROR:
1763 can_id |= CAN_ERR_PROT;
1764 can_error_payload[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
1765 break;
1766 case TTL_CAN_ERROR_INVALID_DLC:
1767 can_id |= CAN_ERR_PROT;
1768 can_error_payload[3] = CAN_ERR_PROT_LOC_DLC;
1769 break;
1772 else {
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];
1779 else {
1780 len = MIN(dlc, 8);
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;
1792 can_header[6] = 0;
1793 can_header[7] = 0;
1795 ws_buffer_append(&rec->data, can_header, sizeof(can_header));
1797 if (error_code) {
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)) {
1800 return TTL_ERROR;
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));
1805 else {
1806 if (size != 0 && !ttl_read_bytes_buffer(in, &rec->data, size, err, err_info)) {
1807 return TTL_ERROR;
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;
1817 static void
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);
1824 static ttl_result_t
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];
1828 uint8_t dlc;
1830 if (item == NULL) {
1831 *err = WTAP_ERR_INTERNAL;
1832 *err_info = ws_strdup("ttl_read_lin_data_entry called with NULL item");
1833 return TTL_ERROR;
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;
1854 if (dlc != 0) {
1855 if (!ttl_read_bytes(in, &lin_payload[0], dlc, err, err_info)) {
1856 return TTL_ERROR;
1858 size -= dlc;
1861 if (size != 0) {
1862 if (!ttl_read_bytes(in, &lin_header[6], 1, err, err_info)) {
1863 return TTL_ERROR;
1865 size -= 1;
1868 if (size != 0) { /* Skip any extra byte */
1869 if (!ttl_skip_bytes(in, size, err, err_info)) {
1870 return TTL_ERROR;
1874 ws_buffer_append(&rec->data, lin_header, sizeof(lin_header));
1876 if (dlc != 0) {
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;
1886 static void
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);
1893 static ttl_result_t
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) {
1896 uint8_t fr_item;
1897 uint8_t fr_header[2];
1899 if (item == NULL) {
1900 *err = WTAP_ERR_INTERNAL;
1901 *err_info = ws_strdup("ttl_read_flexray_data_entry called with NULL item");
1902 return TTL_ERROR;
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)) {
1909 return TTL_ERROR;
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)) {
1927 return TTL_ERROR;
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;
1936 static ttl_result_t
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);
1940 uint64_t timestamp;
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)) {
1945 return TTL_ERROR;
1947 return TTL_UNSUPPORTED;
1950 *err = 0;
1951 item = ttl_lookup_interface(wth, src, err, err_info);
1952 if (*err) {
1953 return TTL_ERROR;
1956 if (size < sizeof(uint64_t)) {
1957 return TTL_CORRUPTED;
1959 if (!ttl_read_bytes(in, &timestamp, sizeof(uint64_t), err, err_info)) {
1960 return TTL_ERROR;
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);
1974 default:
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)) {
1977 return TTL_ERROR;
1979 return TTL_UNSUPPORTED;
1984 static bool
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");
1991 return false;
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) {
1998 return false;
2001 return true;
2005 * For some reason, the timestamp of the nested frame is garbage.
2006 * Copy the timestamp of the first segment in its place.
2008 static bool
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");
2015 return false;
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), &timestamp, sizeof(uint64_t));
2026 return true;
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;
2035 uint64_t timestamp;
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;
2039 ttl_read_t new_in;
2041 if (status == 0xFFFF) { /* Reserved for future use */
2042 if (!ttl_skip_bytes(in, size, err, err_info)) {
2043 return TTL_ERROR;
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, &timestamp, sizeof(uint64_t), err, err_info)) {
2055 return TTL_ERROR;
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)) {
2076 g_free(item);
2077 return TTL_ERROR;
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)) {
2083 g_free(item);
2084 return TTL_ERROR;
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");
2097 return TTL_ERROR;
2101 g_hash_table_insert(ttl->segmented_frames_ht, GUINT_TO_POINTER(key), item);
2103 else {
2104 if (item == NULL) {
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)) {
2107 return TTL_ERROR;
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)) {
2116 return TTL_ERROR;
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));
2130 return TTL_ERROR;
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);
2156 *new_off = offset;
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;
2163 else {
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)) {
2166 return TTL_ERROR;
2170 /* If we're here, we have our reassembled entry */
2171 new_in.buf = reassembled_item->buf;
2172 new_in.size = reassembled_item->size;
2173 new_in.cur_pos = 0;
2174 new_in.validity = VALIDITY_BUF;
2176 /* Avoid recursion by not supporting nested segmented entries */
2177 *err = 0;
2178 if (!ttl_check_segmented_message_recursion(&new_in, err, err_info)) {
2179 g_hash_table_remove(ttl->reassembled_frames_ht, &offset);
2181 if (*err) {
2182 return TTL_ERROR;
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);
2189 return TTL_ERROR;
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);
2198 static ttl_result_t
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)) {
2201 return TTL_ERROR;
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;
2209 uint16_t size;
2210 uint16_t src_addr;
2211 uint8_t type;
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)) {
2223 return TTL_ERROR;
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)) {
2246 return TTL_ERROR;
2248 return TTL_UNSUPPORTED;
2251 switch (type) {
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);
2259 default:
2260 ws_debug("ttl_read_entry: Unknown Entry type: %u", type);
2261 if (!ttl_skip_bytes(in, size, err, err_info)) {
2262 return TTL_ERROR;
2264 return TTL_UNSUPPORTED;
2269 #ifdef HAVE_LIBXML2
2270 static bool
2271 ttl_xml_node_get_number(xmlNodePtr node, xmlXPathContextPtr ctx, double *ret) {
2272 xmlXPathObjectPtr result;
2273 double val;
2275 if (ret == NULL) {
2276 return false;
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)) {
2283 *ret = val;
2284 xmlXPathFreeObject(result);
2285 return true;
2289 return false;
2292 static bool
2293 ttl_xml_node_get_string(xmlNodePtr node, xmlXPathContextPtr ctx, const char* name, char** ret) {
2294 xmlXPathObjectPtr result;
2295 char* str;
2297 if (name == NULL || ret == NULL) {
2298 return false;
2301 str = ws_strdup_printf("./%s[1]/text()", name);
2303 result = xmlXPathNodeEval(node, str, ctx);
2304 g_free(str);
2305 if (result && result->type == XPATH_NODESET && !xmlXPathNodeSetIsEmpty(result->nodesetval)) {
2306 str = xmlXPathCastToString(result);
2307 *ret = ws_strdup(str);
2308 xmlFree(str);
2309 return true;
2312 return false;
2315 static bool
2316 ttl_process_xml_config(ttl_t* ttl, const char* text, int size) {
2317 xmlDocPtr doc;
2318 xmlXPathContextPtr ctx;
2319 xmlXPathObjectPtr cascades, devices, functions;
2320 int i, j, k;
2321 double val;
2322 uint16_t cascade, device, function, addr;
2323 char* user_defined_name = NULL;
2325 doc = xmlParseMemory(text, size);
2326 if (doc == NULL) {
2327 return false;
2330 if (xmlDocGetRootElement(doc) == NULL) {
2331 xmlFreeDoc(doc);
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);
2383 xmlFreeDoc(doc);
2384 return true;
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. */
2392 static int
2393 fgetline(char* buf, int size, FILE* fp)
2395 if (fgets(buf, size, fp)) {
2396 int len = (int)strcspn(buf, "\r\n");
2397 buf[len] = '\0';
2398 return len;
2400 return -1;
2402 } /* fgetline */
2404 static bool
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));
2414 break;
2415 case TTL_LOGGER_DEVICE_ATOM:
2416 if (function == TTL_LOGGER_ATOM_FUNCTION_ETHA) {
2417 return (slave == (master + 1));
2419 break;
2420 case TTL_LOGGER_DEVICE_FPGAB:
2421 switch (function) {
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));
2430 default:
2431 break;
2433 break;
2434 default:
2435 break;
2438 else {
2439 switch (ttl_addr_get_device(master)) {
2440 case TTL_TAP_DEVICE_PT15_FPGA:
2441 switch (function) {
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));
2449 default:
2450 break;
2452 break;
2453 case TTL_TAP_DEVICE_PT20_FPGA:
2454 switch (function) {
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));
2459 default:
2460 break;
2462 break;
2463 case TTL_TAP_DEVICE_PC3_FPGA:
2464 if (function == TTL_PC3_FPGA_FUNCTION_BrdR1a) {
2465 return (slave == (master + 1));
2467 break;
2468 default:
2469 break;
2473 return false;
2476 static bool
2477 ttl_parse_masters_pref_file(ttl_t* ttl, const char* path) {
2478 FILE* fp;
2479 char line[MAX_LINELEN];
2480 char* cp;
2481 uint16_t addr, tmp;
2483 if (path == NULL) {
2484 return false;
2487 fp = ws_fopen(path, "r");
2488 if (fp == NULL) {
2489 return false;
2492 while (fgetline(line, sizeof(line), fp) >= 0) {
2493 if ((cp = strchr(line, '#')))
2494 *cp = '\0';
2496 cp = strtok(line, " \t");
2497 if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 7) {
2498 continue; /* Invalid cascade */
2500 addr = tmp << 10;
2502 cp = strtok(NULL, " \t");
2503 if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 15) {
2504 continue; /* Invalid device */
2506 addr |= tmp << 6;
2508 cp = strtok(NULL, " \t");
2509 if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 63) {
2510 continue; /* Invalid function */
2512 addr |= tmp;
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));
2529 fclose(fp);
2530 return true;
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).
2543 static bool
2544 ttl_init_masters_from_pref_file(ttl_t* ttl) {
2545 char* pref_file;
2546 bool ret;
2548 pref_file = get_persconffile_path(TTL_ADDRESS_MASTER_PREFS, true);
2549 ret = ttl_parse_masters_pref_file(ttl, pref_file);
2550 g_free(pref_file);
2551 if (!ret) {
2552 pref_file = get_persconffile_path(TTL_ADDRESS_MASTER_PREFS, false);
2553 ret = ttl_parse_masters_pref_file(ttl, pref_file);
2554 g_free(pref_file);
2557 return ret;
2560 static bool
2561 ttl_parse_names_pref_file(ttl_t* ttl, const char* path) {
2562 FILE* fp;
2563 char line[MAX_LINELEN];
2564 char* cp;
2565 uint16_t addr, tmp;
2566 char* name;
2568 if (path == NULL) {
2569 return false;
2572 fp = ws_fopen(path, "r");
2573 if (fp == NULL) {
2574 return false;
2577 while (fgetline(line, sizeof(line), fp) >= 0) {
2578 if ((cp = strchr(line, '#')))
2579 *cp = '\0';
2581 cp = strtok(line, " \t");
2582 if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 7) {
2583 continue; /* Invalid cascade */
2585 addr = tmp << 10;
2587 cp = strtok(NULL, " \t");
2588 if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 15) {
2589 continue; /* Invalid device */
2591 addr |= tmp << 6;
2593 cp = strtok(NULL, " \t");
2594 if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 63) {
2595 continue; /* Invalid function */
2597 addr |= tmp;
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);
2606 fclose(fp);
2607 return true;
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.
2617 static bool
2618 ttl_init_names_from_pref_file(ttl_t* ttl) {
2619 char* pref_file;
2620 bool ret;
2622 pref_file = get_persconffile_path(TTL_ADDRESS_NAME_PREFS, true);
2623 ret = ttl_parse_names_pref_file(ttl, pref_file);
2624 g_free(pref_file);
2625 if (!ret) {
2626 pref_file = get_persconffile_path(TTL_ADDRESS_NAME_PREFS, false);
2627 ret = ttl_parse_names_pref_file(ttl, pref_file);
2628 g_free(pref_file);
2631 return ret;
2634 static void
2635 ttl_cleanup(ttl_t* ttl) {
2636 if (ttl != NULL) {
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);
2652 g_free(ttl);
2656 wtap_open_return_val
2657 ttl_open(wtap* wth, int* err, char** err_info) {
2658 ttl_fileheader_t header;
2659 ttl_t* ttl;
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.
2674 *err = 0;
2675 g_free(*err_info);
2676 *err_info = NULL;
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);
2713 else {
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)) {
2716 ttl_cleanup(ttl);
2717 return WTAP_OPEN_ERROR;
2719 offset += TTL_LOGFILE_INFO_SIZE;
2720 #ifdef HAVE_LIBXML2
2721 unsigned int xml_len = header.header_size - offset;
2722 if (xml_len != 0) {
2723 unsigned char* xml = g_try_malloc(xml_len);
2724 if (xml == NULL) {
2725 *err = WTAP_ERR_INTERNAL;
2726 *err_info = ws_strdup("ttl: cannot allocate memory");
2727 ttl_cleanup(ttl);
2728 return false;
2730 if (!wtap_read_bytes(wth->fh, xml, xml_len, err, err_info)) {
2731 g_free(xml);
2732 ttl_cleanup(ttl);
2733 return WTAP_OPEN_ERROR;
2735 if (!ttl_process_xml_config(ttl, xml, xml_len)) {
2736 report_warning("Cannot extract information from TTL XML.");
2738 g_free(xml);
2739 offset += xml_len;
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)) {
2747 ttl_cleanup(ttl);
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) {
2770 return pos;
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) {
2777 ttl_read_t input;
2778 int64_t pos, end;
2779 ttl_result_t res;
2781 input.fh = wth->fh;
2782 input.validity = VALIDITY_FH;
2784 do {
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)) {
2804 *data_offset = pos;
2805 return true;
2808 return false;
2811 static bool ttl_seek_read(wtap* wth, int64_t seek_off, wtap_rec* rec, int* err, char** err_info) {
2812 ttl_read_t input;
2813 ttl_result_t res;
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)) {
2825 return true;
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);
2837 return false;
2840 static void ttl_close(wtap* wth) {
2841 if (wth != NULL) {
2842 ttl_cleanup((ttl_t*)wth->priv);
2843 wth->priv = NULL;
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),
2861 NULL, NULL, NULL
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
2879 * Local variables:
2880 * c-basic-offset: 4
2881 * tab-width: 8
2882 * indent-tabs-mode: nil
2883 * End:
2885 * vi: set shiftwidth=4 tabstop=8 expandtab:
2886 * :indentSize=4:tabSize=8:noTabs=true: