4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * File format support for the Binary Log File (BLF) file format from
7 * Vector Informatik decoder
8 * Copyright (c) 2021-2024 by Dr. Lars Voelker <lars.voelker@technica-engineering.de>
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 * The following was used as a reference for the file format:
15 * https://bitbucket.org/tobylorenz/vector_blf
16 * The repo above includes multiple examples files as well.
20 #define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP
24 #include <epan/dissectors/packet-socketcan.h>
27 #include <epan/value_string.h>
28 #include <wsutil/wslog.h>
29 #include <wsutil/exported_pdu_tlvs.h>
30 #include <wsutil/report_message.h>
31 #include <wsutil/strtoi.h>
32 #include "file_wrappers.h"
37 #define ZLIB_PREFIX(x) zng_ ## x
38 typedef zng_stream zlib_stream
;
41 #define ZLIB_PREFIX(x) x
43 typedef z_stream zlib_stream
;
44 #endif /* HAVE_ZLIB */
47 static const uint8_t blf_magic
[] = { 'L', 'O', 'G', 'G' };
48 static const uint8_t blf_obj_magic
[] = { 'L', 'O', 'B', 'J' };
50 static int blf_file_type_subtype
= -1;
52 void register_blf(void);
54 static bool blf_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
, int64_t *data_offset
);
55 static bool blf_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
* rec
, Buffer
*buf
, int *err
, char **err_info
);
56 static void blf_close(wtap
*wth
);
59 * The virtual buffer looks like this (skips all headers):
60 * uncompressed log container data
61 * uncompressed log container data
64 * The "real" positions, length, etc. reference this layout and not the file.
66 typedef struct blf_log_container
{
67 int64_t infile_start_pos
; /* start position of log container in file */
68 uint64_t infile_length
; /* length of log container in file */
69 uint64_t infile_data_start
; /* start position of data in log container in file */
71 uint64_t real_start_pos
; /* decompressed (virtual) start position including header */
72 uint64_t real_length
; /* decompressed length */
74 uint16_t compression_method
; /* 0: uncompressed, 2: zlib */
76 unsigned char *real_data
; /* cache for decompressed data */
77 } blf_log_container_t
;
79 typedef struct blf_data
{
80 int64_t start_of_last_obj
;
81 int64_t current_real_seek_pos
;
82 uint64_t start_offset_ns
;
84 GArray
*log_containers
;
86 GHashTable
*channel_to_iface_ht
;
87 GHashTable
*channel_to_name_ht
;
88 uint32_t next_interface_id
;
91 typedef struct blf_params
{
102 typedef struct blf_channel_to_iface_entry
{
106 uint32_t interface_id
;
107 } blf_channel_to_iface_entry_t
;
110 blf_free_key(void *key
) {
115 blf_free_channel_to_iface_entry(void *data
) {
120 blf_free_channel_to_name_entry(void *data
) {
125 blf_calc_key_value(int pkt_encap
, uint16_t channel
, uint16_t hwchannel
) {
126 return (int64_t)(((uint64_t)pkt_encap
<< 32) | ((uint64_t)hwchannel
<< 16) | (uint64_t)channel
);
129 /** Return the Epoch ns time of the capture start
131 * This is not intended to fully validate the date and time,
132 * but just to check if the values are plausible.
135 blf_get_start_offset_ns(const blf_date_t
* start_date
) {
137 time_t start_offset_s
;
139 if (start_date
!= NULL
&&
140 (start_date
->month
>= 1 && start_date
->month
<= 12) &&
141 (start_date
->day
>= 1 && start_date
->day
<= 31) &&
142 (start_date
->hour
<= 23) && (start_date
->mins
<= 59) &&
143 (start_date
->sec
<= 61) /* Apparently can be up to 61 on certain systems */
144 ) { /* Not checking if milliseconds are actually less than 1000 */
145 timestamp
.tm_year
= (start_date
->year
> 1970) ? start_date
->year
- 1900 : 70;
146 timestamp
.tm_mon
= start_date
->month
- 1;
147 timestamp
.tm_mday
= start_date
->day
;
148 timestamp
.tm_hour
= start_date
->hour
;
149 timestamp
.tm_min
= start_date
->mins
;
150 timestamp
.tm_sec
= start_date
->sec
;
151 timestamp
.tm_isdst
= -1;
152 start_offset_s
= mktime(×tamp
);
153 if (start_offset_s
>= 0) {
154 return (1000 * 1000 * (start_date
->ms
+ (1000 * (uint64_t)start_offset_s
)));
161 static void add_interface_name(wtap_block_t int_data
, int pkt_encap
, uint16_t channel
, uint16_t hwchannel
, char *name
) {
163 wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "%s", name
);
166 case WTAP_ENCAP_ETHERNET
:
167 /* we use UINT16_MAX to encode no hwchannel */
168 if (hwchannel
== UINT16_MAX
) {
169 wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "ETH-%u", channel
);
171 wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "ETH-%u-%u", channel
, hwchannel
);
174 case WTAP_ENCAP_IEEE_802_11
:
175 wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "WLAN-%u", channel
);
177 case WTAP_ENCAP_FLEXRAY
:
178 wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "FR-%u", channel
);
181 wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "LIN-%u", channel
);
183 case WTAP_ENCAP_SOCKETCAN
:
184 wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "CAN-%u", channel
);
187 wtap_block_add_string_option_format(int_data
, OPT_IDB_NAME
, "ENCAP_%d-%u", pkt_encap
, channel
);
193 blf_add_interface(blf_params_t
*params
, int pkt_encap
, uint32_t channel
, uint16_t hwchannel
, char *name
) {
194 wtap_block_t int_data
= wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO
);
195 wtapng_if_descr_mandatory_t
*if_descr_mand
= (wtapng_if_descr_mandatory_t
*)wtap_block_get_mandatory_data(int_data
);
196 blf_channel_to_iface_entry_t
*item
= NULL
;
198 if_descr_mand
->wtap_encap
= pkt_encap
;
199 add_interface_name(int_data
, pkt_encap
, channel
, hwchannel
, name
);
201 * The time stamp resolution in these files can be per-record;
202 * the maximum resolution is nanoseconds, so we specify that
203 * as the interface's resolution.
205 * We set the resolution for a record on a per-record basis,
206 * based on what the record specifies.
208 if_descr_mand
->time_units_per_second
= 1000 * 1000 * 1000;
209 if_descr_mand
->tsprecision
= WTAP_TSPREC_NSEC
;
210 wtap_block_add_uint8_option(int_data
, OPT_IDB_TSRESOL
, 9);
211 if_descr_mand
->snap_len
= WTAP_MAX_PACKET_SIZE_STANDARD
;
212 if_descr_mand
->num_stat_entries
= 0;
213 if_descr_mand
->interface_statistics
= NULL
;
214 wtap_add_idb(params
->wth
, int_data
);
216 if (params
->wth
->file_encap
== WTAP_ENCAP_NONE
) {
217 params
->wth
->file_encap
= if_descr_mand
->wtap_encap
;
219 if (params
->wth
->file_encap
!= if_descr_mand
->wtap_encap
) {
220 params
->wth
->file_encap
= WTAP_ENCAP_PER_PACKET
;
225 key
= g_new(int64_t, 1);
226 *key
= blf_calc_key_value(pkt_encap
, channel
, hwchannel
);
228 item
= g_new(blf_channel_to_iface_entry_t
, 1);
229 item
->channel
= channel
;
230 item
->hwchannel
= hwchannel
;
231 item
->pkt_encap
= pkt_encap
;
232 item
->interface_id
= params
->blf_data
->next_interface_id
++;
233 g_hash_table_insert(params
->blf_data
->channel_to_iface_ht
, key
, item
);
235 return item
->interface_id
;
238 /** This is used to save the interface name without creating it.
240 * This approach allows up to update the name of the interface
241 * up until the first captured packet.
244 // NOLINTNEXTLINE(misc-no-recursion)
245 blf_prepare_interface_name(blf_params_t
* params
, int pkt_encap
, uint16_t channel
, uint16_t hwchannel
, const char* name
, bool force_new_name
) {
246 int64_t key
= blf_calc_key_value(pkt_encap
, channel
, hwchannel
);
253 if (params
->blf_data
->channel_to_name_ht
== NULL
) {
257 old_name
= (char *)g_hash_table_lookup(params
->blf_data
->channel_to_name_ht
, &key
);
259 if (old_name
!= NULL
&& force_new_name
) {
260 if (!g_hash_table_remove(params
->blf_data
->channel_to_name_ht
, &key
)) {
267 if (old_name
== NULL
&& name
!= NULL
) {
268 new_key
= g_new(int64_t, 1);
270 new_name
= ws_strdup(name
);
271 if (!g_hash_table_insert(params
->blf_data
->channel_to_name_ht
, new_key
, new_name
)) {
279 if (pkt_encap
== WTAP_ENCAP_ETHERNET
) {
280 /* Just for Ethernet, prepare the equivalent STATUS interface */
281 iface_name
= new_name
!= NULL
? ws_strdup_printf("STATUS-%s", new_name
) : NULL
;
283 // We recurse here once.
284 ret
= blf_prepare_interface_name(params
, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, channel
, hwchannel
, iface_name
, force_new_name
);
297 blf_lookup_interface(blf_params_t
*params
, int pkt_encap
, uint16_t channel
, uint16_t hwchannel
, char *name
) {
298 int64_t key
= blf_calc_key_value(pkt_encap
, channel
, hwchannel
);
299 blf_channel_to_iface_entry_t
* item
;
303 if (params
->blf_data
->channel_to_iface_ht
== NULL
) {
307 item
= (blf_channel_to_iface_entry_t
*)g_hash_table_lookup(params
->blf_data
->channel_to_iface_ht
, &key
);
310 return item
->interface_id
;
313 saved_name
= (char*)g_hash_table_lookup(params
->blf_data
->channel_to_name_ht
, &key
);
315 if (saved_name
!= NULL
) {
316 ret
= blf_add_interface(params
, pkt_encap
, channel
, hwchannel
, saved_name
);
317 g_hash_table_remove(params
->blf_data
->channel_to_name_ht
, &key
);
322 return blf_add_interface(params
, pkt_encap
, channel
, hwchannel
, name
);
328 fix_endianness_blf_date(blf_date_t
*date
) {
329 date
->year
= GUINT16_FROM_LE(date
->year
);
330 date
->month
= GUINT16_FROM_LE(date
->month
);
331 date
->dayofweek
= GUINT16_FROM_LE(date
->dayofweek
);
332 date
->day
= GUINT16_FROM_LE(date
->day
);
333 date
->hour
= GUINT16_FROM_LE(date
->hour
);
334 date
->mins
= GUINT16_FROM_LE(date
->mins
);
335 date
->sec
= GUINT16_FROM_LE(date
->sec
);
336 date
->ms
= GUINT16_FROM_LE(date
->ms
);
340 fix_endianness_blf_fileheader(blf_fileheader_t
*header
) {
341 header
->header_length
= GUINT32_FROM_LE(header
->header_length
);
342 header
->len_compressed
= GUINT64_FROM_LE(header
->len_compressed
);
343 header
->len_uncompressed
= GUINT64_FROM_LE(header
->len_uncompressed
);
344 header
->obj_count
= GUINT32_FROM_LE(header
->obj_count
);
345 header
->obj_read
= GUINT32_FROM_LE(header
->obj_read
);
346 fix_endianness_blf_date(&(header
->start_date
));
347 fix_endianness_blf_date(&(header
->end_date
));
348 header
->length3
= GUINT32_FROM_LE(header
->length3
);
352 fix_endianness_blf_blockheader(blf_blockheader_t
*header
) {
353 header
->header_length
= GUINT16_FROM_LE(header
->header_length
);
354 header
->header_type
= GUINT16_FROM_LE(header
->header_type
);
355 header
->object_length
= GUINT32_FROM_LE(header
->object_length
);
356 header
->object_type
= GUINT32_FROM_LE(header
->object_type
);
360 fix_endianness_blf_logcontainerheader(blf_logcontainerheader_t
*header
) {
361 header
->compression_method
= GUINT16_FROM_LE(header
->compression_method
);
362 header
->res1
= GUINT16_FROM_LE(header
->res1
);
363 header
->res2
= GUINT32_FROM_LE(header
->res2
);
364 header
->uncompressed_size
= GUINT32_FROM_LE(header
->uncompressed_size
);
365 header
->res4
= GUINT32_FROM_LE(header
->res4
);
369 fix_endianness_blf_logobjectheader(blf_logobjectheader_t
*header
) {
370 header
->flags
= GUINT32_FROM_LE(header
->flags
);
371 header
->client_index
= GUINT16_FROM_LE(header
->client_index
);
372 header
->object_version
= GUINT16_FROM_LE(header
->object_version
);
373 header
->object_timestamp
= GUINT64_FROM_LE(header
->object_timestamp
);
377 fix_endianness_blf_logobjectheader2(blf_logobjectheader2_t
*header
) {
378 header
->flags
= GUINT32_FROM_LE(header
->flags
);
379 header
->object_version
= GUINT16_FROM_LE(header
->object_version
);
380 header
->object_timestamp
= GUINT64_FROM_LE(header
->object_timestamp
);
381 header
->original_timestamp
= GUINT64_FROM_LE(header
->object_timestamp
);
385 fix_endianness_blf_logobjectheader3(blf_logobjectheader3_t
*header
) {
386 header
->flags
= GUINT32_FROM_LE(header
->flags
);
387 header
->static_size
= GUINT16_FROM_LE(header
->static_size
);
388 header
->object_version
= GUINT16_FROM_LE(header
->object_version
);
389 header
->object_timestamp
= GUINT64_FROM_LE(header
->object_timestamp
);
393 fix_endianness_blf_ethernetframeheader(blf_ethernetframeheader_t
*header
) {
394 header
->channel
= GUINT16_FROM_LE(header
->channel
);
395 header
->direction
= GUINT16_FROM_LE(header
->direction
);
396 header
->ethtype
= GUINT16_FROM_LE(header
->ethtype
);
397 header
->tpid
= GUINT16_FROM_LE(header
->tpid
);
398 header
->tci
= GUINT16_FROM_LE(header
->tci
);
399 header
->payloadlength
= GUINT16_FROM_LE(header
->payloadlength
);
403 fix_endianness_blf_ethernetframeheader_ex(blf_ethernetframeheader_ex_t
*header
) {
404 header
->struct_length
= GUINT16_FROM_LE(header
->struct_length
);
405 header
->flags
= GUINT16_FROM_LE(header
->flags
);
406 header
->channel
= GUINT16_FROM_LE(header
->channel
);
407 header
->hw_channel
= GUINT16_FROM_LE(header
->hw_channel
);
408 header
->frame_duration
= GUINT64_FROM_LE(header
->frame_duration
);
409 header
->frame_checksum
= GUINT32_FROM_LE(header
->frame_checksum
);
410 header
->direction
= GUINT16_FROM_LE(header
->direction
);
411 header
->frame_length
= GUINT16_FROM_LE(header
->frame_length
);
412 header
->frame_handle
= GUINT32_FROM_LE(header
->frame_handle
);
413 header
->error
= GUINT32_FROM_LE(header
->error
);
417 fix_endianness_blf_ethernet_rxerror(blf_ethernet_rxerror_t
* header
) {
418 header
->struct_length
= GUINT16_FROM_LE(header
->struct_length
);
419 header
->channel
= GUINT16_FROM_LE(header
->channel
);
420 header
->direction
= GUINT16_FROM_LE(header
->direction
);
421 header
->hw_channel
= GUINT16_FROM_LE(header
->hw_channel
);
422 header
->frame_checksum
= GUINT32_FROM_LE(header
->frame_checksum
);
423 header
->frame_length
= GUINT16_FROM_LE(header
->frame_length
);
424 header
->error
= GUINT32_FROM_LE(header
->error
);
428 fix_endianness_blf_wlanframeheader(blf_wlanframeheader_t
* header
) {
429 header
->channel
= GUINT16_FROM_LE(header
->channel
);
430 header
->flags
= GUINT16_FROM_LE(header
->flags
);
431 header
->signal_strength
= GUINT16_FROM_LE(header
->signal_strength
);
432 header
->signal_quality
= GUINT16_FROM_LE(header
->signal_quality
);
433 header
->frame_length
= GUINT16_FROM_LE(header
->frame_length
);
437 fix_endianness_blf_canmessage(blf_canmessage_t
*header
) {
438 header
->channel
= GUINT16_FROM_LE(header
->channel
);
439 header
->id
= GUINT32_FROM_LE(header
->id
);
443 fix_endianness_blf_canmessage2_trailer(blf_canmessage2_trailer_t
*header
) {
444 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
445 header
->reserved2
= GUINT16_FROM_LE(header
->reserved1
);
449 fix_endianness_blf_canfdmessage(blf_canfdmessage_t
*header
) {
450 header
->channel
= GUINT16_FROM_LE(header
->channel
);
451 header
->id
= GUINT32_FROM_LE(header
->id
);
452 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
453 header
->reservedCanFdMessage2
= GUINT32_FROM_LE(header
->reservedCanFdMessage2
);
457 fix_endianness_blf_canfdmessage64(blf_canfdmessage64_t
*header
) {
458 header
->id
= GUINT32_FROM_LE(header
->id
);
459 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
460 header
->flags
= GUINT32_FROM_LE(header
->flags
);
461 header
->btrCfgArb
= GUINT32_FROM_LE(header
->btrCfgArb
);
462 header
->btrCfgData
= GUINT32_FROM_LE(header
->btrCfgData
);
463 header
->timeOffsetBrsNs
= GUINT32_FROM_LE(header
->timeOffsetBrsNs
);
464 header
->timeOffsetCrcDelNs
= GUINT32_FROM_LE(header
->timeOffsetCrcDelNs
);
465 header
->bitCount
= GUINT16_FROM_LE(header
->bitCount
);
466 header
->crc
= GUINT32_FROM_LE(header
->crc
);
470 fix_endianness_blf_canerror(blf_canerror_t
*header
) {
471 header
->channel
= GUINT16_FROM_LE(header
->channel
);
472 header
->length
= GUINT16_FROM_LE(header
->length
);
476 fix_endianness_blf_canerrorext(blf_canerrorext_t
*header
) {
477 header
->channel
= GUINT16_FROM_LE(header
->channel
);
478 header
->length
= GUINT16_FROM_LE(header
->length
);
479 header
->flags
= GUINT32_FROM_LE(header
->flags
);
480 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
481 header
->id
= GUINT32_FROM_LE(header
->id
);
482 header
->errorCodeExt
= GUINT16_FROM_LE(header
->errorCodeExt
);
486 fix_endianness_blf_canfderror64(blf_canfderror64_t
*header
) {
487 header
->flags
= GUINT16_FROM_LE(header
->flags
);
488 header
->errorCodeExt
= GUINT16_FROM_LE(header
->errorCodeExt
);
489 header
->extFlags
= GUINT16_FROM_LE(header
->extFlags
);
490 header
->id
= GUINT32_FROM_LE(header
->id
);
491 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
492 header
->btrCfgArb
= GUINT32_FROM_LE(header
->btrCfgArb
);
493 header
->btrCfgData
= GUINT32_FROM_LE(header
->btrCfgData
);
494 header
->timeOffsetBrsNs
= GUINT32_FROM_LE(header
->timeOffsetBrsNs
);
495 header
->timeOffsetCrcDelNs
= GUINT32_FROM_LE(header
->timeOffsetCrcDelNs
);
496 header
->crc
= GUINT32_FROM_LE(header
->crc
);
497 header
->errorPosition
= GUINT16_FROM_LE(header
->errorPosition
);
501 fix_endianness_blf_flexraydata(blf_flexraydata_t
*header
) {
502 header
->channel
= GUINT16_FROM_LE(header
->channel
);
503 header
->messageId
= GUINT16_FROM_LE(header
->messageId
);
504 header
->crc
= GUINT16_FROM_LE(header
->crc
);
505 header
->reservedFlexRayData2
= GUINT16_FROM_LE(header
->reservedFlexRayData2
);
509 fix_endianness_blf_flexraymessage(blf_flexraymessage_t
*header
) {
510 header
->channel
= GUINT16_FROM_LE(header
->channel
);
511 header
->fpgaTick
= GUINT32_FROM_LE(header
->fpgaTick
);
512 header
->fpgaTickOverflow
= GUINT32_FROM_LE(header
->fpgaTickOverflow
);
513 header
->clientIndexFlexRayV6Message
= GUINT32_FROM_LE(header
->clientIndexFlexRayV6Message
);
514 header
->clusterTime
= GUINT32_FROM_LE(header
->clusterTime
);
515 header
->frameId
= GUINT16_FROM_LE(header
->frameId
);
516 header
->headerCrc
= GUINT16_FROM_LE(header
->headerCrc
);
517 header
->frameState
= GUINT16_FROM_LE(header
->frameState
);
518 header
->reservedFlexRayV6Message2
= GUINT16_FROM_LE(header
->reservedFlexRayV6Message2
);
522 fix_endianness_blf_flexrayrcvmessage(blf_flexrayrcvmessage_t
*header
) {
523 header
->channel
= GUINT16_FROM_LE(header
->channel
);
524 header
->version
= GUINT16_FROM_LE(header
->version
);
525 header
->channelMask
= GUINT16_FROM_LE(header
->channelMask
);
526 header
->dir
= GUINT16_FROM_LE(header
->dir
);
527 header
->clientIndex
= GUINT32_FROM_LE(header
->clientIndex
);
528 header
->clusterNo
= GUINT32_FROM_LE(header
->clusterNo
);
529 header
->frameId
= GUINT16_FROM_LE(header
->frameId
);
530 header
->headerCrc1
= GUINT16_FROM_LE(header
->headerCrc1
);
531 header
->headerCrc2
= GUINT16_FROM_LE(header
->headerCrc2
);
532 header
->payloadLength
= GUINT16_FROM_LE(header
->payloadLength
);
533 header
->payloadLengthValid
= GUINT16_FROM_LE(header
->payloadLengthValid
);
534 header
->cycle
= GUINT16_FROM_LE(header
->cycle
);
535 header
->tag
= GUINT32_FROM_LE(header
->tag
);
536 header
->data
= GUINT32_FROM_LE(header
->data
);
537 header
->frameFlags
= GUINT32_FROM_LE(header
->frameFlags
);
538 header
->appParameter
= GUINT32_FROM_LE(header
->appParameter
);
539 /* this would be extra for ext format:
540 header->frameCRC = GUINT32_FROM_LE(header->frameCRC);
541 header->frameLengthInNs = GUINT32_FROM_LE(header->frameLengthInNs);
542 header->frameId1 = GUINT16_FROM_LE(header->frameId1);
543 header->pduOffset = GUINT16_FROM_LE(header->pduOffset);
544 header->blfLogMask = GUINT16_FROM_LE(header->blfLogMask);
549 fix_endianness_blf_linmessage(blf_linmessage_t
* message
) {
550 message
->channel
= GUINT16_FROM_LE(message
->channel
);
551 message
->crc
= GUINT16_FROM_LE(message
->crc
);
552 /* skip the optional part
553 message->res2 = GUINT32_FROM_LE(message->res2);
558 fix_endianness_blf_linbusevent(blf_linbusevent_t
* linbusevent
) {
559 linbusevent
->sof
= GUINT64_FROM_LE(linbusevent
->sof
);
560 linbusevent
->eventBaudrate
= GUINT32_FROM_LE(linbusevent
->eventBaudrate
);
561 linbusevent
->channel
= GUINT16_FROM_LE(linbusevent
->channel
);
565 fix_endianness_blf_linsynchfieldevent(blf_linsynchfieldevent_t
* linsynchfieldevent
) {
566 fix_endianness_blf_linbusevent(&linsynchfieldevent
->linBusEvent
);
567 linsynchfieldevent
->synchBreakLength
= GUINT64_FROM_LE(linsynchfieldevent
->synchBreakLength
);
568 linsynchfieldevent
->synchDelLength
= GUINT64_FROM_LE(linsynchfieldevent
->synchDelLength
);
572 fix_endianness_blf_linmessagedescriptor(blf_linmessagedescriptor_t
* linmessagedescriptor
) {
573 fix_endianness_blf_linsynchfieldevent(&linmessagedescriptor
->linSynchFieldEvent
);
574 linmessagedescriptor
->supplierId
= GUINT16_FROM_LE(linmessagedescriptor
->supplierId
);
575 linmessagedescriptor
->messageId
= GUINT16_FROM_LE(linmessagedescriptor
->messageId
);
579 fix_endianness_blf_lindatabytetimestampevent(blf_lindatabytetimestampevent_t
* lindatabytetimestampevent
) {
581 fix_endianness_blf_linmessagedescriptor(&lindatabytetimestampevent
->linMessageDescriptor
);
582 for (i
= 0; i
< 9; i
++) {
583 lindatabytetimestampevent
->databyteTimestamps
[i
] = GUINT64_FROM_LE(lindatabytetimestampevent
->databyteTimestamps
[i
]);
588 fix_endianness_blf_linmessage2(blf_linmessage2_t
* message
) {
589 fix_endianness_blf_lindatabytetimestampevent(&message
->linDataByteTimestampEvent
);
590 message
->crc
= GUINT16_FROM_LE(message
->crc
);
591 /* skip the optional part
592 message->respBaudrate = GUINT32_FROM_LE(message->respBaudrate);
593 message->exactHeaderBaudrate = GUINT64_FROM_LE(message->exactHeaderBaudrate);
594 message->earlyStopBitOffset = GUINT32_FROM_LE(message->earlyStopBitOffset);
595 message->earlyStopBitOffsetResponse = GUINT32_FROM_LE(message->earlyStopBitOffsetResponse);
600 fix_endianness_blf_lincrcerror2(blf_lincrcerror2_t
* message
) {
601 fix_endianness_blf_lindatabytetimestampevent(&message
->linDataByteTimestampEvent
);
602 message
->crc
= GUINT16_FROM_LE(message
->crc
);
603 /* skip the optional part
604 message->respBaudrate = GUINT32_FROM_LE(message->respBaudrate);
605 message->exactHeaderBaudrate = GUINT64_FROM_LE(message->exactHeaderBaudrate);
606 message->earlyStopBitOffset = GUINT32_FROM_LE(message->earlyStopBitOffset);
607 message->earlyStopBitOffsetResponse = GUINT32_FROM_LE(message->earlyStopBitOffsetResponse);
612 fix_endianness_blf_linrcverror2(blf_linrcverror2_t
* message
) {
613 fix_endianness_blf_lindatabytetimestampevent(&message
->linDataByteTimestampEvent
);
614 /* skip the optional part
615 message->respBaudrate = GUINT32_FROM_LE(message->respBaudrate);
616 message->exactHeaderBaudrate = GUINT64_FROM_LE(message->exactHeaderBaudrate);
617 message->earlyStopBitOffset = GUINT32_FROM_LE(message->earlyStopBitOffset);
618 message->earlyStopBitOffsetResponse = GUINT32_FROM_LE(message->earlyStopBitOffsetResponse);
623 fix_endianness_blf_linsenderror2(blf_linsenderror2_t
* message
) {
624 fix_endianness_blf_linmessagedescriptor(&message
->linMessageDescriptor
);
625 message
->eoh
= GUINT64_FROM_LE(message
->eoh
);
626 /* skip the optional part
627 message->exactHeaderBaudrate = GUINT64_FROM_LE(message->exactHeaderBaudrate);
628 message->earlyStopBitOffset = GUINT32_FROM_LE(message->earlyStopBitOffset);
633 fix_endianness_blf_linwakeupevent2(blf_linwakeupevent2_t
* message
) {
634 fix_endianness_blf_linbusevent(&message
->linBusEvent
);
638 fix_endianness_blf_apptext_header(blf_apptext_t
*header
) {
639 header
->source
= GUINT32_FROM_LE(header
->source
);
640 header
->reservedAppText1
= GUINT32_FROM_LE(header
->reservedAppText1
);
641 header
->textLength
= GUINT32_FROM_LE(header
->textLength
);
642 header
->reservedAppText2
= GUINT32_FROM_LE(header
->reservedAppText2
);
646 fix_endianness_blf_ethernet_status_header(blf_ethernet_status_t
* header
) {
647 header
->channel
= GUINT16_FROM_LE(header
->channel
);
648 header
->flags
= GUINT16_FROM_LE(header
->flags
);
649 /*uint8_t linkStatus;*/
650 /*uint8_t ethernetPhy;*/
653 /*uint8_t connector;*/
654 /*uint8_t clockMode;*/
656 /*uint8_t hardwareChannel;*/
657 header
->bitrate
= GUINT32_FROM_LE(header
->bitrate
);
661 fix_endianness_blf_ethernet_phystate_header(blf_ethernet_phystate_t
* header
) {
662 header
->channel
= GUINT16_FROM_LE(header
->channel
);
663 header
->flags
= GUINT16_FROM_LE(header
->flags
);
667 blf_init_logcontainer(blf_log_container_t
*tmp
) {
668 tmp
->infile_start_pos
= 0;
669 tmp
->infile_length
= 0;
670 tmp
->infile_data_start
= 0;
671 tmp
->real_start_pos
= 0;
672 tmp
->real_length
= 0;
673 tmp
->real_data
= NULL
;
674 tmp
->compression_method
= 0;
678 blf_logcontainers_cmp(const void *a
, const void *b
) {
679 const blf_log_container_t
* container_a
= (blf_log_container_t
*)a
;
680 const blf_log_container_t
* container_b
= (blf_log_container_t
*)b
;
682 if (container_a
->real_start_pos
< container_b
->real_start_pos
) {
685 else if (container_a
->real_start_pos
> container_b
->real_start_pos
) {
694 blf_logcontainers_search(const void *a
, const void *b
) {
695 const blf_log_container_t
* container_a
= (blf_log_container_t
*)a
;
696 uint64_t pos
= *(uint64_t*)b
;
698 if (container_a
->real_start_pos
> pos
) {
701 else if (pos
>= container_a
->real_start_pos
+ container_a
->real_length
) {
709 /** Ensures the given log container is in memory
711 * If the log container already is not already in memory,
712 * it reads it from the current seek position, allocating a
713 * properly sized buffer.
714 * The file offset must be set to the start of the container
715 * data (container->infile_data_start) before calling this function.
718 blf_pull_logcontainer_into_memory(blf_params_t
*params
, blf_log_container_t
*container
, int *err
, char **err_info
) {
720 if (container
== NULL
) {
721 *err
= WTAP_ERR_INTERNAL
;
722 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory called with NULL container");
726 if (container
->real_data
!= NULL
) {
730 /* pull compressed data into buffer */
731 if (container
->infile_start_pos
< 0) {
733 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
734 * malformed file (WTAP_ERR_BAD_FILE)?
736 *err
= WTAP_ERR_INTERNAL
;
737 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: container.infile_start_pos (%" PRId64
") < 0",
738 container
->infile_start_pos
);
741 if (container
->infile_data_start
< (uint64_t)container
->infile_start_pos
) {
743 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
744 * malformed file (WTAP_ERR_BAD_FILE)?
746 *err
= WTAP_ERR_INTERNAL
;
747 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: container.infile_data_start (%" PRIu64
") < container.infile_start_pos (%" PRId64
")",
748 container
->infile_data_start
, container
->infile_start_pos
);
751 if (container
->infile_length
< container
->infile_data_start
- (uint64_t)container
->infile_start_pos
) {
753 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
754 * malformed file (WTAP_ERR_BAD_FILE)?
756 *err
= WTAP_ERR_INTERNAL
;
757 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: container.infile_length (%" PRIu64
") < (container.infile_data_start (%" PRIu64
") - container.infile_start_pos (%" PRId64
")) = %" PRIu64
,
758 container
->infile_length
,
759 container
->infile_data_start
, container
->infile_start_pos
,
760 container
->infile_data_start
- (uint64_t)container
->infile_start_pos
);
763 uint64_t data_length
= container
->infile_length
- (container
->infile_data_start
- (uint64_t)container
->infile_start_pos
);
764 if (data_length
> UINT_MAX
) {
766 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
767 * malformed file (WTAP_ERR_BAD_FILE)?
769 *err
= WTAP_ERR_INTERNAL
;
770 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: data_length (%" PRIu64
") > UINT_MAX",
775 if (container
->real_length
== 0) {
776 ws_info("blf_pull_logcontainer_into_memory: found container with 0 length");
777 /* Skip empty container */
778 if (!wtap_read_bytes_or_eof(params
->fh
, NULL
, (unsigned int)data_length
, err
, err_info
)) {
779 if (*err
== WTAP_ERR_SHORT_READ
) {
781 * XXX - our caller will turn this into an EOF.
782 * How *should* it be treated?
783 * For now, we turn it into Yet Another Internal Error,
784 * pending having better documentation of the file
787 *err
= WTAP_ERR_INTERNAL
;
788 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: short read on 0-length container");
795 if (container
->compression_method
== BLF_COMPRESSION_NONE
) {
796 unsigned char* buf
= g_try_malloc((size_t)container
->real_length
);
798 *err
= WTAP_ERR_INTERNAL
;
799 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: cannot allocate memory");
802 if (!wtap_read_bytes_or_eof(params
->fh
, buf
, (unsigned int)data_length
, err
, err_info
)) {
804 if (*err
== WTAP_ERR_SHORT_READ
) {
806 * XXX - our caller will turn this into an EOF.
807 * How *should* it be treated?
808 * For now, we turn it into Yet Another Internal Error,
809 * pending having better documentation of the file
812 *err
= WTAP_ERR_INTERNAL
;
813 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: short read on uncompressed data");
817 container
->real_data
= buf
;
821 else if (container
->compression_method
== BLF_COMPRESSION_ZLIB
) {
822 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
823 unsigned char *compressed_data
= g_try_malloc((size_t)data_length
);
824 if (compressed_data
== NULL
) {
825 *err
= WTAP_ERR_INTERNAL
;
826 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: cannot allocate memory");
829 if (!wtap_read_bytes_or_eof(params
->fh
, compressed_data
, (unsigned int)data_length
, err
, err_info
)) {
830 g_free(compressed_data
);
831 if (*err
== WTAP_ERR_SHORT_READ
) {
833 * XXX - our caller will turn this into an EOF.
834 * How *should* it be treated?
835 * For now, we turn it into Yet Another Internal Error,
836 * pending having better documentation of the file
839 *err
= WTAP_ERR_INTERNAL
;
840 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: short read on compressed data");
845 unsigned char *buf
= g_try_malloc((size_t)container
->real_length
);
847 g_free(compressed_data
);
848 *err
= WTAP_ERR_INTERNAL
;
849 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: cannot allocate memory");
852 zlib_stream infstream
= {0};
854 infstream
.avail_in
= (unsigned int)data_length
;
855 infstream
.next_in
= compressed_data
;
856 infstream
.avail_out
= (unsigned int)container
->real_length
;
857 infstream
.next_out
= buf
;
859 /* the actual DE-compression work. */
860 if (Z_OK
!= ZLIB_PREFIX(inflateInit
)(&infstream
)) {
862 * XXX - check the error code and handle this appropriately.
865 g_free(compressed_data
);
866 *err
= WTAP_ERR_INTERNAL
;
867 if (infstream
.msg
!= NULL
) {
868 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: inflateInit failed for LogContainer, message\"%s\"",
871 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: inflateInit failed for LogContainer");
873 ws_debug("inflateInit failed for LogContainer");
874 if (infstream
.msg
!= NULL
) {
875 ws_debug("inflateInit returned: \"%s\"", infstream
.msg
);
880 int ret
= ZLIB_PREFIX(inflate
)(&infstream
, Z_NO_FLUSH
);
881 /* Z_OK should not happen here since we know how big the buffer should be */
882 if (Z_STREAM_END
!= ret
) {
886 *err
= WTAP_ERR_DECOMPRESS
;
887 *err_info
= ws_strdup("preset dictionary needed");
891 *err
= WTAP_ERR_INTERNAL
;
892 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: Z_STREAM_ERROR from inflate(), message \"%s\"",
893 (infstream
.msg
!= NULL
) ? infstream
.msg
: "(none)");
897 /* This means "not enough memory". */
903 /* This means "deflate stream invalid" */
904 *err
= WTAP_ERR_DECOMPRESS
;
905 *err_info
= (infstream
.msg
!= NULL
) ? ws_strdup(infstream
.msg
) : NULL
;
909 /* XXX - this is recoverable; what should we do here? */
910 *err
= WTAP_ERR_INTERNAL
;
911 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: Z_BUF_ERROR from inflate(), message \"%s\"",
912 (infstream
.msg
!= NULL
) ? infstream
.msg
: "(none)");
915 case Z_VERSION_ERROR
:
916 *err
= WTAP_ERR_INTERNAL
;
917 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: Z_VERSION_ERROR from inflate(), message \"%s\"",
918 (infstream
.msg
!= NULL
) ? infstream
.msg
: "(none)");
922 *err
= WTAP_ERR_INTERNAL
;
923 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: unexpected error %d from inflate(), message \"%s\"",
925 (infstream
.msg
!= NULL
) ? infstream
.msg
: "(none)");
929 g_free(compressed_data
);
930 ws_debug("inflate failed (return code %d) for LogContainer", ret
);
931 if (infstream
.msg
!= NULL
) {
932 ws_debug("inflate returned: \"%s\"", infstream
.msg
);
934 /* Free up any dynamically-allocated memory in infstream */
935 ZLIB_PREFIX(inflateEnd
)(&infstream
);
939 if (Z_OK
!= ZLIB_PREFIX(inflateEnd
)(&infstream
)) {
941 * The zlib manual says this only returns Z_OK on success
942 * and Z_STREAM_ERROR if the stream state was inconsistent.
944 * It's not clear what useful information can be reported
945 * for Z_STREAM_ERROR; a look at the 1.2.11 source indicates
946 * that no string is returned to indicate what the problem
949 * It's also not clear what to do about infstream if this
952 *err
= WTAP_ERR_INTERNAL
;
953 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: inflateEnd failed for LogContainer");
955 g_free(compressed_data
);
956 ws_debug("inflateEnd failed for LogContainer");
957 if (infstream
.msg
!= NULL
) {
958 ws_debug("inflateEnd returned: \"%s\"", infstream
.msg
);
963 g_free(compressed_data
);
964 container
->real_data
= buf
;
968 *err
= WTAP_ERR_DECOMPRESSION_NOT_SUPPORTED
;
969 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: reading gzip-compressed containers isn't supported");
977 /** Finds the next log container starting at the current file offset
979 * Adds the container to the containers array for later access
982 blf_find_next_logcontainer(blf_params_t
* params
, int* err
, char** err_info
) {
983 blf_blockheader_t header
;
984 blf_logcontainerheader_t logcontainer_header
;
985 blf_log_container_t tmp
;
986 unsigned char* header_ptr
;
989 uint64_t current_real_start
;
990 if (params
->blf_data
->log_containers
->len
== 0) {
991 current_real_start
= 0;
994 const blf_log_container_t
* container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, params
->blf_data
->log_containers
->len
- 1);
995 current_real_start
= container
->real_start_pos
+ container
->real_length
;
998 header_ptr
= (unsigned char*)&header
;
1003 * We read one byte at a time so that we don't have to seek backward (allows us to do a linear read)
1005 while (i
< sizeof(blf_obj_magic
)) {
1006 if (!wtap_read_bytes_or_eof(params
->fh
, &header_ptr
[i
], 1, err
, err_info
)) {
1007 ws_debug("we found end of file");
1010 if (header_ptr
[i
] != blf_obj_magic
[i
]) {
1012 ws_debug("container object magic is not LOBJ");
1015 ws_debug("container object magic is not LOBJ (pos: 0x%" PRIx64
")", file_tell(params
->fh
) - 1);
1020 while (memcmp(&header_ptr
[i
- j
+ 1], blf_obj_magic
, j
)) {
1021 /* Check if the last j bytes match the first j bytes of the magic */
1025 /* The last j bytes match, and the first j bytes are already in the buffer, since j<=i */
1030 /* Character matches */
1035 if (!wtap_read_bytes_or_eof(params
->fh
, &header
.header_length
, sizeof(blf_blockheader_t
) - sizeof(blf_obj_magic
), err
, err_info
)) {
1036 ws_debug("we found end of file");
1040 fix_endianness_blf_blockheader(&header
);
1042 if (header
.header_length
< sizeof(blf_blockheader_t
)) {
1043 *err
= WTAP_ERR_BAD_FILE
;
1044 *err_info
= ws_strdup("blf: header length too short while looking for object");
1048 if (header
.header_type
!= BLF_HEADER_TYPE_DEFAULT
) {
1049 *err
= WTAP_ERR_UNSUPPORTED
;
1050 *err_info
= ws_strdup_printf("blf: unknown header type (%u), I know only BLF_HEADER_TYPE_DEFAULT (1)", header
.header_type
);
1054 if (header
.object_length
< header
.header_length
) {
1055 *err
= WTAP_ERR_BAD_FILE
;
1056 *err_info
= ws_strdup("blf: header object length less than header length while looking for objects");
1060 if (header
.object_type
== BLF_OBJTYPE_LOG_CONTAINER
) {
1061 /* skip unknown header part if needed */
1062 if (header
.header_length
> sizeof(blf_blockheader_t
)) {
1063 /* seek over unknown header part */
1064 if (!wtap_read_bytes(params
->fh
, NULL
, header
.header_length
- sizeof(blf_blockheader_t
), err
, err_info
)) {
1065 ws_debug("error skipping unknown header bytes in log container");
1070 /* Read the log container header */
1071 if (!wtap_read_bytes_or_eof(params
->fh
, &logcontainer_header
, sizeof(blf_logcontainerheader_t
), err
, err_info
)) {
1072 ws_debug("not enough bytes for log container header");
1076 fix_endianness_blf_logcontainerheader(&logcontainer_header
);
1078 blf_init_logcontainer(&tmp
);
1081 tmp
.infile_start_pos
= 0;
1082 tmp
.infile_data_start
= sizeof(blf_logcontainerheader_t
) + header
.header_length
;
1085 tmp
.infile_data_start
= file_tell(params
->fh
);
1086 tmp
.infile_start_pos
= tmp
.infile_data_start
- sizeof(blf_logcontainerheader_t
) - header
.header_length
;
1088 tmp
.infile_length
= header
.object_length
;
1090 tmp
.real_start_pos
= current_real_start
;
1091 tmp
.real_length
= logcontainer_header
.uncompressed_size
;
1092 tmp
.compression_method
= logcontainer_header
.compression_method
;
1094 ws_debug("found log container with real_pos=0x%" PRIx64
", real_length=0x%" PRIx64
, tmp
.real_start_pos
, tmp
.real_length
);
1097 ws_debug("found BLF object without log container");
1099 /* Create a fake log container for the lone object.
1100 * In order to avoid seeking backwards, we need to pull the fake log container now.
1102 unsigned char* buf
= g_try_malloc((size_t)header
.object_length
);
1105 * XXX - we need an "out of memory" error code here.
1107 *err
= WTAP_ERR_INTERNAL
;
1108 *err_info
= ws_strdup("blf_find_next_logcontainer: cannot allocate memory");
1112 memcpy(buf
, &header
, sizeof(blf_blockheader_t
));
1114 if (header
.object_length
> sizeof(blf_blockheader_t
)) {
1115 if (!wtap_read_bytes(params
->fh
, buf
+ sizeof(blf_blockheader_t
), header
.object_length
- sizeof(blf_blockheader_t
), err
, err_info
)) {
1117 ws_debug("cannot pull object without log container");
1122 blf_init_logcontainer(&tmp
);
1124 tmp
.infile_start_pos
= params
->pipe
? 0 : (file_tell(params
->fh
) - header
.object_length
);
1125 tmp
.infile_data_start
= tmp
.infile_start_pos
;
1126 tmp
.infile_length
= header
.object_length
;
1128 tmp
.real_start_pos
= current_real_start
;
1129 tmp
.real_length
= header
.object_length
;
1130 tmp
.compression_method
= BLF_COMPRESSION_NONE
;
1132 tmp
.real_data
= buf
;
1134 ws_debug("found non-log-container object with real_pos=0x%" PRIx64
", real_length=0x%" PRIx64
, tmp
.real_start_pos
, tmp
.real_length
);
1137 g_array_append_val(params
->blf_data
->log_containers
, tmp
);
1143 // NOLINTNEXTLINE(misc-no-recursion)
1144 blf_pull_next_logcontainer(blf_params_t
* params
, int* err
, char** err_info
) {
1145 blf_log_container_t
* container
;
1147 if (!blf_find_next_logcontainer(params
, err
, err_info
)) {
1151 /* Is there a next log container to pull? */
1152 if (params
->blf_data
->log_containers
->len
== 0) {
1157 container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, params
->blf_data
->log_containers
->len
- 1);
1158 if (!blf_pull_logcontainer_into_memory(params
, container
, err
, err_info
)) {
1159 if (*err
== WTAP_ERR_DECOMPRESS
) {
1160 report_warning("Error while decompressing BLF log container number %u (file pos. 0x%" PRIx64
"): %s",
1161 params
->blf_data
->log_containers
->len
- 1, container
->infile_start_pos
, *err_info
? *err_info
: "(none)");
1166 /* Skip this log container and try to get the next one. */
1167 g_array_remove_index(params
->blf_data
->log_containers
, params
->blf_data
->log_containers
->len
- 1);
1168 /* Calling blf_pull_logcontainer_into_memory advances the file pointer. Eventually we will reach the end of the file and stop recursing. */
1169 return blf_pull_next_logcontainer(params
, err
, err_info
);
1179 blf_read_bytes_or_eof(blf_params_t
*params
, uint64_t real_pos
, void *target_buffer
, uint64_t count
, int *err
, char **err_info
) {
1180 blf_log_container_t
* container
;
1181 unsigned container_index
;
1183 uint64_t end_pos
= real_pos
+ count
;
1185 uint64_t copied
= 0;
1187 uint64_t start_in_buf
;
1189 unsigned char *buf
= (unsigned char *)target_buffer
;
1192 ws_debug("called blf_read_bytes_or_eof with 0 count");
1196 if (count
> UINT32_MAX
) {
1197 ws_debug("trying to read too many bytes");
1201 if (params
->random
) {
1203 * Do a binary search for the container in which real_pos
1206 if (!g_array_binary_search(params
->blf_data
->log_containers
, &real_pos
, blf_logcontainers_search
, &container_index
)) {
1208 * XXX - why is this treated as an EOF rather than an error?
1209 * *err appears to be 0, which means our caller treats it as an
1210 * EOF, at least when reading the log object header.
1212 ws_debug("cannot read data because start position cannot be mapped");
1215 container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, container_index
);
1218 if (params
->blf_data
->log_containers
->len
== 0) {
1220 * This is the first (linear) pass, and we haven't yet
1221 * added any containers. Pull the next log container
1222 * into memory, so that the array isn't empty.
1224 if (!blf_pull_next_logcontainer(params
, err
, err_info
)) {
1230 * Search backwards in the array, from the last entry to the
1231 * first, to find the log container in which real_pos is
1234 container_index
= params
->blf_data
->log_containers
->len
;
1236 container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, --container_index
);
1237 } while (real_pos
< container
->real_start_pos
&& container_index
> 0); /* For some reason we skipped past the correct container */
1240 while (real_pos
< end_pos
) {
1242 while (real_pos
>= container
->real_start_pos
+ container
->real_length
) {
1244 if (!params
->random
) { /* First (linear) pass */
1245 if (!blf_pull_next_logcontainer(params
, err
, err_info
)) {
1249 if (container_index
>= params
->blf_data
->log_containers
->len
) {
1250 ws_debug("cannot find real_pos in container");
1253 container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, container_index
);
1254 if (real_pos
< container
->real_start_pos
) {
1255 ws_debug("cannot find real_pos in container");
1260 if (real_pos
< container
->real_start_pos
) {
1261 ws_debug("cannot find real_pos in container");
1265 start_in_buf
= real_pos
- container
->real_start_pos
;
1267 if (params
->random
) {
1268 if (file_seek(params
->fh
, container
->infile_data_start
, SEEK_SET
, err
) == -1) {
1271 if (!blf_pull_logcontainer_into_memory(params
, container
, err
, err_info
)) {
1276 data_left
= container
->real_length
- start_in_buf
;
1278 if (data_left
< (count
- copied
)) {
1279 memcpy(buf
+ copied
, container
->real_data
+ start_in_buf
, data_left
);
1280 copied
+= data_left
;
1281 real_pos
+= data_left
;
1284 memcpy(buf
+ copied
, container
->real_data
+ start_in_buf
, count
- copied
);
1291 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
1292 * malformed file (WTAP_ERR_BAD_FILE)?
1294 *err
= WTAP_ERR_INTERNAL
;
1295 *err_info
= ws_strdup("blf_read_bytes_or_eof: ran out of containers");
1300 blf_read_bytes(blf_params_t
*params
, uint64_t real_pos
, void *target_buffer
, uint64_t count
, int *err
, char **err_info
) {
1301 if (!blf_read_bytes_or_eof(params
, real_pos
, target_buffer
, count
, err
, err_info
)) {
1303 *err
= WTAP_ERR_SHORT_READ
;
1311 blf_init_rec(blf_params_t
*params
, uint32_t flags
, uint64_t object_timestamp
, int pkt_encap
, uint16_t channel
, uint16_t hwchannel
, unsigned caplen
, unsigned len
) {
1312 params
->rec
->rec_type
= REC_TYPE_PACKET
;
1313 params
->rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
1314 params
->rec
->presence_flags
= WTAP_HAS_CAP_LEN
| WTAP_HAS_INTERFACE_ID
;
1315 params
->rec
->ts_rel_cap_valid
= false;
1317 case BLF_TIMESTAMP_RESOLUTION_10US
:
1318 params
->rec
->presence_flags
|= WTAP_HAS_TS
;
1319 params
->rec
->tsprec
= WTAP_TSPREC_10_USEC
;
1320 object_timestamp
*= 10000;
1321 object_timestamp
+= params
->blf_data
->start_offset_ns
;
1322 params
->rec
->ts_rel_cap_valid
= true;
1325 case BLF_TIMESTAMP_RESOLUTION_1NS
:
1326 params
->rec
->presence_flags
|= WTAP_HAS_TS
;
1327 params
->rec
->tsprec
= WTAP_TSPREC_NSEC
;
1328 object_timestamp
+= params
->blf_data
->start_offset_ns
;
1329 params
->rec
->ts_rel_cap_valid
= true;
1333 /* Metadata objects have both flags and timestamp equal to zero, so that combination is not an error. */
1334 if (flags
!= 0 || object_timestamp
!= 0) {
1336 * XXX - report this as an error?
1338 * Or provide a mechanism to allow file readers to report
1339 * a warning (an error that the reader tries to work
1340 * around and that the caller should report)?
1342 ws_debug("Unknown combination of flags and timestamp (0x%x, %" PRIu64
")", flags
, object_timestamp
);
1343 object_timestamp
= 0;
1347 params
->rec
->ts
.secs
= object_timestamp
/ (1000 * 1000 * 1000);
1348 params
->rec
->ts
.nsecs
= object_timestamp
% (1000 * 1000 * 1000);
1349 params
->rec
->rec_header
.packet_header
.caplen
= caplen
;
1350 params
->rec
->rec_header
.packet_header
.len
= len
;
1353 tmp_ts
.secs
= params
->blf_data
->start_offset_ns
/ (1000 * 1000 * 1000);
1354 tmp_ts
.nsecs
= params
->blf_data
->start_offset_ns
% (1000 * 1000 * 1000);
1355 nstime_delta(¶ms
->rec
->ts_rel_cap
, ¶ms
->rec
->ts
, &tmp_ts
);
1357 params
->rec
->rec_header
.packet_header
.pkt_encap
= pkt_encap
;
1358 params
->rec
->rec_header
.packet_header
.interface_id
= blf_lookup_interface(params
, pkt_encap
, channel
, hwchannel
, NULL
);
1360 /* TODO: before we had to remove comments and verdict here to not leak memory but APIs have changed ... */
1364 blf_add_direction_option(blf_params_t
*params
, uint16_t direction
) {
1365 uint32_t tmp
= 0; /* dont care */
1367 switch (direction
) {
1369 tmp
= 1; /* inbound */
1373 tmp
= 2; /* outbound */
1377 /* pcapng.c: #define OPT_EPB_FLAGS 0x0002 */
1378 wtap_block_add_uint32_option(params
->rec
->block
, 0x0002, tmp
);
1382 blf_read_log_object_header(blf_params_t
*params
, int *err
, char **err_info
, int64_t header2_start
, int64_t data_start
, blf_logobjectheader_t
*logheader
) {
1383 if (data_start
- header2_start
< (int64_t)sizeof(blf_logobjectheader_t
)) {
1384 *err
= WTAP_ERR_BAD_FILE
;
1385 *err_info
= ws_strdup("blf: not enough bytes for log object header");
1386 ws_debug("not enough bytes for timestamp header");
1390 if (!blf_read_bytes_or_eof(params
, header2_start
, logheader
, sizeof(*logheader
), err
, err_info
)) {
1391 ws_debug("not enough bytes for logheader");
1394 fix_endianness_blf_logobjectheader(logheader
);
1399 blf_read_log_object_header2(blf_params_t
*params
, int *err
, char **err_info
, int64_t header2_start
, int64_t data_start
, blf_logobjectheader2_t
*logheader
) {
1400 if (data_start
- header2_start
< (int64_t)sizeof(blf_logobjectheader2_t
)) {
1401 *err
= WTAP_ERR_BAD_FILE
;
1402 *err_info
= ws_strdup("blf: not enough bytes for log object header");
1403 ws_debug("not enough bytes for timestamp header");
1407 if (!blf_read_bytes_or_eof(params
, header2_start
, logheader
, sizeof(*logheader
), err
, err_info
)) {
1408 ws_debug("not enough bytes for logheader");
1411 fix_endianness_blf_logobjectheader2(logheader
);
1416 blf_read_log_object_header3(blf_params_t
*params
, int *err
, char **err_info
, int64_t header2_start
, int64_t data_start
, blf_logobjectheader3_t
*logheader
) {
1417 if (data_start
- header2_start
< (int64_t)sizeof(blf_logobjectheader3_t
)) {
1418 *err
= WTAP_ERR_BAD_FILE
;
1419 *err_info
= ws_strdup("blf: not enough bytes for log object header");
1420 ws_debug("not enough bytes for timestamp header");
1424 if (!blf_read_bytes_or_eof(params
, header2_start
, logheader
, sizeof(*logheader
), err
, err_info
)) {
1425 ws_debug("not enough bytes for logheader");
1428 fix_endianness_blf_logobjectheader3(logheader
);
1433 blf_read_ethernetframe(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
1434 blf_ethernetframeheader_t ethheader
;
1436 unsigned caplen
, len
;
1438 if (object_length
< (data_start
- block_start
) + (int) sizeof(blf_ethernetframeheader_t
)) {
1439 *err
= WTAP_ERR_BAD_FILE
;
1440 *err_info
= ws_strdup("blf: ETHERNET_FRAME: not enough bytes for ethernet frame header in object");
1441 ws_debug("not enough bytes for ethernet frame header in object");
1445 if (!blf_read_bytes(params
, data_start
, ðheader
, sizeof(ethheader
), err
, err_info
)) {
1446 ws_debug("not enough bytes for ethernet frame header in file");
1449 fix_endianness_blf_ethernetframeheader(ðheader
);
1452 * BLF breaks up and reorders the Ethernet header and VLAN tag fields.
1453 * This is a really bad design and makes this format one of the worst.
1454 * If you want a fast format that keeps your data intact, avoid this format!
1455 * So, lets hope we can reconstruct the original packet successfully.
1458 tmpbuf
[0] = ethheader
.dst_addr
[0];
1459 tmpbuf
[1] = ethheader
.dst_addr
[1];
1460 tmpbuf
[2] = ethheader
.dst_addr
[2];
1461 tmpbuf
[3] = ethheader
.dst_addr
[3];
1462 tmpbuf
[4] = ethheader
.dst_addr
[4];
1463 tmpbuf
[5] = ethheader
.dst_addr
[5];
1464 tmpbuf
[6] = ethheader
.src_addr
[0];
1465 tmpbuf
[7] = ethheader
.src_addr
[1];
1466 tmpbuf
[8] = ethheader
.src_addr
[2];
1467 tmpbuf
[9] = ethheader
.src_addr
[3];
1468 tmpbuf
[10] = ethheader
.src_addr
[4];
1469 tmpbuf
[11] = ethheader
.src_addr
[5];
1471 if (ethheader
.tpid
!= 0 && ethheader
.tci
!= 0) {
1472 tmpbuf
[12] = (ethheader
.tpid
& 0xff00) >> 8;
1473 tmpbuf
[13] = (ethheader
.tpid
& 0x00ff);
1474 tmpbuf
[14] = (ethheader
.tci
& 0xff00) >> 8;
1475 tmpbuf
[15] = (ethheader
.tci
& 0x00ff);
1476 tmpbuf
[16] = (ethheader
.ethtype
& 0xff00) >> 8;
1477 tmpbuf
[17] = (ethheader
.ethtype
& 0x00ff);
1478 ws_buffer_assure_space(params
->buf
, (size_t)18 + ethheader
.payloadlength
);
1479 ws_buffer_append(params
->buf
, tmpbuf
, (size_t)18);
1480 caplen
= ((uint32_t)18 + ethheader
.payloadlength
);
1481 len
= ((uint32_t)18 + ethheader
.payloadlength
);
1483 tmpbuf
[12] = (ethheader
.ethtype
& 0xff00) >> 8;
1484 tmpbuf
[13] = (ethheader
.ethtype
& 0x00ff);
1485 ws_buffer_assure_space(params
->buf
, (size_t)14 + ethheader
.payloadlength
);
1486 ws_buffer_append(params
->buf
, tmpbuf
, (size_t)14);
1487 caplen
= ((uint32_t)14 + ethheader
.payloadlength
);
1488 len
= ((uint32_t)14 + ethheader
.payloadlength
);
1491 if (!blf_read_bytes(params
, data_start
+ sizeof(blf_ethernetframeheader_t
), ws_buffer_end_ptr(params
->buf
), ethheader
.payloadlength
, err
, err_info
)) {
1492 ws_debug("copying ethernet frame failed");
1495 params
->buf
->first_free
+= ethheader
.payloadlength
;
1497 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, UINT16_MAX
, caplen
, len
);
1498 blf_add_direction_option(params
, ethheader
.direction
);
1504 blf_read_ethernetframe_ext(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
,int64_t data_start
,
1505 int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, gboolean error
) {
1506 blf_ethernetframeheader_ex_t ethheader
;
1508 if (object_length
< (data_start
- block_start
) + (int) sizeof(blf_ethernetframeheader_ex_t
)) {
1509 *err
= WTAP_ERR_BAD_FILE
;
1510 *err_info
= ws_strdup_printf("blf: %s: not enough bytes for ethernet frame header in object", error
? "ETHERNET_ERROR_EX" : "ETHERNET_FRAME_EX");
1511 ws_debug("not enough bytes for ethernet frame header in object");
1515 if (!blf_read_bytes(params
, data_start
, ðheader
, sizeof(blf_ethernetframeheader_ex_t
), err
, err_info
)) {
1516 ws_debug("not enough bytes for ethernet frame header in file");
1519 fix_endianness_blf_ethernetframeheader_ex(ðheader
);
1521 ws_buffer_assure_space(params
->buf
, ethheader
.frame_length
);
1523 if (object_length
- (data_start
- block_start
) - sizeof(blf_ethernetframeheader_ex_t
) < ethheader
.frame_length
) {
1524 *err
= WTAP_ERR_BAD_FILE
;
1525 *err_info
= ws_strdup_printf("blf: %s: frame too short", error
? "ETHERNET_ERROR_EX" : "ETHERNET_FRAME_EX");
1526 ws_debug("frame too short");
1530 if (!blf_read_bytes(params
, data_start
+ sizeof(blf_ethernetframeheader_ex_t
), ws_buffer_start_ptr(params
->buf
), ethheader
.frame_length
, err
, err_info
)) {
1531 ws_debug("copying ethernet frame failed");
1535 if (ethheader
.flags
& BLF_ETHERNET_EX_HARDWARECHANNEL
) {
1536 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, ethheader
.hw_channel
, ethheader
.frame_length
, ethheader
.frame_length
);
1537 wtap_block_add_uint32_option(params
->rec
->block
, OPT_PKT_QUEUE
, ethheader
.hw_channel
);
1540 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, UINT16_MAX
, ethheader
.frame_length
, ethheader
.frame_length
);
1543 blf_add_direction_option(params
, ethheader
.direction
);
1549 blf_read_ethernet_rxerror(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
1550 blf_ethernet_rxerror_t ethheader
;
1552 if (object_length
< (data_start
- block_start
) + (int)sizeof(blf_ethernet_rxerror_t
)) {
1553 *err
= WTAP_ERR_BAD_FILE
;
1554 *err_info
= ws_strdup("blf: ETHERNET_RXERROR: not enough bytes for ethernet frame header in object");
1555 ws_debug("not enough bytes for ethernet rx error header in object");
1559 if (!blf_read_bytes(params
, data_start
, ðheader
, sizeof(blf_ethernet_rxerror_t
), err
, err_info
)) {
1560 ws_debug("not enough bytes for ethernet rx error header in file");
1563 fix_endianness_blf_ethernet_rxerror(ðheader
);
1565 ws_buffer_assure_space(params
->buf
, ethheader
.frame_length
);
1567 if (object_length
- (data_start
- block_start
) < ethheader
.frame_length
) {
1568 *err
= WTAP_ERR_BAD_FILE
;
1569 *err_info
= ws_strdup("blf: ETHERNET_RXERROR: frame too short");
1570 ws_debug("frame too short");
1574 if (!blf_read_bytes(params
, data_start
+ sizeof(blf_ethernet_rxerror_t
), ws_buffer_start_ptr(params
->buf
), ethheader
.frame_length
, err
, err_info
)) {
1575 ws_debug("copying ethernet rx error failed");
1579 if (ethheader
.hw_channel
!= 0) { /* In this object type, a value of 0 is considered invalid. */
1580 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, ethheader
.hw_channel
, ethheader
.frame_length
, ethheader
.frame_length
);
1581 wtap_block_add_uint32_option(params
->rec
->block
, OPT_PKT_QUEUE
, ethheader
.hw_channel
);
1584 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, UINT16_MAX
, ethheader
.frame_length
, ethheader
.frame_length
);
1586 blf_add_direction_option(params
, ethheader
.direction
);
1592 * XXX - provide radio information to our caller in the pseudo-header.
1595 blf_read_wlanframe(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
1596 blf_wlanframeheader_t wlanheader
;
1598 if (object_length
< (data_start
- block_start
) + (int)sizeof(blf_wlanframeheader_t
)) {
1599 *err
= WTAP_ERR_BAD_FILE
;
1600 *err_info
= ws_strdup("blf: WLAN_FRAME: not enough bytes for wlan frame header in object");
1601 ws_debug("not enough bytes for wlan frame header in object");
1605 if (!blf_read_bytes(params
, data_start
, &wlanheader
, sizeof(blf_wlanframeheader_t
), err
, err_info
)) {
1606 ws_debug("not enough bytes for wlan frame header in file");
1609 fix_endianness_blf_wlanframeheader(&wlanheader
);
1611 ws_buffer_assure_space(params
->buf
, wlanheader
.frame_length
);
1613 if (object_length
- (data_start
- block_start
) - sizeof(blf_wlanframeheader_t
) < wlanheader
.frame_length
) {
1614 *err
= WTAP_ERR_BAD_FILE
;
1615 *err_info
= ws_strdup("blf: WLAN_FRAME: frame too short");
1616 ws_debug("frame too short");
1620 if (!blf_read_bytes(params
, data_start
+ sizeof(blf_wlanframeheader_t
), ws_buffer_start_ptr(params
->buf
), wlanheader
.frame_length
, err
, err_info
)) {
1621 ws_debug("copying wlan frame failed");
1625 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_IEEE_802_11
, wlanheader
.channel
, UINT16_MAX
, wlanheader
.frame_length
, wlanheader
.frame_length
);
1626 blf_add_direction_option(params
, wlanheader
.direction
);
1631 static uint8_t can_dlc_to_length
[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8 };
1632 static uint8_t canfd_dlc_to_length
[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64 };
1635 blf_can_fill_buf_and_rec(blf_params_t
*params
, int *err
, char **err_info
, uint32_t canid
, uint8_t payload_length
, uint8_t payload_length_valid
, uint64_t start_position
,
1636 uint32_t flags
, uint64_t object_timestamp
, uint16_t channel
, uint8_t canfd_flags
) {
1638 unsigned caplen
, len
;
1640 tmpbuf
[0] = (canid
& 0xff000000) >> 24;
1641 tmpbuf
[1] = (canid
& 0x00ff0000) >> 16;
1642 tmpbuf
[2] = (canid
& 0x0000ff00) >> 8;
1643 tmpbuf
[3] = (canid
& 0x000000ff);
1644 tmpbuf
[4] = payload_length
;
1645 tmpbuf
[5] = canfd_flags
;
1649 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length_valid
);
1650 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
1651 caplen
= sizeof(tmpbuf
) + payload_length_valid
;
1652 len
= sizeof(tmpbuf
) + payload_length
;
1654 if (payload_length_valid
> 0 && !blf_read_bytes(params
, start_position
, ws_buffer_end_ptr(params
->buf
), payload_length_valid
, err
, err_info
)) {
1655 ws_debug("copying can payload failed");
1658 params
->buf
->first_free
+= payload_length_valid
;
1660 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_SOCKETCAN
, channel
, UINT16_MAX
, caplen
, len
);
1666 blf_read_canmessage(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, bool can_message2
) {
1667 blf_canmessage_t canheader
;
1668 blf_canmessage2_trailer_t can2trailer
;
1671 uint8_t payload_length
;
1673 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1674 *err
= WTAP_ERR_BAD_FILE
;
1675 *err_info
= ws_strdup_printf("blf: %s: not enough bytes for can header in object",
1676 can_message2
? "CAN_MESSAGE2" : "CAN_MESSAGE");
1677 ws_debug("not enough bytes for can header in object");
1681 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1682 ws_debug("not enough bytes for can header in file");
1685 fix_endianness_blf_canmessage(&canheader
);
1687 canheader
.dlc
&= 0x0f;
1689 payload_length
= canheader
.dlc
;
1690 if (payload_length
> 8) {
1691 ws_debug("regular CAN tries more than 8 bytes? Cutting to 8!");
1695 canid
= canheader
.id
;
1697 if ((canheader
.flags
& BLF_CANMESSAGE_FLAG_RTR
) == BLF_CANMESSAGE_FLAG_RTR
) {
1698 canid
|= CAN_RTR_FLAG
;
1702 if (!blf_can_fill_buf_and_rec(params
, err
, err_info
, canid
, payload_length
, payload_length
, data_start
+ sizeof(canheader
), flags
, object_timestamp
, canheader
.channel
, 0)) {
1706 /* actually, we do not really need the data, right now.... */
1708 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
) + 8 + (int) sizeof(can2trailer
)) {
1709 *err
= WTAP_ERR_BAD_FILE
;
1710 *err_info
= ws_strdup("blf: CAN_MESSAGE2: not enough bytes for can message 2 trailer");
1711 ws_debug("not enough bytes for can message 2 trailer");
1714 if (!blf_read_bytes(params
, data_start
+ sizeof(canheader
) + 8, &can2trailer
, sizeof(can2trailer
), err
, err_info
)) {
1715 ws_debug("not enough bytes for can message 2 trailer in file");
1718 fix_endianness_blf_canmessage2_trailer(&can2trailer
);
1721 blf_add_direction_option(params
, (canheader
.flags
& BLF_CANMESSAGE_FLAG_TX
) == BLF_CANMESSAGE_FLAG_TX
? BLF_DIR_TX
: BLF_DIR_RX
);
1727 blf_read_canfdmessage(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
1728 blf_canfdmessage_t canheader
;
1732 uint8_t payload_length
;
1733 uint8_t payload_length_valid
;
1734 uint8_t canfd_flags
;
1736 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1737 *err
= WTAP_ERR_BAD_FILE
;
1738 *err_info
= ws_strdup("blf: CAN_FD_MESSAGE: not enough bytes for canfd header in object");
1739 ws_debug("not enough bytes for canfd header in object");
1743 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1744 ws_debug("not enough bytes for canfd header in file");
1747 fix_endianness_blf_canfdmessage(&canheader
);
1749 canheader
.dlc
&= 0x0f;
1751 canfd
= (canheader
.canfdflags
& BLF_CANFDMESSAGE_CANFDFLAG_EDL
) == BLF_CANFDMESSAGE_CANFDFLAG_EDL
;
1753 payload_length
= canfd_dlc_to_length
[canheader
.dlc
];
1754 canfd_flags
= (canheader
.canfdflags
& BLF_CANFDMESSAGE_CANFDFLAG_EDL
) << 2 | (canheader
.canfdflags
& BLF_CANFDMESSAGE_CANFDFLAG_ESI
) >> 1 | (canheader
.canfdflags
& BLF_CANFDMESSAGE_CANFDFLAG_BRS
) >> 1;
1756 if (canheader
.dlc
> 8) {
1757 ws_debug("regular CAN tries more than 8 bytes?");
1759 payload_length
= can_dlc_to_length
[canheader
.dlc
];
1763 if (payload_length
> canheader
.validDataBytes
) {
1764 ws_debug("shortening canfd payload because valid data bytes shorter!");
1765 payload_length
= canheader
.validDataBytes
;
1768 canid
= canheader
.id
;
1770 if (!canfd
&& (canheader
.flags
& BLF_CANMESSAGE_FLAG_RTR
) == BLF_CANMESSAGE_FLAG_RTR
) {
1771 canid
|= CAN_RTR_FLAG
;
1772 payload_length
= 0; /* Should already be zero from validDataBytes */
1775 payload_length_valid
= payload_length
;
1777 if (payload_length_valid
> object_length
- (data_start
- block_start
) + sizeof(canheader
)) {
1778 ws_debug("shortening can payload because buffer is too short!");
1779 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
));
1782 if (!blf_can_fill_buf_and_rec(params
, err
, err_info
, canid
, payload_length
, payload_length_valid
, data_start
+ sizeof(canheader
), flags
, object_timestamp
, canheader
.channel
, canfd_flags
)) {
1786 blf_add_direction_option(params
, (canheader
.flags
& BLF_CANMESSAGE_FLAG_TX
) == BLF_CANMESSAGE_FLAG_TX
? BLF_DIR_TX
: BLF_DIR_RX
);
1792 blf_read_canfdmessage64(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
1793 blf_canfdmessage64_t canheader
;
1797 uint8_t payload_length
;
1798 uint8_t payload_length_valid
;
1799 uint8_t canfd_flags
;
1801 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1802 *err
= WTAP_ERR_BAD_FILE
;
1803 *err_info
= ws_strdup("blf: CAN_FD_MESSAGE_64: not enough bytes for canfd header in object");
1804 ws_debug("not enough bytes for canfd header in object");
1808 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1809 ws_debug("not enough bytes for canfd header in file");
1812 fix_endianness_blf_canfdmessage64(&canheader
);
1814 canheader
.dlc
&= 0x0f;
1816 canfd
= (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_EDL
) == BLF_CANFDMESSAGE64_FLAG_EDL
;
1818 payload_length
= canfd_dlc_to_length
[canheader
.dlc
];
1819 canfd_flags
= (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_EDL
) >> 10 | (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_ESI
) >> 13 | (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_BRS
) >> 13;
1821 if (canheader
.dlc
> 8) {
1822 ws_debug("regular CAN tries more than 8 bytes?");
1824 payload_length
= can_dlc_to_length
[canheader
.dlc
];
1828 if (payload_length
> canheader
.validDataBytes
) {
1829 ws_debug("shortening canfd payload because valid data bytes shorter!");
1830 payload_length
= canheader
.validDataBytes
;
1833 canid
= canheader
.id
;
1835 if (!canfd
&& (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_REMOTE_FRAME
) == BLF_CANFDMESSAGE64_FLAG_REMOTE_FRAME
) {
1836 canid
|= CAN_RTR_FLAG
;
1837 payload_length
= 0; /* Should already be zero from validDataBytes */
1840 payload_length_valid
= payload_length
;
1842 if (payload_length_valid
> object_length
- (data_start
- block_start
)) {
1843 ws_debug("shortening can payload because buffer is too short!");
1844 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
));
1847 if (!blf_can_fill_buf_and_rec(params
, err
, err_info
, canid
, payload_length
, payload_length_valid
, data_start
+ sizeof(canheader
), flags
, object_timestamp
, canheader
.channel
, canfd_flags
)) {
1851 blf_add_direction_option(params
, canheader
.dir
);
1857 blf_read_canerror(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, bool overload
) {
1858 blf_canerror_t canheader
;
1860 uint8_t payload_length
;
1861 uint8_t tmpbuf
[16] = {0};
1863 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1864 *err
= WTAP_ERR_BAD_FILE
;
1865 *err_info
= ws_strdup("blf: CAN_ERROR: not enough bytes for canerror header in object");
1866 ws_debug("not enough bytes for canerror header in object");
1870 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1871 ws_debug("not enough bytes for canerror header in file");
1874 fix_endianness_blf_canerror(&canheader
);
1876 // Set CAN_ERR_FLAG in unused bits of Can ID to indicate error in socketcan
1877 canid
= CAN_ERR_FLAG
;
1879 // Fixed packet data length for socketcan error messages
1880 payload_length
= CAN_ERR_DLC
;
1883 tmpbuf
[10] = CAN_ERR_PROT_OVERLOAD
;
1884 canid
|= CAN_ERR_PROT
;
1887 tmpbuf
[0] = (canid
& 0xff000000) >> 24;
1888 tmpbuf
[1] = (canid
& 0x00ff0000) >> 16;
1889 tmpbuf
[2] = (canid
& 0x0000ff00) >> 8;
1890 tmpbuf
[3] = (canid
& 0x000000ff);
1891 tmpbuf
[4] = payload_length
;
1893 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
1894 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
1896 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_SOCKETCAN
, canheader
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
1901 blf_read_canerrorext(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
1902 blf_canerrorext_t canheader
;
1904 bool err_ack
= false;
1905 bool err_prot
= false;
1908 uint8_t payload_length
;
1909 uint8_t tmpbuf
[16] = {0};
1911 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1912 *err
= WTAP_ERR_BAD_FILE
;
1913 *err_info
= ws_strdup("blf: CAN_ERROR_EXT: not enough bytes for canerrorext header in object");
1914 ws_debug("not enough bytes for canerrorext header in object");
1918 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1919 ws_debug("not enough bytes for canerrorext header in file");
1922 fix_endianness_blf_canerrorext(&canheader
);
1924 if (canheader
.flags
& BLF_CANERROREXT_FLAG_CANCORE
) {
1925 // Map Vector Can Core error codes to compareable socketcan errors
1926 switch ((canheader
.errorCodeExt
>> 6) & 0x3f) {
1927 case BLF_CANERROREXT_ECC_MEANING_BIT_ERROR
:
1929 tmpbuf
[10] = CAN_ERR_PROT_BIT
;
1931 case BLF_CANERROREXT_ECC_MEANING_FORM_ERROR
:
1933 tmpbuf
[10] = CAN_ERR_PROT_FORM
;
1935 case BLF_CANERROREXT_ECC_MEANING_STUFF_ERROR
:
1937 tmpbuf
[10] = CAN_ERR_PROT_STUFF
;
1939 case BLF_CANERROREXT_ECC_MEANING_CRC_ERROR
:
1941 tmpbuf
[11] = CAN_ERR_PROT_LOC_CRC_SEQ
;
1943 case BLF_CANERROREXT_ECC_MEANING_NACK_ERROR
:
1945 tmpbuf
[11] = CAN_ERR_PROT_LOC_ACK
;
1947 case BLF_CANERROREXT_ECC_MEANING_OVERLOAD
:
1949 tmpbuf
[10] = CAN_ERR_PROT_OVERLOAD
;
1953 tmpbuf
[10] = CAN_ERR_PROT_UNSPEC
;
1956 err_ack
= err_ack
|| (canheader
.errorCodeExt
& BLF_CANERROREXT_EXTECC_NOT_ACK
) == 0x0;
1958 // Don't set protocol error on ack errors
1963 // CanID contains error class in socketcan
1964 canid
= CAN_ERR_FLAG
;
1965 canid
|= err_prot
? CAN_ERR_PROT
: 0;
1966 canid
|= err_ack
? CAN_ERR_ACK
: 0;
1968 // Fixed packet data length for socketcan error messages
1969 payload_length
= CAN_ERR_DLC
;
1970 canheader
.dlc
= payload_length
;
1972 tmpbuf
[0] = (canid
& 0xff000000) >> 24;
1973 tmpbuf
[1] = (canid
& 0x00ff0000) >> 16;
1974 tmpbuf
[2] = (canid
& 0x0000ff00) >> 8;
1975 tmpbuf
[3] = (canid
& 0x000000ff);
1976 tmpbuf
[4] = payload_length
;
1978 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
1979 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
1981 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_SOCKETCAN
, canheader
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
1982 if (canheader
.flags
& BLF_CANERROREXT_FLAG_CANCORE
) {
1983 direction_tx
= (canheader
.errorCodeExt
& BLF_CANERROREXT_EXTECC_TX
) == BLF_CANERROREXT_EXTECC_TX
;
1984 blf_add_direction_option(params
, direction_tx
? BLF_DIR_TX
: BLF_DIR_RX
);
1990 blf_read_canfderror64(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
1991 blf_canfderror64_t canheader
;
1993 bool err_ack
= false;
1994 bool err_prot
= false;
1997 uint8_t payload_length
;
1998 uint8_t tmpbuf
[16] = {0};
2000 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
2001 *err
= WTAP_ERR_BAD_FILE
;
2002 *err_info
= ws_strdup("blf: CAN_FD_ERROR_64: not enough bytes for canfderror header in object");
2003 ws_debug("not enough bytes for canfderror header in object");
2007 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
2008 ws_debug("not enough bytes for canfderror header in file");
2011 fix_endianness_blf_canfderror64(&canheader
);
2013 if (canheader
.flags
& BLF_CANERROREXT_FLAG_CANCORE
) {
2014 // Map Vector Can Core error codes to compareable socketcan errors
2015 switch ((canheader
.errorCodeExt
>> 6) & 0x3f) {
2016 case BLF_CANERROREXT_ECC_MEANING_BIT_ERROR
:
2018 tmpbuf
[10] = CAN_ERR_PROT_BIT
;
2020 case BLF_CANERROREXT_ECC_MEANING_FORM_ERROR
:
2022 tmpbuf
[10] = CAN_ERR_PROT_FORM
;
2024 case BLF_CANERROREXT_ECC_MEANING_STUFF_ERROR
:
2026 tmpbuf
[10] = CAN_ERR_PROT_STUFF
;
2028 case BLF_CANERROREXT_ECC_MEANING_CRC_ERROR
:
2030 tmpbuf
[11] = CAN_ERR_PROT_LOC_CRC_SEQ
;
2032 case BLF_CANERROREXT_ECC_MEANING_NACK_ERROR
:
2034 tmpbuf
[11] = CAN_ERR_PROT_LOC_ACK
;
2036 case BLF_CANERROREXT_ECC_MEANING_OVERLOAD
:
2038 tmpbuf
[10] = CAN_ERR_PROT_OVERLOAD
;
2042 tmpbuf
[10] = CAN_ERR_PROT_UNSPEC
;
2045 err_ack
= err_ack
|| (canheader
.errorCodeExt
& BLF_CANERROREXT_EXTECC_NOT_ACK
) == 0x0;
2047 // Don't set protocol error on ack errors
2052 // CanID contains error class in socketcan
2053 canid
= CAN_ERR_FLAG
;
2054 canid
|= err_prot
? CAN_ERR_PROT
: 0;
2055 canid
|= err_ack
? CAN_ERR_ACK
: 0;
2057 // Fixed packet data length for socketcan error messages
2058 payload_length
= CAN_ERR_DLC
;
2059 canheader
.dlc
= payload_length
;
2061 tmpbuf
[0] = (canid
& 0xff000000) >> 24;
2062 tmpbuf
[1] = (canid
& 0x00ff0000) >> 16;
2063 tmpbuf
[2] = (canid
& 0x0000ff00) >> 8;
2064 tmpbuf
[3] = (canid
& 0x000000ff);
2065 tmpbuf
[4] = payload_length
;
2066 // Don't set FDF, ESI and BRS flags, since error messages are always encapsulated in Classic CAN frames
2068 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2069 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2071 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_SOCKETCAN
, canheader
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2072 if (canheader
.flags
& BLF_CANERROREXT_FLAG_CANCORE
) {
2073 direction_tx
= (canheader
.errorCodeExt
& BLF_CANERROREXT_EXTECC_TX
) == BLF_CANERROREXT_EXTECC_TX
;
2074 blf_add_direction_option(params
, direction_tx
? BLF_DIR_TX
: BLF_DIR_RX
);
2080 blf_read_flexraydata(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
2081 blf_flexraydata_t frheader
;
2083 uint8_t payload_length
;
2084 uint8_t payload_length_valid
;
2086 unsigned caplen
, len
;
2088 if (object_length
< (data_start
- block_start
) + (int) sizeof(frheader
)) {
2089 *err
= WTAP_ERR_BAD_FILE
;
2090 *err_info
= ws_strdup("blf: FLEXRAY_DATA: not enough bytes for flexrayheader in object");
2091 ws_debug("not enough bytes for flexrayheader in object");
2095 if (!blf_read_bytes(params
, data_start
, &frheader
, sizeof(frheader
), err
, err_info
)) {
2096 ws_debug("not enough bytes for flexrayheader header in file");
2099 fix_endianness_blf_flexraydata(&frheader
);
2101 payload_length
= frheader
.len
;
2102 payload_length_valid
= payload_length
;
2104 if ((frheader
.len
& 0x01) == 0x01) {
2105 ws_debug("reading odd length in FlexRay!?");
2108 if (payload_length_valid
> object_length
- (data_start
- block_start
) - sizeof(frheader
)) {
2109 ws_debug("shortening FlexRay payload because buffer is too short!");
2110 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
) - sizeof(frheader
));
2113 if (frheader
.channel
!= 0 && frheader
.channel
!= 1) {
2114 ws_debug("FlexRay supports only two channels.");
2117 /* Measurement Header */
2118 if (frheader
.channel
== 0) {
2119 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
;
2121 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
| BLF_FLEXRAYDATA_CHANNEL_B
;
2128 tmpbuf
[2] = 0x20 | ((0x0700 & frheader
.messageId
) >> 8);
2129 tmpbuf
[3] = 0x00ff & frheader
.messageId
;
2130 tmpbuf
[4] = (0xfe & frheader
.len
) | ((frheader
.crc
& 0x0400) >> 10);
2131 tmpbuf
[5] = (0x03fc & frheader
.crc
) >> 2;
2132 tmpbuf
[6] = ((0x0003 & frheader
.crc
) << 6) | (0x3f & frheader
.mux
);
2134 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length_valid
);
2135 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2136 caplen
= sizeof(tmpbuf
) + payload_length_valid
;
2137 len
= sizeof(tmpbuf
) + payload_length
;
2139 if (payload_length_valid
> 0 && !blf_read_bytes(params
, data_start
+ sizeof(frheader
), ws_buffer_end_ptr(params
->buf
), payload_length_valid
, err
, err_info
)) {
2140 ws_debug("copying flexray payload failed");
2143 params
->buf
->first_free
+= payload_length_valid
;
2145 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_FLEXRAY
, frheader
.channel
, UINT16_MAX
, caplen
, len
);
2146 blf_add_direction_option(params
, frheader
.dir
);
2152 blf_read_flexraymessage(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
2153 blf_flexraymessage_t frheader
;
2155 uint8_t payload_length
;
2156 uint8_t payload_length_valid
;
2158 unsigned caplen
, len
;
2160 if (object_length
< (data_start
- block_start
) + (int) sizeof(frheader
)) {
2161 *err
= WTAP_ERR_BAD_FILE
;
2162 *err_info
= ws_strdup("blf: FLEXRAY_MESSAGE: not enough bytes for flexrayheader in object");
2163 ws_debug("not enough bytes for flexrayheader in object");
2167 if (!blf_read_bytes(params
, data_start
, &frheader
, sizeof(frheader
), err
, err_info
)) {
2168 ws_debug("not enough bytes for flexrayheader header in file");
2171 fix_endianness_blf_flexraymessage(&frheader
);
2173 payload_length
= frheader
.length
;
2174 payload_length_valid
= payload_length
;
2176 if ((frheader
.length
& 0x01) == 0x01) {
2177 ws_debug("reading odd length in FlexRay!?");
2180 if (payload_length_valid
> object_length
- (data_start
- block_start
) - sizeof(frheader
)) {
2181 ws_debug("shortening FlexRay payload because buffer is too short!");
2182 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
) - sizeof(frheader
));
2185 if (frheader
.channel
!= 0 && frheader
.channel
!= 1) {
2186 ws_debug("FlexRay supports only two channels.");
2189 /* Measurement Header */
2190 if (frheader
.channel
== 0) {
2191 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
;
2193 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
| BLF_FLEXRAYDATA_CHANNEL_B
;
2200 tmpbuf
[2] = ((0x0700 & frheader
.frameId
) >> 8);
2201 if ((frheader
.frameState
& BLF_FLEXRAYMESSAGE_STATE_PPI
) == BLF_FLEXRAYMESSAGE_STATE_PPI
) {
2202 tmpbuf
[2] |= BLF_DLT_FLEXRAY_PPI
;
2205 if ((frheader
.frameState
& BLF_FLEXRAYMESSAGE_STATE_SFI
) == BLF_FLEXRAYMESSAGE_STATE_SFI
) {
2206 tmpbuf
[2] |= BLF_DLT_FLEXRAY_SFI
;
2209 if ((frheader
.frameState
& BLF_FLEXRAYMESSAGE_STATE_NFI
) != BLF_FLEXRAYMESSAGE_STATE_NFI
) {
2210 /* NFI needs to be inversed !? */
2211 tmpbuf
[2] |= BLF_DLT_FLEXRAY_NFI
;
2214 if ((frheader
.frameState
& BLF_FLEXRAYMESSAGE_STATE_STFI
) == BLF_FLEXRAYMESSAGE_STATE_STFI
) {
2215 tmpbuf
[2] |= BLF_DLT_FLEXRAY_STFI
;
2218 tmpbuf
[3] = 0x00ff & frheader
.frameId
;
2219 tmpbuf
[4] = (0xfe & frheader
.length
) | ((frheader
.headerCrc
& 0x0400) >> 10);
2220 tmpbuf
[5] = (0x03fc & frheader
.headerCrc
) >> 2;
2221 tmpbuf
[6] = ((0x0003 & frheader
.headerCrc
) << 6) | (0x3f & frheader
.cycle
);
2223 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length_valid
);
2224 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2225 caplen
= sizeof(tmpbuf
) + payload_length_valid
;
2226 len
= sizeof(tmpbuf
) + payload_length
;
2228 if (payload_length_valid
> 0 && !blf_read_bytes(params
, data_start
+ sizeof(frheader
), ws_buffer_end_ptr(params
->buf
), payload_length_valid
, err
, err_info
)) {
2229 ws_debug("copying flexray payload failed");
2232 params
->buf
->first_free
+= payload_length_valid
;
2234 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_FLEXRAY
, frheader
.channel
, UINT16_MAX
, caplen
, len
);
2235 blf_add_direction_option(params
, frheader
.dir
);
2241 blf_read_flexrayrcvmessageex(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, bool ext
) {
2242 blf_flexrayrcvmessage_t frheader
;
2244 uint16_t payload_length
;
2245 uint16_t payload_length_valid
;
2247 int frheadersize
= sizeof(frheader
);
2248 unsigned caplen
, len
;
2254 if ((int64_t)object_length
< (data_start
- block_start
) + frheadersize
) {
2255 *err
= WTAP_ERR_BAD_FILE
;
2256 *err_info
= ws_strdup_printf("blf: %s: not enough bytes for flexrayheader in object",
2257 ext
? "FLEXRAY_RCVMESSAGE_EX" : "FLEXRAY_RCVMESSAGE");
2258 ws_debug("not enough bytes for flexrayheader in object");
2262 if (!blf_read_bytes(params
, data_start
, &frheader
, sizeof(frheader
), err
, err_info
)) {
2263 ws_debug("not enough bytes for flexrayheader header in file");
2266 fix_endianness_blf_flexrayrcvmessage(&frheader
);
2269 frheader
.dir
&= 0xff;
2270 frheader
.cycle
&= 0xff;
2273 payload_length
= frheader
.payloadLength
;
2274 payload_length_valid
= frheader
.payloadLengthValid
;
2276 if ((frheader
.payloadLength
& 0x01) == 0x01) {
2277 ws_debug("reading odd length in FlexRay!?");
2280 if (payload_length_valid
> object_length
- (data_start
- block_start
) - frheadersize
) {
2281 ws_debug("shortening FlexRay payload because buffer is too short!");
2282 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
) - frheadersize
);
2285 /* Measurement Header */
2286 /* TODO: It seems that this format support both channels at the same time!? */
2287 if (frheader
.channelMask
== BLF_FLEXRAYRCVMSG_CHANNELMASK_A
) {
2288 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
;
2290 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
| BLF_FLEXRAYDATA_CHANNEL_B
;
2297 tmpbuf
[2] = ((0x0700 & frheader
.frameId
) >> 8);
2298 if ((frheader
.frameFlags
& BLF_FLEXRAYRCVMSG_FRAME_FLAG_PAYLOAD_PREAM
) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_PAYLOAD_PREAM
) {
2299 tmpbuf
[2] |= BLF_DLT_FLEXRAY_PPI
;
2302 if ((frheader
.frameFlags
& BLF_FLEXRAYRCVMSG_FRAME_FLAG_SYNC
) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_SYNC
) {
2303 tmpbuf
[2] |= BLF_DLT_FLEXRAY_SFI
;
2306 if ((frheader
.frameFlags
& BLF_FLEXRAYRCVMSG_FRAME_FLAG_NULL_FRAME
) != BLF_FLEXRAYRCVMSG_FRAME_FLAG_NULL_FRAME
) {
2307 /* NFI needs to be inversed !? */
2308 tmpbuf
[2] |= BLF_DLT_FLEXRAY_NFI
;
2311 if ((frheader
.frameFlags
& BLF_FLEXRAYRCVMSG_FRAME_FLAG_STARTUP
) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_STARTUP
) {
2312 tmpbuf
[2] |= BLF_DLT_FLEXRAY_STFI
;
2315 tmpbuf
[3] = 0x00ff & frheader
.frameId
;
2316 tmpbuf
[4] = (0xfe & frheader
.payloadLength
) | ((frheader
.headerCrc1
& 0x0400) >> 10);
2317 tmpbuf
[5] = (0x03fc & frheader
.headerCrc1
) >> 2;
2318 tmpbuf
[6] = ((0x0003 & frheader
.headerCrc1
) << 6) | (0x3f & frheader
.cycle
);
2320 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length_valid
);
2321 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2322 caplen
= sizeof(tmpbuf
) + payload_length_valid
;
2323 len
= sizeof(tmpbuf
) + payload_length
;
2325 if (payload_length_valid
> 0 && !blf_read_bytes(params
, data_start
+ frheadersize
, ws_buffer_end_ptr(params
->buf
), payload_length_valid
, err
, err_info
)) {
2326 ws_debug("copying flexray payload failed");
2329 params
->buf
->first_free
+= payload_length_valid
;
2331 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_FLEXRAY
, frheader
.channelMask
, UINT16_MAX
, caplen
, len
);
2332 blf_add_direction_option(params
, frheader
.dir
);
2338 blf_read_linmessage(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, bool crc_error
) {
2339 blf_linmessage_t linmessage
;
2341 uint8_t payload_length
;
2344 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2345 *err
= WTAP_ERR_BAD_FILE
;
2346 *err_info
= ws_strdup_printf("blf: %s: not enough bytes for %s in object", crc_error
? "LIN_CRC_ERROR" : "LIN_MESSAGE", crc_error
? "lincrcerror" : "linmessage");
2347 ws_debug("not enough bytes for %s in object", crc_error
? "lincrcerror" : "linmessage");
2351 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2352 ws_debug("not enough bytes for %s in file", crc_error
? "lincrcerror" : "linmessage");
2355 fix_endianness_blf_linmessage(&linmessage
);
2357 linmessage
.dlc
&= 0x0f;
2358 linmessage
.id
&= 0x3f;
2360 payload_length
= MIN(linmessage
.dlc
, 8);
2363 tmpbuf
[0] = 1; /* message format rev = 1 */
2364 tmpbuf
[1] = 0; /* reserved */
2365 tmpbuf
[2] = 0; /* reserved */
2366 tmpbuf
[3] = 0; /* reserved */
2367 tmpbuf
[4] = linmessage
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2368 tmpbuf
[5] = linmessage
.id
; /* parity (2bit) | id (6bit) */
2369 tmpbuf
[6] = (uint8_t)(linmessage
.crc
& 0xff); /* checksum */
2370 tmpbuf
[7] = 0; /* errors */
2376 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length
);
2377 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2378 ws_buffer_append(params
->buf
, linmessage
.data
, payload_length
);
2379 len
= sizeof(tmpbuf
) + payload_length
;
2381 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.channel
, UINT16_MAX
, len
, len
);
2382 blf_add_direction_option(params
, linmessage
.dir
);
2388 blf_read_linrcverror(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
2389 blf_linrcverror_t linmessage
;
2391 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2392 *err
= WTAP_ERR_BAD_FILE
;
2393 *err_info
= ws_strdup("blf: LIN_RCV_ERROR: not enough bytes for linrcverror in object");
2394 ws_debug("not enough bytes for linrcverror in object");
2398 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2399 ws_debug("not enough bytes for linrcverror in file");
2402 linmessage
.channel
= GUINT16_FROM_LE(linmessage
.channel
);
2404 linmessage
.dlc
&= 0x0f;
2405 linmessage
.id
&= 0x3f;
2408 tmpbuf
[0] = 1; /* message format rev = 1 */
2409 tmpbuf
[1] = 0; /* reserved */
2410 tmpbuf
[2] = 0; /* reserved */
2411 tmpbuf
[3] = 0; /* reserved */
2412 tmpbuf
[4] = linmessage
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2413 tmpbuf
[5] = linmessage
.id
; /* parity (2bit) | id (6bit) */
2414 tmpbuf
[6] = 0; /* checksum */
2415 /* XXX - This object can represent many different error types.
2416 * For now we always treat it as framing error,
2417 * but in the future we should expand it. */
2418 tmpbuf
[7] = 0x02; /* errors */
2420 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2421 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2423 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2429 blf_read_linsenderror(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
2430 blf_linsenderror_t linmessage
;
2432 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2433 *err
= WTAP_ERR_BAD_FILE
;
2434 *err_info
= ws_strdup("blf: LIN_SND_ERROR: not enough bytes for linsenderror in object");
2435 ws_debug("not enough bytes for linsenderror in object");
2439 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2440 ws_debug("not enough bytes for linsenderror in file");
2443 linmessage
.channel
= GUINT16_FROM_LE(linmessage
.channel
);
2445 linmessage
.dlc
&= 0x0f;
2446 linmessage
.id
&= 0x3f;
2449 tmpbuf
[0] = 1; /* message format rev = 1 */
2450 tmpbuf
[1] = 0; /* reserved */
2451 tmpbuf
[2] = 0; /* reserved */
2452 tmpbuf
[3] = 0; /* reserved */
2453 tmpbuf
[4] = linmessage
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2454 tmpbuf
[5] = linmessage
.id
; /* parity (2bit) | id (6bit) */
2455 tmpbuf
[6] = 0; /* checksum */
2456 tmpbuf
[7] = 0x01; /* errors */
2458 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2459 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2461 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2467 blf_read_linwakeupevent(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
2468 blf_linwakeupevent_t linevent
;
2470 if (object_length
< (data_start
- block_start
) + (int)sizeof(linevent
)) {
2471 *err
= WTAP_ERR_BAD_FILE
;
2472 *err_info
= ws_strdup("blf: LIN_WAKEUP: not enough bytes for linwakeup in object");
2473 ws_debug("not enough bytes for linwakeup in object");
2477 if (!blf_read_bytes(params
, data_start
, &linevent
, sizeof(linevent
), err
, err_info
)) {
2478 ws_debug("not enough bytes for linwakeup in file");
2481 linevent
.channel
= GUINT16_FROM_LE(linevent
.channel
);
2483 uint8_t tmpbuf
[12]; /* LIN events have a fixed length of 12 bytes */
2484 tmpbuf
[0] = 1; /* message format rev = 1 */
2485 tmpbuf
[1] = 0; /* reserved */
2486 tmpbuf
[2] = 0; /* reserved */
2487 tmpbuf
[3] = 0; /* reserved */
2488 tmpbuf
[4] = 3 << 2; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2489 tmpbuf
[5] = 0; /* parity (2bit) | id (6bit) */
2490 tmpbuf
[6] = 0; /* checksum */
2491 tmpbuf
[7] = 0; /* errors */
2499 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2500 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2502 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linevent
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2508 blf_read_linmessage2(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, uint16_t object_version
) {
2509 blf_linmessage2_t linmessage
;
2511 uint8_t payload_length
;
2514 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2515 *err
= WTAP_ERR_BAD_FILE
;
2516 *err_info
= ws_strdup("blf: LIN_MESSAGE2: not enough bytes for linmessage2 in object");
2517 ws_debug("not enough bytes for linmessage2 in object");
2521 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2522 ws_debug("not enough bytes for linmessage2 in file");
2525 fix_endianness_blf_linmessage2(&linmessage
);
2527 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
&= 0x0f;
2528 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
&= 0x3f;
2530 payload_length
= MIN(linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
, 8);
2533 tmpbuf
[0] = 1; /* message format rev = 1 */
2534 tmpbuf
[1] = 0; /* reserved */
2535 tmpbuf
[2] = 0; /* reserved */
2536 tmpbuf
[3] = 0; /* reserved */
2537 tmpbuf
[4] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2538 if (object_version
>= 1) { /* The 'checksumModel' field is valid only if objectVersion >= 1 */
2539 switch (linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.checksumModel
) {
2541 tmpbuf
[4] |= 1; /* Classic */
2544 tmpbuf
[4] |= 2; /* Enhanced */
2550 tmpbuf
[5] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
; /* parity (2bit) | id (6bit) */
2551 tmpbuf
[6] = (uint8_t)(linmessage
.crc
& 0xff); /* checksum */
2552 tmpbuf
[7] = 0; /* errors */
2554 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length
);
2555 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2556 ws_buffer_append(params
->buf
, linmessage
.data
, payload_length
);
2557 len
= sizeof(tmpbuf
) + payload_length
;
2559 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.linSynchFieldEvent
.linBusEvent
.channel
, UINT16_MAX
, len
, len
);
2560 blf_add_direction_option(params
, linmessage
.dir
);
2566 blf_read_lincrcerror2(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, uint16_t object_version
) {
2567 blf_lincrcerror2_t linmessage
;
2569 uint8_t payload_length
;
2572 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2573 *err
= WTAP_ERR_BAD_FILE
;
2574 *err_info
= ws_strdup("blf: LIN_CRC_ERROR2: not enough bytes for lincrcerror2 in object");
2575 ws_debug("not enough bytes for lincrcerror2 in object");
2579 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2580 ws_debug("not enough bytes for lincrcerror2 in file");
2583 fix_endianness_blf_lincrcerror2(&linmessage
);
2585 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
&= 0x0f;
2586 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
&= 0x3f;
2588 payload_length
= MIN(linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
, 8);
2591 tmpbuf
[0] = 1; /* message format rev = 1 */
2592 tmpbuf
[1] = 0; /* reserved */
2593 tmpbuf
[2] = 0; /* reserved */
2594 tmpbuf
[3] = 0; /* reserved */
2595 tmpbuf
[4] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2596 if (object_version
>= 1) { /* The 'checksumModel' field is valid only if objectVersion >= 1 */
2597 switch (linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.checksumModel
) {
2599 tmpbuf
[4] |= 1; /* Classic */
2602 tmpbuf
[4] |= 2; /* Enhanced */
2608 tmpbuf
[5] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
; /* parity (2bit) | id (6bit) */
2609 tmpbuf
[6] = (uint8_t)(linmessage
.crc
& 0xff); /* checksum */
2610 tmpbuf
[7] = 0x08; /* errors */
2612 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length
);
2613 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2614 ws_buffer_append(params
->buf
, linmessage
.data
, payload_length
);
2615 len
= sizeof(tmpbuf
) + payload_length
;
2617 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.linSynchFieldEvent
.linBusEvent
.channel
, UINT16_MAX
, len
, len
);
2618 blf_add_direction_option(params
, linmessage
.dir
);
2624 blf_read_linrcverror2(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, uint16_t object_version
) {
2625 blf_linrcverror2_t linmessage
;
2627 uint8_t payload_length
;
2630 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2631 *err
= WTAP_ERR_BAD_FILE
;
2632 *err_info
= ws_strdup("blf: LIN_RCV_ERROR2: not enough bytes for linrcverror2 in object");
2633 ws_debug("not enough bytes for linrcverror2 in object");
2637 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2638 ws_debug("not enough bytes for linrcverror2 in file");
2641 fix_endianness_blf_linrcverror2(&linmessage
);
2643 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
&= 0x0f;
2644 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
&= 0x3f;
2646 if (linmessage
.hasDataBytes
) {
2647 payload_length
= MIN(linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
, 8);
2654 tmpbuf
[0] = 1; /* message format rev = 1 */
2655 tmpbuf
[1] = 0; /* reserved */
2656 tmpbuf
[2] = 0; /* reserved */
2657 tmpbuf
[3] = 0; /* reserved */
2658 tmpbuf
[4] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2659 if (object_version
>= 1) { /* The 'checksumModel' field is valid only if objectVersion >= 1 */
2660 switch (linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.checksumModel
) {
2662 tmpbuf
[4] |= 1; /* Classic */
2665 tmpbuf
[4] |= 2; /* Enhanced */
2671 tmpbuf
[5] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
; /* parity (2bit) | id (6bit) */
2672 tmpbuf
[6] = 0; /* checksum */
2673 /* XXX - This object can represent many different error types.
2674 * For now we always treat it as framing error,
2675 * but in the future we should expand it. */
2676 tmpbuf
[7] = 0x02; /* errors */
2678 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length
);
2679 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2680 if (payload_length
> 0) {
2681 ws_buffer_append(params
->buf
, linmessage
.data
, payload_length
);
2683 len
= sizeof(tmpbuf
) + payload_length
;
2685 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.linSynchFieldEvent
.linBusEvent
.channel
, UINT16_MAX
, len
, len
);
2691 blf_read_linsenderror2(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, uint16_t object_version
) {
2692 blf_linsenderror2_t linmessage
;
2694 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2695 *err
= WTAP_ERR_BAD_FILE
;
2696 *err_info
= ws_strdup("blf: LIN_SND_ERROR2: not enough bytes for linsenderror2 in object");
2697 ws_debug("not enough bytes for linsenderror2 in object");
2701 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2702 ws_debug("not enough bytes for linsenderror2 in file");
2705 fix_endianness_blf_linsenderror2(&linmessage
);
2707 linmessage
.linMessageDescriptor
.dlc
&= 0x0f;
2708 linmessage
.linMessageDescriptor
.id
&= 0x3f;
2711 tmpbuf
[0] = 1; /* message format rev = 1 */
2712 tmpbuf
[1] = 0; /* reserved */
2713 tmpbuf
[2] = 0; /* reserved */
2714 tmpbuf
[3] = 0; /* reserved */
2715 tmpbuf
[4] = linmessage
.linMessageDescriptor
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2716 if (object_version
>= 1) { /* The 'checksumModel' field is valid only if objectVersion >= 1 */
2717 switch (linmessage
.linMessageDescriptor
.checksumModel
) {
2719 tmpbuf
[4] |= 1; /* Classic */
2722 tmpbuf
[4] |= 2; /* Enhanced */
2728 tmpbuf
[5] = linmessage
.linMessageDescriptor
.id
; /* parity (2bit) | id (6bit) */
2729 tmpbuf
[6] = 0; /* checksum */
2730 tmpbuf
[7] = 0x01; /* errors */
2732 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2733 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2735 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.linMessageDescriptor
.linSynchFieldEvent
.linBusEvent
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2741 blf_read_linwakeupevent2(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
2742 blf_linwakeupevent2_t linevent
;
2744 if (object_length
< (data_start
- block_start
) + (int)sizeof(linevent
)) {
2745 *err
= WTAP_ERR_BAD_FILE
;
2746 *err_info
= ws_strdup("blf: LIN_WAKEUP2: not enough bytes for linwakeup2 in object");
2747 ws_debug("not enough bytes for linwakeup2 in object");
2751 if (!blf_read_bytes(params
, data_start
, &linevent
, sizeof(linevent
), err
, err_info
)) {
2752 ws_debug("not enough bytes for linwakeup2 in file");
2755 fix_endianness_blf_linwakeupevent2(&linevent
);
2757 uint8_t tmpbuf
[12]; /* LIN events have a fixed length of 12 bytes */
2758 tmpbuf
[0] = 1; /* message format rev = 1 */
2759 tmpbuf
[1] = 0; /* reserved */
2760 tmpbuf
[2] = 0; /* reserved */
2761 tmpbuf
[3] = 0; /* reserved */
2762 tmpbuf
[4] = 3 << 2; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2763 tmpbuf
[5] = 0; /* parity (2bit) | id (6bit) */
2764 tmpbuf
[6] = 0; /* checksum */
2765 tmpbuf
[7] = 0; /* errors */
2773 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2774 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2776 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linevent
.linBusEvent
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2782 blf_read_linsleepmodeevent(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
2783 blf_linsleepmodeevent_t linevent
;
2785 if (object_length
< (data_start
- block_start
) + (int)sizeof(linevent
)) {
2786 *err
= WTAP_ERR_BAD_FILE
;
2787 *err_info
= ws_strdup("blf: LIN_SLEEP: not enough bytes for linsleep in object");
2788 ws_debug("not enough bytes for linsleep in object");
2792 if (!blf_read_bytes(params
, data_start
, &linevent
, sizeof(linevent
), err
, err_info
)) {
2793 ws_debug("not enough bytes for linsleep in file");
2796 linevent
.channel
= GUINT16_FROM_LE(linevent
.channel
);
2798 uint8_t tmpbuf
[12]; /* LIN events have a fixed length of 12 bytes */
2799 tmpbuf
[0] = 1; /* message format rev = 1 */
2800 tmpbuf
[1] = 0; /* reserved */
2801 tmpbuf
[2] = 0; /* reserved */
2802 tmpbuf
[3] = 0; /* reserved */
2803 tmpbuf
[4] = 3 << 2; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2804 tmpbuf
[5] = 0; /* parity (2bit) | id (6bit) */
2805 tmpbuf
[6] = 0; /* checksum */
2806 tmpbuf
[7] = 0; /* errors */
2808 switch (linevent
.reason
) {
2809 case BLF_LIN_SLEEP_REASON_GO_TO_SLEEP_FRAME
:
2810 /* Go-to-Sleep event by Go-to-Sleep frame */
2816 case BLF_LIN_SLEEP_REASON_BUS_IDLE_TIMEOUT
:
2817 case BLF_LIN_SLEEP_REASON_SILENT_SLEEPMODE_CMD
:
2818 /* Go-to-Sleep event by Inactivity for more than 4s */
2824 case BLF_LIN_WU_REASON_EXTERNAL_WAKEUP_SIG
:
2825 case BLF_LIN_WU_REASON_INTERNAL_WAKEUP_SIG
:
2826 case BLF_LIN_WU_REASON_BUS_TRAFFIC
: /* There's no "wake-up by bus traffic" event in the LIN packet. */
2827 /* Wake-up event by Wake-up signal */
2833 case BLF_LIN_WU_SLEEP_REASON_START_STATE
:
2834 case BLF_LIN_NO_SLEEP_REASON_BUS_TRAFFIC
:
2835 /* If we're just reporting on the initial state,
2836 * or the interface doesn't want to go to sleep,
2837 * report the current state as "event". */
2838 if (linevent
.flags
& 0x2) {
2839 /* Wake-up event by Wake-up signal */
2846 /* Go-to-Sleep event by Inactivity for more than 4s */
2861 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2862 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2864 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linevent
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2869 uint16_t blf_get_xml_channel_number(const char* start
, const char* end
) {
2874 if (start
== NULL
|| end
== NULL
|| end
<= start
) {
2878 len
= (size_t)(end
- start
);
2879 text
= g_try_malloc(len
+ 1); /* Accommodate '\0' */
2881 ws_debug("cannot allocate memory");
2884 memcpy(text
, start
, len
);
2887 if (!ws_strtou16(text
, NULL
, &res
)) {
2895 char* blf_get_xml_channel_name(const char* start
, const char* end
) {
2899 if (start
== NULL
|| end
== NULL
|| end
<= start
) {
2903 len
= (size_t)(end
- start
);
2904 text
= g_try_malloc(len
+ 1); /* Accommodate '\0' */
2906 ws_debug("cannot allocate memory");
2909 memcpy(text
, start
, len
);
2915 bool blf_parse_xml_port(const char* start
, const char* end
, char** name
, uint16_t* hwchannel
, bool* simulated
) {
2916 static const char name_magic
[] = "name=";
2917 static const char hwchannel_magic
[] = "hwchannel=";
2918 static const char simulated_magic
[] = "simulated=";
2925 if (start
== NULL
|| end
== NULL
|| name
== NULL
|| end
<= start
) {
2929 len
= (size_t)(end
- start
);
2930 text
= g_try_malloc(len
+ 1); /* Accommodate '\0' */
2932 ws_debug("cannot allocate memory");
2935 memcpy(text
, start
, len
);
2938 tokens
= g_strsplit_set(text
, ";", -1);
2940 if (tokens
== NULL
) {
2941 ws_debug("cannot split XML port data");
2946 *hwchannel
= UINT16_MAX
;
2949 for (int i
= 0; tokens
[i
] != NULL
; i
++) {
2951 if (strncmp(token
, name_magic
, strlen(name_magic
)) == 0) {
2952 if (*name
== NULL
) { /* Avoid memory leak in case of malformed string */
2953 *name
= ws_strdup(token
+ strlen(name_magic
));
2956 else if (strncmp(token
, hwchannel_magic
, strlen(hwchannel_magic
)) == 0) {
2957 if (!ws_strtou16(token
+ strlen(hwchannel_magic
), NULL
, hwchannel
)) {
2958 *hwchannel
= UINT16_MAX
;
2961 else if (strncmp(token
, simulated_magic
, strlen(simulated_magic
)) == 0) {
2962 if (strlen(token
) > strlen(simulated_magic
) && token
[strlen(simulated_magic
)] != '0') {
2963 *simulated
= true; /* TODO: Find a way to use this information */
2973 int blf_get_xml_pkt_encap(const char* start
, const char* end
) {
2976 if (start
== NULL
|| end
== NULL
|| end
<= start
) {
2980 len
= (size_t)(end
- start
);
2982 if (strncmp(start
, "CAN", len
) == 0) {
2983 return WTAP_ENCAP_SOCKETCAN
;
2985 if (strncmp(start
, "FlexRay", len
) == 0) {
2986 return WTAP_ENCAP_FLEXRAY
;
2988 if (strncmp(start
, "LIN", len
) == 0) {
2989 return WTAP_ENCAP_LIN
;
2991 if (strncmp(start
, "Ethernet", len
) == 0) {
2992 return WTAP_ENCAP_ETHERNET
;
2994 if (strncmp(start
, "WLAN", len
) == 0) { /* Not confirmed with a real capture */
2995 return WTAP_ENCAP_IEEE_802_11
;
3001 /** Finds a NULL-terminated string in a block of memory.
3003 * 'start' points to the first byte of the block of memory.
3004 * 'end' points to the first byte after the end of the block of memory,
3005 * so that the size of the block is end-start.
3006 * 'str' is a NULL-terminated string.
3008 const char* blf_strmem(const char* start
, const char* end
, const char* str
) {
3009 if (start
== NULL
|| end
== NULL
|| str
== NULL
|| end
<= start
) {
3013 return ws_memmem(start
, end
- start
, str
, strlen(str
));
3016 /** Extracts the channel and port names from a channels XML.
3018 * A sample channels XML looks like this:
3020 * <?xml version="1.0" encoding="UTF-8"?>
3021 * <channels version="1">
3022 * <channel number="1" type="CAN" network="CAN01">
3024 * <database file="DB.arxml" path="C:\...\" cluster="CAN01" />
3025 * <database file="DB.dbc" path="C:\...\" cluster="General" />
3028 * <channel number="1" type="LIN" network="LIN01">
3030 * <database file="DB.dbc" path="C:\...\" cluster="General" />
3031 * <database file="DB.ldf" path="C:\...\" cluster="LIN01" />
3034 * <channel number="1" type="Ethernet" network="ETH01">
3036 * <database file="DB.dbc" path="C:\...\" cluster="General" />
3038 * <channel_properties>
3039 * <elist name="ports">
3040 * <eli name="port">name=Port1;hwchannel=11;simulated=1</eli>
3041 * <eli name="port">name=Port2;hwchannel=12;simulated=0</eli>
3043 * </channel_properties>
3048 blf_set_xml_channels(blf_params_t
* params
, const char* text
, size_t len
) {
3049 static const char xml_magic
[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
3050 static const char channels_start_magic
[] = "<channels ";
3051 static const char channels_end_magic
[] = "</channels>";
3052 static const char channel_start_magic
[] = "<channel ";
3053 static const char channel_end_magic
[] = "</channel>";
3054 static const char number_start_magic
[] = "number=\"";
3055 static const char number_end_magic
[] = "\"";
3056 static const char type_start_magic
[] = "type=\"";
3057 static const char type_end_magic
[] = "\"";
3058 static const char network_start_magic
[] = "network=\"";
3059 static const char network_end_magic
[] = "\"";
3060 static const char ports_start_magic
[] = "<elist name=\"ports\">";
3061 static const char ports_end_magic
[] = "</elist>";
3062 static const char port_start_magic
[] = "<eli name=\"port\">";
3063 static const char port_end_magic
[] = "</eli>";
3065 const char* xml_start
;
3066 const char* channels_start
;
3067 const char* channels_end
;
3068 const char* channel_start
;
3069 const char* channel_end
;
3070 const char* number_start
;
3071 const char* number_end
;
3072 const char* type_start
;
3073 const char* type_end
;
3074 const char* network_start
;
3075 const char* network_end
;
3076 const char* ports_start
;
3077 const char* ports_end
;
3078 const char* port_start
;
3079 const char* port_end
;
3081 const char* search_start
;
3086 uint16_t hwchannel
= UINT16_MAX
;
3087 char* channel_name
= NULL
;
3088 char* port_name
= NULL
;
3089 bool simulated
= false;
3090 char* iface_name
= NULL
;
3092 if (text
== NULL
|| len
< strlen(xml_magic
)) {
3096 xml_start
= blf_strmem(text
, text
+ len
, xml_magic
);
3097 if (xml_start
== NULL
) {
3098 ws_debug("no valid xml magic found");
3101 search_start
= xml_start
+ strlen(xml_magic
);
3103 channels_start
= blf_strmem(search_start
, text
+ len
, channels_start_magic
);
3104 channels_end
= blf_strmem(search_start
, text
+ len
, channels_end_magic
);
3105 if (channels_start
== NULL
|| channels_end
== NULL
|| channels_end
<= channels_start
+ strlen(channels_start_magic
)) {
3106 ws_debug("no channels tag found in xml");
3109 search_start
= channels_start
+ strlen(channels_start_magic
);
3111 while (search_start
< channels_end
) {
3112 channel_start
= blf_strmem(search_start
, channels_end
, channel_start_magic
);
3113 search_start
= search_start
+ strlen(channel_start_magic
);
3114 channel_end
= blf_strmem(search_start
, channels_end
, channel_end_magic
);
3115 if (channel_start
== NULL
|| channel_end
== NULL
|| channel_end
<= channel_start
+ strlen(channel_start_magic
)) {
3116 ws_debug("found end of channel list");
3120 number_start
= blf_strmem(channel_start
, channel_end
, number_start_magic
);
3121 if (number_start
== NULL
) {
3122 ws_debug("channel without number found in xml");
3123 search_start
= channel_end
+ strlen(channel_end_magic
);
3127 number_end
= blf_strmem(number_start
+ strlen(number_start_magic
), channel_end
, number_end_magic
);
3128 if (number_end
== NULL
) {
3129 ws_debug("channel with malformed number attribute found in xml");
3130 search_start
= channel_end
+ strlen(channel_end_magic
);
3134 channel
= blf_get_xml_channel_number(number_start
+ strlen(number_start_magic
), number_end
);
3135 if (channel
== UINT16_MAX
) {
3136 ws_debug("invalid channel number found in xml");
3137 search_start
= channel_end
+ strlen(channel_end_magic
);
3141 type_start
= blf_strmem(channel_start
, channel_end
, type_start_magic
);
3142 if (type_start
== NULL
) {
3143 ws_debug("channel without type found in xml");
3144 search_start
= channel_end
+ strlen(channel_end_magic
);
3148 type_end
= blf_strmem(type_start
+ strlen(type_start_magic
), channel_end
, type_end_magic
);
3149 if (type_end
== NULL
) {
3150 ws_debug("channel with malformed type attribute found in xml");
3151 search_start
= channel_end
+ strlen(channel_end_magic
);
3155 pkt_encap
= blf_get_xml_pkt_encap(type_start
+ strlen(type_start_magic
), type_end
);
3157 network_start
= blf_strmem(channel_start
, channel_end
, network_start_magic
);
3158 if (network_start
== NULL
) {
3159 ws_debug("channel without name found in xml");
3160 search_start
= channel_end
+ strlen(channel_end_magic
);
3164 network_end
= blf_strmem(network_start
+ strlen(network_start_magic
), channel_end
, network_end_magic
);
3165 if (network_end
== NULL
) {
3166 ws_debug("channel with malformed network attribute found in xml");
3167 search_start
= channel_end
+ strlen(channel_end_magic
);
3171 channel_name
= blf_get_xml_channel_name(network_start
+ strlen(network_start_magic
), network_end
);
3172 if (channel_name
== NULL
|| strlen(channel_name
) == 0) {
3173 ws_debug("channel with empty name found in xml");
3175 g_free(channel_name
);
3176 channel_name
= NULL
;
3178 search_start
= channel_end
+ strlen(channel_end_magic
);
3182 ws_debug("Found channel in XML: PKT_ENCAP: %d, ID: %u, name: %s", pkt_encap
, channel
, channel_name
);
3183 blf_prepare_interface_name(params
, pkt_encap
, channel
, UINT16_MAX
, channel_name
, true);
3185 search_start
= MAX(MAX(number_end
+ strlen(number_end_magic
), type_end
+ strlen(type_end_magic
)), network_end
+ strlen(network_end_magic
));
3187 ports_start
= blf_strmem(search_start
, channel_end
, ports_start_magic
);
3188 if (ports_start
== NULL
) {
3189 /* Not an error, channel has no ports */
3190 g_free(channel_name
);
3191 channel_name
= NULL
;
3192 search_start
= channel_end
+ strlen(channel_end_magic
);
3196 search_start
= ports_start
+ strlen(ports_start_magic
);
3198 ports_end
= blf_strmem(search_start
, channel_end
, ports_end_magic
);
3199 if (ports_end
== NULL
) {
3200 ws_debug("channel with malformed ports tag found in xml");
3201 g_free(channel_name
);
3202 channel_name
= NULL
;
3203 search_start
= channel_end
+ strlen(channel_end_magic
);
3207 while (search_start
< ports_end
) {
3208 port_start
= blf_strmem(search_start
, ports_end
, port_start_magic
);
3209 port_end
= blf_strmem(search_start
+ strlen(port_start_magic
), ports_end
, port_end_magic
);
3210 if (port_start
== NULL
|| port_end
== NULL
|| port_end
<= port_start
+ strlen(port_start_magic
)) {
3211 ws_debug("found end of ports list");
3212 search_start
= ports_end
+ strlen(ports_end_magic
);
3216 res
= blf_parse_xml_port(port_start
+ strlen(port_start_magic
), port_end
, &port_name
, &hwchannel
, &simulated
);
3217 if (!res
|| port_name
== NULL
|| hwchannel
== UINT16_MAX
) {
3222 ws_debug("port with missing or malformed info found in xml");
3223 search_start
= port_end
+ strlen(port_end_magic
);
3227 iface_name
= ws_strdup_printf("%s::%s", channel_name
, port_name
);
3228 ws_debug("Found channel in XML: PKT_ENCAP: %d, ID: %u, HW ID: %u, name: %s", pkt_encap
, channel
, hwchannel
, iface_name
);
3229 blf_prepare_interface_name(params
, pkt_encap
, channel
, hwchannel
, iface_name
, true);
3237 search_start
= port_end
+ strlen(port_end_magic
);
3240 g_free(channel_name
);
3241 channel_name
= NULL
;
3243 search_start
= channel_end
+ strlen(channel_end_magic
);
3250 blf_read_apptextmessage(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, size_t metadata_cont
) {
3251 blf_apptext_t apptextheader
;
3253 if (object_length
< (data_start
- block_start
) + (int)sizeof(apptextheader
)) {
3254 *err
= WTAP_ERR_BAD_FILE
;
3255 *err_info
= ws_strdup("blf: APP_TEXT: not enough bytes for apptext header in object");
3256 ws_debug("not enough bytes for apptext header in object");
3257 return BLF_APPTEXT_FAILED
;
3260 if (!blf_read_bytes(params
, data_start
, &apptextheader
, sizeof(apptextheader
), err
, err_info
)) {
3261 ws_debug("not enough bytes for apptext header in file");
3262 return BLF_APPTEXT_FAILED
;
3264 fix_endianness_blf_apptext_header(&apptextheader
);
3266 if (metadata_cont
&& apptextheader
.source
!= BLF_APPTEXT_METADATA
) {
3267 /* If we're in the middle of a sequence of metadata objects,
3268 * but we get an AppText object from another source,
3269 * skip the previously incomplete object and start fresh.
3274 /* Add an extra byte for a terminating '\0' */
3275 char* text
= g_try_malloc((size_t)apptextheader
.textLength
+ 1);
3277 ws_debug("cannot allocate memory");
3278 return BLF_APPTEXT_FAILED
;
3281 if (!blf_read_bytes(params
, data_start
+ sizeof(apptextheader
), text
, apptextheader
.textLength
, err
, err_info
)) {
3282 ws_debug("not enough bytes for apptext text in file");
3284 return BLF_APPTEXT_FAILED
;
3286 text
[apptextheader
.textLength
] = '\0'; /* Here's the '\0' */
3288 switch (apptextheader
.source
) {
3289 case BLF_APPTEXT_CHANNEL
:
3292 /* returns a NULL terminated array of NULL terminates strings */
3293 char** tokens
= g_strsplit_set(text
, ";", -1);
3295 if (tokens
== NULL
|| tokens
[0] == NULL
|| tokens
[1] == NULL
) {
3296 if (tokens
!= NULL
) {
3300 return BLF_APPTEXT_CHANNEL
;
3303 uint16_t channel
= (apptextheader
.reservedAppText1
>> 8) & 0xff;
3306 switch ((apptextheader
.reservedAppText1
>> 16) & 0xff) {
3307 case BLF_BUSTYPE_CAN
:
3308 pkt_encap
= WTAP_ENCAP_SOCKETCAN
;
3311 case BLF_BUSTYPE_FLEXRAY
:
3312 pkt_encap
= WTAP_ENCAP_FLEXRAY
;
3315 case BLF_BUSTYPE_LIN
:
3316 pkt_encap
= WTAP_ENCAP_LIN
;
3319 case BLF_BUSTYPE_ETHERNET
:
3320 pkt_encap
= WTAP_ENCAP_ETHERNET
;
3323 case BLF_BUSTYPE_WLAN
:
3324 pkt_encap
= WTAP_ENCAP_IEEE_802_11
;
3328 pkt_encap
= 0xffffffff;
3332 /* we use lookup to create interface, if not existing yet */
3333 blf_prepare_interface_name(params
, pkt_encap
, channel
, UINT16_MAX
, tokens
[1], false);
3337 return BLF_APPTEXT_CHANNEL
;
3339 case BLF_APPTEXT_METADATA
:
3340 if (metadata_cont
) {
3341 /* Set the buffer pointer to the end of the previous object */
3342 params
->buf
->first_free
= metadata_cont
;
3345 /* First object of a sequence of one or more */
3346 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_DISSECTOR_NAME
, "data-text-lines");
3347 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_COL_PROT_TEXT
, "BLF App text");
3348 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_COL_INFO_TEXT
, "Metadata");
3349 wtap_buffer_append_epdu_end(params
->buf
);
3352 ws_buffer_assure_space(params
->buf
, apptextheader
.textLength
);
3353 ws_buffer_append(params
->buf
, text
, apptextheader
.textLength
);
3356 if ((apptextheader
.reservedAppText1
& 0x00ffffff) > apptextheader
.textLength
) {
3357 /* Continues in the next object */
3358 return BLF_APPTEXT_CONT
;
3361 if (((apptextheader
.reservedAppText1
>> 24) & 0xff) == BLF_APPTEXT_XML_CHANNELS
) {
3362 blf_set_xml_channels(params
, params
->buf
->data
, ws_buffer_length(params
->buf
));
3365 /* Override the timestamp with 0 for metadata objects. Thay can only occur at the beginning of the file, and they usually already have a timestamp of 0. */
3366 blf_init_rec(params
, 0, 0, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, 0, UINT16_MAX
, (uint32_t)ws_buffer_length(params
->buf
), (uint32_t)ws_buffer_length(params
->buf
));
3367 return BLF_APPTEXT_METADATA
;
3368 case BLF_APPTEXT_COMMENT
:
3369 case BLF_APPTEXT_ATTACHMENT
:
3370 case BLF_APPTEXT_TRACELINE
:
3372 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_DISSECTOR_NAME
, "data-text-lines");
3373 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_COL_PROT_TEXT
, "BLF App text");
3375 char* info_line
= NULL
;
3376 switch (apptextheader
.source
) {
3377 case BLF_APPTEXT_COMMENT
:
3378 info_line
= ws_strdup_printf("Comment: %s", text
);
3380 case BLF_APPTEXT_ATTACHMENT
:
3381 info_line
= ws_strdup_printf("Attachment: %s", text
);
3383 case BLF_APPTEXT_TRACELINE
:
3384 info_line
= ws_strdup_printf("Trace line%s: %s", (apptextheader
.reservedAppText1
& 0x00000010) ? "" : " (hidden)", text
);
3390 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_COL_INFO_TEXT
, info_line
);
3391 wtap_buffer_append_epdu_end(params
->buf
);
3393 size_t text_length
= strlen(text
); /* The string can contain '\0' before textLength bytes */
3394 ws_buffer_assure_space(params
->buf
, text_length
); /* The dissector doesn't need NULL-terminated strings */
3395 ws_buffer_append(params
->buf
, text
, text_length
);
3397 /* We'll write this as a WS UPPER PDU packet with a text blob */
3398 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, 0, UINT16_MAX
, (uint32_t)ws_buffer_length(params
->buf
), (uint32_t)ws_buffer_length(params
->buf
));
3403 return apptextheader
.source
;
3407 return BLF_APPTEXT_CHANNEL
; /* Cheat - no block to write */;
3409 return BLF_APPTEXT_CHANNEL
; /* Cheat - no block to write */
3413 blf_read_ethernet_status(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, uint16_t object_version
) {
3414 blf_ethernet_status_t ethernet_status_header
;
3416 uint64_t linkUpDuration
;
3418 if (object_length
< (data_start
- block_start
) + (int)sizeof(ethernet_status_header
) + (int)(object_version
>= 1 ? 8 : 0)) {
3419 *err
= WTAP_ERR_BAD_FILE
;
3420 *err_info
= ws_strdup("blf: ETHERNET_STATUS: not enough bytes for ethernet status header in object");
3421 ws_debug("not enough bytes for ethernet status header in object");
3425 if (!blf_read_bytes(params
, data_start
, ðernet_status_header
, sizeof(ethernet_status_header
), err
, err_info
)) {
3426 ws_debug("not enough bytes for ethernet_status_header header in file");
3430 if (object_version
>= 1) {
3431 if (!blf_read_bytes(params
, data_start
+ sizeof(ethernet_status_header
), &linkUpDuration
, 8, err
, err_info
)) {
3432 ws_debug("not enough bytes for ethernet_status_header header in file");
3435 linkUpDuration
= GUINT64_FROM_LE(linkUpDuration
);
3438 fix_endianness_blf_ethernet_status_header(ðernet_status_header
);
3440 tmpbuf
[0] = (ethernet_status_header
.channel
& 0xff00) >> 8;
3441 tmpbuf
[1] = (ethernet_status_header
.channel
& 0x00ff);
3442 tmpbuf
[2] = (ethernet_status_header
.flags
& 0xff00) >> 8;
3443 tmpbuf
[3] = (ethernet_status_header
.flags
& 0x00ff);
3444 tmpbuf
[4] = (ethernet_status_header
.linkStatus
);
3445 tmpbuf
[5] = (ethernet_status_header
.ethernetPhy
);
3446 tmpbuf
[6] = (ethernet_status_header
.duplex
);
3447 tmpbuf
[7] = (ethernet_status_header
.mdi
);
3448 tmpbuf
[8] = (ethernet_status_header
.connector
);
3449 tmpbuf
[9] = (ethernet_status_header
.clockMode
);
3450 tmpbuf
[10] = (ethernet_status_header
.pairs
);
3451 tmpbuf
[11] = (ethernet_status_header
.hardwareChannel
);
3452 tmpbuf
[12] = (ethernet_status_header
.bitrate
& 0xff000000) >> 24;
3453 tmpbuf
[13] = (ethernet_status_header
.bitrate
& 0x00ff0000) >> 16;
3454 tmpbuf
[14] = (ethernet_status_header
.bitrate
& 0x0000ff00) >> 8;
3455 tmpbuf
[15] = (ethernet_status_header
.bitrate
& 0x000000ff);
3457 if (object_version
>= 1) {
3458 tmpbuf
[16] = (uint8_t)((linkUpDuration
& UINT64_C(0xff00000000000000)) >> 56);
3459 tmpbuf
[17] = (uint8_t)((linkUpDuration
& UINT64_C(0x00ff000000000000)) >> 48);
3460 tmpbuf
[18] = (uint8_t)((linkUpDuration
& UINT64_C(0x0000ff0000000000)) >> 40);
3461 tmpbuf
[19] = (uint8_t)((linkUpDuration
& UINT64_C(0x000000ff00000000)) >> 32);
3462 tmpbuf
[20] = (uint8_t)((linkUpDuration
& UINT64_C(0x00000000ff000000)) >> 24);
3463 tmpbuf
[21] = (uint8_t)((linkUpDuration
& UINT64_C(0x0000000000ff0000)) >> 16);
3464 tmpbuf
[22] = (uint8_t)((linkUpDuration
& UINT64_C(0x000000000000ff00)) >> 8);
3465 tmpbuf
[23] = (uint8_t)((linkUpDuration
& UINT64_C(0x00000000000000ff)));
3468 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_DISSECTOR_NAME
, "blf-ethernetstatus-obj");
3469 wtap_buffer_append_epdu_end(params
->buf
);
3471 ws_buffer_assure_space(params
->buf
, sizeof(ethernet_status_header
));
3472 ws_buffer_append(params
->buf
, tmpbuf
, (size_t)(object_version
>= 1 ? 24 : 16));
3474 /* We'll write this as a WS UPPER PDU packet with a data blob */
3475 /* This will create an interface with the "name" of the matching
3476 * WTAP_ENCAP_ETHERNET interface with the same channel and hardware
3477 * channel prefixed with "STATUS" and with a different interface ID,
3478 * because IDBs in pcapng can only have one linktype.
3479 * The other option would be to write everything as UPPER_PDU, including
3480 * the Ethernet data (with one of the "eth_" dissectors.)
3482 char* iface_name
= ws_strdup_printf("STATUS-ETH-%u-%u", ethernet_status_header
.channel
, ethernet_status_header
.hardwareChannel
);
3483 blf_lookup_interface(params
, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, ethernet_status_header
.channel
, ethernet_status_header
.hardwareChannel
, iface_name
);
3485 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, ethernet_status_header
.channel
, ethernet_status_header
.hardwareChannel
, (uint32_t)ws_buffer_length(params
->buf
), (uint32_t)ws_buffer_length(params
->buf
));
3487 if ((ethernet_status_header
.flags
& BLF_ETH_STATUS_HARDWARECHANNEL
) == BLF_ETH_STATUS_HARDWARECHANNEL
) {
3488 /* If HW channel valid */
3489 wtap_block_add_uint32_option(params
->rec
->block
, OPT_PKT_QUEUE
, ethernet_status_header
.hardwareChannel
);
3496 blf_read_ethernet_phystate(blf_params_t
* params
, int* err
, char** err_info
, int64_t block_start
, int64_t data_start
, int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
) {
3497 blf_ethernet_phystate_t ethernet_phystate_header
;
3500 if (object_length
< (data_start
- block_start
) + (int)sizeof(ethernet_phystate_header
)) {
3501 *err
= WTAP_ERR_BAD_FILE
;
3502 *err_info
= ws_strdup("blf: ETHERNET_PHY_STATE: not enough bytes for ethernet phystate header in object");
3503 ws_debug("not enough bytes for ethernet phystate header in object");
3507 if (!blf_read_bytes(params
, data_start
, ðernet_phystate_header
, sizeof(ethernet_phystate_header
), err
, err_info
)) {
3508 ws_debug("not enough bytes for ethernet phystate header in file");
3512 fix_endianness_blf_ethernet_phystate_header(ðernet_phystate_header
);
3514 tmpbuf
[0] = (ethernet_phystate_header
.channel
& 0xff00) >> 8;
3515 tmpbuf
[1] = (ethernet_phystate_header
.channel
& 0x00ff);
3516 tmpbuf
[2] = (ethernet_phystate_header
.flags
& 0xff00) >> 8;
3517 tmpbuf
[3] = (ethernet_phystate_header
.flags
& 0x00ff);
3518 tmpbuf
[4] = (ethernet_phystate_header
.phyState
);
3519 tmpbuf
[5] = (ethernet_phystate_header
.phyEvent
);
3520 tmpbuf
[6] = (ethernet_phystate_header
.hardwareChannel
);
3521 tmpbuf
[7] = (ethernet_phystate_header
.res1
);
3523 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_DISSECTOR_NAME
, "blf-ethernetphystate-obj");
3524 wtap_buffer_append_epdu_end(params
->buf
);
3526 ws_buffer_assure_space(params
->buf
, sizeof(ethernet_phystate_header
));
3527 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(ethernet_phystate_header
));
3529 /* We'll write this as a WS UPPER PDU packet with a data blob */
3530 /* This will create an interface with the "name" of the matching
3531 * WTAP_ENCAP_ETHERNET interface with the same channel and hardware
3532 * channel prefixed with "STATUS" and with a different interface ID,
3533 * because IDBs in pcapng can only have one linktype.
3534 * The other option would be to write everything as UPPER_PDU, including
3535 * the Ethernet data (with one of the "eth_" dissectors.)
3537 char* iface_name
= ws_strdup_printf("STATUS-ETH-%u-%u", ethernet_phystate_header
.channel
, ethernet_phystate_header
.hardwareChannel
);
3538 blf_lookup_interface(params
, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, ethernet_phystate_header
.channel
, ethernet_phystate_header
.hardwareChannel
, iface_name
);
3540 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, ethernet_phystate_header
.channel
, ethernet_phystate_header
.hardwareChannel
, (uint32_t)ws_buffer_length(params
->buf
), (uint32_t)ws_buffer_length(params
->buf
));
3542 if ((ethernet_phystate_header
.flags
& BLF_PHY_STATE_HARDWARECHANNEL
) == BLF_PHY_STATE_HARDWARECHANNEL
) {
3543 /* If HW channel valid */
3544 wtap_block_add_uint32_option(params
->rec
->block
, OPT_PKT_QUEUE
, ethernet_phystate_header
.hardwareChannel
);
3551 blf_read_block(blf_params_t
*params
, int64_t start_pos
, int *err
, char **err_info
) {
3552 blf_blockheader_t header
;
3553 blf_logobjectheader_t logheader
;
3554 blf_logobjectheader2_t logheader2
;
3555 blf_logobjectheader3_t logheader3
;
3557 uint64_t object_timestamp
;
3558 uint16_t object_version
;
3559 int64_t last_metadata_start
= 0;
3560 size_t metadata_cont
= 0;
3565 /* Resetting buffer */
3566 params
->buf
->first_free
= params
->buf
->start
;
3569 if (!blf_read_bytes_or_eof(params
, start_pos
, &header
, sizeof header
, err
, err_info
)) {
3570 ws_debug("not enough bytes for block header or unsupported file");
3571 if (*err
== WTAP_ERR_SHORT_READ
) {
3572 /* we have found the end that is not a short read therefore. */
3580 fix_endianness_blf_blockheader(&header
);
3582 if (memcmp(header
.magic
, blf_obj_magic
, sizeof(blf_obj_magic
))) {
3583 ws_debug("object magic is not LOBJ (pos: 0x%" PRIx64
")", start_pos
);
3589 /* we are moving back and try again but 1 byte later */
3590 /* TODO: better understand how this paddings works... */
3593 params
->blf_data
->start_of_last_obj
= start_pos
;
3595 if (!params
->random
) {
3596 /* Make sure that we start after this object next time,
3597 * but only if it's a linear read. We can have random reads
3598 * during the linear read, so we have to make sure we don't
3599 * lose track of our position.
3601 params
->blf_data
->current_real_seek_pos
= start_pos
+ MAX(MAX(16, header
.object_length
), header
.header_length
);
3604 switch (header
.header_type
) {
3605 case BLF_HEADER_TYPE_DEFAULT
:
3606 if (!blf_read_log_object_header(params
, err
, err_info
, start_pos
+ sizeof(blf_blockheader_t
), start_pos
+ header
.header_length
, &logheader
)) {
3609 flags
= logheader
.flags
;
3610 object_timestamp
= logheader
.object_timestamp
;
3611 object_version
= logheader
.object_version
;
3614 case BLF_HEADER_TYPE_2
:
3615 if (!blf_read_log_object_header2(params
, err
, err_info
, start_pos
+ sizeof(blf_blockheader_t
), start_pos
+ header
.header_length
, &logheader2
)) {
3618 flags
= logheader2
.flags
;
3619 object_timestamp
= logheader2
.object_timestamp
;
3620 object_version
= logheader2
.object_version
;
3623 case BLF_HEADER_TYPE_3
:
3624 if (!blf_read_log_object_header3(params
, err
, err_info
, start_pos
+ sizeof(blf_blockheader_t
), start_pos
+ header
.header_length
, &logheader3
)) {
3627 flags
= logheader3
.flags
;
3628 object_timestamp
= logheader3
.object_timestamp
;
3629 object_version
= logheader3
.object_version
;
3633 *err
= WTAP_ERR_UNSUPPORTED
;
3634 *err_info
= ws_strdup_printf("blf: unknown header type %u", header
.header_type
);
3635 ws_debug("unknown header type");
3639 if (metadata_cont
&& header
.object_type
!= BLF_OBJTYPE_APP_TEXT
) {
3640 /* If we're in the middle of a sequence of AppText metadata objects,
3641 * but we get an AppText object from another source,
3642 * skip the previous incomplete packet and start fresh.
3645 last_metadata_start
= 0;
3648 switch (header
.object_type
) {
3649 case BLF_OBJTYPE_LOG_CONTAINER
:
3650 *err
= WTAP_ERR_UNSUPPORTED
;
3651 *err_info
= ws_strdup("blf: log container in log container not supported");
3652 ws_debug("log container in log container not supported");
3655 case BLF_OBJTYPE_ETHERNET_FRAME
:
3656 return blf_read_ethernetframe(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3658 case BLF_OBJTYPE_ETHERNET_FRAME_EX
:
3659 return blf_read_ethernetframe_ext(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3661 case BLF_OBJTYPE_ETHERNET_RX_ERROR
:
3662 return blf_read_ethernet_rxerror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3664 case BLF_OBJTYPE_ETHERNET_ERROR_EX
:
3665 return blf_read_ethernetframe_ext(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3667 case BLF_OBJTYPE_WLAN_FRAME
:
3668 return blf_read_wlanframe(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3670 case BLF_OBJTYPE_CAN_MESSAGE
:
3671 return blf_read_canmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3673 case BLF_OBJTYPE_CAN_ERROR
:
3674 return blf_read_canerror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3676 case BLF_OBJTYPE_CAN_OVERLOAD
:
3677 return blf_read_canerror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3679 case BLF_OBJTYPE_CAN_MESSAGE2
:
3680 return blf_read_canmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3682 case BLF_OBJTYPE_CAN_ERROR_EXT
:
3683 return blf_read_canerrorext(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3685 case BLF_OBJTYPE_CAN_FD_MESSAGE
:
3686 return blf_read_canfdmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3688 case BLF_OBJTYPE_CAN_FD_MESSAGE_64
:
3689 return blf_read_canfdmessage64(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3691 case BLF_OBJTYPE_CAN_FD_ERROR_64
:
3692 return blf_read_canfderror64(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3694 case BLF_OBJTYPE_FLEXRAY_DATA
:
3695 return blf_read_flexraydata(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3697 case BLF_OBJTYPE_FLEXRAY_MESSAGE
:
3698 return blf_read_flexraymessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3700 case BLF_OBJTYPE_FLEXRAY_RCVMESSAGE
:
3701 return blf_read_flexrayrcvmessageex(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3703 case BLF_OBJTYPE_FLEXRAY_RCVMESSAGE_EX
:
3704 return blf_read_flexrayrcvmessageex(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3706 case BLF_OBJTYPE_LIN_MESSAGE
:
3707 return blf_read_linmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3709 case BLF_OBJTYPE_LIN_CRC_ERROR
:
3710 return blf_read_linmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3712 case BLF_OBJTYPE_LIN_RCV_ERROR
:
3713 return blf_read_linrcverror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3715 case BLF_OBJTYPE_LIN_SND_ERROR
:
3716 return blf_read_linsenderror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3718 case BLF_OBJTYPE_LIN_WAKEUP
:
3719 return blf_read_linwakeupevent(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3721 case BLF_OBJTYPE_LIN_MESSAGE2
:
3722 return blf_read_linmessage2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3724 case BLF_OBJTYPE_LIN_CRC_ERROR2
:
3725 return blf_read_lincrcerror2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3727 case BLF_OBJTYPE_LIN_RCV_ERROR2
:
3728 return blf_read_linrcverror2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3730 case BLF_OBJTYPE_LIN_SND_ERROR2
:
3731 return blf_read_linsenderror2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3733 case BLF_OBJTYPE_LIN_WAKEUP2
:
3734 return blf_read_linwakeupevent2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3736 case BLF_OBJTYPE_LIN_SLEEP
:
3737 return blf_read_linsleepmodeevent(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3739 case BLF_OBJTYPE_APP_TEXT
:
3741 int result
= blf_read_apptextmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, metadata_cont
);
3742 if (result
== BLF_APPTEXT_CONT
) {
3743 if (!metadata_cont
) {
3744 /* First object of a sequence, save its start position */
3745 last_metadata_start
= start_pos
;
3747 /* Save a pointer to the end of the buffer */
3748 metadata_cont
= params
->buf
->first_free
;
3751 if (result
== BLF_APPTEXT_METADATA
&& metadata_cont
) {
3752 /* Last object of a sequence, restore the start position of the first object */
3753 params
->blf_data
->start_of_last_obj
= last_metadata_start
;
3755 /* Reset everything and start fresh */
3756 last_metadata_start
= 0;
3760 case BLF_APPTEXT_FAILED
:
3762 case BLF_APPTEXT_COMMENT
:
3763 case BLF_APPTEXT_METADATA
:
3764 case BLF_APPTEXT_ATTACHMENT
:
3765 case BLF_APPTEXT_TRACELINE
:
3767 case BLF_APPTEXT_CHANNEL
:
3768 case BLF_APPTEXT_CONT
:
3770 /* we do not return since there is no packet to show here */
3771 start_pos
+= MAX(MAX(16, header
.object_length
), header
.header_length
);
3777 case BLF_OBJTYPE_ETHERNET_STATUS
:
3778 return blf_read_ethernet_status(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3780 case BLF_OBJTYPE_ETHERNET_PHY_STATE
:
3781 return blf_read_ethernet_phystate(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3783 case BLF_OBJTYPE_ENV_INTEGER
:
3784 case BLF_OBJTYPE_ENV_DOUBLE
:
3785 case BLF_OBJTYPE_ENV_STRING
:
3786 case BLF_OBJTYPE_ENV_DATA
:
3787 case BLF_OBJTYPE_SYS_VARIABLE
:
3788 case BLF_OBJTYPE_RESERVED5
: /* Despite the name, this is actually used. Maybe it's worth investigating the content. */
3789 case BLF_OBJTYPE_TEST_STRUCTURE
:
3790 ws_debug("skipping unsupported object type 0x%04x", header
.object_type
);
3791 start_pos
+= MAX(MAX(16, header
.object_length
), header
.header_length
);
3794 ws_info("unknown object type 0x%04x", header
.object_type
);
3795 start_pos
+= MAX(MAX(16, header
.object_length
), header
.header_length
);
3802 static bool blf_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
, int64_t *data_offset
) {
3803 blf_params_t blf_tmp
;
3806 blf_tmp
.fh
= wth
->fh
;
3807 blf_tmp
.random
= false;
3808 blf_tmp
.pipe
= wth
->ispipe
;
3811 blf_tmp
.blf_data
= (blf_t
*)wth
->priv
;
3813 if (!blf_read_block(&blf_tmp
, blf_tmp
.blf_data
->current_real_seek_pos
, err
, err_info
)) {
3816 *data_offset
= blf_tmp
.blf_data
->start_of_last_obj
;
3821 static bool blf_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
) {
3822 blf_params_t blf_tmp
;
3825 blf_tmp
.fh
= wth
->random_fh
;
3826 blf_tmp
.random
= true;
3827 blf_tmp
.pipe
= wth
->ispipe
;
3830 blf_tmp
.blf_data
= (blf_t
*)wth
->priv
;
3832 if (!blf_read_block(&blf_tmp
, seek_off
, err
, err_info
)) {
3833 ws_debug("couldn't read packet block (err=%d).", *err
);
3840 static void blf_free(blf_t
*blf
) {
3842 if (blf
->log_containers
!= NULL
) {
3843 for (unsigned i
= 0; i
< blf
->log_containers
->len
; i
++) {
3844 blf_log_container_t
* log_container
= &g_array_index(blf
->log_containers
, blf_log_container_t
, i
);
3845 if (log_container
->real_data
!= NULL
) {
3846 g_free(log_container
->real_data
);
3849 g_array_free(blf
->log_containers
, true);
3850 blf
->log_containers
= NULL
;
3852 if (blf
->channel_to_iface_ht
!= NULL
) {
3853 g_hash_table_destroy(blf
->channel_to_iface_ht
);
3854 blf
->channel_to_iface_ht
= NULL
;
3856 if (blf
->channel_to_name_ht
!= NULL
) {
3857 g_hash_table_destroy(blf
->channel_to_name_ht
);
3858 blf
->channel_to_name_ht
= NULL
;
3863 static void blf_close(wtap
*wth
) {
3864 blf_free((blf_t
*)wth
->priv
);
3866 /* TODO: do we need to reverse the wtap_add_idb? how? */
3869 wtap_open_return_val
3870 blf_open(wtap
*wth
, int *err
, char **err_info
) {
3871 blf_fileheader_t header
;
3874 ws_debug("opening file");
3876 if (!wtap_read_bytes_or_eof(wth
->fh
, &header
, sizeof(blf_fileheader_t
), err
, err_info
)) {
3878 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err
);
3879 if (*err
== 0 || *err
== WTAP_ERR_SHORT_READ
) {
3881 * Short read or EOF.
3883 * We're reading this as part of an open, so
3884 * the file is too short to be a blf file.
3889 return WTAP_OPEN_NOT_MINE
;
3891 return WTAP_OPEN_ERROR
;
3894 fix_endianness_blf_fileheader(&header
);
3896 if (memcmp(header
.magic
, blf_magic
, sizeof(blf_magic
))) {
3897 return WTAP_OPEN_NOT_MINE
;
3900 /* This seems to be an BLF! */
3901 /* Check for a valid header length */
3902 if (header
.header_length
< sizeof(blf_fileheader_t
)) {
3903 *err
= WTAP_ERR_BAD_FILE
;
3904 *err_info
= ws_strdup("blf: file header length too short");
3905 return WTAP_OPEN_ERROR
;
3908 /* skip past the header, which may include padding/reserved space */
3909 if (!wtap_read_bytes(wth
->fh
, NULL
, header
.header_length
- sizeof(blf_fileheader_t
), err
, err_info
)) {
3910 return WTAP_OPEN_ERROR
;
3913 /* Prepare our private context. */
3914 blf
= g_new(blf_t
, 1);
3915 blf
->log_containers
= g_array_new(false, false, sizeof(blf_log_container_t
));
3916 blf
->current_real_seek_pos
= 0;
3917 blf
->start_offset_ns
= blf_get_start_offset_ns(&header
.start_date
);
3919 blf
->channel_to_iface_ht
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &blf_free_key
, &blf_free_channel_to_iface_entry
);
3920 blf
->channel_to_name_ht
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, &blf_free_key
, &blf_free_channel_to_name_entry
);
3921 blf
->next_interface_id
= 0;
3923 wth
->priv
= (void *)blf
;
3924 wth
->file_encap
= WTAP_ENCAP_NONE
;
3925 wth
->snapshot_length
= 0;
3926 wth
->file_tsprec
= WTAP_TSPREC_UNKNOWN
;
3927 wth
->subtype_read
= blf_read
;
3928 wth
->subtype_seek_read
= blf_seek_read
;
3929 wth
->subtype_close
= blf_close
;
3930 wth
->file_type_subtype
= blf_file_type_subtype
;
3932 return WTAP_OPEN_MINE
;
3935 /* Options for interface blocks. */
3936 static const struct supported_option_type interface_block_options_supported
[] = {
3937 /* No comments, just an interface name. */
3938 { OPT_IDB_NAME
, ONE_OPTION_SUPPORTED
}
3941 static const struct supported_block_type blf_blocks_supported
[] = {
3942 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
},
3943 { WTAP_BLOCK_IF_ID_AND_INFO
, MULTIPLE_BLOCKS_SUPPORTED
, OPTION_TYPES_SUPPORTED(interface_block_options_supported
) },
3946 static const struct file_type_subtype_info blf_info
= {
3947 "Vector Informatik Binary Logging Format (BLF) logfile", "blf", "blf", NULL
,
3948 false, BLOCKS_SUPPORTED(blf_blocks_supported
),
3952 void register_blf(void)
3954 blf_file_type_subtype
= wtap_register_file_type_subtype(&blf_info
);
3957 * Register name for backwards compatibility with the
3958 * wtap_filetypes table in Lua.
3960 wtap_register_backwards_compatibility_lua_name("BLF", blf_file_type_subtype
);
3964 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3969 * indent-tabs-mode: nil
3972 * vi: set shiftwidth=4 tabstop=8 expandtab:
3973 * :indentSize=4:tabSize=8:noTabs=true: