Coverage Report

Created: 2026-01-02 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/wiretap/ttl.c
Line
Count
Source
1
/* ttl.c
2
 *
3
 * Wiretap Library
4
 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5
 *
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).
10
 *
11
 * Copyright (c) 2024 by Giovanni Musto <giovanni.musto@partner.italdesign.it>
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
16
#include <config.h>
17
0
#define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP
18
19
#include "ttl.h"
20
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
#include <wsutil/pint.h>
28
#include <libxml/tree.h>
29
#include <libxml/parser.h>
30
#include <libxml/xpath.h>
31
#include "file_wrappers.h"
32
#include "wtap_module.h"
33
34
static const uint8_t ttl_magic[] = { 'T', 'T', 'L', ' ' };
35
36
static int ttl_file_type_subtype = -1;
37
38
0
#define TTL_ADDRESS_NAME_PREFS      "file_format_ttl_names"
39
0
#define TTL_ADDRESS_MASTER_PREFS    "file_format_ttl_masters"
40
41
void register_ttl(void);
42
static bool ttl_read(wtap* wth, wtap_rec* rec, int* err, char** err_info, int64_t* data_offset);
43
static bool ttl_seek_read(wtap* wth, int64_t seek_off, wtap_rec* rec, int* err, char** err_info);
44
static void ttl_close(wtap* wth);
45
46
typedef struct ttl_data {
47
    uint32_t    block_size;
48
    uint32_t    header_size;
49
    uint32_t    next_interface_id;
50
51
    GHashTable* address_to_iface_ht;
52
    GHashTable* address_to_master_ht;
53
    GHashTable* address_to_name_ht;
54
    GHashTable* segmented_frames_ht;
55
    GHashTable* reassembled_frames_ht;
56
} ttl_t;
57
58
typedef enum ttl_read_validity {
59
    VALIDITY_FH = 1,
60
    VALIDITY_BUF = 2
61
} ttl_read_validity_t;
62
63
/*
64
 * Usually, 'fh' is valid and is used by ttl_read_bytes, but in case of
65
 * segmented entries, 'buf' will be set to the reassembled nested entry.
66
 */
67
typedef struct ttl_read {
68
    union {
69
        FILE_T  fh;
70
        struct {
71
            uint8_t*    buf;
72
            uint32_t    size;
73
            uint32_t    cur_pos;
74
        };
75
    };
76
    ttl_read_validity_t validity;
77
} ttl_read_t;
78
79
/*
80
 * Values smaller than 0 indicate errors, 0 means OK, 1 means everything is
81
 * good, but the entry is unsupported. 2 means that the file looks corrupted
82
 * or unaligned and our caller should try to fix the situation.
83
 */
84
typedef enum {
85
    TTL_ERROR = -1,
86
    TTL_NO_ERROR = 0,
87
    TTL_UNSUPPORTED = 1,
88
    TTL_CORRUPTED = 2
89
} ttl_result_t;
90
91
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);
92
93
/*
94
 * This struct is used to map the source address of an entry to an actual
95
 * interface.
96
 *
97
 * The field 'channelB' has meaning only for FlexRay and it means that the
98
 * packet belongs to FlexRay's Channel B.
99
 */
100
typedef struct ttl_addr_to_iface_entry {
101
    int         pkt_encap;
102
    bool        channelB;
103
104
    uint32_t    interface_id;
105
} ttl_addr_to_iface_entry_t;
106
107
typedef struct ttl_segmented_entry {
108
    uint64_t        timestamp;
109
    uint32_t        size;   /* Full size of the reassembled entry */
110
    uint32_t        type;   /* Type of the entry */
111
112
    uint32_t        size_so_far;
113
    uint8_t         next_segment;
114
    unsigned char*  buf;
115
} ttl_segmented_entry_t;
116
117
typedef struct ttl_reassembled_entry {
118
    uint64_t        timestamp;
119
    uint32_t        size;
120
    unsigned char*  buf;
121
} ttl_reassembled_entry_t;
122
123
void
124
0
ttl_free_segmented_entry(void* data) {
125
0
    ttl_segmented_entry_t* item;
126
0
    if (data != NULL) {
127
0
        item = (ttl_segmented_entry_t*)data;
128
0
        if (item->buf != NULL) {
129
0
            g_free(item->buf);
130
0
        }
131
0
        g_free(data);
132
0
    }
133
0
}
134
135
void
136
0
ttl_free_reassembled_entry(void* data) {
137
0
    ttl_reassembled_entry_t* item;
138
0
    if (data != NULL) {
139
0
        item = (ttl_reassembled_entry_t*)data;
140
0
        if (item->buf != NULL) {
141
0
            g_free(item->buf);
142
0
        }
143
0
        g_free(data);
144
0
    }
145
0
}
146
147
#ifndef OPT_EPB_FLAGS
148
0
    #define OPT_EPB_FLAGS   0x0002  /* Copied from pcapng.c */
149
#endif
150
151
#ifndef FLEXRAY_FRAME
152
0
    #define FLEXRAY_FRAME   0x01    /* Copied from packet-flexray.c */
153
#endif
154
155
#ifndef FLEXRAY_SYMBOL
156
    #define FLEXRAY_SYMBOL  0x02    /* Copied from packet-flexray.c */
157
#endif
158
159
static void
160
0
fix_endianness_ttl_fileheader(ttl_fileheader_t* header) {
161
0
    header->version = GUINT32_FROM_LE(header->version);
162
0
    header->block_size = GUINT32_FROM_LE(header->block_size);
163
0
    header->header_size = GUINT32_FROM_LE(header->header_size);
164
0
}
165
166
static void
167
0
fix_endianness_ttl_entryheader(ttl_entryheader_t* header) {
168
0
    header->size_type = GUINT16_FROM_LE(header->size_type);
169
0
    header->dest_addr = GUINT16_FROM_LE(header->dest_addr);
170
0
    header->src_addr = GUINT16_FROM_LE(header->src_addr);
171
0
    header->status_info = GUINT16_FROM_LE(header->status_info);
172
0
}
173
174
/*
175
 * This function returns the "master" address of coupled addresses.
176
 *
177
 * The output is different from the input in two cases:
178
 * 1. Coupled Ethernet channel, such as the slave side of a tap
179
 * 2. FlexRay Channel B, in order to couple it to Channel A
180
 *
181
 * In both cases, the returned address is the one of the "main" channel, so
182
 * that both addresses can be mapped to the same interface.
183
 *
184
 * If a hash table is passed as input, and an entry is present for addr,
185
 * then the stored result is returned. If there's no match, or no hash table
186
 * is passed as input, then the default behaviour applies:
187
 * - For FlexRay, always return corresponding Channel A if addr is Channel B.
188
 * - For Ethernet:
189
 *   - Return the same address if cascade is 0 (i.e. the channel belongs to
190
 *     the logger).
191
 *   - Return the address of the master if addr belongs to a tap (cascade != 0)
192
 */
193
0
uint16_t ttl_get_master_address(GHashTable* ht, uint16_t addr) {
194
0
    uint8_t function = ttl_addr_get_function(addr);
195
196
0
    if (ht != NULL) {
197
0
        void* master;
198
0
        if (g_hash_table_lookup_extended(ht, GUINT_TO_POINTER(addr), NULL, &master)) {
199
0
            return (uint16_t)GPOINTER_TO_UINT(master);
200
0
        }
201
0
    }
202
203
0
    if (ttl_addr_get_cascade(addr) == 0) {  /* The address refers to the logger itself */
204
0
        switch (ttl_addr_get_device(addr))
205
0
        {
206
0
        case TTL_LOGGER_DEVICE_FPGA:
207
0
            switch (function) {
208
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH2:
209
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH2:
210
0
                return (addr - 45);
211
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH3:
212
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH3:
213
0
                return (addr - 47);
214
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B:
215
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B:
216
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B:
217
0
                return (addr - 1);
218
0
            default:
219
0
                break;
220
0
            }
221
0
            break;
222
0
        case TTL_LOGGER_DEVICE_TRICORE1:
223
0
        case TTL_LOGGER_DEVICE_TRICORE2:
224
0
        case TTL_LOGGER_DEVICE_TRICORE3:
225
0
            if (function == TTL_LOGGER_TRICORE_FUNCTION_FLEXRAYB) {
226
0
                return (addr - 1);
227
0
            }
228
0
            break;
229
0
        case TTL_LOGGER_DEVICE_TDA4x:
230
0
            if (function == TTL_LOGGER_TDA4x_FUNCTION_FLEXRAY1B) {
231
0
                return (addr - 1);
232
0
            }
233
0
            break;
234
0
        case TTL_LOGGER_DEVICE_FPGAA:
235
0
            if (function == TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B) {
236
0
                return (addr - 1);
237
0
            }
238
0
            break;
239
0
        case TTL_LOGGER_DEVICE_FPGAB:
240
0
            switch (function) {
241
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH2:
242
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH2:
243
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1a_CH2:
244
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1b_CH2:
245
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2a_CH2:
246
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2b_CH2:
247
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3a_CH2:
248
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3b_CH2:
249
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4a_CH2:
250
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4b_CH2:
251
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5a_CH2:
252
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5b_CH2:
253
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6a_CH2:
254
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6b_CH2:
255
0
                return (addr - 14);
256
0
            default:
257
0
                break;
258
0
            }
259
0
            break;
260
0
        default:
261
0
            break;
262
0
        }
263
0
    }
264
0
    else {  /* The address refers to a TAP */
265
0
        switch (ttl_addr_get_device(addr)) {
266
0
        case TTL_TAP_DEVICE_PT15_FPGA:
267
0
            switch (function) {
268
0
            case TTL_PT15_FPGA_FUNCTION_BrdR1b:
269
0
            case TTL_PT15_FPGA_FUNCTION_BrdR2b:
270
0
            case TTL_PT15_FPGA_FUNCTION_BrdR3b:
271
0
            case TTL_PT15_FPGA_FUNCTION_BrdR4b:
272
0
            case TTL_PT15_FPGA_FUNCTION_BrdR5b:
273
0
            case TTL_PT15_FPGA_FUNCTION_BrdR6b:
274
0
                return (addr - 1);
275
0
            default:
276
0
                break;
277
0
            }
278
0
            break;
279
0
        case TTL_TAP_DEVICE_PT20_FPGA:
280
0
            switch (function) {
281
0
            case TTL_PT20_FPGA_FUNCTION_GbEth1b:
282
0
            case TTL_PT20_FPGA_FUNCTION_GbEth2b:
283
0
            case TTL_PT20_FPGA_FUNCTION_GbEth3b:
284
0
                return (addr - 1);
285
0
            default:
286
0
                break;
287
0
            }
288
0
            break;
289
0
        case TTL_TAP_DEVICE_PC3_FPGA:
290
0
            if (function == TTL_PC3_FPGA_FUNCTION_BrdR1b) {
291
0
                return (addr - 1);
292
0
            }
293
0
            break;
294
0
        case TTL_TAP_DEVICE_PC3_AURIX:
295
0
            switch (function) {
296
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B:
297
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B:
298
0
                return (addr - 1);
299
0
            default:
300
0
                break;
301
0
            }
302
0
            break;
303
0
        default:
304
0
            break;
305
0
        }
306
0
    }
307
308
0
    return addr;
309
0
}
310
311
0
bool ttl_is_chb_addr(uint16_t addr) {
312
0
    uint8_t function = ttl_addr_get_function(addr);
313
314
0
    if (ttl_addr_get_cascade(addr) == 0) {  /* The address refers to the logger itself */
315
0
        switch (ttl_addr_get_device(addr))
316
0
        {
317
0
        case TTL_LOGGER_DEVICE_FPGA:
318
0
            switch (function) {
319
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B:
320
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B:
321
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B:
322
0
                return true;
323
0
            default:
324
0
                break;
325
0
            }
326
0
            break;
327
0
        case TTL_LOGGER_DEVICE_TRICORE1:
328
0
        case TTL_LOGGER_DEVICE_TRICORE2:
329
0
        case TTL_LOGGER_DEVICE_TRICORE3:
330
0
            if (function == TTL_LOGGER_TRICORE_FUNCTION_FLEXRAYB) {
331
0
                return true;
332
0
            }
333
0
            break;
334
0
        case TTL_LOGGER_DEVICE_FPGAA:
335
0
            if (function == TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B) {
336
0
                return true;
337
0
            }
338
0
            break;
339
0
        default:
340
0
            break;
341
0
        }
342
0
    }
343
0
    else {  /* The address refers to a TAP */
344
0
        switch (ttl_addr_get_device(addr)) {
345
0
        case TTL_TAP_DEVICE_PC3_AURIX:
346
0
            switch (function) {
347
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B:
348
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B:
349
0
                return true;
350
0
            default:
351
0
                break;
352
0
            }
353
0
            break;
354
0
        default:
355
0
            break;
356
0
        }
357
0
    }
358
359
0
    return false;
360
0
}
361
362
0
int ttl_get_address_iface_type(uint16_t addr) {
363
0
    uint8_t function = ttl_addr_get_function(addr);
364
365
0
    if (ttl_addr_get_cascade(addr) == 0) { /* The address refers to the logger itself */
366
0
        switch (ttl_addr_get_device(addr))
367
0
        {
368
0
        case TTL_LOGGER_DEVICE_FPGA:
369
0
            switch (function) {
370
0
            case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST25:
371
0
            case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST150:
372
0
            case TTL_LOGGER_FPGA_FUNCTION_EXT1_MOST25:
373
0
                return WTAP_ENCAP_MOST;
374
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH1:
375
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH1:
376
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH2:
377
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH2:
378
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH3:
379
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH3:
380
0
                return WTAP_ENCAP_ETHERNET;
381
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1A:
382
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B:
383
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2A:
384
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B:
385
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3A:
386
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B:
387
0
                return WTAP_ENCAP_FLEXRAY;
388
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN1:
389
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN2:
390
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN3:
391
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN4:
392
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN5:
393
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN6:
394
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN7:
395
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN8:
396
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN9:
397
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN10:
398
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN11:
399
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN12:
400
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN13:
401
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN14:
402
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN15:
403
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN16:
404
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN17:
405
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN18:
406
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN19:
407
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN20:
408
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN21:
409
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN22:
410
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN23:
411
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN24:
412
0
                return WTAP_ENCAP_SOCKETCAN;
413
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN1:
414
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN2:
415
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN3:
416
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN4:
417
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN5:
418
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN6:
419
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN7:
420
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN8:
421
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN9:
422
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN10:
423
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN11:
424
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN12:
425
0
                return WTAP_ENCAP_LIN;
426
0
            default:
427
0
                break;
428
0
            }
429
430
0
            break;
431
0
        case TTL_LOGGER_DEVICE_ATOM:
432
0
            switch (function) {
433
0
            case TTL_LOGGER_ATOM_FUNCTION_ETHA:
434
0
            case TTL_LOGGER_ATOM_FUNCTION_ETHB:
435
0
                return WTAP_ENCAP_ETHERNET;
436
0
            default:
437
0
                break;
438
0
            }
439
440
0
            break;
441
0
        case TTL_LOGGER_DEVICE_TRICORE1:
442
0
            switch (function) {
443
0
            case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1A:
444
0
            case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1B:
445
0
            case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1:
446
0
            case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1AB:
447
0
                return WTAP_ENCAP_FLEXRAY;
448
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CAN1:
449
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CAN2:
450
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CAN3:
451
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CAN4:
452
0
                return WTAP_ENCAP_SOCKETCAN;
453
0
            default:
454
0
                break;
455
0
            }
456
457
0
            break;
458
0
        case TTL_LOGGER_DEVICE_TRICORE2:
459
0
            switch (function) {
460
0
            case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2A:
461
0
            case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2B:
462
0
            case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2:
463
0
            case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2AB:
464
0
                return WTAP_ENCAP_FLEXRAY;
465
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CAN6:
466
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CAN7:
467
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CAN10:
468
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CAN12:
469
0
                return WTAP_ENCAP_SOCKETCAN;
470
0
            default:
471
0
                break;
472
0
            }
473
474
0
            break;
475
0
        case TTL_LOGGER_DEVICE_TRICORE3:
476
0
            switch (function) {
477
0
            case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3A:
478
0
            case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3B:
479
0
            case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3:
480
0
            case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3AB:
481
0
                return WTAP_ENCAP_FLEXRAY;
482
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CAN5:
483
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CAN8:
484
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CAN9:
485
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CAN11:
486
0
                return WTAP_ENCAP_SOCKETCAN;
487
0
            default:
488
0
                break;
489
0
            }
490
491
0
            break;
492
0
        case TTL_LOGGER_DEVICE_TDA4x:
493
0
            switch (function) {
494
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN1:
495
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN2:
496
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN3:
497
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN4:
498
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN5:
499
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN6:
500
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN7:
501
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN8:
502
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN9:
503
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN10:
504
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN11:
505
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN12:
506
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN13:
507
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN14:
508
0
                return WTAP_ENCAP_SOCKETCAN;
509
0
            default:
510
0
                break;
511
0
            }
512
513
0
            break;
514
0
        case TTL_LOGGER_DEVICE_FPGAA:
515
0
            switch (function) {
516
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN1:
517
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN2:
518
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN3:
519
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN4:
520
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN5:
521
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN6:
522
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN7:
523
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN8:
524
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN9:
525
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN10:
526
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN11:
527
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN12:
528
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN13:
529
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN14:
530
0
                return WTAP_ENCAP_SOCKETCAN;
531
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN1:
532
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN2:
533
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN3:
534
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN4:
535
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN5:
536
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN6:
537
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN7:
538
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN8:
539
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN9:
540
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN10:
541
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN11:
542
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN12:
543
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN13:
544
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN14:
545
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN15:
546
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN16:
547
0
                return WTAP_ENCAP_LIN;
548
0
            case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1A:
549
0
            case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B:
550
0
                return WTAP_ENCAP_FLEXRAY;
551
0
            default:
552
0
                break;
553
0
            }
554
555
0
            break;
556
0
        case TTL_LOGGER_DEVICE_FPGAB:
557
0
            switch (function) {
558
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH1:
559
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH1:
560
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1a_CH1:
561
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1b_CH1:
562
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2a_CH1:
563
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2b_CH1:
564
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3a_CH1:
565
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3b_CH1:
566
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4a_CH1:
567
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4b_CH1:
568
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5a_CH1:
569
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5b_CH1:
570
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6a_CH1:
571
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6b_CH1:
572
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH2:
573
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH2:
574
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1a_CH2:
575
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1b_CH2:
576
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2a_CH2:
577
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2b_CH2:
578
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3a_CH2:
579
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3b_CH2:
580
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4a_CH2:
581
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4b_CH2:
582
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5a_CH2:
583
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5b_CH2:
584
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6a_CH2:
585
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6b_CH2:
586
0
                return WTAP_ENCAP_ETHERNET;
587
0
            default:
588
0
                break;
589
0
            }
590
591
0
            break;
592
0
        default:
593
0
            break;
594
0
        }
595
0
    }
596
0
    else {  /* The address refers to a TAP */
597
0
        switch (ttl_addr_get_device(addr)) {
598
0
        case TTL_TAP_DEVICE_PT15_FPGA:
599
0
            switch (function) {
600
0
            case TTL_PT15_FPGA_FUNCTION_CAN1:
601
0
            case TTL_PT15_FPGA_FUNCTION_CAN2:
602
0
                return WTAP_ENCAP_SOCKETCAN;
603
0
            case TTL_PT15_FPGA_FUNCTION_BrdR1a:
604
0
            case TTL_PT15_FPGA_FUNCTION_BrdR1b:
605
0
            case TTL_PT15_FPGA_FUNCTION_BrdR2a:
606
0
            case TTL_PT15_FPGA_FUNCTION_BrdR2b:
607
0
            case TTL_PT15_FPGA_FUNCTION_BrdR3a:
608
0
            case TTL_PT15_FPGA_FUNCTION_BrdR3b:
609
0
            case TTL_PT15_FPGA_FUNCTION_BrdR4a:
610
0
            case TTL_PT15_FPGA_FUNCTION_BrdR4b:
611
0
            case TTL_PT15_FPGA_FUNCTION_BrdR5a:
612
0
            case TTL_PT15_FPGA_FUNCTION_BrdR5b:
613
0
            case TTL_PT15_FPGA_FUNCTION_BrdR6a:
614
0
            case TTL_PT15_FPGA_FUNCTION_BrdR6b:
615
0
                return WTAP_ENCAP_ETHERNET;
616
0
            case TTL_PT15_FPGA_FUNCTION_MDIO:   /* TODO: Support this */
617
0
            default:
618
0
                break;
619
0
            }
620
621
0
            break;
622
0
        case TTL_TAP_DEVICE_PT20_FPGA:
623
0
            switch (function) {
624
0
            case TTL_PT20_FPGA_FUNCTION_CAN1:
625
0
            case TTL_PT20_FPGA_FUNCTION_CAN2:
626
0
            case TTL_PT20_FPGA_FUNCTION_CAN3:
627
0
            case TTL_PT20_FPGA_FUNCTION_CAN4:
628
0
            case TTL_PT20_FPGA_FUNCTION_CAN5:
629
0
                return WTAP_ENCAP_SOCKETCAN;
630
0
            case TTL_PT20_FPGA_FUNCTION_GbEth1a:
631
0
            case TTL_PT20_FPGA_FUNCTION_GbEth1b:
632
0
            case TTL_PT20_FPGA_FUNCTION_GbEth2a:
633
0
            case TTL_PT20_FPGA_FUNCTION_GbEth2b:
634
0
            case TTL_PT20_FPGA_FUNCTION_GbEth3a:
635
0
            case TTL_PT20_FPGA_FUNCTION_GbEth3b:
636
0
                return WTAP_ENCAP_ETHERNET;
637
0
            case TTL_PT20_FPGA_FUNCTION_MDIO:   /* TODO: Support this */
638
0
            default:
639
0
                break;
640
0
            }
641
642
0
            break;
643
0
        case TTL_TAP_DEVICE_PC3_FPGA:
644
0
            switch (function) {
645
0
            case TTL_PC3_FPGA_FUNCTION_BrdR1a:
646
0
            case TTL_PC3_FPGA_FUNCTION_BrdR1b:
647
0
                return WTAP_ENCAP_ETHERNET;
648
0
            default:
649
0
                break;
650
0
            }
651
652
0
            break;
653
0
        case TTL_TAP_DEVICE_PC3_AURIX:
654
0
            switch (function) {
655
0
            case TTL_PC3_AURIX_FUNCTION_CAN1:
656
0
            case TTL_PC3_AURIX_FUNCTION_CAN2:
657
0
            case TTL_PC3_AURIX_FUNCTION_CAN3:
658
0
            case TTL_PC3_AURIX_FUNCTION_CAN4:
659
0
                return WTAP_ENCAP_SOCKETCAN;
660
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY1A:
661
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B:
662
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY2A:
663
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B:
664
0
                return WTAP_ENCAP_FLEXRAY;
665
0
            default:
666
0
                break;
667
0
            }
668
669
0
            break;
670
0
        case TTL_TAP_DEVICE_ZELDA_CANFD:
671
0
            switch (function) {
672
0
            case TTL_TAP_DEVICE_ZELDA_CANFD1:
673
0
            case TTL_TAP_DEVICE_ZELDA_CANFD2:
674
0
            case TTL_TAP_DEVICE_ZELDA_CANFD3:
675
0
            case TTL_TAP_DEVICE_ZELDA_CANFD4:
676
0
            case TTL_TAP_DEVICE_ZELDA_CANFD5:
677
0
            case TTL_TAP_DEVICE_ZELDA_CANFD6:
678
0
            case TTL_TAP_DEVICE_ZELDA_CANFD7:
679
0
            case TTL_TAP_DEVICE_ZELDA_CANFD8:
680
0
            case TTL_TAP_DEVICE_ZELDA_CANFD9:
681
0
            case TTL_TAP_DEVICE_ZELDA_CANFD10:
682
0
            case TTL_TAP_DEVICE_ZELDA_CANFD11:
683
0
            case TTL_TAP_DEVICE_ZELDA_CANFD12:
684
0
            case TTL_TAP_DEVICE_ZELDA_CANFD13:
685
0
            case TTL_TAP_DEVICE_ZELDA_CANFD14:
686
0
            case TTL_TAP_DEVICE_ZELDA_CANFD15:
687
0
                return WTAP_ENCAP_SOCKETCAN;
688
0
            default:
689
0
                break;
690
0
            }
691
692
0
            break;
693
0
        case TTL_TAP_DEVICE_ZELDA_LIN:
694
0
            switch (function) {
695
0
            case TTL_TAP_DEVICE_ZELDA_LIN1:
696
0
            case TTL_TAP_DEVICE_ZELDA_LIN2:
697
0
            case TTL_TAP_DEVICE_ZELDA_LIN3:
698
0
            case TTL_TAP_DEVICE_ZELDA_LIN4:
699
0
            case TTL_TAP_DEVICE_ZELDA_LIN5:
700
0
            case TTL_TAP_DEVICE_ZELDA_LIN6:
701
0
            case TTL_TAP_DEVICE_ZELDA_LIN7:
702
0
            case TTL_TAP_DEVICE_ZELDA_LIN8:
703
0
            case TTL_TAP_DEVICE_ZELDA_LIN9:
704
0
            case TTL_TAP_DEVICE_ZELDA_LIN10:
705
0
            case TTL_TAP_DEVICE_ZELDA_LIN11:
706
0
            case TTL_TAP_DEVICE_ZELDA_LIN12:
707
0
            case TTL_TAP_DEVICE_ZELDA_LIN13:
708
0
            case TTL_TAP_DEVICE_ZELDA_LIN14:
709
0
            case TTL_TAP_DEVICE_ZELDA_LIN15:
710
0
            case TTL_TAP_DEVICE_ZELDA_LIN16:
711
0
            case TTL_TAP_DEVICE_ZELDA_LIN17:
712
0
            case TTL_TAP_DEVICE_ZELDA_LIN18:
713
0
            case TTL_TAP_DEVICE_ZELDA_LIN19:
714
0
            case TTL_TAP_DEVICE_ZELDA_LIN20:
715
0
            case TTL_TAP_DEVICE_ZELDA_LIN21:
716
0
            case TTL_TAP_DEVICE_ZELDA_LIN22:
717
0
            case TTL_TAP_DEVICE_ZELDA_LIN23:
718
0
            case TTL_TAP_DEVICE_ZELDA_LIN24:
719
0
                return WTAP_ENCAP_LIN;
720
0
            default:
721
0
                break;
722
0
            }
723
724
0
            break;
725
0
        default:
726
0
            break;
727
0
        }
728
0
    }
729
730
0
    return WTAP_ENCAP_UNKNOWN;
731
0
}
732
733
static const char* const ttl_cascade_names[] = { "Logger", "Tap1", "Tap2", "Tap3", "Tap4", "Tap5", "Tap6", "Tap7" };
734
735
0
const char* ttl_get_cascade_name(uint16_t addr) {
736
0
    return ttl_cascade_names[ttl_addr_get_cascade(addr)];
737
0
}
738
739
0
const char* ttl_get_device_name(uint16_t addr) {
740
0
    if (ttl_addr_get_cascade(addr) == 0) {
741
0
        switch (ttl_addr_get_device(addr)) {
742
0
        case TTL_LOGGER_DEVICE_FPGA:
743
0
        case TTL_LOGGER_DEVICE_FPGAA:
744
0
        case TTL_LOGGER_DEVICE_FPGAB:
745
0
            return "FPGA";
746
0
        case TTL_LOGGER_DEVICE_ATOM:
747
0
            return "Atom";
748
0
        case TTL_LOGGER_DEVICE_TRICORE1:
749
0
        case TTL_LOGGER_DEVICE_TRICORE2:
750
0
        case TTL_LOGGER_DEVICE_TRICORE3:
751
0
            return "Tricore";
752
0
        case TTL_LOGGER_DEVICE_TDA4x:
753
0
            return "TDA4x";
754
0
        default:
755
0
            break;
756
0
        }
757
0
    }
758
0
    else {
759
0
        switch (ttl_addr_get_device(addr)) {
760
0
        case TTL_TAP_DEVICE_PT15_FPGA:
761
0
        case TTL_TAP_DEVICE_PT15_HPS_LINUX:
762
0
            return "PT15";
763
0
        case TTL_TAP_DEVICE_PT20_FPGA:
764
0
        case TTL_TAP_DEVICE_PT20_HPS_LINUX:
765
0
            return "PT20";
766
0
        case TTL_TAP_DEVICE_PC3_FPGA:
767
0
        case TTL_TAP_DEVICE_PC3_HPS_LINUX:
768
0
        case TTL_TAP_DEVICE_PC3_AURIX:
769
0
            return "PC3";
770
0
        case TTL_TAP_DEVICE_ZELDA_CANFD:
771
0
        case TTL_TAP_DEVICE_ZELDA_LIN:
772
0
            return "Zelda";
773
0
        default:
774
0
            break;
775
0
        }
776
0
    }
777
778
0
    return "Unknown";
779
0
}
780
781
0
const char* ttl_get_function_name(uint16_t addr) {
782
0
    uint8_t function = ttl_addr_get_function(addr);
783
784
0
    if (ttl_addr_get_cascade(addr) == 0) {
785
0
        switch (ttl_addr_get_device(addr)) {
786
0
        case TTL_LOGGER_DEVICE_FPGA:
787
0
            switch (function) {
788
0
            case TTL_LOGGER_FPGA_FUNCTION_CORE:
789
0
                return "Core";
790
0
            case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST25:
791
0
                return "Ext0_MOST25";
792
0
            case TTL_LOGGER_FPGA_FUNCTION_EXT0_MOST150:
793
0
                return "MOST150";
794
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH1:
795
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH2:
796
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHA_CH3:
797
0
                return "EthernetA";
798
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH1:
799
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH2:
800
0
            case TTL_LOGGER_FPGA_FUNCTION_ETHB_CH3:
801
0
                return "EthernetB";
802
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1A:
803
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY1B:
804
0
                return "FlexRay1";
805
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2A:
806
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY2B:
807
0
                return "FlexRay2";
808
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3A:
809
0
            case TTL_LOGGER_FPGA_FUNCTION_FLEXRAY3B:
810
0
                return "FlexRay3";
811
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN1:
812
0
                return "CAN1";
813
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN2:
814
0
                return "CAN2";
815
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN3:
816
0
                return "CAN3";
817
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN4:
818
0
                return "CAN4";
819
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN5:
820
0
                return "CAN5";
821
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN6:
822
0
                return "CAN6";
823
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN7:
824
0
                return "CAN7";
825
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN8:
826
0
                return "CAN8";
827
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN9:
828
0
                return "CAN9";
829
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN10:
830
0
                return "CAN10";
831
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN11:
832
0
                return "CAN11";
833
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN12:
834
0
                return "CAN12";
835
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN13:
836
0
                return "CAN13";
837
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN14:
838
0
                return "CAN14";
839
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN15:
840
0
                return "CAN15";
841
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN16:
842
0
                return "CAN16";
843
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN17:
844
0
                return "CAN17";
845
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN18:
846
0
                return "CAN18";
847
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN19:
848
0
                return "CAN19";
849
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN20:
850
0
                return "CAN20";
851
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN21:
852
0
                return "CAN21";
853
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN22:
854
0
                return "CAN22";
855
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN23:
856
0
                return "CAN23";
857
0
            case TTL_LOGGER_FPGA_FUNCTION_CAN24:
858
0
                return "CAN24";
859
0
            case TTL_LOGGER_FPGA_FUNCTION_EXT1_MOST25:
860
0
                return "MOST25";
861
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN1:
862
0
                return "LIN1";
863
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN2:
864
0
                return "LIN2";
865
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN3:
866
0
                return "LIN3";
867
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN4:
868
0
                return "LIN4";
869
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN5:
870
0
                return "LIN5";
871
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN6:
872
0
                return "LIN6";
873
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN7:
874
0
                return "LIN7";
875
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN8:
876
0
                return "LIN8";
877
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN9:
878
0
                return "LIN9";
879
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN10:
880
0
                return "LIN10";
881
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN11:
882
0
                return "LIN11";
883
0
            case TTL_LOGGER_FPGA_FUNCTION_LIN12:
884
0
                return "LIN12";
885
0
            default:
886
0
                break;
887
0
            }
888
0
            break;
889
0
        case TTL_LOGGER_DEVICE_ATOM:
890
0
            switch (function) {
891
0
            case TTL_LOGGER_ATOM_FUNCTION_ETHA:
892
0
                return "EthernetA";
893
0
            case TTL_LOGGER_ATOM_FUNCTION_ETHB:
894
0
                return "EthernetB";
895
0
            default:
896
0
                break;
897
0
            }
898
0
            break;
899
0
        case TTL_LOGGER_DEVICE_TRICORE1:
900
0
            switch (function) {
901
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CORE:
902
0
                return "Core1";
903
0
            case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1A:
904
0
            case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1B:
905
0
            case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1:
906
0
            case TTL_LOGGER_TRICORE1_FUNCTION_FLEXRAY1AB:
907
0
                return "FlexRay1";
908
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CAN1:
909
0
                return "CAN1";
910
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CAN2:
911
0
                return "CAN2";
912
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CAN3:
913
0
                return "CAN3";
914
0
            case TTL_LOGGER_TRICORE1_FUNCTION_CAN4:
915
0
                return "CAN4";
916
0
            case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGOUT1:
917
0
                return "AnalogOut1";
918
0
            case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALOUT5:
919
0
                return "DigitalOut5";
920
0
            case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALOUT6:
921
0
                return "DigitalOut6";
922
0
            case TTL_LOGGER_TRICORE1_FUNCTION_SERIAL1:
923
0
                return "Serial1";
924
0
            case TTL_LOGGER_TRICORE1_FUNCTION_SERIAL2:
925
0
                return "Serial2";
926
0
            case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN6:
927
0
                return "AnalogIn6";
928
0
            case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN8:
929
0
                return "AnalogIn8";
930
0
            case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN11:
931
0
                return "AnalogIn11";
932
0
            case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN14:
933
0
                return "AnalogIn14";
934
0
            case TTL_LOGGER_TRICORE1_FUNCTION_ANALOGIN15:
935
0
                return "AnalogIn15";
936
0
            case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN8:
937
0
                return "DigitalIn8";
938
0
            case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN10:
939
0
                return "DigitalIn10";
940
0
            case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN11:
941
0
                return "DigitalIn11";
942
0
            case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN12:
943
0
                return "DigitalIn12";
944
0
            case TTL_LOGGER_TRICORE1_FUNCTION_DIGITALIN13:
945
0
                return "DigitalIn13";
946
0
            case TTL_LOGGER_TRICORE1_FUNCTION_KL15IN:
947
0
                return "KL15";
948
0
            case TTL_LOGGER_TRICORE1_FUNCTION_KL30IN:
949
0
                return "KL30";
950
0
            default:
951
0
                break;
952
0
            }
953
0
            break;
954
0
        case TTL_LOGGER_DEVICE_TRICORE2:
955
0
            switch (function) {
956
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CORE:
957
0
                return "Core2";
958
0
            case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2A:
959
0
            case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2B:
960
0
            case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2:
961
0
            case TTL_LOGGER_TRICORE2_FUNCTION_FLEXRAY2AB:
962
0
                return "FlexRay2";
963
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CAN6:
964
0
                return "CAN6";
965
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CAN7:
966
0
                return "CAN7";
967
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CAN10:
968
0
                return "CAN10";
969
0
            case TTL_LOGGER_TRICORE2_FUNCTION_CAN12:
970
0
                return "CAN12";
971
0
            case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGOUT2:
972
0
                return "AnalogOut2";
973
0
            case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALOUT3:
974
0
                return "DigitalOut3";
975
0
            case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALOUT4:
976
0
                return "DigitalOut4";
977
0
            case TTL_LOGGER_TRICORE2_FUNCTION_SERIAL3:
978
0
                return "Serial3";
979
0
            case TTL_LOGGER_TRICORE2_FUNCTION_SERIAL4:
980
0
                return "Serial4";
981
0
            case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN3:
982
0
                return "AnalogIn3";
983
0
            case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN4:
984
0
                return "AnalogIn4";
985
0
            case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN5:
986
0
                return "AnalogIn5";
987
0
            case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN7:
988
0
                return "AnalogIn7";
989
0
            case TTL_LOGGER_TRICORE2_FUNCTION_ANALOGIN9:
990
0
                return "AnalogIn9";
991
0
            case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN6:
992
0
                return "DigitalIn6";
993
0
            case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN7:
994
0
                return "DigitalIn7";
995
0
            case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN9:
996
0
                return "DigitalIn9";
997
0
            case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN14:
998
0
                return "DigitalIn14";
999
0
            case TTL_LOGGER_TRICORE2_FUNCTION_DIGITALIN15:
1000
0
                return "DigitalIn15";
1001
0
            default:
1002
0
                break;
1003
0
            }
1004
0
            break;
1005
0
        case TTL_LOGGER_DEVICE_TRICORE3:
1006
0
            switch (function) {
1007
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CORE:
1008
0
                return "Core3";
1009
0
            case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3A:
1010
0
            case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3B:
1011
0
            case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3:
1012
0
            case TTL_LOGGER_TRICORE3_FUNCTION_FLEXRAY3AB:
1013
0
                return "FlexRay3";
1014
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CAN5:
1015
0
                return "CAN5";
1016
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CAN8:
1017
0
                return "CAN8";
1018
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CAN9:
1019
0
                return "CAN9";
1020
0
            case TTL_LOGGER_TRICORE3_FUNCTION_CAN11:
1021
0
                return "CAN11";
1022
0
            case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGOUT3:
1023
0
                return "AnalogOut3";
1024
0
            case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALOUT1:
1025
0
                return "DigitalOut1";
1026
0
            case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALOUT2:
1027
0
                return "DigitalOut2";
1028
0
            case TTL_LOGGER_TRICORE3_FUNCTION_SERIAL5:
1029
0
                return "Serial5";
1030
0
            case TTL_LOGGER_TRICORE3_FUNCTION_SERIAL6:
1031
0
                return "Serial6";
1032
0
            case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN1:
1033
0
                return "AnalogIn1";
1034
0
            case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN2:
1035
0
                return "AnalogIn2";
1036
0
            case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN10:
1037
0
                return "AnalogIn10";
1038
0
            case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN12:
1039
0
                return "AnalogIn12";
1040
0
            case TTL_LOGGER_TRICORE3_FUNCTION_ANALOGIN13:
1041
0
                return "AnalogIn13";
1042
0
            case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN1:
1043
0
                return "DigitalIn1";
1044
0
            case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN2:
1045
0
                return "DigitalIn2";
1046
0
            case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN3:
1047
0
                return "DigitalIn3";
1048
0
            case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN4:
1049
0
                return "DigitalIn4";
1050
0
            case TTL_LOGGER_TRICORE3_FUNCTION_DIGITALIN5:
1051
0
                return "DigitalIn5";
1052
0
            default:
1053
0
                break;
1054
0
            }
1055
0
            break;
1056
0
        case TTL_LOGGER_DEVICE_TDA4x:
1057
0
            switch (function) {
1058
0
            case TTL_LOGGER_TDA4x_FUNCTION_CORE:
1059
0
                return "Core";
1060
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN1:
1061
0
                return "CAN1";
1062
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN2:
1063
0
                return "CAN2";
1064
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN3:
1065
0
                return "CAN3";
1066
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN4:
1067
0
                return "CAN4";
1068
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN5:
1069
0
                return "CAN5";
1070
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN6:
1071
0
                return "CAN6";
1072
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN7:
1073
0
                return "CAN7";
1074
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN8:
1075
0
                return "CAN8";
1076
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN9:
1077
0
                return "CAN9";
1078
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN10:
1079
0
                return "CAN10";
1080
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN11:
1081
0
                return "CAN11";
1082
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL1:
1083
0
                return "Serial1";
1084
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL2:
1085
0
                return "Serial2";
1086
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL3:
1087
0
                return "Serial3";
1088
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL4:
1089
0
                return "Serial4";
1090
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL5:
1091
0
                return "Serial5";
1092
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL6:
1093
0
                return "Serial6";
1094
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL7:
1095
0
                return "Serial7";
1096
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL8:
1097
0
                return "Serial8";
1098
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL9:
1099
0
                return "Serial9";
1100
0
            case TTL_LOGGER_TDA4x_FUNCTION_SERIAL10:
1101
0
                return "Serial10";
1102
0
            case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN1:
1103
0
                return "AnalogIn1";
1104
0
            case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN2:
1105
0
                return "AnalogIn2";
1106
0
            case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN3:
1107
0
                return "AnalogIn3";
1108
0
            case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN4:
1109
0
                return "AnalogIn4";
1110
0
            case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN5:
1111
0
                return "AnalogIn5";
1112
0
            case TTL_LOGGER_TDA4x_FUNCTION_ANALOGIN6:
1113
0
                return "AnalogIn6";
1114
0
            case TTL_LOGGER_TDA4x_FUNCTION_ANALOGOUT1:
1115
0
                return "AnalogOut1";
1116
0
            case TTL_LOGGER_TDA4x_FUNCTION_ANALOGOUT2:
1117
0
                return "AnalogOut2";
1118
0
            case TTL_LOGGER_TDA4x_FUNCTION_KL15IN:
1119
0
                return "KL15";
1120
0
            case TTL_LOGGER_TDA4x_FUNCTION_KL30IN:
1121
0
                return "KL30";
1122
0
            case TTL_LOGGER_TDA4x_FUNCTION_FLEXRAY1A:
1123
0
            case TTL_LOGGER_TDA4x_FUNCTION_FLEXRAY1B:
1124
0
            case TTL_LOGGER_TDA4x_FUNCTION_FLEXRAY1AB:
1125
0
                return "FlexRay1";
1126
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN12:
1127
0
                return "CAN12";
1128
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN13:
1129
0
                return "CAN13";
1130
0
            case TTL_LOGGER_TDA4x_FUNCTION_CAN14:
1131
0
                return "CAN14";
1132
1133
0
            default:
1134
0
                break;
1135
0
            }
1136
0
            break;
1137
0
        case TTL_LOGGER_DEVICE_FPGAA:
1138
0
            switch (function) {
1139
0
            case TTL_LOGGER_FPGAA_FUNCTION_CORE:
1140
0
                return "Core";
1141
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN1:
1142
0
                return "CAN1";
1143
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN2:
1144
0
                return "CAN2";
1145
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN3:
1146
0
                return "CAN3";
1147
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN4:
1148
0
                return "CAN4";
1149
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN5:
1150
0
                return "CAN5";
1151
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN6:
1152
0
                return "CAN6";
1153
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN7:
1154
0
                return "CAN7";
1155
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN8:
1156
0
                return "CAN8";
1157
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN9:
1158
0
                return "CAN9";
1159
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN10:
1160
0
                return "CAN10";
1161
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN11:
1162
0
                return "CAN11";
1163
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN1:
1164
0
                return "LIN1";
1165
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN2:
1166
0
                return "LIN2";
1167
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN3:
1168
0
                return "LIN3";
1169
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN4:
1170
0
                return "LIN4";
1171
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN5:
1172
0
                return "LIN5";
1173
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN6:
1174
0
                return "LIN6";
1175
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN7:
1176
0
                return "LIN7";
1177
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN8:
1178
0
                return "LIN8";
1179
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN9:
1180
0
                return "LIN9";
1181
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN10:
1182
0
                return "LIN10";
1183
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN11:
1184
0
                return "LIN11";
1185
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN12:
1186
0
                return "LIN12";
1187
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN13:
1188
0
                return "LIN13";
1189
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN14:
1190
0
                return "LIN14";
1191
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN15:
1192
0
                return "LIN15";
1193
0
            case TTL_LOGGER_FPGAA_FUNCTION_LIN16:
1194
0
                return "LIN16";
1195
0
            case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1A:
1196
0
            case TTL_LOGGER_FPGAA_FUNCTION_FLEXRAY1B:
1197
0
                return "FlexRay1";
1198
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL1:
1199
0
                return "Serial1";
1200
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL2:
1201
0
                return "Serial2";
1202
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL3:
1203
0
                return "Serial3";
1204
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL4:
1205
0
                return "Serial4";
1206
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL5:
1207
0
                return "Serial5";
1208
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL6:
1209
0
                return "Serial6";
1210
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL7:
1211
0
                return "Serial7";
1212
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL8:
1213
0
                return "Serial8";
1214
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL9:
1215
0
                return "Serial9";
1216
0
            case TTL_LOGGER_FPGAA_FUNCTION_SERIAL10:
1217
0
                return "Serial10";
1218
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN12:
1219
0
                return "CAN12";
1220
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN13:
1221
0
                return "CAN13";
1222
0
            case TTL_LOGGER_FPGAA_FUNCTION_CAN14:
1223
0
                return "CAN14";
1224
0
            default:
1225
0
                break;
1226
0
            }
1227
0
            break;
1228
0
        case TTL_LOGGER_DEVICE_FPGAB:
1229
0
            switch (function) {
1230
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH1:
1231
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH2:
1232
0
                return "EthernetA";
1233
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH1:
1234
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHB_CH2:
1235
0
                return "EthernetB";
1236
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1a_CH1:
1237
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1a_CH2:
1238
0
                return "AutomotiveEthernet1a";
1239
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1b_CH1:
1240
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1b_CH2:
1241
0
                return "AutomotiveEthernet1b";
1242
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2a_CH1:
1243
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2a_CH2:
1244
0
                return "AutomotiveEthernet2a";
1245
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2b_CH1:
1246
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2b_CH2:
1247
0
                return "AutomotiveEthernet2b";
1248
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3a_CH1:
1249
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3a_CH2:
1250
0
                return "AutomotiveEthernet3a";
1251
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3b_CH1:
1252
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3b_CH2:
1253
0
                return "AutomotiveEthernet3b";
1254
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4a_CH1:
1255
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4a_CH2:
1256
0
                return "AutomotiveEthernet4a";
1257
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4b_CH1:
1258
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4b_CH2:
1259
0
                return "AutomotiveEthernet4b";
1260
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5a_CH1:
1261
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5a_CH2:
1262
0
                return "AutomotiveEthernet5a";
1263
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5b_CH1:
1264
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5b_CH2:
1265
0
                return "AutomotiveEthernet5b";
1266
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6a_CH1:
1267
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6a_CH2:
1268
0
                return "AutomotiveEthernet6a";
1269
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6b_CH1:
1270
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6b_CH2:
1271
0
                return "AutomotiveEthernet6b";
1272
0
            default:
1273
0
                break;
1274
0
            }
1275
0
            break;
1276
0
        default:
1277
0
            break;
1278
0
        }
1279
0
    }
1280
0
    else {
1281
0
        switch (ttl_addr_get_device(addr)) {
1282
0
        case TTL_TAP_DEVICE_PT15_FPGA:
1283
0
            switch (function) {
1284
0
            case TTL_PT15_FPGA_FUNCTION_CORE:
1285
0
                return "Core";
1286
0
            case TTL_PT15_FPGA_FUNCTION_CAN1:
1287
0
                return "CAN1";
1288
0
            case TTL_PT15_FPGA_FUNCTION_CAN2:
1289
0
                return "CAN2";
1290
0
            case TTL_PT15_FPGA_FUNCTION_BrdR1a:
1291
0
                return "BR1a";
1292
0
            case TTL_PT15_FPGA_FUNCTION_BrdR1b:
1293
0
                return "BR1b";
1294
0
            case TTL_PT15_FPGA_FUNCTION_BrdR2a:
1295
0
                return "BR2a";
1296
0
            case TTL_PT15_FPGA_FUNCTION_BrdR2b:
1297
0
                return "BR2b";
1298
0
            case TTL_PT15_FPGA_FUNCTION_BrdR3a:
1299
0
                return "BR3a";
1300
0
            case TTL_PT15_FPGA_FUNCTION_BrdR3b:
1301
0
                return "BR3b";
1302
0
            case TTL_PT15_FPGA_FUNCTION_BrdR4a:
1303
0
                return "BR4a";
1304
0
            case TTL_PT15_FPGA_FUNCTION_BrdR4b:
1305
0
                return "BR4b";
1306
0
            case TTL_PT15_FPGA_FUNCTION_BrdR5a:
1307
0
                return "BR5a";
1308
0
            case TTL_PT15_FPGA_FUNCTION_BrdR5b:
1309
0
                return "BR5b";
1310
0
            case TTL_PT15_FPGA_FUNCTION_BrdR6a:
1311
0
                return "BR6a";
1312
0
            case TTL_PT15_FPGA_FUNCTION_BrdR6b:
1313
0
                return "BR6b";
1314
0
            case TTL_PT15_FPGA_FUNCTION_MDIO:
1315
0
                return "MDIO";
1316
0
            default:
1317
0
                break;
1318
0
            }
1319
0
            break;
1320
0
        case TTL_TAP_DEVICE_PT20_FPGA:
1321
0
            switch (function) {
1322
0
            case TTL_PT20_FPGA_FUNCTION_CORE:
1323
0
                return "Core";
1324
0
            case TTL_PT20_FPGA_FUNCTION_CAN1:
1325
0
                return "CAN1";
1326
0
            case TTL_PT20_FPGA_FUNCTION_CAN2:
1327
0
                return "CAN2";
1328
0
            case TTL_PT20_FPGA_FUNCTION_CAN3:
1329
0
                return "CAN3";
1330
0
            case TTL_PT20_FPGA_FUNCTION_CAN4:
1331
0
                return "CAN4";
1332
0
            case TTL_PT20_FPGA_FUNCTION_CAN5:
1333
0
                return "CAN5";
1334
0
            case TTL_PT20_FPGA_FUNCTION_GbEth1a:
1335
0
                return "GbEth1a";
1336
0
            case TTL_PT20_FPGA_FUNCTION_GbEth1b:
1337
0
                return "GbEth1b";
1338
0
            case TTL_PT20_FPGA_FUNCTION_GbEth2a:
1339
0
                return "GbEth2a";
1340
0
            case TTL_PT20_FPGA_FUNCTION_GbEth2b:
1341
0
                return "GbEth2b";
1342
0
            case TTL_PT20_FPGA_FUNCTION_GbEth3a:
1343
0
                return "GbEth3a";
1344
0
            case TTL_PT20_FPGA_FUNCTION_GbEth3b:
1345
0
                return "GbEth3b";
1346
0
            case TTL_PT20_FPGA_FUNCTION_MDIO:
1347
0
                return "MDIO";
1348
0
            default:
1349
0
                break;
1350
0
            }
1351
0
            break;
1352
0
        case TTL_TAP_DEVICE_PC3_FPGA:
1353
0
            switch (function) {
1354
0
            case TTL_PC3_FPGA_FUNCTION_CORE:
1355
0
                return "FPGA_Core";
1356
0
            case TTL_PC3_FPGA_FUNCTION_BrdR1a:
1357
0
                return "BR1a";
1358
0
            case TTL_PC3_FPGA_FUNCTION_BrdR1b:
1359
0
                return "BR1b";
1360
0
            default:
1361
0
                break;
1362
0
            }
1363
0
            break;
1364
0
        case TTL_TAP_DEVICE_PC3_AURIX:
1365
0
            switch (function) {
1366
0
            case TTL_PC3_AURIX_FUNCTION_CORE:
1367
0
                return "Aurix_Core";
1368
0
            case TTL_PC3_AURIX_FUNCTION_CAN1:
1369
0
                return "CAN1";
1370
0
            case TTL_PC3_AURIX_FUNCTION_CAN2:
1371
0
                return "CAN2";
1372
0
            case TTL_PC3_AURIX_FUNCTION_CAN3:
1373
0
                return "CAN3";
1374
0
            case TTL_PC3_AURIX_FUNCTION_CAN4:
1375
0
                return "CAN4";
1376
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY1A:
1377
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY1B:
1378
0
                return "FlexRay1";
1379
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY2A:
1380
0
            case TTL_PC3_AURIX_FUNCTION_FLEXRAY2B:
1381
0
                return "FlexRay2";
1382
0
            case TTL_PC3_AURIX_FUNCTION_DIGITALIN1:
1383
0
                return "DigitalIn1";
1384
0
            case TTL_PC3_AURIX_FUNCTION_DIGITALIN2:
1385
0
                return "DigitalIn2";
1386
0
            case TTL_PC3_AURIX_FUNCTION_DIGITALOUT1:
1387
0
                return "DigitalOut1";
1388
0
            case TTL_PC3_AURIX_FUNCTION_DIGITALOUT2:
1389
0
                return "DigitalOut2";
1390
0
            default:
1391
0
                break;
1392
0
            }
1393
0
            break;
1394
0
        case TTL_TAP_DEVICE_ZELDA_CANFD:
1395
0
            switch (function) {
1396
0
            case TTL_TAP_DEVICE_ZELDA_CORE:
1397
0
                return "CANFD_Core";
1398
0
            case TTL_TAP_DEVICE_ZELDA_CANFD1:
1399
0
                return "CANFD1";
1400
0
            case TTL_TAP_DEVICE_ZELDA_CANFD2:
1401
0
                return "CANFD2";
1402
0
            case TTL_TAP_DEVICE_ZELDA_CANFD3:
1403
0
                return "CANFD3";
1404
0
            case TTL_TAP_DEVICE_ZELDA_CANFD4:
1405
0
                return "CANFD4";
1406
0
            case TTL_TAP_DEVICE_ZELDA_CANFD5:
1407
0
                return "CANFD5";
1408
0
            case TTL_TAP_DEVICE_ZELDA_CANFD6:
1409
0
                return "CANFD6";
1410
0
            case TTL_TAP_DEVICE_ZELDA_CANFD7:
1411
0
                return "CANFD7";
1412
0
            case TTL_TAP_DEVICE_ZELDA_CANFD8:
1413
0
                return "CANFD8";
1414
0
            case TTL_TAP_DEVICE_ZELDA_CANFD9:
1415
0
                return "CANFD9";
1416
0
            case TTL_TAP_DEVICE_ZELDA_CANFD10:
1417
0
                return "CANFD10";
1418
0
            case TTL_TAP_DEVICE_ZELDA_CANFD11:
1419
0
                return "CANFD11";
1420
0
            case TTL_TAP_DEVICE_ZELDA_CANFD12:
1421
0
                return "CANFD12";
1422
0
            case TTL_TAP_DEVICE_ZELDA_CANFD13:
1423
0
                return "CANFD13";
1424
0
            case TTL_TAP_DEVICE_ZELDA_CANFD14:
1425
0
                return "CANFD14";
1426
0
            case TTL_TAP_DEVICE_ZELDA_CANFD15:
1427
0
                return "CANFD15";
1428
0
            default:
1429
0
                break;
1430
0
            }
1431
0
            break;
1432
0
        case TTL_TAP_DEVICE_ZELDA_LIN:
1433
0
            switch (function) {
1434
0
            case TTL_TAP_DEVICE_ZELDA_CORE:
1435
0
                return "LIN_Core";
1436
0
            case TTL_TAP_DEVICE_ZELDA_LIN1:
1437
0
                return "LIN1";
1438
0
            case TTL_TAP_DEVICE_ZELDA_LIN2:
1439
0
                return "LIN2";
1440
0
            case TTL_TAP_DEVICE_ZELDA_LIN3:
1441
0
                return "LIN3";
1442
0
            case TTL_TAP_DEVICE_ZELDA_LIN4:
1443
0
                return "LIN4";
1444
0
            case TTL_TAP_DEVICE_ZELDA_LIN5:
1445
0
                return "LIN5";
1446
0
            case TTL_TAP_DEVICE_ZELDA_LIN6:
1447
0
                return "LIN6";
1448
0
            case TTL_TAP_DEVICE_ZELDA_LIN7:
1449
0
                return "LIN7";
1450
0
            case TTL_TAP_DEVICE_ZELDA_LIN8:
1451
0
                return "LIN8";
1452
0
            case TTL_TAP_DEVICE_ZELDA_LIN9:
1453
0
                return "LIN9";
1454
0
            case TTL_TAP_DEVICE_ZELDA_LIN10:
1455
0
                return "LIN10";
1456
0
            case TTL_TAP_DEVICE_ZELDA_LIN11:
1457
0
                return "LIN11";
1458
0
            case TTL_TAP_DEVICE_ZELDA_LIN12:
1459
0
                return "LIN12";
1460
0
            case TTL_TAP_DEVICE_ZELDA_LIN13:
1461
0
                return "LIN13";
1462
0
            case TTL_TAP_DEVICE_ZELDA_LIN14:
1463
0
                return "LIN14";
1464
0
            case TTL_TAP_DEVICE_ZELDA_LIN15:
1465
0
                return "LIN15";
1466
0
            case TTL_TAP_DEVICE_ZELDA_LIN16:
1467
0
                return "LIN16";
1468
0
            case TTL_TAP_DEVICE_ZELDA_LIN17:
1469
0
                return "LIN17";
1470
0
            case TTL_TAP_DEVICE_ZELDA_LIN18:
1471
0
                return "LIN18";
1472
0
            case TTL_TAP_DEVICE_ZELDA_LIN19:
1473
0
                return "LIN19";
1474
0
            case TTL_TAP_DEVICE_ZELDA_LIN20:
1475
0
                return "LIN20";
1476
0
            case TTL_TAP_DEVICE_ZELDA_LIN21:
1477
0
                return "LIN21";
1478
0
            case TTL_TAP_DEVICE_ZELDA_LIN22:
1479
0
                return "LIN22";
1480
0
            case TTL_TAP_DEVICE_ZELDA_LIN23:
1481
0
                return "LIN23";
1482
0
            case TTL_TAP_DEVICE_ZELDA_LIN24:
1483
0
                return "LIN24";
1484
0
            default:
1485
0
                break;
1486
0
            }
1487
0
            break;
1488
0
        default:
1489
0
            break;
1490
0
        }
1491
0
    }
1492
1493
0
    return "Unknown";
1494
0
}
1495
1496
static wtap_opttype_return_val
1497
0
ttl_add_interface_name(wtap_block_t int_data, uint16_t addr, const char* name) {
1498
0
    if (name != NULL) {
1499
0
        return wtap_block_add_string_option(int_data, OPT_IDB_NAME, name, strlen(name));
1500
0
    }
1501
1502
0
    return wtap_block_add_string_option_format(int_data, OPT_IDB_NAME, "%s::%s::%s",
1503
0
                                               ttl_get_cascade_name(addr),
1504
0
                                               ttl_get_device_name(addr),
1505
0
                                               ttl_get_function_name(addr));
1506
0
}
1507
1508
/*
1509
 * This function will create the interface and populate the
1510
 * 'address_to_iface_ht' hash table.
1511
 */
1512
static bool
1513
0
ttl_create_interface(wtap* wth, int pkt_encap, uint16_t addr, const char* name) {
1514
0
    wtap_block_t int_data;
1515
0
    wtapng_if_descr_mandatory_t* if_descr_mand;
1516
1517
0
    if (wth == NULL) {
1518
0
        return false;
1519
0
    }
1520
1521
0
    int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
1522
0
    if_descr_mand = wtap_block_get_mandatory_data(int_data);
1523
1524
0
    if_descr_mand->wtap_encap = pkt_encap;
1525
0
    ttl_add_interface_name(int_data, addr, name);
1526
1527
0
    if_descr_mand->time_units_per_second = 1000 * 1000;
1528
0
    if_descr_mand->tsprecision = WTAP_TSPREC_USEC;
1529
0
    wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 6);
1530
0
    if_descr_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;
1531
0
    if_descr_mand->num_stat_entries = 0;
1532
0
    if_descr_mand->interface_statistics = NULL;
1533
0
    wtap_add_idb(wth, int_data);
1534
1535
0
    if (wth->file_encap == WTAP_ENCAP_NONE) {
1536
0
        wth->file_encap = if_descr_mand->wtap_encap;
1537
0
    }
1538
0
    else if (wth->file_encap != if_descr_mand->wtap_encap) {
1539
0
        wth->file_encap = WTAP_ENCAP_PER_PACKET;
1540
0
    }
1541
1542
0
    return true;
1543
0
}
1544
1545
0
#define TTL_LOOKUP_INTERFACE_MAX_ITERATIONS 2
1546
0
#define ttl_lookup_interface(...)   ttl_lookup_interface_int(__VA_ARGS__, 0)
1547
1548
// NOLINTNEXTLINE(misc-no-recursion)
1549
0
static const ttl_addr_to_iface_entry_t* ttl_lookup_interface_int(wtap* wth, uint16_t addr, int* err, char** err_info, int iteration) {
1550
0
    ttl_addr_to_iface_entry_t* item;
1551
0
    ttl_t*      ttl;
1552
0
    uint32_t    iface_id;
1553
0
    uint16_t    master_addr;
1554
0
    int         pkt_encap;
1555
1556
0
    if (wth == NULL) {
1557
0
        return NULL;
1558
0
    }
1559
1560
0
    ttl = (ttl_t*)wth->priv;
1561
0
    if (ttl == NULL || ttl->address_to_iface_ht == NULL) {
1562
0
        return NULL;
1563
0
    }
1564
1565
    /* Recursion limit to avoid coding errors. */
1566
0
    if (iteration > TTL_LOOKUP_INTERFACE_MAX_ITERATIONS) {
1567
0
        *err = WTAP_ERR_INTERNAL;
1568
0
        *err_info = ws_strdup_printf("ttl_lookup_interface(): more iterations than allowed: %d (max. %d)", iteration, TTL_LOOKUP_INTERFACE_MAX_ITERATIONS);
1569
0
        return NULL;
1570
0
    }
1571
1572
0
    item = g_hash_table_lookup(ttl->address_to_iface_ht, GUINT_TO_POINTER(addr));
1573
0
    if (item != NULL) {
1574
0
        return item;
1575
0
    }
1576
1577
0
    pkt_encap = ttl_get_address_iface_type(addr);
1578
0
    if (pkt_encap <= WTAP_ENCAP_UNKNOWN) {
1579
0
        return NULL;
1580
0
    }
1581
1582
0
    master_addr = ttl_get_master_address(ttl->address_to_master_ht, addr);
1583
0
    if (addr != master_addr) {   /* The interface ID is the "slave" one */
1584
0
        const ttl_addr_to_iface_entry_t* master_item = ttl_lookup_interface_int(wth, master_addr, err, err_info, iteration + 1);
1585
0
        if (master_item == NULL) {
1586
0
            return NULL;
1587
0
        }
1588
1589
0
        iface_id = master_item->interface_id;
1590
0
    }
1591
0
    else {  /* Create a new interface */
1592
0
        const char* saved_name = g_hash_table_lookup(ttl->address_to_name_ht, GUINT_TO_POINTER(addr));
1593
0
        bool ret = ttl_create_interface(wth, pkt_encap, addr, saved_name);
1594
1595
0
        if (saved_name != NULL) {
1596
0
            g_hash_table_remove(ttl->address_to_name_ht, GUINT_TO_POINTER(addr));
1597
0
        }
1598
1599
0
        if (!ret) {
1600
0
            return NULL;
1601
0
        }
1602
1603
0
        iface_id = ttl->next_interface_id++;
1604
0
    }
1605
1606
    /* Create the entry */
1607
0
    item = g_new(ttl_addr_to_iface_entry_t, 1);
1608
0
    item->interface_id = iface_id;
1609
0
    item->pkt_encap = pkt_encap;
1610
0
    item->channelB = ttl_is_chb_addr(addr);
1611
0
    g_hash_table_insert(ttl->address_to_iface_ht, GUINT_TO_POINTER(addr), item);
1612
1613
0
    return item;
1614
0
}
1615
1616
static void
1617
0
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) {
1618
0
    wtap_setup_packet_rec(rec, pkt_encap);
1619
0
    rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
1620
0
    rec->presence_flags = WTAP_HAS_CAP_LEN | WTAP_HAS_INTERFACE_ID | WTAP_HAS_TS;
1621
0
    rec->tsprec = WTAP_TSPREC_USEC;
1622
0
    rec->ts.secs = timestamp / (1000 * 1000);
1623
0
    rec->ts.nsecs = 1000 * (timestamp % (1000 * 1000));
1624
0
    rec->rec_header.packet_header.caplen = caplen;
1625
0
    rec->rec_header.packet_header.len = len;
1626
1627
0
    rec->rec_header.packet_header.interface_id = iface_id;
1628
1629
0
    wtap_block_add_uint32_option(rec->block, OPT_PKT_QUEUE, addr);
1630
0
}
1631
1632
static bool
1633
0
ttl_read_bytes(ttl_read_t* in, void* out, uint16_t size, int* err, char** err_info) {
1634
0
    switch (in->validity) {
1635
0
    case VALIDITY_FH:
1636
0
        if (!wtap_read_bytes_or_eof(in->fh, out, size, err, err_info)) {
1637
0
            ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err);
1638
0
            return false;
1639
0
        }
1640
0
        break;
1641
0
    case VALIDITY_BUF:
1642
0
        if (size != 0) {
1643
0
            if ((in->cur_pos + size) > in->size) {
1644
0
                *err = WTAP_ERR_SHORT_READ;
1645
0
                *err_info = ws_strdup("ttl_read_bytes(): Attempt to read beyond buffer end");
1646
0
                return false;
1647
0
            }
1648
0
            if (out != NULL) {
1649
0
                memcpy(out, in->buf + in->cur_pos, size);
1650
0
            }
1651
0
            in->cur_pos += size;
1652
0
        }
1653
0
        break;
1654
0
    default:
1655
0
        *err = WTAP_ERR_INTERNAL;
1656
0
        *err_info = ws_strdup_printf("ttl_read_bytes(): ttl_read_t unknown validity flags: %d", in->validity);
1657
0
        return false;
1658
0
    }
1659
1660
0
    return true;
1661
0
}
1662
1663
static bool
1664
0
ttl_read_bytes_buffer(ttl_read_t* in, Buffer* buf, uint16_t size, int* err, char** err_info) {
1665
0
    ws_buffer_assure_space(buf, size);
1666
0
    if (!ttl_read_bytes(in, ws_buffer_end_ptr(buf), size, err, err_info)) {
1667
0
        return false;
1668
0
    }
1669
0
    ws_buffer_increase_length(buf, size);
1670
0
    return true;
1671
0
}
1672
1673
static bool
1674
0
ttl_skip_bytes(ttl_read_t* in, uint16_t size, int* err, char** err_info) {
1675
0
    return ttl_read_bytes(in, NULL, size, err, err_info);
1676
0
}
1677
1678
static void
1679
0
ttl_add_eth_dir_option(wtap_rec* rec, uint16_t status) {
1680
0
    uint32_t opt = PACK_FLAGS_DIRECTION_UNKNOWN;
1681
1682
0
    switch (status) {
1683
0
    case TTL_ETH_STATUS_VALID_FRAME:
1684
0
    case TTL_ETH_STATUS_CRC_ERROR_FRAME:
1685
0
    case TTL_ETH_STATUS_LENGTH_ERROR_FRAME:
1686
0
    case TTL_ETH_STATUS_PHY_ERROR_FRAME:
1687
0
        opt = PACK_FLAGS_DIRECTION_INBOUND;
1688
0
        break;
1689
0
    case TTL_ETH_STATUS_TX_ERROR_FRAME:
1690
0
    case TTL_ETH_STATUS_TX_FREEMEM_INFO_FRAME:
1691
0
    case TTL_ETH_STATUS_TX_FRAME:
1692
0
        opt = PACK_FLAGS_DIRECTION_OUTBOUND;
1693
0
        break;
1694
0
    default:
1695
0
        break;
1696
0
    }
1697
1698
0
    wtap_block_add_uint32_option(rec->block, OPT_EPB_FLAGS, opt);
1699
0
}
1700
1701
static ttl_result_t
1702
ttl_read_eth_data_entry(wtap_rec* rec, int* err, char** err_info, ttl_read_t* in, uint16_t size, uint16_t addr,
1703
0
                        const ttl_addr_to_iface_entry_t* item, uint16_t status, uint64_t timestamp) {
1704
0
    if (item == NULL) {
1705
0
        *err = WTAP_ERR_INTERNAL;
1706
0
        *err_info = ws_strdup("ttl_read_eth_data_entry called with NULL item");
1707
0
        return TTL_ERROR;
1708
0
    }
1709
1710
0
    if (status == TTL_ETH_STATUS_PHY_STATUS) {  /* TODO */
1711
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
1712
0
            return TTL_ERROR;
1713
0
        }
1714
0
        return TTL_UNSUPPORTED;
1715
0
    }
1716
1717
0
    if (size < 2) { /* 2 unused bytes */
1718
0
        return TTL_CORRUPTED;
1719
0
    }
1720
0
    if (!ttl_skip_bytes(in, 2, err, err_info)) {
1721
0
        return TTL_ERROR;
1722
0
    }
1723
0
    size -= 2;
1724
1725
0
    if (size != 0 && !ttl_read_bytes_buffer(in, &rec->data, size, err, err_info)) {
1726
0
        return TTL_ERROR;
1727
0
    }
1728
1729
0
    ttl_init_rec(rec, timestamp, addr, item->pkt_encap, item->interface_id, size, size);
1730
0
    ttl_add_eth_dir_option(rec, status);
1731
1732
0
    return TTL_NO_ERROR;
1733
0
}
1734
1735
static void
1736
0
ttl_add_can_dir_option(wtap_rec* rec) {
1737
0
    uint32_t opt = PACK_FLAGS_DIRECTION_INBOUND;    /* For the moment, we only support this */
1738
1739
0
    wtap_block_add_uint32_option(rec->block, OPT_EPB_FLAGS, opt);
1740
0
}
1741
1742
static const uint8_t canfd_dlc_to_length[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64 };
1743
1744
static ttl_result_t
1745
ttl_read_can_data_entry(wtap_rec* rec, int* err, char** err_info, ttl_read_t* in, uint16_t size, uint16_t addr,
1746
0
                        const ttl_addr_to_iface_entry_t* item, uint16_t status, uint64_t timestamp) {
1747
0
    uint32_t    can_id = 0;
1748
0
    uint8_t     dlc, error_code, len, canfd_flags = 0;
1749
0
    uint8_t     can_header[8], can_error_payload[CAN_ERR_DLC] = {0};
1750
1751
0
    if (item == NULL) {
1752
0
        *err = WTAP_ERR_INTERNAL;
1753
0
        *err_info = ws_strdup("ttl_read_can_data_entry called with NULL item");
1754
0
        return TTL_ERROR;
1755
0
    }
1756
1757
0
    dlc = (status & TTL_CAN_STATUS_DLC_MASK) >> TTL_CAN_STATUS_DLC_POS;
1758
0
    error_code = (status & TTL_CAN_STATUS_ERROR_CODE_MASK) >> TTL_CAN_STATUS_ERROR_CODE_POS;
1759
1760
0
    if (status & TTL_CAN_STATUS_VALID_BIT_MASK) {   /* DLC, ID and Payload are valid */
1761
0
        if (size < sizeof(uint32_t)) {    /* No more data */
1762
0
            return TTL_CORRUPTED;
1763
0
        }
1764
1765
0
        if (!ttl_read_bytes(in, &can_id, sizeof(uint32_t), err, err_info)) {
1766
0
            return TTL_ERROR;
1767
0
        }
1768
0
        can_id = GUINT32_FROM_LE(can_id);
1769
0
        size -= sizeof(uint32_t);
1770
1771
0
        if (size == 0 && !(status & TTL_CAN_STATUS_RTR_BIT_MASK)) {
1772
            /* No more data, and it's not a remote transmission frame */
1773
0
            return TTL_CORRUPTED;
1774
0
        }
1775
0
    }
1776
1777
0
    if (error_code) {
1778
0
        can_id = CAN_ERR_FLAG;
1779
0
        if (status & TTL_CAN_STATUS_BUSOFF_MASK) can_id |= CAN_ERR_BUSOFF;
1780
0
        len = CAN_ERR_DLC;
1781
1782
0
        switch (error_code) {
1783
0
        case TTL_CAN_ERROR_STUFF_ERROR:
1784
0
            can_id |= CAN_ERR_PROT;
1785
0
            can_error_payload[2] = CAN_ERR_PROT_STUFF;
1786
0
            break;
1787
0
        case TTL_CAN_ERROR_FORM_ERROR:
1788
0
            can_id |= CAN_ERR_PROT;
1789
0
            can_error_payload[2] = CAN_ERR_PROT_FORM;
1790
0
            break;
1791
0
        case TTL_CAN_ERROR_ACK_ERROR:
1792
0
            can_id |= CAN_ERR_ACK;
1793
0
            break;
1794
0
        case TTL_CAN_ERROR_BIT1_ERROR:
1795
0
            can_id |= CAN_ERR_PROT;
1796
0
            can_error_payload[2] = CAN_ERR_PROT_BIT1;
1797
0
            break;
1798
0
        case TTL_CAN_ERROR_BIT0_ERROR:
1799
0
            can_id |= CAN_ERR_PROT;
1800
0
            can_error_payload[2] = CAN_ERR_PROT_BIT0;
1801
0
            break;
1802
0
        case TTL_CAN_ERROR_CRC_ERROR:
1803
0
            can_id |= CAN_ERR_PROT;
1804
0
            can_error_payload[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
1805
0
            break;
1806
0
        case TTL_CAN_ERROR_INVALID_DLC:
1807
0
            can_id |= CAN_ERR_PROT;
1808
0
            can_error_payload[3] = CAN_ERR_PROT_LOC_DLC;
1809
0
            break;
1810
0
        }
1811
0
    }
1812
0
    else {
1813
0
        if (status & TTL_CAN_STATUS_RTR_BIT_MASK) can_id |= CAN_RTR_FLAG;
1814
0
        if (status & TTL_CAN_STATUS_IDE_BIT_MASK) can_id |= CAN_EFF_FLAG;
1815
0
        if (status & TTL_CAN_STATUS_EDL_BIT_MASK) {
1816
0
            canfd_flags |= CANFD_FDF;
1817
0
            len = canfd_dlc_to_length[dlc];
1818
0
        }
1819
0
        else {
1820
0
            len = MIN(dlc, 8);
1821
0
        }
1822
0
        if (status & TTL_CAN_STATUS_BRS_BIT_MASK) canfd_flags |= CANFD_BRS;
1823
0
        if (status & TTL_CAN_STATUS_ESI_BIT_MASK) canfd_flags |= CANFD_ESI;
1824
0
    }
1825
1826
0
    phtonu32(&can_header[0], can_id);
1827
0
    phtonu8(&can_header[4], len);
1828
0
    phtonu8(&can_header[5], canfd_flags);
1829
0
    phtonu8(&can_header[6], 0);
1830
0
    phtonu8(&can_header[7], 0);
1831
1832
0
    ws_buffer_append(&rec->data, can_header, sizeof(can_header));
1833
1834
0
    if (error_code) {
1835
0
        ws_buffer_append(&rec->data, can_error_payload, sizeof(can_error_payload));
1836
0
        if (size != 0 && !ttl_skip_bytes(in, size, err, err_info)) {
1837
0
            return TTL_ERROR;
1838
0
        }
1839
0
        ttl_init_rec(rec, timestamp, addr, item->pkt_encap, item->interface_id,
1840
0
                     sizeof(can_header) + sizeof(can_error_payload), sizeof(can_header) + sizeof(can_error_payload));
1841
0
    }
1842
0
    else {
1843
0
        if (size != 0 && !ttl_read_bytes_buffer(in, &rec->data, size, err, err_info)) {
1844
0
            return TTL_ERROR;
1845
0
        }
1846
0
        ttl_init_rec(rec, timestamp, addr, item->pkt_encap, item->interface_id, size + sizeof(can_header), len + sizeof(can_header));
1847
0
    }
1848
1849
0
    ttl_add_can_dir_option(rec);
1850
1851
0
    return TTL_NO_ERROR;
1852
0
}
1853
1854
static void
1855
0
ttl_add_lin_dir_option(wtap_rec* rec) {
1856
0
    uint32_t opt = PACK_FLAGS_DIRECTION_INBOUND;    /* For the moment, we only support this */
1857
1858
0
    wtap_block_add_uint32_option(rec->block, OPT_EPB_FLAGS, opt);
1859
0
}
1860
1861
static ttl_result_t
1862
ttl_read_lin_data_entry(wtap_rec* rec, int* err, char** err_info, ttl_read_t* in, uint16_t size, uint16_t addr,
1863
0
                        const ttl_addr_to_iface_entry_t* item, uint16_t status, uint64_t timestamp) {
1864
0
    uint8_t     lin_header[8], lin_payload[8];
1865
0
    uint8_t     dlc;
1866
1867
0
    if (item == NULL) {
1868
0
        *err = WTAP_ERR_INTERNAL;
1869
0
        *err_info = ws_strdup("ttl_read_lin_data_entry called with NULL item");
1870
0
        return TTL_ERROR;
1871
0
    }
1872
1873
0
    dlc = size != 0 ? MIN((size - 1), 8) : 0;
1874
1875
0
    lin_header[0] = 1; /* message format rev = 1 */
1876
0
    lin_header[1] = 0; /* reserved */
1877
0
    lin_header[2] = 0; /* reserved */
1878
0
    lin_header[3] = 0; /* reserved */
1879
0
    lin_header[4] = dlc << 4;   /* dlc (4bit) | type (2bit) | checksum type (2bit) */
1880
0
    lin_header[5] = status & TTL_LIN_STATUS_PID_MASK;  /* parity (2bit) | id (6bit) */
1881
0
    lin_header[6] = 0; /* checksum */
1882
0
    lin_header[7] = 0; /* errors */
1883
1884
0
    if (status & TTL_LIN_ERROR_PARITY_ERROR) lin_header[7] |= 0x04;
1885
0
    if (status & TTL_LIN_ERROR_SYNC_ERROR) lin_header[7] |= 0x02;  /* Is this correct? */
1886
0
    if (status & TTL_LIN_ERROR_NO_DATA_ERROR) lin_header[7] |= 0x01;
1887
0
    if (status & TTL_LIN_ERROR_ABORT_ERROR) lin_header[7] |= 0x02; /* Is this correct? */
1888
    /* Set the checksum error if the checksum is wrong with respect to both types */
1889
0
    if ((status & TTL_LIN_ERROR_ANY_CHECKSUM) == TTL_LIN_ERROR_ANY_CHECKSUM) lin_header[7] |= 0x08;
1890
1891
0
    if (dlc != 0) {
1892
0
        if (!ttl_read_bytes(in, &lin_payload[0], dlc, err, err_info)) {
1893
0
            return TTL_ERROR;
1894
0
        }
1895
0
        size -= dlc;
1896
0
    }
1897
1898
0
    if (size != 0) {
1899
0
        if (!ttl_read_bytes(in, &lin_header[6], 1, err, err_info)) {
1900
0
            return TTL_ERROR;
1901
0
        }
1902
0
        size -= 1;
1903
0
    }
1904
1905
0
    if (size != 0) {    /* Skip any extra byte */
1906
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
1907
0
            return TTL_ERROR;
1908
0
        }
1909
0
    }
1910
1911
0
    ws_buffer_append(&rec->data, lin_header, sizeof(lin_header));
1912
1913
0
    if (dlc != 0) {
1914
0
        ws_buffer_append(&rec->data, lin_payload, dlc);
1915
0
    }
1916
1917
0
    ttl_init_rec(rec, timestamp, addr, item->pkt_encap, item->interface_id, dlc + sizeof(lin_header), dlc + sizeof(lin_header));
1918
0
    ttl_add_lin_dir_option(rec);
1919
1920
0
    return TTL_NO_ERROR;
1921
0
}
1922
1923
static void
1924
0
ttl_add_flexray_dir_option(wtap_rec* rec) {
1925
0
    uint32_t opt = PACK_FLAGS_DIRECTION_INBOUND;    /* For the moment, we only support this */
1926
1927
0
    wtap_block_add_uint32_option(rec->block, OPT_EPB_FLAGS, opt);
1928
0
}
1929
1930
static ttl_result_t
1931
ttl_read_flexray_data_entry(wtap_rec* rec, int* err, char** err_info, ttl_read_t* in, uint16_t size, uint16_t addr,
1932
0
                            const ttl_addr_to_iface_entry_t* item, uint16_t status, uint64_t timestamp) {
1933
0
    uint8_t     fr_item;
1934
0
    uint8_t     fr_header[2];
1935
1936
0
    if (item == NULL) {
1937
0
        *err = WTAP_ERR_INTERNAL;
1938
0
        *err_info = ws_strdup("ttl_read_flexray_data_entry called with NULL item");
1939
0
        return TTL_ERROR;
1940
0
    }
1941
1942
0
    fr_item = status & TTL_FLEXRAY_ITEM_MASK;
1943
1944
0
    if (fr_item != TTL_FLEXRAY_ITEM_REGULAR_FRAME && fr_item != TTL_FLEXRAY_ITEM_ABORTED_FRAME) {   /* TODO */
1945
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
1946
0
            return TTL_ERROR;
1947
0
        }
1948
0
        return TTL_UNSUPPORTED;
1949
0
    }
1950
1951
0
    fr_header[0] = FLEXRAY_FRAME;
1952
0
    fr_header[1] = 0;   /* Errors */
1953
1954
0
    if (item->channelB) fr_header[0] |= 0x80;
1955
1956
0
    if (status & (TTL_FLEXRAY_FSS_ERROR_MASK | TTL_FLEXRAY_BSS_ERROR_MASK)) fr_header[1] |= 0x02;
1957
0
    if (status & TTL_FLEXRAY_FES_ERROR_MASK) fr_header[1] |= 0x04;
1958
0
    if (status & TTL_FLEXRAY_FRAME_CRC_ERROR_MASK) fr_header[1] |= 0x10;
1959
0
    if (status & TTL_FLEXRAY_HEADER_CRC_ERROR_MASK) fr_header[1] |= 0x08;
1960
1961
0
    ws_buffer_append(&rec->data, fr_header, sizeof(fr_header));
1962
1963
0
    if (size != 0 && !ttl_read_bytes_buffer(in, &rec->data, size, err, err_info)) {
1964
0
        return TTL_ERROR;
1965
0
    }
1966
1967
0
    ttl_init_rec(rec, timestamp, addr, item->pkt_encap, item->interface_id, size + sizeof(fr_header), size + sizeof(fr_header));
1968
0
    ttl_add_flexray_dir_option(rec);
1969
1970
0
    return TTL_NO_ERROR;
1971
0
}
1972
1973
static ttl_result_t
1974
0
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) {
1975
0
    const ttl_addr_to_iface_entry_t* item;
1976
0
    int         pkt_encap = ttl_get_address_iface_type(src);
1977
0
    uint64_t    timestamp;
1978
1979
0
    if (pkt_encap <= WTAP_ENCAP_UNKNOWN) {
1980
0
        ws_debug("ttl_read_data_entry: Unsupported source address found in TTL_BUS_DATA_ENTRY: 0x%X", src);
1981
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
1982
0
            return TTL_ERROR;
1983
0
        }
1984
0
        return TTL_UNSUPPORTED;
1985
0
    }
1986
1987
0
    *err = 0;
1988
0
    item = ttl_lookup_interface(wth, src, err, err_info);
1989
0
    if (*err) {
1990
0
        return TTL_ERROR;
1991
0
    }
1992
1993
0
    if (size < sizeof(uint64_t)) {
1994
0
        return TTL_CORRUPTED;
1995
0
    }
1996
0
    if (!ttl_read_bytes(in, &timestamp, sizeof(uint64_t), err, err_info)) {
1997
0
        return TTL_ERROR;
1998
0
    }
1999
0
    timestamp = GUINT64_FROM_LE(timestamp);
2000
0
    size -= sizeof(uint64_t);
2001
2002
0
    switch (pkt_encap) {
2003
0
    case WTAP_ENCAP_ETHERNET:
2004
0
        return ttl_read_eth_data_entry(rec, err, err_info, in, size, src, item, status, timestamp);
2005
0
    case WTAP_ENCAP_SOCKETCAN:
2006
0
        return ttl_read_can_data_entry(rec, err, err_info, in, size, src, item, status, timestamp);
2007
0
    case WTAP_ENCAP_LIN:
2008
0
        return ttl_read_lin_data_entry(rec, err, err_info, in, size, src, item, status, timestamp);
2009
0
    case WTAP_ENCAP_FLEXRAY:
2010
0
        return ttl_read_flexray_data_entry(rec, err, err_info, in, size, src, item, status, timestamp);
2011
0
    default:
2012
0
        ws_debug("ttl_read_data_entry: Unsupported packet type found in TTL_BUS_DATA_ENTRY: %d", pkt_encap);
2013
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
2014
0
            return TTL_ERROR;
2015
0
        }
2016
0
        return TTL_UNSUPPORTED;
2017
0
    }
2018
2019
0
}
2020
2021
static bool
2022
0
ttl_check_segmented_message_recursion(const ttl_read_t* in, int* err, char** err_info) {
2023
0
    ttl_entryheader_t header;
2024
2025
0
    if (in->validity != VALIDITY_BUF) {
2026
0
        *err = WTAP_ERR_INTERNAL;
2027
0
        *err_info = ws_strdup("tt_fix_segmented_message_entry_payload: input buffer is not valid");
2028
0
        return false;
2029
0
    }
2030
2031
0
    memcpy(&header, in->buf + in->cur_pos, sizeof(ttl_entryheader_t));
2032
0
    fix_endianness_ttl_entryheader(&header);
2033
2034
0
    if ((header.size_type >> 12) == TTL_SEGMENTED_MESSAGE_ENTRY) {
2035
0
        return false;
2036
0
    }
2037
2038
0
    return true;
2039
0
}
2040
2041
/*
2042
 * For some reason, the timestamp of the nested frame is garbage.
2043
 * Copy the timestamp of the first segment in its place.
2044
 */
2045
static bool
2046
0
ttl_fix_segmented_message_entry_timestamp(const ttl_read_t* in, uint64_t timestamp, int* err, char** err_info) {
2047
0
    ttl_entryheader_t header;
2048
2049
0
    if (in->validity != VALIDITY_BUF) {
2050
0
        *err = WTAP_ERR_INTERNAL;
2051
0
        *err_info = ws_strdup("tt_fix_segmented_message_entry_payload: input buffer is not valid");
2052
0
        return false;
2053
0
    }
2054
2055
0
    memcpy(&header, in->buf + in->cur_pos, sizeof(ttl_entryheader_t));
2056
0
    fix_endianness_ttl_entryheader(&header);
2057
2058
0
    if ((header.size_type >> 12) == TTL_BUS_DATA_ENTRY) {
2059
0
        timestamp = GUINT64_TO_LE(timestamp);
2060
0
        memcpy(in->buf + in->cur_pos + sizeof(ttl_entryheader_t), &timestamp, sizeof(uint64_t));
2061
0
    }
2062
2063
0
    return true;
2064
0
}
2065
2066
// NOLINTNEXTLINE(misc-no-recursion)
2067
static ttl_result_t ttl_read_segmented_message_entry(wtap* wth, wtap_rec* rec, int* err, char** err_info, ttl_read_t* in,
2068
0
                                                     uint16_t size, uint16_t src, uint16_t status, int64_t offset) {
2069
0
    ttl_segmented_entry_t* item;
2070
0
    ttl_reassembled_entry_t* reassembled_item;
2071
0
    ttl_t*      ttl = (ttl_t*)wth->priv;
2072
0
    uint64_t    timestamp;
2073
0
    uint8_t     frame_num = status & 0x000f;
2074
0
    uint8_t     seg_frame_id = (status >> 4) & 0x000f;
2075
0
    uint32_t    key = ((uint32_t)seg_frame_id << 16) | src;
2076
0
    ttl_read_t  new_in;
2077
2078
0
    if (status == 0xFFFF) { /* Reserved for future use */
2079
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
2080
0
            return TTL_ERROR;
2081
0
        }
2082
0
        return TTL_UNSUPPORTED;
2083
0
    }
2084
2085
0
    reassembled_item = g_hash_table_lookup(ttl->reassembled_frames_ht, &offset);
2086
2087
0
    if (reassembled_item == NULL) {
2088
0
        if (size < sizeof(uint64_t)) {
2089
0
            return TTL_CORRUPTED;
2090
0
        }
2091
0
        if (!ttl_read_bytes(in, &timestamp, sizeof(uint64_t), err, err_info)) {
2092
0
            return TTL_ERROR;
2093
0
        }
2094
0
        timestamp = GUINT64_FROM_LE(timestamp);
2095
0
        size -= sizeof(uint64_t);
2096
2097
0
        item = g_hash_table_lookup(ttl->segmented_frames_ht, GUINT_TO_POINTER(key));
2098
2099
0
        if (frame_num == 0) {   /* This is the first segment */
2100
0
            if (item != NULL) { /* New header with reassemble in progress */
2101
0
                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);
2102
0
                g_hash_table_remove(ttl->segmented_frames_ht, GUINT_TO_POINTER(key));
2103
0
            }
2104
2105
0
            if (size < (2 * sizeof(uint32_t))) {    /* Size and type below */
2106
0
                return TTL_CORRUPTED;
2107
0
            }
2108
2109
0
            item = (ttl_segmented_entry_t*)g_new0(ttl_segmented_entry_t, 1);
2110
0
            item->timestamp = timestamp;
2111
2112
0
            if (!ttl_read_bytes(in, &item->size, sizeof(uint32_t), err, err_info)) {
2113
0
                g_free(item);
2114
0
                return TTL_ERROR;
2115
0
            }
2116
0
            item->size = GUINT32_FROM_LE(item->size);
2117
0
            size -= sizeof(uint32_t);
2118
2119
0
            if (!ttl_read_bytes(in, &item->type, sizeof(uint32_t), err, err_info)) {
2120
0
                g_free(item);
2121
0
                return TTL_ERROR;
2122
0
            }
2123
0
            item->type = GUINT32_FROM_LE(item->type);
2124
0
            size -= sizeof(uint32_t);
2125
2126
            /* If the reassembled size is too big, we go on as usual, but without a buffer.
2127
             * This way we avoid problems with segments later.
2128
             */
2129
0
            if (item->size <= WTAP_MAX_PACKET_SIZE_STANDARD) {
2130
0
                item->buf = g_try_malloc(item->size);
2131
0
                if (item->buf == NULL) {
2132
0
                    g_free(item);
2133
0
                    *err = WTAP_ERR_INTERNAL;
2134
0
                    *err_info = ws_strdup("ttl_read_segmented_message_entry: cannot allocate memory");
2135
0
                    return TTL_ERROR;
2136
0
                }
2137
0
            }
2138
2139
0
            g_hash_table_insert(ttl->segmented_frames_ht, GUINT_TO_POINTER(key), item);
2140
0
        }
2141
0
        else {
2142
0
            if (item == NULL) {
2143
0
                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);
2144
0
                if (!ttl_skip_bytes(in, size, err, err_info)) {
2145
0
                    return TTL_ERROR;
2146
0
                }
2147
0
                return TTL_UNSUPPORTED;
2148
0
            }
2149
2150
0
            if (item->next_segment != frame_num) {
2151
0
                ws_debug("ttl_read_segmented_message_entry: Found out of order segment (expected %d, found %d) for SRC %d, FRAME ID %d",
2152
0
                    item->next_segment, frame_num, src, seg_frame_id);
2153
0
                if (!ttl_skip_bytes(in, size, err, err_info)) {
2154
0
                    return TTL_ERROR;
2155
0
                }
2156
0
                return TTL_UNSUPPORTED;
2157
0
            }
2158
0
        }
2159
2160
0
        if ((item->size_so_far + size) > item->size) {
2161
0
            g_hash_table_remove(ttl->segmented_frames_ht, GUINT_TO_POINTER(key));
2162
0
            return TTL_CORRUPTED;
2163
0
        }
2164
2165
0
        void* dest_buf = item->buf != NULL ? item->buf + item->size_so_far : NULL;
2166
0
        if (!ttl_read_bytes(in, dest_buf, size, err, err_info)) {
2167
0
            g_hash_table_remove(ttl->segmented_frames_ht, GUINT_TO_POINTER(key));
2168
0
            return TTL_ERROR;
2169
0
        }
2170
0
        item->size_so_far += size;
2171
0
        item->next_segment++;
2172
2173
0
        if (item->size_so_far >= item->size) {  /* Reassemble complete */
2174
0
            if (item->buf == NULL) {
2175
                /* Silently discard packets we reassembled without data */
2176
0
                g_hash_table_remove(ttl->segmented_frames_ht, GUINT_TO_POINTER(key));
2177
0
                return TTL_UNSUPPORTED;
2178
0
            }
2179
2180
0
            if (item->type != TTL_SEGMENTED_MESSAGE_ENTRY_TYPE_NESTED_FRAME) {
2181
0
                ws_debug("ttl_read_segmented_message_entry: Unsupported type found: %d", item->type);
2182
0
                g_hash_table_remove(ttl->segmented_frames_ht, GUINT_TO_POINTER(key));
2183
0
                return TTL_UNSUPPORTED;
2184
0
            }
2185
2186
0
            reassembled_item = (ttl_reassembled_entry_t*)g_new(ttl_reassembled_entry_t, 1);
2187
0
            reassembled_item->timestamp = item->timestamp;
2188
0
            reassembled_item->size = item->size;
2189
0
            reassembled_item->buf = item->buf;
2190
2191
0
            item->buf = NULL;   /* Dereference it so that it doesn't get destroyed */
2192
0
            g_hash_table_remove(ttl->segmented_frames_ht, GUINT_TO_POINTER(key));
2193
0
            int64_t* new_off = g_new(int64_t, 1);
2194
0
            *new_off = offset;
2195
0
            g_hash_table_insert(ttl->reassembled_frames_ht, new_off, reassembled_item);
2196
0
        }
2197
0
        else {  /* Reassemble not complete, wait for the rest */
2198
0
            return TTL_UNSUPPORTED;
2199
0
        }
2200
0
    }
2201
0
    else {
2202
        /* We already have the reassembled item, maybe we're re-visiting this entry. Simply skip to the end. */
2203
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
2204
0
            return TTL_ERROR;
2205
0
        }
2206
0
    }
2207
2208
    /* If we're here, we have our reassembled entry */
2209
0
    new_in.buf = reassembled_item->buf;
2210
0
    new_in.size = reassembled_item->size;
2211
0
    new_in.cur_pos = 0;
2212
0
    new_in.validity = VALIDITY_BUF;
2213
2214
    /* Avoid recursion by not supporting nested segmented entries */
2215
0
    *err = 0;
2216
0
    if (!ttl_check_segmented_message_recursion(&new_in, err, err_info)) {
2217
0
        g_hash_table_remove(ttl->reassembled_frames_ht, &offset);
2218
2219
0
        if (*err) {
2220
0
            return TTL_ERROR;
2221
0
        }
2222
0
        return TTL_UNSUPPORTED;
2223
0
    }
2224
2225
0
    if (!ttl_fix_segmented_message_entry_timestamp(&new_in, reassembled_item->timestamp, err, err_info)) {
2226
0
        g_hash_table_remove(ttl->reassembled_frames_ht, &offset);
2227
0
        return TTL_ERROR;
2228
0
    }
2229
2230
    /* Read it as if it was a normal entry, but passing the buffer
2231
     * as input instead of the file handler.
2232
     */
2233
0
    return ttl_read_entry(wth, rec, err, err_info, &new_in, 0, new_in.size);
2234
0
}
2235
2236
static ttl_result_t
2237
0
ttl_read_padding_entry(int* err, char** err_info, ttl_read_t* in, uint16_t size) {
2238
0
    if (!ttl_skip_bytes(in, size, err, err_info)) {
2239
0
        return TTL_ERROR;
2240
0
    }
2241
0
    return TTL_UNSUPPORTED;
2242
0
}
2243
2244
// NOLINTNEXTLINE(misc-no-recursion)
2245
0
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) {
2246
0
    ttl_entryheader_t header;
2247
0
    uint16_t    size;
2248
0
    uint16_t    src_addr;
2249
0
    uint8_t     type;
2250
2251
0
    if ((end - offset) < (int64_t)sizeof(ttl_entryheader_t)) {
2252
        /*
2253
         * We probably have a corrupted file, try to recover our alignment
2254
         * by skipping to the next block.
2255
         */
2256
0
        return TTL_CORRUPTED;
2257
0
    }
2258
2259
    /* Try to read the (next) entry header */
2260
0
    if (!ttl_read_bytes(in, &header, sizeof(ttl_entryheader_t), err, err_info)) {
2261
0
        return TTL_ERROR;
2262
0
    }
2263
0
    fix_endianness_ttl_entryheader(&header);
2264
2265
0
    type = header.size_type >> 12;
2266
0
    size = header.size_type & TTL_SIZE_MASK;
2267
0
    src_addr = header.src_addr & TTL_ADDRESS_MASK;
2268
2269
0
    if (size < sizeof(ttl_entryheader_t) || size > (end - offset)) {
2270
        /*
2271
         * Hope the file is simply unaligned and skipping to the next block
2272
         * will fix everything. This could also be the sign of a malformed
2273
         * file; in that case, this error will repeat itself many times.
2274
         */
2275
0
        return TTL_CORRUPTED;
2276
0
    }
2277
2278
0
    size -= sizeof(ttl_entryheader_t);
2279
2280
0
    if (header.dest_addr & TTL_META1_COMPRESSED_FORMAT_MASK) {
2281
        /* We do not support this kind of entries yet. */
2282
0
        ws_debug("ttl_read_entry: Skipping entry with compressed timestamp");
2283
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
2284
0
            return TTL_ERROR;
2285
0
        }
2286
0
        return TTL_UNSUPPORTED;
2287
0
    }
2288
2289
0
    switch (type) {
2290
0
    case TTL_BUS_DATA_ENTRY:
2291
0
        return ttl_read_data_entry(wth, rec, err, err_info, in, size, src_addr, header.status_info);
2292
0
    case TTL_SEGMENTED_MESSAGE_ENTRY:
2293
        /* Recursion is avoided inside ttl_read_segmented_message_entry() */
2294
0
        return ttl_read_segmented_message_entry(wth, rec, err, err_info, in, size, src_addr, header.status_info, offset);
2295
0
    case TTL_PADDING_ENTRY:
2296
0
        return ttl_read_padding_entry(err, err_info, in, size);
2297
0
    default:
2298
0
        ws_debug("ttl_read_entry: Unknown Entry type: %u", type);
2299
0
        if (!ttl_skip_bytes(in, size, err, err_info)) {
2300
0
            return TTL_ERROR;
2301
0
        }
2302
0
        return TTL_UNSUPPORTED;
2303
0
    }
2304
2305
0
}
2306
2307
static bool
2308
0
ttl_xml_node_get_number(xmlNodePtr node, xmlXPathContextPtr ctx, double *ret) {
2309
0
    xmlXPathObjectPtr result;
2310
0
    double val;
2311
2312
0
    if (ret == NULL) {
2313
0
        return false;
2314
0
    }
2315
2316
0
    result = xmlXPathNodeEval(node, (const xmlChar*)"./Number[1]/text()", ctx);
2317
0
    if (result && result->type == XPATH_NODESET && !xmlXPathNodeSetIsEmpty(result->nodesetval)) {
2318
0
        val = xmlXPathCastToNumber(result);
2319
0
        if (!xmlXPathIsNaN(val)) {
2320
0
            *ret = val;
2321
0
            xmlXPathFreeObject(result);
2322
0
            return true;
2323
0
        }
2324
0
    }
2325
2326
0
    xmlXPathFreeObject(result);
2327
0
    return false;
2328
0
}
2329
2330
static bool
2331
0
ttl_xml_node_get_string(xmlNodePtr node, xmlXPathContextPtr ctx, const char* name, char** ret) {
2332
0
    xmlXPathObjectPtr result;
2333
0
    char* str;
2334
2335
0
    if (name == NULL || ret == NULL) {
2336
0
        return false;
2337
0
    }
2338
2339
0
    str = ws_strdup_printf("./%s[1]/text()", name);
2340
2341
0
    result = xmlXPathNodeEval(node, (const xmlChar*)str, ctx);
2342
0
    g_free(str);
2343
0
    if (result && result->type == XPATH_NODESET && !xmlXPathNodeSetIsEmpty(result->nodesetval)) {
2344
0
        str = (char*)xmlXPathCastToString(result);
2345
0
        xmlXPathFreeObject(result);
2346
0
        *ret = ws_strdup(str);
2347
0
        xmlFree(str);
2348
0
        return true;
2349
0
    }
2350
2351
0
    xmlXPathFreeObject(result);
2352
0
    return false;
2353
0
}
2354
2355
static bool
2356
0
ttl_process_xml_config(ttl_t* ttl, const char* text, int size) {
2357
0
    xmlDocPtr           doc;
2358
0
    xmlXPathContextPtr  ctx;
2359
0
    xmlXPathObjectPtr   cascades, devices, functions;
2360
0
    int         i, j, k;
2361
0
    double      val;
2362
0
    uint16_t    cascade, device, function, addr;
2363
0
    char*       user_defined_name = NULL;
2364
2365
0
    doc = xmlParseMemory(text, size);
2366
0
    if (doc == NULL) {
2367
0
        return false;
2368
0
    }
2369
2370
0
    if (xmlDocGetRootElement(doc) == NULL) {
2371
0
        xmlFreeDoc(doc);
2372
0
        return false;   /* Empty XML */
2373
0
    }
2374
2375
0
    ctx = xmlXPathNewContext(doc);
2376
0
    cascades = xmlXPathEvalExpression((const xmlChar*)"/LoggerConfiguration/HWList/Cascades/Cascade", ctx);
2377
0
    if (cascades && cascades->type == XPATH_NODESET && !xmlXPathNodeSetIsEmpty(cascades->nodesetval)) {
2378
0
        for (i = 0; i < cascades->nodesetval->nodeNr; i++) {
2379
0
            if (ttl_xml_node_get_number(cascades->nodesetval->nodeTab[i], ctx, &val) && val >= 0 && val <= 7) {
2380
0
                cascade = (uint16_t)val;
2381
0
                if (val == 0) { /* Only the configuration of the logger is inside the TTL file. The TAPs have their own configuration */
2382
2383
0
                    devices = xmlXPathNodeEval(cascades->nodesetval->nodeTab[i], (const xmlChar*)"./Devices/Device", ctx);
2384
0
                    if (devices && devices->type == XPATH_NODESET && !xmlXPathNodeSetIsEmpty(devices->nodesetval)) {
2385
0
                        for (j = 0; j < devices->nodesetval->nodeNr; j++) {
2386
0
                            if (ttl_xml_node_get_number(devices->nodesetval->nodeTab[j], ctx, &val) && val >= 0 && val <= 15) {
2387
0
                                device = (uint16_t)val;
2388
2389
0
                                functions = xmlXPathNodeEval(devices->nodesetval->nodeTab[j], (const xmlChar*)"./Functions/Function", ctx);
2390
0
                                if (functions && functions->type == XPATH_NODESET && !xmlXPathNodeSetIsEmpty(functions->nodesetval)) {
2391
0
                                    for (k = 0; k < functions->nodesetval->nodeNr; k++) {
2392
0
                                        if (ttl_xml_node_get_number(functions->nodesetval->nodeTab[k], ctx, &val) && val >= 0 && val <= 63) {
2393
0
                                            function = (uint16_t)val;
2394
0
                                            addr = cascade << 10 | device << 6 | function;
2395
2396
0
                                            if (g_hash_table_lookup(ttl->address_to_name_ht, GUINT_TO_POINTER(addr)) == NULL) {
2397
                                                /* Get the name only if we don't already have it */
2398
0
                                                if (ttl_xml_node_get_string(functions->nodesetval->nodeTab[k], ctx, "UserDefinedName", &user_defined_name)) {
2399
0
                                                    g_hash_table_insert(ttl->address_to_name_ht, GUINT_TO_POINTER(addr), user_defined_name);
2400
                                                    /* XXX - At this point, we should check if the interface (in case of Ethernet)
2401
                                                     * is a standalone interface or it's a coupled interface. Since getting this
2402
                                                     * information from the XML is a pain, and the configuration will never be
2403
                                                     * exhaustive, give up and rely on the user setting the mapping themself.
2404
                                                     */
2405
0
                                                }
2406
0
                                            }
2407
2408
0
                                        }
2409
0
                                    }
2410
0
                                }
2411
0
                                xmlXPathFreeObject(functions);
2412
0
                            }
2413
0
                        }
2414
0
                    }
2415
0
                    xmlXPathFreeObject(devices);
2416
0
                }
2417
0
            }
2418
0
        }
2419
0
    }
2420
0
    xmlXPathFreeObject(cascades);
2421
2422
0
    xmlXPathFreeContext(ctx);
2423
0
    xmlFreeDoc(doc);
2424
0
    return true;
2425
0
}
2426
2427
/* Maximum supported line length of preference files */
2428
#define MAX_LINELEN     1024
2429
2430
/** Read a line without trailing (CR)LF. Returns -1 on failure.  */
2431
static int
2432
fgetline(char* buf, int size, FILE* fp)
2433
0
{
2434
0
    if (fgets(buf, size, fp)) {
2435
0
        int len = (int)strcspn(buf, "\r\n");
2436
0
        buf[len] = '\0';
2437
0
        return len;
2438
0
    }
2439
0
    return -1;
2440
2441
0
} /* fgetline */
2442
2443
static bool
2444
0
ttl_is_master_slave_relation_correct(uint16_t master, uint16_t slave) {
2445
0
    uint8_t function = ttl_addr_get_function(master);
2446
2447
0
    if (ttl_addr_get_cascade(master) == 0) {
2448
0
        switch (ttl_addr_get_device(master)) {
2449
0
        case TTL_LOGGER_DEVICE_FPGA:
2450
0
            if (function == TTL_LOGGER_FPGA_FUNCTION_ETHA_CH1) {
2451
0
                return (slave == (master + 1));
2452
0
            }
2453
0
            break;
2454
0
        case TTL_LOGGER_DEVICE_ATOM:
2455
0
            if (function == TTL_LOGGER_ATOM_FUNCTION_ETHA) {
2456
0
                return (slave == (master + 1));
2457
0
            }
2458
0
            break;
2459
0
        case TTL_LOGGER_DEVICE_FPGAB:
2460
0
            switch (function) {
2461
0
            case TTL_LOGGER_FPGAB_FUNCTION_ETHA_CH1:
2462
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH1a_CH1:
2463
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH2a_CH1:
2464
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH3a_CH1:
2465
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH4a_CH1:
2466
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH5a_CH1:
2467
0
            case TTL_LOGGER_FPGAB_FUNCTION_AETH6a_CH1:
2468
0
                return (slave == (master + 1));
2469
0
            default:
2470
0
                break;
2471
0
            }
2472
0
            break;
2473
0
        default:
2474
0
            break;
2475
0
        }
2476
0
    }
2477
0
    else {
2478
0
        switch (ttl_addr_get_device(master)) {
2479
0
        case TTL_TAP_DEVICE_PT15_FPGA:
2480
0
            switch (function) {
2481
0
            case TTL_PT15_FPGA_FUNCTION_BrdR1a:
2482
0
            case TTL_PT15_FPGA_FUNCTION_BrdR2a:
2483
0
            case TTL_PT15_FPGA_FUNCTION_BrdR3a:
2484
0
            case TTL_PT15_FPGA_FUNCTION_BrdR4a:
2485
0
            case TTL_PT15_FPGA_FUNCTION_BrdR5a:
2486
0
            case TTL_PT15_FPGA_FUNCTION_BrdR6a:
2487
0
                return (slave == (master + 1));
2488
0
            default:
2489
0
                break;
2490
0
            }
2491
0
            break;
2492
0
        case TTL_TAP_DEVICE_PT20_FPGA:
2493
0
            switch (function) {
2494
0
            case TTL_PT20_FPGA_FUNCTION_GbEth1a:
2495
0
            case TTL_PT20_FPGA_FUNCTION_GbEth2a:
2496
0
            case TTL_PT20_FPGA_FUNCTION_GbEth3a:
2497
0
                return (slave == (master + 1));
2498
0
            default:
2499
0
                break;
2500
0
            }
2501
0
            break;
2502
0
        case TTL_TAP_DEVICE_PC3_FPGA:
2503
0
            if (function == TTL_PC3_FPGA_FUNCTION_BrdR1a) {
2504
0
                return (slave == (master + 1));
2505
0
            }
2506
0
            break;
2507
0
        default:
2508
0
            break;
2509
0
        }
2510
0
    }
2511
2512
0
    return false;
2513
0
}
2514
2515
static bool
2516
0
ttl_parse_masters_pref_file(ttl_t* ttl, const char* path) {
2517
0
    FILE*       fp;
2518
0
    char        line[MAX_LINELEN];
2519
0
    char*       cp;
2520
0
    uint16_t    addr, tmp;
2521
2522
0
    if (path == NULL) {
2523
0
        return false;
2524
0
    }
2525
2526
0
    fp = ws_fopen(path, "r");
2527
0
    if (fp == NULL) {
2528
0
        return false;
2529
0
    }
2530
2531
0
    while (fgetline(line, sizeof(line), fp) >= 0) {
2532
0
        if ((cp = strchr(line, '#')))
2533
0
            *cp = '\0';
2534
2535
0
        cp = strtok(line, " \t");
2536
0
        if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 7) {
2537
0
            continue;   /* Invalid cascade */
2538
0
        }
2539
0
        addr = tmp << 10;
2540
2541
0
        cp = strtok(NULL, " \t");
2542
0
        if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 15) {
2543
0
            continue;   /* Invalid device */
2544
0
        }
2545
0
        addr |= tmp << 6;
2546
2547
0
        cp = strtok(NULL, " \t");
2548
0
        if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 63) {
2549
0
            continue;   /* Invalid function */
2550
0
        }
2551
0
        addr |= tmp;
2552
2553
0
        cp = strtok(NULL, " \t");
2554
0
        if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 1) {
2555
0
            continue;   /* Invalid flag */
2556
0
        }
2557
2558
0
        if (tmp) {  /* The address is coupled to the master */
2559
0
            if (addr != 0 && ttl_is_master_slave_relation_correct(addr - 1, addr)) {
2560
0
                g_hash_table_insert(ttl->address_to_master_ht, GUINT_TO_POINTER(addr), GUINT_TO_POINTER(addr - 1));
2561
0
            }
2562
0
        }
2563
0
        else {  /* The address is independent from the master */
2564
0
            g_hash_table_insert(ttl->address_to_master_ht, GUINT_TO_POINTER(addr), GUINT_TO_POINTER(addr));
2565
0
        }
2566
0
    }
2567
2568
0
    fclose(fp);
2569
0
    return true;
2570
0
}
2571
2572
/*
2573
 * This function gets the working mode of the Ethernet interfaces from a
2574
 * configuration file. This only applies to the interfaces that can be
2575
 * configured both as the second side of a tap and independent interfaces.
2576
 * The entry format is the following:   Cascade  Device  Function    Flag
2577
 * A flag value of 0 means independent interface, while 1 means coupled with
2578
 * its master. If an entry is not present, the interface will be treated
2579
 * by ttl_lookup_interface() according to the default behaviour (currently,
2580
 * independent interface for the logger and coupled interface for the taps).
2581
 */
2582
static bool
2583
0
ttl_init_masters_from_pref_file(ttl_t* ttl, const char* app_env_var_prefix) {
2584
0
    char*   pref_file;
2585
0
    bool    ret;
2586
2587
0
    pref_file = get_persconffile_path(TTL_ADDRESS_MASTER_PREFS, true, app_env_var_prefix);
2588
0
    ret = ttl_parse_masters_pref_file(ttl, pref_file);
2589
0
    g_free(pref_file);
2590
0
    if (!ret) {
2591
0
        pref_file = get_persconffile_path(TTL_ADDRESS_MASTER_PREFS, false, app_env_var_prefix);
2592
0
        ret = ttl_parse_masters_pref_file(ttl, pref_file);
2593
0
        g_free(pref_file);
2594
0
    }
2595
2596
0
    return ret;
2597
0
}
2598
2599
static bool
2600
0
ttl_parse_names_pref_file(ttl_t* ttl, const char* path) {
2601
0
    FILE*       fp;
2602
0
    char        line[MAX_LINELEN];
2603
0
    char*       cp;
2604
0
    uint16_t    addr, tmp;
2605
0
    char*       name;
2606
2607
0
    if (path == NULL) {
2608
0
        return false;
2609
0
    }
2610
2611
0
    fp = ws_fopen(path, "r");
2612
0
    if (fp == NULL) {
2613
0
        return false;
2614
0
    }
2615
2616
0
    while (fgetline(line, sizeof(line), fp) >= 0) {
2617
0
        if ((cp = strchr(line, '#')))
2618
0
            *cp = '\0';
2619
2620
0
        cp = strtok(line, " \t");
2621
0
        if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 7) {
2622
0
            continue;   /* Invalid cascade */
2623
0
        }
2624
0
        addr = tmp << 10;
2625
2626
0
        cp = strtok(NULL, " \t");
2627
0
        if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 15) {
2628
0
            continue;   /* Invalid device */
2629
0
        }
2630
0
        addr |= tmp << 6;
2631
2632
0
        cp = strtok(NULL, " \t");
2633
0
        if (cp == NULL || !ws_strtou16(cp, NULL, &tmp) || tmp > 63) {
2634
0
            continue;   /* Invalid function */
2635
0
        }
2636
0
        addr |= tmp;
2637
2638
0
        cp = strtok(NULL, " \t");
2639
0
        if (cp != NULL && strlen(cp) != 0) {
2640
0
            name = ws_strdup(cp);
2641
0
            g_hash_table_insert(ttl->address_to_name_ht, GUINT_TO_POINTER(addr), name);
2642
0
        }
2643
0
    }
2644
2645
0
    fclose(fp);
2646
0
    return true;
2647
0
}
2648
2649
/*
2650
 * This function gets the names of the interfaces from a configuration file.
2651
 * The entry format is the following:   Cascade  Device  Function    Name
2652
 * If an entry is not present, the value from the configuration XML in the file
2653
 * is used. If also that is not present, a meaningful name is generated in
2654
 * ttl_add_interface_name() starting from the interface address.
2655
 */
2656
static bool
2657
0
ttl_init_names_from_pref_file(ttl_t* ttl, const char* app_env_var_prefix) {
2658
0
    char*   pref_file;
2659
0
    bool    ret;
2660
2661
0
    pref_file = get_persconffile_path(TTL_ADDRESS_NAME_PREFS, true, app_env_var_prefix);
2662
0
    ret = ttl_parse_names_pref_file(ttl, pref_file);
2663
0
    g_free(pref_file);
2664
0
    if (!ret) {
2665
0
        pref_file = get_persconffile_path(TTL_ADDRESS_NAME_PREFS, false, app_env_var_prefix);
2666
0
        ret = ttl_parse_names_pref_file(ttl, pref_file);
2667
0
        g_free(pref_file);
2668
0
    }
2669
2670
0
    return ret;
2671
0
}
2672
2673
static void
2674
0
ttl_cleanup(ttl_t* ttl) {
2675
0
    if (ttl != NULL) {
2676
0
        if (ttl->address_to_iface_ht != NULL) {
2677
0
            g_hash_table_destroy(ttl->address_to_iface_ht);
2678
0
        }
2679
0
        if (ttl->address_to_master_ht != NULL) {
2680
0
            g_hash_table_destroy(ttl->address_to_master_ht);
2681
0
        }
2682
0
        if (ttl->address_to_name_ht != NULL) {
2683
0
            g_hash_table_destroy(ttl->address_to_name_ht);
2684
0
        }
2685
0
        if (ttl->segmented_frames_ht != NULL) {
2686
0
            g_hash_table_destroy(ttl->segmented_frames_ht);
2687
0
        }
2688
0
        if (ttl->reassembled_frames_ht != NULL) {
2689
0
            g_hash_table_destroy(ttl->reassembled_frames_ht);
2690
0
        }
2691
0
        g_free(ttl);
2692
0
    }
2693
0
}
2694
2695
wtap_open_return_val
2696
0
ttl_open(wtap* wth, int* err, char** err_info) {
2697
0
    ttl_fileheader_t    header;
2698
0
    ttl_t*              ttl;
2699
0
    unsigned int        offset;
2700
2701
0
    ws_debug("opening file");
2702
2703
0
    if (!wtap_read_bytes_or_eof(wth->fh, &header, sizeof(ttl_fileheader_t), err, err_info)) {
2704
2705
0
        ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err);
2706
0
        if (*err == 0 || *err == WTAP_ERR_SHORT_READ) {
2707
            /*
2708
             * Short read or EOF.
2709
             *
2710
             * We're reading this as part of an open, so
2711
             * the file is too short to be a ttl file.
2712
             */
2713
0
            *err = 0;
2714
0
            g_free(*err_info);
2715
0
            *err_info = NULL;
2716
0
            return WTAP_OPEN_NOT_MINE;
2717
0
        }
2718
0
        return WTAP_OPEN_ERROR;
2719
0
    }
2720
2721
0
    fix_endianness_ttl_fileheader(&header);
2722
2723
0
    if (memcmp(header.magic, ttl_magic, sizeof(ttl_magic))) {
2724
0
        return WTAP_OPEN_NOT_MINE;
2725
0
    }
2726
    /* This seems to be a TLL! */
2727
2728
    /* Check for valid block size */
2729
0
    if (header.block_size == 0) {
2730
0
        *err = WTAP_ERR_BAD_FILE;
2731
0
        *err_info = ws_strdup("ttl: block size cannot be 0");
2732
0
        return WTAP_OPEN_ERROR;
2733
0
    }
2734
    /* Check for a valid header length */
2735
0
    if (header.header_size < sizeof(ttl_fileheader_t)) {
2736
0
        *err = WTAP_ERR_BAD_FILE;
2737
0
        *err_info = ws_strdup("ttl: file header length too short");
2738
0
        return WTAP_OPEN_ERROR;
2739
0
    }
2740
2741
0
    offset = (unsigned int)sizeof(ttl_fileheader_t);
2742
2743
    /* Prepare our private context. */
2744
0
    ttl = g_new(ttl_t, 1);
2745
0
    ttl->next_interface_id = 0;
2746
0
    ttl->block_size = header.block_size;
2747
0
    ttl->header_size = header.header_size;
2748
0
    ttl->address_to_iface_ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
2749
0
    ttl->address_to_master_ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
2750
0
    ttl->address_to_name_ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
2751
0
    ttl->segmented_frames_ht = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, ttl_free_segmented_entry);
2752
0
    ttl->reassembled_frames_ht = g_hash_table_new_full(g_int64_hash, g_int64_equal, g_free, ttl_free_reassembled_entry);
2753
2754
0
    if (header.version >= 10) {
2755
0
        if (header.header_size < (offset + TTL_LOGFILE_INFO_SIZE)) {
2756
0
            report_warning("Found TTL file version %u with shorter header length than expected.", header.version);
2757
0
        }
2758
0
        else {
2759
            /* TODO: Extract needed info from the rest of the header. */
2760
0
            if (!wtap_read_bytes(wth->fh, NULL, TTL_LOGFILE_INFO_SIZE, err, err_info)) {
2761
0
                ttl_cleanup(ttl);
2762
0
                return WTAP_OPEN_ERROR;
2763
0
            }
2764
0
            offset += TTL_LOGFILE_INFO_SIZE;
2765
0
            unsigned int xml_len = header.header_size - offset;
2766
0
            if (xml_len != 0) {
2767
0
                char* xml = g_try_malloc(xml_len);
2768
0
                if (xml == NULL) {
2769
0
                    *err = WTAP_ERR_INTERNAL;
2770
0
                    *err_info = ws_strdup("ttl: cannot allocate memory");
2771
0
                    ttl_cleanup(ttl);
2772
0
                    return false;
2773
0
                }
2774
0
                if (!wtap_read_bytes(wth->fh, xml, xml_len, err, err_info)) {
2775
0
                    g_free(xml);
2776
0
                    ttl_cleanup(ttl);
2777
0
                    return WTAP_OPEN_ERROR;
2778
0
                }
2779
0
                if (!ttl_process_xml_config(ttl, xml, xml_len)) {
2780
0
                    report_warning("Cannot extract information from TTL XML.");
2781
0
                }
2782
0
                g_free(xml);
2783
0
                offset += xml_len;
2784
0
            }
2785
0
        }
2786
0
    }
2787
2788
0
    if ((header.header_size - offset) != 0) {
2789
0
        if (!wtap_read_bytes(wth->fh, NULL, header.header_size - offset, err, err_info)) {
2790
0
            ttl_cleanup(ttl);
2791
0
            return WTAP_OPEN_ERROR;
2792
0
        }
2793
0
    }
2794
2795
0
    ttl_init_masters_from_pref_file(ttl, wth->app_env_var_prefix);
2796
0
    ttl_init_names_from_pref_file(ttl, wth->app_env_var_prefix);
2797
2798
0
    wth->priv = (void*)ttl;
2799
0
    wth->file_encap = WTAP_ENCAP_NONE;
2800
0
    wth->snapshot_length = 0;
2801
0
    wth->file_tsprec = WTAP_TSPREC_UNKNOWN;
2802
0
    wth->subtype_read = ttl_read;
2803
0
    wth->subtype_seek_read = ttl_seek_read;
2804
0
    wth->subtype_close = ttl_close;
2805
0
    wth->file_type_subtype = ttl_file_type_subtype;
2806
2807
0
    return WTAP_OPEN_MINE;
2808
0
}
2809
2810
static inline int64_t
2811
0
ttl_next_block(const ttl_t* ttl, int64_t pos) {
2812
0
    if (ttl == NULL || pos < 0 || pos < ttl->header_size) {
2813
0
        return pos;
2814
0
    }
2815
2816
0
    return pos + ttl->block_size - ((pos - ttl->header_size) % ttl->block_size);
2817
0
}
2818
2819
0
static bool ttl_read(wtap* wth, wtap_rec* rec, int* err, char** err_info, int64_t* data_offset) {
2820
0
    ttl_read_t      input;
2821
0
    int64_t         pos, end;
2822
0
    ttl_result_t    res;
2823
2824
0
    input.fh = wth->fh;
2825
0
    input.validity = VALIDITY_FH;
2826
2827
0
    do {
2828
0
        pos = file_tell(wth->fh);
2829
0
        end = ttl_next_block((ttl_t*)wth->priv, pos);
2830
2831
0
        res = ttl_read_entry(wth, rec, err, err_info, &input, pos, end);
2832
0
        if (G_UNLIKELY(res == TTL_CORRUPTED)) {
2833
0
            ws_warning("ttl_read(): Unaligned block found, skipping to next block offset: 0x%" PRIx64, end);
2834
0
            report_warning("Found unaligned TTL block. Skipping to the next one.");
2835
0
            if (file_seek(wth->fh, end, SEEK_SET, err) < 0) {
2836
0
                return false;   /* Seek error */
2837
0
            }
2838
0
        }
2839
        /*
2840
         * XXX - For now we simply skip over any entry we don't understand,
2841
         * but in the future we might want an easy way to report warnings
2842
         * without spamming the user with dialog boxes.
2843
         */
2844
0
    } while (res > TTL_NO_ERROR);
2845
2846
0
    if (G_LIKELY(res == TTL_NO_ERROR)) {
2847
0
        *data_offset = pos;
2848
0
        return true;
2849
0
    }
2850
2851
0
    return false;
2852
0
}
2853
2854
0
static bool ttl_seek_read(wtap* wth, int64_t seek_off, wtap_rec* rec, int* err, char** err_info) {
2855
0
    ttl_read_t      input;
2856
0
    ttl_result_t    res;
2857
2858
0
    input.fh = wth->random_fh;
2859
0
    input.validity = VALIDITY_FH;
2860
2861
    /* seek to the right file position */
2862
0
    if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) < 0) {
2863
0
        return false;   /* Seek error */
2864
0
    }
2865
2866
0
    res = ttl_read_entry(wth, rec, err, err_info, &input, seek_off, ttl_next_block((ttl_t*)wth->priv, seek_off));
2867
0
    if (G_LIKELY(res == TTL_NO_ERROR)) {
2868
0
        return true;
2869
0
    }
2870
2871
0
    if (res > TTL_NO_ERROR) {
2872
        /*
2873
         * If we're here, there has been an error during the first pass and we
2874
         * returned true on an unsupported or unaligned entry.
2875
         */
2876
0
        *err = WTAP_ERR_INTERNAL;
2877
0
        *err_info = ws_strdup_printf("ttl_seek_read called with invalid offset: 0x%" PRIx64, seek_off);
2878
0
    }
2879
2880
0
    return false;
2881
0
}
2882
2883
0
static void ttl_close(wtap* wth) {
2884
0
    if (wth != NULL) {
2885
0
        ttl_cleanup((ttl_t*)wth->priv);
2886
0
        wth->priv = NULL;
2887
0
    }
2888
0
}
2889
2890
 /* Options for interface blocks. */
2891
static const struct supported_option_type interface_block_options_supported[] = {
2892
    /* No comments, just an interface name. */
2893
    { OPT_IDB_NAME, ONE_OPTION_SUPPORTED }
2894
};
2895
2896
static const struct supported_block_type ttl_blocks_supported[] = {
2897
    { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED },
2898
    { WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported) },
2899
};
2900
2901
static const struct file_type_subtype_info ttl_info = {
2902
        "TTTech Computertechnik TTX Logger (TTL) logfile", "ttl", "ttl", NULL,
2903
        false, BLOCKS_SUPPORTED(ttl_blocks_supported),
2904
        NULL, NULL, NULL
2905
};
2906
2907
void register_ttl(void)
2908
14
{
2909
14
    ttl_file_type_subtype = wtap_register_file_type_subtype(&ttl_info);
2910
2911
    /*
2912
     * Register name for backwards compatibility with the
2913
     * wtap_filetypes table in Lua.
2914
     */
2915
14
    wtap_register_backwards_compatibility_lua_name("TTL", ttl_file_type_subtype);
2916
14
}
2917
2918
2919
 /*
2920
  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2921
  *
2922
  * Local variables:
2923
  * c-basic-offset: 4
2924
  * tab-width: 8
2925
  * indent-tabs-mode: nil
2926
  * End:
2927
  *
2928
  * vi: set shiftwidth=4 tabstop=8 expandtab:
2929
  * :indentSize=4:tabSize=8:noTabs=true:
2930
  */