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
->api_version
= GUINT32_FROM_LE(header
->api_version
);
343 header
->len_compressed
= GUINT64_FROM_LE(header
->len_compressed
);
344 header
->len_uncompressed
= GUINT64_FROM_LE(header
->len_uncompressed
);
345 header
->obj_count
= GUINT32_FROM_LE(header
->obj_count
);
346 header
->application_build
= GUINT32_FROM_LE(header
->application_build
);
347 fix_endianness_blf_date(&(header
->start_date
));
348 fix_endianness_blf_date(&(header
->end_date
));
349 header
->restore_point_offset
= GUINT32_FROM_LE(header
->restore_point_offset
);
353 fix_endianness_blf_blockheader(blf_blockheader_t
*header
) {
354 header
->header_length
= GUINT16_FROM_LE(header
->header_length
);
355 header
->header_type
= GUINT16_FROM_LE(header
->header_type
);
356 header
->object_length
= GUINT32_FROM_LE(header
->object_length
);
357 header
->object_type
= GUINT32_FROM_LE(header
->object_type
);
361 fix_endianness_blf_logcontainerheader(blf_logcontainerheader_t
*header
) {
362 header
->compression_method
= GUINT16_FROM_LE(header
->compression_method
);
363 header
->res1
= GUINT16_FROM_LE(header
->res1
);
364 header
->res2
= GUINT32_FROM_LE(header
->res2
);
365 header
->uncompressed_size
= GUINT32_FROM_LE(header
->uncompressed_size
);
366 header
->res4
= GUINT32_FROM_LE(header
->res4
);
370 fix_endianness_blf_logobjectheader(blf_logobjectheader_t
*header
) {
371 header
->flags
= GUINT32_FROM_LE(header
->flags
);
372 header
->client_index
= GUINT16_FROM_LE(header
->client_index
);
373 header
->object_version
= GUINT16_FROM_LE(header
->object_version
);
374 header
->object_timestamp
= GUINT64_FROM_LE(header
->object_timestamp
);
378 fix_endianness_blf_logobjectheader2(blf_logobjectheader2_t
*header
) {
379 header
->flags
= GUINT32_FROM_LE(header
->flags
);
380 header
->object_version
= GUINT16_FROM_LE(header
->object_version
);
381 header
->object_timestamp
= GUINT64_FROM_LE(header
->object_timestamp
);
382 header
->original_timestamp
= GUINT64_FROM_LE(header
->object_timestamp
);
386 fix_endianness_blf_logobjectheader3(blf_logobjectheader3_t
*header
) {
387 header
->flags
= GUINT32_FROM_LE(header
->flags
);
388 header
->static_size
= GUINT16_FROM_LE(header
->static_size
);
389 header
->object_version
= GUINT16_FROM_LE(header
->object_version
);
390 header
->object_timestamp
= GUINT64_FROM_LE(header
->object_timestamp
);
394 fix_endianness_blf_ethernetframeheader(blf_ethernetframeheader_t
*header
) {
395 header
->channel
= GUINT16_FROM_LE(header
->channel
);
396 header
->direction
= GUINT16_FROM_LE(header
->direction
);
397 header
->ethtype
= GUINT16_FROM_LE(header
->ethtype
);
398 header
->tpid
= GUINT16_FROM_LE(header
->tpid
);
399 header
->tci
= GUINT16_FROM_LE(header
->tci
);
400 header
->payloadlength
= GUINT16_FROM_LE(header
->payloadlength
);
404 fix_endianness_blf_ethernetframeheader_ex(blf_ethernetframeheader_ex_t
*header
) {
405 header
->struct_length
= GUINT16_FROM_LE(header
->struct_length
);
406 header
->flags
= GUINT16_FROM_LE(header
->flags
);
407 header
->channel
= GUINT16_FROM_LE(header
->channel
);
408 header
->hw_channel
= GUINT16_FROM_LE(header
->hw_channel
);
409 header
->frame_duration
= GUINT64_FROM_LE(header
->frame_duration
);
410 header
->frame_checksum
= GUINT32_FROM_LE(header
->frame_checksum
);
411 header
->direction
= GUINT16_FROM_LE(header
->direction
);
412 header
->frame_length
= GUINT16_FROM_LE(header
->frame_length
);
413 header
->frame_handle
= GUINT32_FROM_LE(header
->frame_handle
);
414 header
->error
= GUINT32_FROM_LE(header
->error
);
418 fix_endianness_blf_ethernet_rxerror(blf_ethernet_rxerror_t
* header
) {
419 header
->struct_length
= GUINT16_FROM_LE(header
->struct_length
);
420 header
->channel
= GUINT16_FROM_LE(header
->channel
);
421 header
->direction
= GUINT16_FROM_LE(header
->direction
);
422 header
->hw_channel
= GUINT16_FROM_LE(header
->hw_channel
);
423 header
->frame_checksum
= GUINT32_FROM_LE(header
->frame_checksum
);
424 header
->frame_length
= GUINT16_FROM_LE(header
->frame_length
);
425 header
->error
= GUINT32_FROM_LE(header
->error
);
429 fix_endianness_blf_wlanframeheader(blf_wlanframeheader_t
* header
) {
430 header
->channel
= GUINT16_FROM_LE(header
->channel
);
431 header
->flags
= GUINT16_FROM_LE(header
->flags
);
432 header
->signal_strength
= GUINT16_FROM_LE(header
->signal_strength
);
433 header
->signal_quality
= GUINT16_FROM_LE(header
->signal_quality
);
434 header
->frame_length
= GUINT16_FROM_LE(header
->frame_length
);
438 fix_endianness_blf_canmessage(blf_canmessage_t
*header
) {
439 header
->channel
= GUINT16_FROM_LE(header
->channel
);
440 header
->id
= GUINT32_FROM_LE(header
->id
);
444 fix_endianness_blf_canmessage2_trailer(blf_canmessage2_trailer_t
*header
) {
445 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
446 header
->reserved2
= GUINT16_FROM_LE(header
->reserved1
);
450 fix_endianness_blf_canfdmessage(blf_canfdmessage_t
*header
) {
451 header
->channel
= GUINT16_FROM_LE(header
->channel
);
452 header
->id
= GUINT32_FROM_LE(header
->id
);
453 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
454 header
->reservedCanFdMessage2
= GUINT32_FROM_LE(header
->reservedCanFdMessage2
);
458 fix_endianness_blf_canfdmessage64(blf_canfdmessage64_t
*header
) {
459 header
->id
= GUINT32_FROM_LE(header
->id
);
460 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
461 header
->flags
= GUINT32_FROM_LE(header
->flags
);
462 header
->btrCfgArb
= GUINT32_FROM_LE(header
->btrCfgArb
);
463 header
->btrCfgData
= GUINT32_FROM_LE(header
->btrCfgData
);
464 header
->timeOffsetBrsNs
= GUINT32_FROM_LE(header
->timeOffsetBrsNs
);
465 header
->timeOffsetCrcDelNs
= GUINT32_FROM_LE(header
->timeOffsetCrcDelNs
);
466 header
->bitCount
= GUINT16_FROM_LE(header
->bitCount
);
467 header
->crc
= GUINT32_FROM_LE(header
->crc
);
471 fix_endianness_blf_canerror(blf_canerror_t
*header
) {
472 header
->channel
= GUINT16_FROM_LE(header
->channel
);
473 header
->length
= GUINT16_FROM_LE(header
->length
);
477 fix_endianness_blf_canerrorext(blf_canerrorext_t
*header
) {
478 header
->channel
= GUINT16_FROM_LE(header
->channel
);
479 header
->length
= GUINT16_FROM_LE(header
->length
);
480 header
->flags
= GUINT32_FROM_LE(header
->flags
);
481 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
482 header
->id
= GUINT32_FROM_LE(header
->id
);
483 header
->errorCodeExt
= GUINT16_FROM_LE(header
->errorCodeExt
);
487 fix_endianness_blf_canfderror64(blf_canfderror64_t
*header
) {
488 header
->flags
= GUINT16_FROM_LE(header
->flags
);
489 header
->errorCodeExt
= GUINT16_FROM_LE(header
->errorCodeExt
);
490 header
->extFlags
= GUINT16_FROM_LE(header
->extFlags
);
491 header
->id
= GUINT32_FROM_LE(header
->id
);
492 header
->frameLength_in_ns
= GUINT32_FROM_LE(header
->frameLength_in_ns
);
493 header
->btrCfgArb
= GUINT32_FROM_LE(header
->btrCfgArb
);
494 header
->btrCfgData
= GUINT32_FROM_LE(header
->btrCfgData
);
495 header
->timeOffsetBrsNs
= GUINT32_FROM_LE(header
->timeOffsetBrsNs
);
496 header
->timeOffsetCrcDelNs
= GUINT32_FROM_LE(header
->timeOffsetCrcDelNs
);
497 header
->crc
= GUINT32_FROM_LE(header
->crc
);
498 header
->errorPosition
= GUINT16_FROM_LE(header
->errorPosition
);
502 fix_endianness_blf_flexraydata(blf_flexraydata_t
*header
) {
503 header
->channel
= GUINT16_FROM_LE(header
->channel
);
504 header
->messageId
= GUINT16_FROM_LE(header
->messageId
);
505 header
->crc
= GUINT16_FROM_LE(header
->crc
);
506 header
->reservedFlexRayData2
= GUINT16_FROM_LE(header
->reservedFlexRayData2
);
510 fix_endianness_blf_flexraymessage(blf_flexraymessage_t
*header
) {
511 header
->channel
= GUINT16_FROM_LE(header
->channel
);
512 header
->fpgaTick
= GUINT32_FROM_LE(header
->fpgaTick
);
513 header
->fpgaTickOverflow
= GUINT32_FROM_LE(header
->fpgaTickOverflow
);
514 header
->clientIndexFlexRayV6Message
= GUINT32_FROM_LE(header
->clientIndexFlexRayV6Message
);
515 header
->clusterTime
= GUINT32_FROM_LE(header
->clusterTime
);
516 header
->frameId
= GUINT16_FROM_LE(header
->frameId
);
517 header
->headerCrc
= GUINT16_FROM_LE(header
->headerCrc
);
518 header
->frameState
= GUINT16_FROM_LE(header
->frameState
);
519 header
->reservedFlexRayV6Message2
= GUINT16_FROM_LE(header
->reservedFlexRayV6Message2
);
523 fix_endianness_blf_flexrayrcvmessage(blf_flexrayrcvmessage_t
*header
) {
524 header
->channel
= GUINT16_FROM_LE(header
->channel
);
525 header
->version
= GUINT16_FROM_LE(header
->version
);
526 header
->channelMask
= GUINT16_FROM_LE(header
->channelMask
);
527 header
->dir
= GUINT16_FROM_LE(header
->dir
);
528 header
->clientIndex
= GUINT32_FROM_LE(header
->clientIndex
);
529 header
->clusterNo
= GUINT32_FROM_LE(header
->clusterNo
);
530 header
->frameId
= GUINT16_FROM_LE(header
->frameId
);
531 header
->headerCrc1
= GUINT16_FROM_LE(header
->headerCrc1
);
532 header
->headerCrc2
= GUINT16_FROM_LE(header
->headerCrc2
);
533 header
->payloadLength
= GUINT16_FROM_LE(header
->payloadLength
);
534 header
->payloadLengthValid
= GUINT16_FROM_LE(header
->payloadLengthValid
);
535 header
->cycle
= GUINT16_FROM_LE(header
->cycle
);
536 header
->tag
= GUINT32_FROM_LE(header
->tag
);
537 header
->data
= GUINT32_FROM_LE(header
->data
);
538 header
->frameFlags
= GUINT32_FROM_LE(header
->frameFlags
);
539 header
->appParameter
= GUINT32_FROM_LE(header
->appParameter
);
540 /* this would be extra for ext format:
541 header->frameCRC = GUINT32_FROM_LE(header->frameCRC);
542 header->frameLengthInNs = GUINT32_FROM_LE(header->frameLengthInNs);
543 header->frameId1 = GUINT16_FROM_LE(header->frameId1);
544 header->pduOffset = GUINT16_FROM_LE(header->pduOffset);
545 header->blfLogMask = GUINT16_FROM_LE(header->blfLogMask);
550 fix_endianness_blf_linmessage(blf_linmessage_t
* message
) {
551 message
->channel
= GUINT16_FROM_LE(message
->channel
);
552 message
->crc
= GUINT16_FROM_LE(message
->crc
);
553 /* skip the optional part
554 message->res2 = GUINT32_FROM_LE(message->res2);
559 fix_endianness_blf_linbusevent(blf_linbusevent_t
* linbusevent
) {
560 linbusevent
->sof
= GUINT64_FROM_LE(linbusevent
->sof
);
561 linbusevent
->eventBaudrate
= GUINT32_FROM_LE(linbusevent
->eventBaudrate
);
562 linbusevent
->channel
= GUINT16_FROM_LE(linbusevent
->channel
);
566 fix_endianness_blf_linsynchfieldevent(blf_linsynchfieldevent_t
* linsynchfieldevent
) {
567 fix_endianness_blf_linbusevent(&linsynchfieldevent
->linBusEvent
);
568 linsynchfieldevent
->synchBreakLength
= GUINT64_FROM_LE(linsynchfieldevent
->synchBreakLength
);
569 linsynchfieldevent
->synchDelLength
= GUINT64_FROM_LE(linsynchfieldevent
->synchDelLength
);
573 fix_endianness_blf_linmessagedescriptor(blf_linmessagedescriptor_t
* linmessagedescriptor
) {
574 fix_endianness_blf_linsynchfieldevent(&linmessagedescriptor
->linSynchFieldEvent
);
575 linmessagedescriptor
->supplierId
= GUINT16_FROM_LE(linmessagedescriptor
->supplierId
);
576 linmessagedescriptor
->messageId
= GUINT16_FROM_LE(linmessagedescriptor
->messageId
);
580 fix_endianness_blf_lindatabytetimestampevent(blf_lindatabytetimestampevent_t
* lindatabytetimestampevent
) {
582 fix_endianness_blf_linmessagedescriptor(&lindatabytetimestampevent
->linMessageDescriptor
);
583 for (i
= 0; i
< 9; i
++) {
584 lindatabytetimestampevent
->databyteTimestamps
[i
] = GUINT64_FROM_LE(lindatabytetimestampevent
->databyteTimestamps
[i
]);
589 fix_endianness_blf_linmessage2(blf_linmessage2_t
* message
) {
590 fix_endianness_blf_lindatabytetimestampevent(&message
->linDataByteTimestampEvent
);
591 message
->crc
= GUINT16_FROM_LE(message
->crc
);
592 /* skip the optional part
593 message->respBaudrate = GUINT32_FROM_LE(message->respBaudrate);
594 message->exactHeaderBaudrate = GUINT64_FROM_LE(message->exactHeaderBaudrate);
595 message->earlyStopBitOffset = GUINT32_FROM_LE(message->earlyStopBitOffset);
596 message->earlyStopBitOffsetResponse = GUINT32_FROM_LE(message->earlyStopBitOffsetResponse);
601 fix_endianness_blf_lincrcerror2(blf_lincrcerror2_t
* message
) {
602 fix_endianness_blf_lindatabytetimestampevent(&message
->linDataByteTimestampEvent
);
603 message
->crc
= GUINT16_FROM_LE(message
->crc
);
604 /* skip the optional part
605 message->respBaudrate = GUINT32_FROM_LE(message->respBaudrate);
606 message->exactHeaderBaudrate = GUINT64_FROM_LE(message->exactHeaderBaudrate);
607 message->earlyStopBitOffset = GUINT32_FROM_LE(message->earlyStopBitOffset);
608 message->earlyStopBitOffsetResponse = GUINT32_FROM_LE(message->earlyStopBitOffsetResponse);
613 fix_endianness_blf_linrcverror2(blf_linrcverror2_t
* message
) {
614 fix_endianness_blf_lindatabytetimestampevent(&message
->linDataByteTimestampEvent
);
615 /* skip the optional part
616 message->respBaudrate = GUINT32_FROM_LE(message->respBaudrate);
617 message->exactHeaderBaudrate = GUINT64_FROM_LE(message->exactHeaderBaudrate);
618 message->earlyStopBitOffset = GUINT32_FROM_LE(message->earlyStopBitOffset);
619 message->earlyStopBitOffsetResponse = GUINT32_FROM_LE(message->earlyStopBitOffsetResponse);
624 fix_endianness_blf_linsenderror2(blf_linsenderror2_t
* message
) {
625 fix_endianness_blf_linmessagedescriptor(&message
->linMessageDescriptor
);
626 message
->eoh
= GUINT64_FROM_LE(message
->eoh
);
627 /* skip the optional part
628 message->exactHeaderBaudrate = GUINT64_FROM_LE(message->exactHeaderBaudrate);
629 message->earlyStopBitOffset = GUINT32_FROM_LE(message->earlyStopBitOffset);
634 fix_endianness_blf_linwakeupevent2(blf_linwakeupevent2_t
* message
) {
635 fix_endianness_blf_linbusevent(&message
->linBusEvent
);
639 fix_endianness_blf_apptext_header(blf_apptext_t
*header
) {
640 header
->source
= GUINT32_FROM_LE(header
->source
);
641 header
->reservedAppText1
= GUINT32_FROM_LE(header
->reservedAppText1
);
642 header
->textLength
= GUINT32_FROM_LE(header
->textLength
);
643 header
->reservedAppText2
= GUINT32_FROM_LE(header
->reservedAppText2
);
647 fix_endianness_blf_ethernet_status_header(blf_ethernet_status_t
* header
) {
648 header
->channel
= GUINT16_FROM_LE(header
->channel
);
649 header
->flags
= GUINT16_FROM_LE(header
->flags
);
650 /*uint8_t linkStatus;*/
651 /*uint8_t ethernetPhy;*/
654 /*uint8_t connector;*/
655 /*uint8_t clockMode;*/
657 /*uint8_t hardwareChannel;*/
658 header
->bitrate
= GUINT32_FROM_LE(header
->bitrate
);
662 fix_endianness_blf_ethernet_phystate_header(blf_ethernet_phystate_t
* header
) {
663 header
->channel
= GUINT16_FROM_LE(header
->channel
);
664 header
->flags
= GUINT16_FROM_LE(header
->flags
);
668 blf_init_logcontainer(blf_log_container_t
*tmp
) {
669 tmp
->infile_start_pos
= 0;
670 tmp
->infile_length
= 0;
671 tmp
->infile_data_start
= 0;
672 tmp
->real_start_pos
= 0;
673 tmp
->real_length
= 0;
674 tmp
->real_data
= NULL
;
675 tmp
->compression_method
= 0;
679 blf_logcontainers_cmp(const void *a
, const void *b
) {
680 const blf_log_container_t
* container_a
= (blf_log_container_t
*)a
;
681 const blf_log_container_t
* container_b
= (blf_log_container_t
*)b
;
683 if (container_a
->real_start_pos
< container_b
->real_start_pos
) {
686 else if (container_a
->real_start_pos
> container_b
->real_start_pos
) {
695 blf_logcontainers_search(const void *a
, const void *b
) {
696 const blf_log_container_t
* container_a
= (blf_log_container_t
*)a
;
697 uint64_t pos
= *(uint64_t*)b
;
699 if (container_a
->real_start_pos
> pos
) {
702 else if (pos
>= container_a
->real_start_pos
+ container_a
->real_length
) {
710 /** Ensures the given log container is in memory
712 * If the log container already is not already in memory,
713 * it reads it from the current seek position, allocating a
714 * properly sized buffer.
715 * The file offset must be set to the start of the container
716 * data (container->infile_data_start) before calling this function.
719 blf_pull_logcontainer_into_memory(blf_params_t
*params
, blf_log_container_t
*container
, int *err
, char **err_info
) {
721 if (container
== NULL
) {
722 *err
= WTAP_ERR_INTERNAL
;
723 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory called with NULL container");
727 if (container
->real_data
!= NULL
) {
731 /* pull compressed data into buffer */
732 if (container
->infile_start_pos
< 0) {
734 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
735 * malformed file (WTAP_ERR_BAD_FILE)?
737 *err
= WTAP_ERR_INTERNAL
;
738 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: container.infile_start_pos (%" PRId64
") < 0",
739 container
->infile_start_pos
);
742 if (container
->infile_data_start
< (uint64_t)container
->infile_start_pos
) {
744 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
745 * malformed file (WTAP_ERR_BAD_FILE)?
747 *err
= WTAP_ERR_INTERNAL
;
748 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: container.infile_data_start (%" PRIu64
") < container.infile_start_pos (%" PRId64
")",
749 container
->infile_data_start
, container
->infile_start_pos
);
752 if (container
->infile_length
< container
->infile_data_start
- (uint64_t)container
->infile_start_pos
) {
754 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
755 * malformed file (WTAP_ERR_BAD_FILE)?
757 *err
= WTAP_ERR_INTERNAL
;
758 *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
,
759 container
->infile_length
,
760 container
->infile_data_start
, container
->infile_start_pos
,
761 container
->infile_data_start
- (uint64_t)container
->infile_start_pos
);
764 uint64_t data_length
= container
->infile_length
- (container
->infile_data_start
- (uint64_t)container
->infile_start_pos
);
765 if (data_length
> UINT_MAX
) {
767 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
768 * malformed file (WTAP_ERR_BAD_FILE)?
770 *err
= WTAP_ERR_INTERNAL
;
771 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: data_length (%" PRIu64
") > UINT_MAX",
776 if (container
->real_length
== 0) {
777 ws_info("blf_pull_logcontainer_into_memory: found container with 0 length");
778 /* Skip empty container */
779 if (!wtap_read_bytes_or_eof(params
->fh
, NULL
, (unsigned int)data_length
, err
, err_info
)) {
780 if (*err
== WTAP_ERR_SHORT_READ
) {
782 * XXX - our caller will turn this into an EOF.
783 * How *should* it be treated?
784 * For now, we turn it into Yet Another Internal Error,
785 * pending having better documentation of the file
788 *err
= WTAP_ERR_INTERNAL
;
789 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: short read on 0-length container");
796 if (container
->compression_method
== BLF_COMPRESSION_NONE
) {
797 unsigned char* buf
= g_try_malloc((size_t)container
->real_length
);
799 *err
= WTAP_ERR_INTERNAL
;
800 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: cannot allocate memory");
803 if (!wtap_read_bytes_or_eof(params
->fh
, buf
, (unsigned int)data_length
, err
, err_info
)) {
805 if (*err
== WTAP_ERR_SHORT_READ
) {
807 * XXX - our caller will turn this into an EOF.
808 * How *should* it be treated?
809 * For now, we turn it into Yet Another Internal Error,
810 * pending having better documentation of the file
813 *err
= WTAP_ERR_INTERNAL
;
814 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: short read on uncompressed data");
818 container
->real_data
= buf
;
822 else if (container
->compression_method
== BLF_COMPRESSION_ZLIB
) {
823 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
824 unsigned char *compressed_data
= g_try_malloc((size_t)data_length
);
825 if (compressed_data
== NULL
) {
826 *err
= WTAP_ERR_INTERNAL
;
827 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: cannot allocate memory");
830 if (!wtap_read_bytes_or_eof(params
->fh
, compressed_data
, (unsigned int)data_length
, err
, err_info
)) {
831 g_free(compressed_data
);
832 if (*err
== WTAP_ERR_SHORT_READ
) {
834 * XXX - our caller will turn this into an EOF.
835 * How *should* it be treated?
836 * For now, we turn it into Yet Another Internal Error,
837 * pending having better documentation of the file
840 *err
= WTAP_ERR_INTERNAL
;
841 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: short read on compressed data");
846 unsigned char *buf
= g_try_malloc((size_t)container
->real_length
);
848 g_free(compressed_data
);
849 *err
= WTAP_ERR_INTERNAL
;
850 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: cannot allocate memory");
853 zlib_stream infstream
= {0};
855 infstream
.avail_in
= (unsigned int)data_length
;
856 infstream
.next_in
= compressed_data
;
857 infstream
.avail_out
= (unsigned int)container
->real_length
;
858 infstream
.next_out
= buf
;
860 /* the actual DE-compression work. */
861 if (Z_OK
!= ZLIB_PREFIX(inflateInit
)(&infstream
)) {
863 * XXX - check the error code and handle this appropriately.
866 g_free(compressed_data
);
867 *err
= WTAP_ERR_INTERNAL
;
868 if (infstream
.msg
!= NULL
) {
869 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: inflateInit failed for LogContainer, message\"%s\"",
872 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: inflateInit failed for LogContainer");
874 ws_debug("inflateInit failed for LogContainer");
875 if (infstream
.msg
!= NULL
) {
876 ws_debug("inflateInit returned: \"%s\"", infstream
.msg
);
881 int ret
= ZLIB_PREFIX(inflate
)(&infstream
, Z_NO_FLUSH
);
882 /* Z_OK should not happen here since we know how big the buffer should be */
883 if (Z_STREAM_END
!= ret
) {
887 *err
= WTAP_ERR_DECOMPRESS
;
888 *err_info
= ws_strdup("preset dictionary needed");
892 *err
= WTAP_ERR_INTERNAL
;
893 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: Z_STREAM_ERROR from inflate(), message \"%s\"",
894 (infstream
.msg
!= NULL
) ? infstream
.msg
: "(none)");
898 /* This means "not enough memory". */
904 /* This means "deflate stream invalid" */
905 *err
= WTAP_ERR_DECOMPRESS
;
906 *err_info
= (infstream
.msg
!= NULL
) ? ws_strdup(infstream
.msg
) : NULL
;
910 /* XXX - this is recoverable; what should we do here? */
911 *err
= WTAP_ERR_INTERNAL
;
912 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: Z_BUF_ERROR from inflate(), message \"%s\"",
913 (infstream
.msg
!= NULL
) ? infstream
.msg
: "(none)");
916 case Z_VERSION_ERROR
:
917 *err
= WTAP_ERR_INTERNAL
;
918 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: Z_VERSION_ERROR from inflate(), message \"%s\"",
919 (infstream
.msg
!= NULL
) ? infstream
.msg
: "(none)");
923 *err
= WTAP_ERR_INTERNAL
;
924 *err_info
= ws_strdup_printf("blf_pull_logcontainer_into_memory: unexpected error %d from inflate(), message \"%s\"",
926 (infstream
.msg
!= NULL
) ? infstream
.msg
: "(none)");
930 g_free(compressed_data
);
931 ws_debug("inflate failed (return code %d) for LogContainer", ret
);
932 if (infstream
.msg
!= NULL
) {
933 ws_debug("inflate returned: \"%s\"", infstream
.msg
);
935 /* Free up any dynamically-allocated memory in infstream */
936 ZLIB_PREFIX(inflateEnd
)(&infstream
);
940 if (Z_OK
!= ZLIB_PREFIX(inflateEnd
)(&infstream
)) {
942 * The zlib manual says this only returns Z_OK on success
943 * and Z_STREAM_ERROR if the stream state was inconsistent.
945 * It's not clear what useful information can be reported
946 * for Z_STREAM_ERROR; a look at the 1.2.11 source indicates
947 * that no string is returned to indicate what the problem
950 * It's also not clear what to do about infstream if this
953 *err
= WTAP_ERR_INTERNAL
;
954 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: inflateEnd failed for LogContainer");
956 g_free(compressed_data
);
957 ws_debug("inflateEnd failed for LogContainer");
958 if (infstream
.msg
!= NULL
) {
959 ws_debug("inflateEnd returned: \"%s\"", infstream
.msg
);
964 g_free(compressed_data
);
965 container
->real_data
= buf
;
969 *err
= WTAP_ERR_DECOMPRESSION_NOT_SUPPORTED
;
970 *err_info
= ws_strdup("blf_pull_logcontainer_into_memory: reading gzip-compressed containers isn't supported");
978 /** Finds the next log container starting at the current file offset
980 * Adds the container to the containers array for later access
983 blf_find_next_logcontainer(blf_params_t
* params
, int* err
, char** err_info
) {
984 blf_blockheader_t header
;
985 blf_logcontainerheader_t logcontainer_header
;
986 blf_log_container_t tmp
;
987 unsigned char* header_ptr
;
990 uint64_t current_real_start
;
991 if (params
->blf_data
->log_containers
->len
== 0) {
992 current_real_start
= 0;
995 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);
996 current_real_start
= container
->real_start_pos
+ container
->real_length
;
999 header_ptr
= (unsigned char*)&header
;
1004 * We read one byte at a time so that we don't have to seek backward (allows us to do a linear read)
1006 while (i
< sizeof(blf_obj_magic
)) {
1007 if (!wtap_read_bytes_or_eof(params
->fh
, &header_ptr
[i
], 1, err
, err_info
)) {
1008 ws_debug("we found end of file");
1011 if (header_ptr
[i
] != blf_obj_magic
[i
]) {
1013 ws_debug("container object magic is not LOBJ");
1016 ws_debug("container object magic is not LOBJ (pos: 0x%" PRIx64
")", file_tell(params
->fh
) - 1);
1021 while (memcmp(&header_ptr
[i
- j
+ 1], blf_obj_magic
, j
)) {
1022 /* Check if the last j bytes match the first j bytes of the magic */
1026 /* The last j bytes match, and the first j bytes are already in the buffer, since j<=i */
1031 /* Character matches */
1036 if (!wtap_read_bytes_or_eof(params
->fh
, &header
.header_length
, sizeof(blf_blockheader_t
) - sizeof(blf_obj_magic
), err
, err_info
)) {
1037 ws_debug("we found end of file");
1041 fix_endianness_blf_blockheader(&header
);
1043 if (header
.header_length
< sizeof(blf_blockheader_t
)) {
1044 *err
= WTAP_ERR_BAD_FILE
;
1045 *err_info
= ws_strdup("blf: header length too short while looking for object");
1049 if (header
.header_type
!= BLF_HEADER_TYPE_DEFAULT
) {
1050 *err
= WTAP_ERR_UNSUPPORTED
;
1051 *err_info
= ws_strdup_printf("blf: unknown header type (%u), I know only BLF_HEADER_TYPE_DEFAULT (1)", header
.header_type
);
1055 if (header
.object_length
< header
.header_length
) {
1056 *err
= WTAP_ERR_BAD_FILE
;
1057 *err_info
= ws_strdup("blf: header object length less than header length while looking for objects");
1061 if (header
.object_type
== BLF_OBJTYPE_LOG_CONTAINER
) {
1062 /* skip unknown header part if needed */
1063 if (header
.header_length
> sizeof(blf_blockheader_t
)) {
1064 /* seek over unknown header part */
1065 if (!wtap_read_bytes(params
->fh
, NULL
, header
.header_length
- sizeof(blf_blockheader_t
), err
, err_info
)) {
1066 ws_debug("error skipping unknown header bytes in log container");
1071 /* Read the log container header */
1072 if (!wtap_read_bytes_or_eof(params
->fh
, &logcontainer_header
, sizeof(blf_logcontainerheader_t
), err
, err_info
)) {
1073 ws_debug("not enough bytes for log container header");
1077 fix_endianness_blf_logcontainerheader(&logcontainer_header
);
1079 blf_init_logcontainer(&tmp
);
1082 tmp
.infile_start_pos
= 0;
1083 tmp
.infile_data_start
= sizeof(blf_logcontainerheader_t
) + header
.header_length
;
1086 tmp
.infile_data_start
= file_tell(params
->fh
);
1087 tmp
.infile_start_pos
= tmp
.infile_data_start
- sizeof(blf_logcontainerheader_t
) - header
.header_length
;
1089 tmp
.infile_length
= header
.object_length
;
1091 tmp
.real_start_pos
= current_real_start
;
1092 tmp
.real_length
= logcontainer_header
.uncompressed_size
;
1093 tmp
.compression_method
= logcontainer_header
.compression_method
;
1095 ws_debug("found log container with real_pos=0x%" PRIx64
", real_length=0x%" PRIx64
, tmp
.real_start_pos
, tmp
.real_length
);
1098 ws_debug("found BLF object without log container");
1100 /* Create a fake log container for the lone object.
1101 * In order to avoid seeking backwards, we need to pull the fake log container now.
1103 unsigned char* buf
= g_try_malloc((size_t)header
.object_length
);
1106 * XXX - we need an "out of memory" error code here.
1108 *err
= WTAP_ERR_INTERNAL
;
1109 *err_info
= ws_strdup("blf_find_next_logcontainer: cannot allocate memory");
1113 memcpy(buf
, &header
, sizeof(blf_blockheader_t
));
1115 if (header
.object_length
> sizeof(blf_blockheader_t
)) {
1116 if (!wtap_read_bytes(params
->fh
, buf
+ sizeof(blf_blockheader_t
), header
.object_length
- sizeof(blf_blockheader_t
), err
, err_info
)) {
1118 ws_debug("cannot pull object without log container");
1123 blf_init_logcontainer(&tmp
);
1125 tmp
.infile_start_pos
= params
->pipe
? 0 : (file_tell(params
->fh
) - header
.object_length
);
1126 tmp
.infile_data_start
= tmp
.infile_start_pos
;
1127 tmp
.infile_length
= header
.object_length
;
1129 tmp
.real_start_pos
= current_real_start
;
1130 tmp
.real_length
= header
.object_length
;
1131 tmp
.compression_method
= BLF_COMPRESSION_NONE
;
1133 tmp
.real_data
= buf
;
1135 ws_debug("found non-log-container object with real_pos=0x%" PRIx64
", real_length=0x%" PRIx64
, tmp
.real_start_pos
, tmp
.real_length
);
1138 g_array_append_val(params
->blf_data
->log_containers
, tmp
);
1144 // NOLINTNEXTLINE(misc-no-recursion)
1145 blf_pull_next_logcontainer(blf_params_t
* params
, int* err
, char** err_info
) {
1146 blf_log_container_t
* container
;
1148 if (!blf_find_next_logcontainer(params
, err
, err_info
)) {
1152 /* Is there a next log container to pull? */
1153 if (params
->blf_data
->log_containers
->len
== 0) {
1158 container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, params
->blf_data
->log_containers
->len
- 1);
1159 if (!blf_pull_logcontainer_into_memory(params
, container
, err
, err_info
)) {
1160 if (*err
== WTAP_ERR_DECOMPRESS
) {
1161 report_warning("Error while decompressing BLF log container number %u (file pos. 0x%" PRIx64
"): %s",
1162 params
->blf_data
->log_containers
->len
- 1, container
->infile_start_pos
, *err_info
? *err_info
: "(none)");
1167 /* Skip this log container and try to get the next one. */
1168 g_array_remove_index(params
->blf_data
->log_containers
, params
->blf_data
->log_containers
->len
- 1);
1169 /* Calling blf_pull_logcontainer_into_memory advances the file pointer. Eventually we will reach the end of the file and stop recursing. */
1170 return blf_pull_next_logcontainer(params
, err
, err_info
);
1180 blf_read_bytes_or_eof(blf_params_t
*params
, uint64_t real_pos
, void *target_buffer
, uint64_t count
, int *err
, char **err_info
) {
1181 blf_log_container_t
* container
;
1182 unsigned container_index
;
1184 uint64_t end_pos
= real_pos
+ count
;
1186 uint64_t copied
= 0;
1188 uint64_t start_in_buf
;
1190 unsigned char *buf
= (unsigned char *)target_buffer
;
1193 ws_debug("called blf_read_bytes_or_eof with 0 count");
1197 if (count
> UINT32_MAX
) {
1198 ws_debug("trying to read too many bytes");
1202 if (params
->random
) {
1204 * Do a binary search for the container in which real_pos
1207 if (!g_array_binary_search(params
->blf_data
->log_containers
, &real_pos
, blf_logcontainers_search
, &container_index
)) {
1209 * XXX - why is this treated as an EOF rather than an error?
1210 * *err appears to be 0, which means our caller treats it as an
1211 * EOF, at least when reading the log object header.
1213 ws_debug("cannot read data because start position cannot be mapped");
1216 container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, container_index
);
1219 if (params
->blf_data
->log_containers
->len
== 0) {
1221 * This is the first (linear) pass, and we haven't yet
1222 * added any containers. Pull the next log container
1223 * into memory, so that the array isn't empty.
1225 if (!blf_pull_next_logcontainer(params
, err
, err_info
)) {
1231 * Search backwards in the array, from the last entry to the
1232 * first, to find the log container in which real_pos is
1235 container_index
= params
->blf_data
->log_containers
->len
;
1237 container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, --container_index
);
1238 } while (real_pos
< container
->real_start_pos
&& container_index
> 0); /* For some reason we skipped past the correct container */
1241 while (real_pos
< end_pos
) {
1243 while (real_pos
>= container
->real_start_pos
+ container
->real_length
) {
1245 if (!params
->random
) { /* First (linear) pass */
1246 if (!blf_pull_next_logcontainer(params
, err
, err_info
)) {
1250 if (container_index
>= params
->blf_data
->log_containers
->len
) {
1251 ws_debug("cannot find real_pos in container");
1254 container
= &g_array_index(params
->blf_data
->log_containers
, blf_log_container_t
, container_index
);
1255 if (real_pos
< container
->real_start_pos
) {
1256 ws_debug("cannot find real_pos in container");
1261 if (real_pos
< container
->real_start_pos
) {
1262 ws_debug("cannot find real_pos in container");
1266 start_in_buf
= real_pos
- container
->real_start_pos
;
1268 if (params
->random
) {
1269 if (file_seek(params
->fh
, container
->infile_data_start
, SEEK_SET
, err
) == -1) {
1272 if (!blf_pull_logcontainer_into_memory(params
, container
, err
, err_info
)) {
1277 data_left
= container
->real_length
- start_in_buf
;
1279 if (data_left
< (count
- copied
)) {
1280 memcpy(buf
+ copied
, container
->real_data
+ start_in_buf
, data_left
);
1281 copied
+= data_left
;
1282 real_pos
+= data_left
;
1285 memcpy(buf
+ copied
, container
->real_data
+ start_in_buf
, count
- copied
);
1292 * XXX - does this represent a bug (WTAP_ERR_INTERNAL) or a
1293 * malformed file (WTAP_ERR_BAD_FILE)?
1295 *err
= WTAP_ERR_INTERNAL
;
1296 *err_info
= ws_strdup("blf_read_bytes_or_eof: ran out of containers");
1301 blf_read_bytes(blf_params_t
*params
, uint64_t real_pos
, void *target_buffer
, uint64_t count
, int *err
, char **err_info
) {
1302 if (!blf_read_bytes_or_eof(params
, real_pos
, target_buffer
, count
, err
, err_info
)) {
1304 *err
= WTAP_ERR_SHORT_READ
;
1312 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
) {
1313 params
->rec
->rec_type
= REC_TYPE_PACKET
;
1314 params
->rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
1315 params
->rec
->presence_flags
= WTAP_HAS_CAP_LEN
| WTAP_HAS_INTERFACE_ID
;
1316 params
->rec
->ts_rel_cap_valid
= false;
1318 case BLF_TIMESTAMP_RESOLUTION_10US
:
1319 params
->rec
->presence_flags
|= WTAP_HAS_TS
;
1320 params
->rec
->tsprec
= WTAP_TSPREC_10_USEC
;
1321 object_timestamp
*= 10000;
1322 object_timestamp
+= params
->blf_data
->start_offset_ns
;
1323 params
->rec
->ts_rel_cap_valid
= true;
1326 case BLF_TIMESTAMP_RESOLUTION_1NS
:
1327 params
->rec
->presence_flags
|= WTAP_HAS_TS
;
1328 params
->rec
->tsprec
= WTAP_TSPREC_NSEC
;
1329 object_timestamp
+= params
->blf_data
->start_offset_ns
;
1330 params
->rec
->ts_rel_cap_valid
= true;
1334 /* Metadata objects have both flags and timestamp equal to zero, so that combination is not an error. */
1335 if (flags
!= 0 || object_timestamp
!= 0) {
1337 * XXX - report this as an error?
1339 * Or provide a mechanism to allow file readers to report
1340 * a warning (an error that the reader tries to work
1341 * around and that the caller should report)?
1343 ws_debug("Unknown combination of flags and timestamp (0x%x, %" PRIu64
")", flags
, object_timestamp
);
1344 object_timestamp
= 0;
1348 params
->rec
->ts
.secs
= object_timestamp
/ (1000 * 1000 * 1000);
1349 params
->rec
->ts
.nsecs
= object_timestamp
% (1000 * 1000 * 1000);
1350 params
->rec
->rec_header
.packet_header
.caplen
= caplen
;
1351 params
->rec
->rec_header
.packet_header
.len
= len
;
1354 tmp_ts
.secs
= params
->blf_data
->start_offset_ns
/ (1000 * 1000 * 1000);
1355 tmp_ts
.nsecs
= params
->blf_data
->start_offset_ns
% (1000 * 1000 * 1000);
1356 nstime_delta(¶ms
->rec
->ts_rel_cap
, ¶ms
->rec
->ts
, &tmp_ts
);
1358 params
->rec
->rec_header
.packet_header
.pkt_encap
= pkt_encap
;
1359 params
->rec
->rec_header
.packet_header
.interface_id
= blf_lookup_interface(params
, pkt_encap
, channel
, hwchannel
, NULL
);
1361 /* TODO: before we had to remove comments and verdict here to not leak memory but APIs have changed ... */
1365 blf_add_direction_option(blf_params_t
*params
, uint16_t direction
) {
1366 uint32_t tmp
= 0; /* dont care */
1368 switch (direction
) {
1370 tmp
= 1; /* inbound */
1374 tmp
= 2; /* outbound */
1378 /* pcapng.c: #define OPT_EPB_FLAGS 0x0002 */
1379 wtap_block_add_uint32_option(params
->rec
->block
, 0x0002, tmp
);
1383 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
) {
1384 if (data_start
- header2_start
< (int64_t)sizeof(blf_logobjectheader_t
)) {
1385 *err
= WTAP_ERR_BAD_FILE
;
1386 *err_info
= ws_strdup("blf: not enough bytes for log object header");
1387 ws_debug("not enough bytes for timestamp header");
1391 if (!blf_read_bytes_or_eof(params
, header2_start
, logheader
, sizeof(*logheader
), err
, err_info
)) {
1392 ws_debug("not enough bytes for logheader");
1395 fix_endianness_blf_logobjectheader(logheader
);
1400 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
) {
1401 if (data_start
- header2_start
< (int64_t)sizeof(blf_logobjectheader2_t
)) {
1402 *err
= WTAP_ERR_BAD_FILE
;
1403 *err_info
= ws_strdup("blf: not enough bytes for log object header");
1404 ws_debug("not enough bytes for timestamp header");
1408 if (!blf_read_bytes_or_eof(params
, header2_start
, logheader
, sizeof(*logheader
), err
, err_info
)) {
1409 ws_debug("not enough bytes for logheader");
1412 fix_endianness_blf_logobjectheader2(logheader
);
1417 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
) {
1418 if (data_start
- header2_start
< (int64_t)sizeof(blf_logobjectheader3_t
)) {
1419 *err
= WTAP_ERR_BAD_FILE
;
1420 *err_info
= ws_strdup("blf: not enough bytes for log object header");
1421 ws_debug("not enough bytes for timestamp header");
1425 if (!blf_read_bytes_or_eof(params
, header2_start
, logheader
, sizeof(*logheader
), err
, err_info
)) {
1426 ws_debug("not enough bytes for logheader");
1429 fix_endianness_blf_logobjectheader3(logheader
);
1434 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
) {
1435 blf_ethernetframeheader_t ethheader
;
1437 unsigned caplen
, len
;
1439 if (object_length
< (data_start
- block_start
) + (int) sizeof(blf_ethernetframeheader_t
)) {
1440 *err
= WTAP_ERR_BAD_FILE
;
1441 *err_info
= ws_strdup("blf: ETHERNET_FRAME: not enough bytes for ethernet frame header in object");
1442 ws_debug("not enough bytes for ethernet frame header in object");
1446 if (!blf_read_bytes(params
, data_start
, ðheader
, sizeof(ethheader
), err
, err_info
)) {
1447 ws_debug("not enough bytes for ethernet frame header in file");
1450 fix_endianness_blf_ethernetframeheader(ðheader
);
1453 * BLF breaks up and reorders the Ethernet header and VLAN tag fields.
1454 * This is a really bad design and makes this format one of the worst.
1455 * If you want a fast format that keeps your data intact, avoid this format!
1456 * So, lets hope we can reconstruct the original packet successfully.
1459 tmpbuf
[0] = ethheader
.dst_addr
[0];
1460 tmpbuf
[1] = ethheader
.dst_addr
[1];
1461 tmpbuf
[2] = ethheader
.dst_addr
[2];
1462 tmpbuf
[3] = ethheader
.dst_addr
[3];
1463 tmpbuf
[4] = ethheader
.dst_addr
[4];
1464 tmpbuf
[5] = ethheader
.dst_addr
[5];
1465 tmpbuf
[6] = ethheader
.src_addr
[0];
1466 tmpbuf
[7] = ethheader
.src_addr
[1];
1467 tmpbuf
[8] = ethheader
.src_addr
[2];
1468 tmpbuf
[9] = ethheader
.src_addr
[3];
1469 tmpbuf
[10] = ethheader
.src_addr
[4];
1470 tmpbuf
[11] = ethheader
.src_addr
[5];
1472 if (ethheader
.tpid
!= 0 && ethheader
.tci
!= 0) {
1473 tmpbuf
[12] = (ethheader
.tpid
& 0xff00) >> 8;
1474 tmpbuf
[13] = (ethheader
.tpid
& 0x00ff);
1475 tmpbuf
[14] = (ethheader
.tci
& 0xff00) >> 8;
1476 tmpbuf
[15] = (ethheader
.tci
& 0x00ff);
1477 tmpbuf
[16] = (ethheader
.ethtype
& 0xff00) >> 8;
1478 tmpbuf
[17] = (ethheader
.ethtype
& 0x00ff);
1479 ws_buffer_assure_space(params
->buf
, (size_t)18 + ethheader
.payloadlength
);
1480 ws_buffer_append(params
->buf
, tmpbuf
, (size_t)18);
1481 caplen
= ((uint32_t)18 + ethheader
.payloadlength
);
1482 len
= ((uint32_t)18 + ethheader
.payloadlength
);
1484 tmpbuf
[12] = (ethheader
.ethtype
& 0xff00) >> 8;
1485 tmpbuf
[13] = (ethheader
.ethtype
& 0x00ff);
1486 ws_buffer_assure_space(params
->buf
, (size_t)14 + ethheader
.payloadlength
);
1487 ws_buffer_append(params
->buf
, tmpbuf
, (size_t)14);
1488 caplen
= ((uint32_t)14 + ethheader
.payloadlength
);
1489 len
= ((uint32_t)14 + ethheader
.payloadlength
);
1492 if (!blf_read_bytes(params
, data_start
+ sizeof(blf_ethernetframeheader_t
), ws_buffer_end_ptr(params
->buf
), ethheader
.payloadlength
, err
, err_info
)) {
1493 ws_debug("copying ethernet frame failed");
1496 params
->buf
->first_free
+= ethheader
.payloadlength
;
1498 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, UINT16_MAX
, caplen
, len
);
1499 blf_add_direction_option(params
, ethheader
.direction
);
1505 blf_read_ethernetframe_ext(blf_params_t
*params
, int *err
, char **err_info
, int64_t block_start
,int64_t data_start
,
1506 int64_t object_length
, uint32_t flags
, uint64_t object_timestamp
, gboolean error
) {
1507 blf_ethernetframeheader_ex_t ethheader
;
1509 if (object_length
< (data_start
- block_start
) + (int) sizeof(blf_ethernetframeheader_ex_t
)) {
1510 *err
= WTAP_ERR_BAD_FILE
;
1511 *err_info
= ws_strdup_printf("blf: %s: not enough bytes for ethernet frame header in object", error
? "ETHERNET_ERROR_EX" : "ETHERNET_FRAME_EX");
1512 ws_debug("not enough bytes for ethernet frame header in object");
1516 if (!blf_read_bytes(params
, data_start
, ðheader
, sizeof(blf_ethernetframeheader_ex_t
), err
, err_info
)) {
1517 ws_debug("not enough bytes for ethernet frame header in file");
1520 fix_endianness_blf_ethernetframeheader_ex(ðheader
);
1522 ws_buffer_assure_space(params
->buf
, ethheader
.frame_length
);
1524 if (object_length
- (data_start
- block_start
) - sizeof(blf_ethernetframeheader_ex_t
) < ethheader
.frame_length
) {
1525 *err
= WTAP_ERR_BAD_FILE
;
1526 *err_info
= ws_strdup_printf("blf: %s: frame too short", error
? "ETHERNET_ERROR_EX" : "ETHERNET_FRAME_EX");
1527 ws_debug("frame too short");
1531 if (!blf_read_bytes(params
, data_start
+ sizeof(blf_ethernetframeheader_ex_t
), ws_buffer_start_ptr(params
->buf
), ethheader
.frame_length
, err
, err_info
)) {
1532 ws_debug("copying ethernet frame failed");
1536 if (ethheader
.flags
& BLF_ETHERNET_EX_HARDWARECHANNEL
) {
1537 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, ethheader
.hw_channel
, ethheader
.frame_length
, ethheader
.frame_length
);
1538 wtap_block_add_uint32_option(params
->rec
->block
, OPT_PKT_QUEUE
, ethheader
.hw_channel
);
1541 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, UINT16_MAX
, ethheader
.frame_length
, ethheader
.frame_length
);
1544 blf_add_direction_option(params
, ethheader
.direction
);
1550 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
) {
1551 blf_ethernet_rxerror_t ethheader
;
1553 if (object_length
< (data_start
- block_start
) + (int)sizeof(blf_ethernet_rxerror_t
)) {
1554 *err
= WTAP_ERR_BAD_FILE
;
1555 *err_info
= ws_strdup("blf: ETHERNET_RXERROR: not enough bytes for ethernet frame header in object");
1556 ws_debug("not enough bytes for ethernet rx error header in object");
1560 if (!blf_read_bytes(params
, data_start
, ðheader
, sizeof(blf_ethernet_rxerror_t
), err
, err_info
)) {
1561 ws_debug("not enough bytes for ethernet rx error header in file");
1564 fix_endianness_blf_ethernet_rxerror(ðheader
);
1566 ws_buffer_assure_space(params
->buf
, ethheader
.frame_length
);
1568 if (object_length
- (data_start
- block_start
) < ethheader
.frame_length
) {
1569 *err
= WTAP_ERR_BAD_FILE
;
1570 *err_info
= ws_strdup("blf: ETHERNET_RXERROR: frame too short");
1571 ws_debug("frame too short");
1575 if (!blf_read_bytes(params
, data_start
+ sizeof(blf_ethernet_rxerror_t
), ws_buffer_start_ptr(params
->buf
), ethheader
.frame_length
, err
, err_info
)) {
1576 ws_debug("copying ethernet rx error failed");
1580 if (ethheader
.hw_channel
!= 0) { /* In this object type, a value of 0 is considered invalid. */
1581 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, ethheader
.hw_channel
, ethheader
.frame_length
, ethheader
.frame_length
);
1582 wtap_block_add_uint32_option(params
->rec
->block
, OPT_PKT_QUEUE
, ethheader
.hw_channel
);
1585 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_ETHERNET
, ethheader
.channel
, UINT16_MAX
, ethheader
.frame_length
, ethheader
.frame_length
);
1587 blf_add_direction_option(params
, ethheader
.direction
);
1593 * XXX - provide radio information to our caller in the pseudo-header.
1596 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
) {
1597 blf_wlanframeheader_t wlanheader
;
1599 if (object_length
< (data_start
- block_start
) + (int)sizeof(blf_wlanframeheader_t
)) {
1600 *err
= WTAP_ERR_BAD_FILE
;
1601 *err_info
= ws_strdup("blf: WLAN_FRAME: not enough bytes for wlan frame header in object");
1602 ws_debug("not enough bytes for wlan frame header in object");
1606 if (!blf_read_bytes(params
, data_start
, &wlanheader
, sizeof(blf_wlanframeheader_t
), err
, err_info
)) {
1607 ws_debug("not enough bytes for wlan frame header in file");
1610 fix_endianness_blf_wlanframeheader(&wlanheader
);
1612 ws_buffer_assure_space(params
->buf
, wlanheader
.frame_length
);
1614 if (object_length
- (data_start
- block_start
) - sizeof(blf_wlanframeheader_t
) < wlanheader
.frame_length
) {
1615 *err
= WTAP_ERR_BAD_FILE
;
1616 *err_info
= ws_strdup("blf: WLAN_FRAME: frame too short");
1617 ws_debug("frame too short");
1621 if (!blf_read_bytes(params
, data_start
+ sizeof(blf_wlanframeheader_t
), ws_buffer_start_ptr(params
->buf
), wlanheader
.frame_length
, err
, err_info
)) {
1622 ws_debug("copying wlan frame failed");
1626 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_IEEE_802_11
, wlanheader
.channel
, UINT16_MAX
, wlanheader
.frame_length
, wlanheader
.frame_length
);
1627 blf_add_direction_option(params
, wlanheader
.direction
);
1632 static uint8_t can_dlc_to_length
[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8 };
1633 static uint8_t canfd_dlc_to_length
[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64 };
1636 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
,
1637 uint32_t flags
, uint64_t object_timestamp
, uint16_t channel
, uint8_t canfd_flags
) {
1639 unsigned caplen
, len
;
1641 tmpbuf
[0] = (canid
& 0xff000000) >> 24;
1642 tmpbuf
[1] = (canid
& 0x00ff0000) >> 16;
1643 tmpbuf
[2] = (canid
& 0x0000ff00) >> 8;
1644 tmpbuf
[3] = (canid
& 0x000000ff);
1645 tmpbuf
[4] = payload_length
;
1646 tmpbuf
[5] = canfd_flags
;
1650 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length_valid
);
1651 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
1652 caplen
= sizeof(tmpbuf
) + payload_length_valid
;
1653 len
= sizeof(tmpbuf
) + payload_length
;
1655 if (payload_length_valid
> 0 && !blf_read_bytes(params
, start_position
, ws_buffer_end_ptr(params
->buf
), payload_length_valid
, err
, err_info
)) {
1656 ws_debug("copying can payload failed");
1659 params
->buf
->first_free
+= payload_length_valid
;
1661 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_SOCKETCAN
, channel
, UINT16_MAX
, caplen
, len
);
1667 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
) {
1668 blf_canmessage_t canheader
;
1669 blf_canmessage2_trailer_t can2trailer
;
1672 uint8_t payload_length
;
1674 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1675 *err
= WTAP_ERR_BAD_FILE
;
1676 *err_info
= ws_strdup_printf("blf: %s: not enough bytes for can header in object",
1677 can_message2
? "CAN_MESSAGE2" : "CAN_MESSAGE");
1678 ws_debug("not enough bytes for can header in object");
1682 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1683 ws_debug("not enough bytes for can header in file");
1686 fix_endianness_blf_canmessage(&canheader
);
1688 canheader
.dlc
&= 0x0f;
1690 payload_length
= canheader
.dlc
;
1691 if (payload_length
> 8) {
1692 ws_debug("regular CAN tries more than 8 bytes? Cutting to 8!");
1696 canid
= canheader
.id
;
1698 if ((canheader
.flags
& BLF_CANMESSAGE_FLAG_RTR
) == BLF_CANMESSAGE_FLAG_RTR
) {
1699 canid
|= CAN_RTR_FLAG
;
1703 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)) {
1707 /* actually, we do not really need the data, right now.... */
1709 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
) + 8 + (int) sizeof(can2trailer
)) {
1710 *err
= WTAP_ERR_BAD_FILE
;
1711 *err_info
= ws_strdup("blf: CAN_MESSAGE2: not enough bytes for can message 2 trailer");
1712 ws_debug("not enough bytes for can message 2 trailer");
1715 if (!blf_read_bytes(params
, data_start
+ sizeof(canheader
) + 8, &can2trailer
, sizeof(can2trailer
), err
, err_info
)) {
1716 ws_debug("not enough bytes for can message 2 trailer in file");
1719 fix_endianness_blf_canmessage2_trailer(&can2trailer
);
1722 blf_add_direction_option(params
, (canheader
.flags
& BLF_CANMESSAGE_FLAG_TX
) == BLF_CANMESSAGE_FLAG_TX
? BLF_DIR_TX
: BLF_DIR_RX
);
1728 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
) {
1729 blf_canfdmessage_t canheader
;
1733 uint8_t payload_length
;
1734 uint8_t payload_length_valid
;
1735 uint8_t canfd_flags
;
1737 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1738 *err
= WTAP_ERR_BAD_FILE
;
1739 *err_info
= ws_strdup("blf: CAN_FD_MESSAGE: not enough bytes for canfd header in object");
1740 ws_debug("not enough bytes for canfd header in object");
1744 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1745 ws_debug("not enough bytes for canfd header in file");
1748 fix_endianness_blf_canfdmessage(&canheader
);
1750 canheader
.dlc
&= 0x0f;
1752 canfd
= (canheader
.canfdflags
& BLF_CANFDMESSAGE_CANFDFLAG_EDL
) == BLF_CANFDMESSAGE_CANFDFLAG_EDL
;
1754 payload_length
= canfd_dlc_to_length
[canheader
.dlc
];
1755 canfd_flags
= (canheader
.canfdflags
& BLF_CANFDMESSAGE_CANFDFLAG_EDL
) << 2 | (canheader
.canfdflags
& BLF_CANFDMESSAGE_CANFDFLAG_ESI
) >> 1 | (canheader
.canfdflags
& BLF_CANFDMESSAGE_CANFDFLAG_BRS
) >> 1;
1757 if (canheader
.dlc
> 8) {
1758 ws_debug("regular CAN tries more than 8 bytes?");
1760 payload_length
= can_dlc_to_length
[canheader
.dlc
];
1764 if (payload_length
> canheader
.validDataBytes
) {
1765 ws_debug("shortening canfd payload because valid data bytes shorter!");
1766 payload_length
= canheader
.validDataBytes
;
1769 canid
= canheader
.id
;
1771 if (!canfd
&& (canheader
.flags
& BLF_CANMESSAGE_FLAG_RTR
) == BLF_CANMESSAGE_FLAG_RTR
) {
1772 canid
|= CAN_RTR_FLAG
;
1773 payload_length
= 0; /* Should already be zero from validDataBytes */
1776 payload_length_valid
= payload_length
;
1778 if (payload_length_valid
> object_length
- (data_start
- block_start
) + sizeof(canheader
)) {
1779 ws_debug("shortening can payload because buffer is too short!");
1780 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
));
1783 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
)) {
1787 blf_add_direction_option(params
, (canheader
.flags
& BLF_CANMESSAGE_FLAG_TX
) == BLF_CANMESSAGE_FLAG_TX
? BLF_DIR_TX
: BLF_DIR_RX
);
1793 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
) {
1794 blf_canfdmessage64_t canheader
;
1798 uint8_t payload_length
;
1799 uint8_t payload_length_valid
;
1800 uint8_t canfd_flags
;
1802 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1803 *err
= WTAP_ERR_BAD_FILE
;
1804 *err_info
= ws_strdup("blf: CAN_FD_MESSAGE_64: not enough bytes for canfd header in object");
1805 ws_debug("not enough bytes for canfd header in object");
1809 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1810 ws_debug("not enough bytes for canfd header in file");
1813 fix_endianness_blf_canfdmessage64(&canheader
);
1815 canheader
.dlc
&= 0x0f;
1817 canfd
= (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_EDL
) == BLF_CANFDMESSAGE64_FLAG_EDL
;
1819 payload_length
= canfd_dlc_to_length
[canheader
.dlc
];
1820 canfd_flags
= (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_EDL
) >> 10 | (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_ESI
) >> 13 | (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_BRS
) >> 13;
1822 if (canheader
.dlc
> 8) {
1823 ws_debug("regular CAN tries more than 8 bytes?");
1825 payload_length
= can_dlc_to_length
[canheader
.dlc
];
1829 if (payload_length
> canheader
.validDataBytes
) {
1830 ws_debug("shortening canfd payload because valid data bytes shorter!");
1831 payload_length
= canheader
.validDataBytes
;
1834 canid
= canheader
.id
;
1836 if (!canfd
&& (canheader
.flags
& BLF_CANFDMESSAGE64_FLAG_REMOTE_FRAME
) == BLF_CANFDMESSAGE64_FLAG_REMOTE_FRAME
) {
1837 canid
|= CAN_RTR_FLAG
;
1838 payload_length
= 0; /* Should already be zero from validDataBytes */
1841 payload_length_valid
= payload_length
;
1843 if (payload_length_valid
> object_length
- (data_start
- block_start
)) {
1844 ws_debug("shortening can payload because buffer is too short!");
1845 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
));
1848 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
)) {
1852 blf_add_direction_option(params
, canheader
.dir
);
1858 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
) {
1859 blf_canerror_t canheader
;
1861 uint8_t payload_length
;
1862 uint8_t tmpbuf
[16] = {0};
1864 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1865 *err
= WTAP_ERR_BAD_FILE
;
1866 *err_info
= ws_strdup("blf: CAN_ERROR: not enough bytes for canerror header in object");
1867 ws_debug("not enough bytes for canerror header in object");
1871 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1872 ws_debug("not enough bytes for canerror header in file");
1875 fix_endianness_blf_canerror(&canheader
);
1877 // Set CAN_ERR_FLAG in unused bits of Can ID to indicate error in socketcan
1878 canid
= CAN_ERR_FLAG
;
1880 // Fixed packet data length for socketcan error messages
1881 payload_length
= CAN_ERR_DLC
;
1884 tmpbuf
[10] = CAN_ERR_PROT_OVERLOAD
;
1885 canid
|= CAN_ERR_PROT
;
1888 tmpbuf
[0] = (canid
& 0xff000000) >> 24;
1889 tmpbuf
[1] = (canid
& 0x00ff0000) >> 16;
1890 tmpbuf
[2] = (canid
& 0x0000ff00) >> 8;
1891 tmpbuf
[3] = (canid
& 0x000000ff);
1892 tmpbuf
[4] = payload_length
;
1894 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
1895 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
1897 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_SOCKETCAN
, canheader
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
1902 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
) {
1903 blf_canerrorext_t canheader
;
1905 bool err_ack
= false;
1906 bool err_prot
= false;
1909 uint8_t payload_length
;
1910 uint8_t tmpbuf
[16] = {0};
1912 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
1913 *err
= WTAP_ERR_BAD_FILE
;
1914 *err_info
= ws_strdup("blf: CAN_ERROR_EXT: not enough bytes for canerrorext header in object");
1915 ws_debug("not enough bytes for canerrorext header in object");
1919 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
1920 ws_debug("not enough bytes for canerrorext header in file");
1923 fix_endianness_blf_canerrorext(&canheader
);
1925 if (canheader
.flags
& BLF_CANERROREXT_FLAG_CANCORE
) {
1926 // Map Vector Can Core error codes to compareable socketcan errors
1927 switch ((canheader
.errorCodeExt
>> 6) & 0x3f) {
1928 case BLF_CANERROREXT_ECC_MEANING_BIT_ERROR
:
1930 tmpbuf
[10] = CAN_ERR_PROT_BIT
;
1932 case BLF_CANERROREXT_ECC_MEANING_FORM_ERROR
:
1934 tmpbuf
[10] = CAN_ERR_PROT_FORM
;
1936 case BLF_CANERROREXT_ECC_MEANING_STUFF_ERROR
:
1938 tmpbuf
[10] = CAN_ERR_PROT_STUFF
;
1940 case BLF_CANERROREXT_ECC_MEANING_CRC_ERROR
:
1942 tmpbuf
[11] = CAN_ERR_PROT_LOC_CRC_SEQ
;
1944 case BLF_CANERROREXT_ECC_MEANING_NACK_ERROR
:
1946 tmpbuf
[11] = CAN_ERR_PROT_LOC_ACK
;
1948 case BLF_CANERROREXT_ECC_MEANING_OVERLOAD
:
1950 tmpbuf
[10] = CAN_ERR_PROT_OVERLOAD
;
1954 tmpbuf
[10] = CAN_ERR_PROT_UNSPEC
;
1957 err_ack
= err_ack
|| (canheader
.errorCodeExt
& BLF_CANERROREXT_EXTECC_NOT_ACK
) == 0x0;
1959 // Don't set protocol error on ack errors
1964 // CanID contains error class in socketcan
1965 canid
= CAN_ERR_FLAG
;
1966 canid
|= err_prot
? CAN_ERR_PROT
: 0;
1967 canid
|= err_ack
? CAN_ERR_ACK
: 0;
1969 // Fixed packet data length for socketcan error messages
1970 payload_length
= CAN_ERR_DLC
;
1971 canheader
.dlc
= payload_length
;
1973 tmpbuf
[0] = (canid
& 0xff000000) >> 24;
1974 tmpbuf
[1] = (canid
& 0x00ff0000) >> 16;
1975 tmpbuf
[2] = (canid
& 0x0000ff00) >> 8;
1976 tmpbuf
[3] = (canid
& 0x000000ff);
1977 tmpbuf
[4] = payload_length
;
1979 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
1980 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
1982 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_SOCKETCAN
, canheader
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
1983 if (canheader
.flags
& BLF_CANERROREXT_FLAG_CANCORE
) {
1984 direction_tx
= (canheader
.errorCodeExt
& BLF_CANERROREXT_EXTECC_TX
) == BLF_CANERROREXT_EXTECC_TX
;
1985 blf_add_direction_option(params
, direction_tx
? BLF_DIR_TX
: BLF_DIR_RX
);
1991 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
) {
1992 blf_canfderror64_t canheader
;
1994 bool err_ack
= false;
1995 bool err_prot
= false;
1998 uint8_t payload_length
;
1999 uint8_t tmpbuf
[16] = {0};
2001 if (object_length
< (data_start
- block_start
) + (int) sizeof(canheader
)) {
2002 *err
= WTAP_ERR_BAD_FILE
;
2003 *err_info
= ws_strdup("blf: CAN_FD_ERROR_64: not enough bytes for canfderror header in object");
2004 ws_debug("not enough bytes for canfderror header in object");
2008 if (!blf_read_bytes(params
, data_start
, &canheader
, sizeof(canheader
), err
, err_info
)) {
2009 ws_debug("not enough bytes for canfderror header in file");
2012 fix_endianness_blf_canfderror64(&canheader
);
2014 if (canheader
.flags
& BLF_CANERROREXT_FLAG_CANCORE
) {
2015 // Map Vector Can Core error codes to compareable socketcan errors
2016 switch ((canheader
.errorCodeExt
>> 6) & 0x3f) {
2017 case BLF_CANERROREXT_ECC_MEANING_BIT_ERROR
:
2019 tmpbuf
[10] = CAN_ERR_PROT_BIT
;
2021 case BLF_CANERROREXT_ECC_MEANING_FORM_ERROR
:
2023 tmpbuf
[10] = CAN_ERR_PROT_FORM
;
2025 case BLF_CANERROREXT_ECC_MEANING_STUFF_ERROR
:
2027 tmpbuf
[10] = CAN_ERR_PROT_STUFF
;
2029 case BLF_CANERROREXT_ECC_MEANING_CRC_ERROR
:
2031 tmpbuf
[11] = CAN_ERR_PROT_LOC_CRC_SEQ
;
2033 case BLF_CANERROREXT_ECC_MEANING_NACK_ERROR
:
2035 tmpbuf
[11] = CAN_ERR_PROT_LOC_ACK
;
2037 case BLF_CANERROREXT_ECC_MEANING_OVERLOAD
:
2039 tmpbuf
[10] = CAN_ERR_PROT_OVERLOAD
;
2043 tmpbuf
[10] = CAN_ERR_PROT_UNSPEC
;
2046 err_ack
= err_ack
|| (canheader
.errorCodeExt
& BLF_CANERROREXT_EXTECC_NOT_ACK
) == 0x0;
2048 // Don't set protocol error on ack errors
2053 // CanID contains error class in socketcan
2054 canid
= CAN_ERR_FLAG
;
2055 canid
|= err_prot
? CAN_ERR_PROT
: 0;
2056 canid
|= err_ack
? CAN_ERR_ACK
: 0;
2058 // Fixed packet data length for socketcan error messages
2059 payload_length
= CAN_ERR_DLC
;
2060 canheader
.dlc
= payload_length
;
2062 tmpbuf
[0] = (canid
& 0xff000000) >> 24;
2063 tmpbuf
[1] = (canid
& 0x00ff0000) >> 16;
2064 tmpbuf
[2] = (canid
& 0x0000ff00) >> 8;
2065 tmpbuf
[3] = (canid
& 0x000000ff);
2066 tmpbuf
[4] = payload_length
;
2067 // Don't set FDF, ESI and BRS flags, since error messages are always encapsulated in Classic CAN frames
2069 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2070 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2072 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_SOCKETCAN
, canheader
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2073 if (canheader
.flags
& BLF_CANERROREXT_FLAG_CANCORE
) {
2074 direction_tx
= (canheader
.errorCodeExt
& BLF_CANERROREXT_EXTECC_TX
) == BLF_CANERROREXT_EXTECC_TX
;
2075 blf_add_direction_option(params
, direction_tx
? BLF_DIR_TX
: BLF_DIR_RX
);
2081 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
) {
2082 blf_flexraydata_t frheader
;
2084 uint8_t payload_length
;
2085 uint8_t payload_length_valid
;
2087 unsigned caplen
, len
;
2089 if (object_length
< (data_start
- block_start
) + (int) sizeof(frheader
)) {
2090 *err
= WTAP_ERR_BAD_FILE
;
2091 *err_info
= ws_strdup("blf: FLEXRAY_DATA: not enough bytes for flexrayheader in object");
2092 ws_debug("not enough bytes for flexrayheader in object");
2096 if (!blf_read_bytes(params
, data_start
, &frheader
, sizeof(frheader
), err
, err_info
)) {
2097 ws_debug("not enough bytes for flexrayheader header in file");
2100 fix_endianness_blf_flexraydata(&frheader
);
2102 payload_length
= frheader
.len
;
2103 payload_length_valid
= payload_length
;
2105 if ((frheader
.len
& 0x01) == 0x01) {
2106 ws_debug("reading odd length in FlexRay!?");
2109 if (payload_length_valid
> object_length
- (data_start
- block_start
) - sizeof(frheader
)) {
2110 ws_debug("shortening FlexRay payload because buffer is too short!");
2111 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
) - sizeof(frheader
));
2114 if (frheader
.channel
!= 0 && frheader
.channel
!= 1) {
2115 ws_debug("FlexRay supports only two channels.");
2118 /* Measurement Header */
2119 if (frheader
.channel
== 0) {
2120 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
;
2122 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
| BLF_FLEXRAYDATA_CHANNEL_B
;
2129 tmpbuf
[2] = 0x20 | ((0x0700 & frheader
.messageId
) >> 8);
2130 tmpbuf
[3] = 0x00ff & frheader
.messageId
;
2131 tmpbuf
[4] = (0xfe & frheader
.len
) | ((frheader
.crc
& 0x0400) >> 10);
2132 tmpbuf
[5] = (0x03fc & frheader
.crc
) >> 2;
2133 tmpbuf
[6] = ((0x0003 & frheader
.crc
) << 6) | (0x3f & frheader
.mux
);
2135 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length_valid
);
2136 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2137 caplen
= sizeof(tmpbuf
) + payload_length_valid
;
2138 len
= sizeof(tmpbuf
) + payload_length
;
2140 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
)) {
2141 ws_debug("copying flexray payload failed");
2144 params
->buf
->first_free
+= payload_length_valid
;
2146 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_FLEXRAY
, frheader
.channel
, UINT16_MAX
, caplen
, len
);
2147 blf_add_direction_option(params
, frheader
.dir
);
2153 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
) {
2154 blf_flexraymessage_t frheader
;
2156 uint8_t payload_length
;
2157 uint8_t payload_length_valid
;
2159 unsigned caplen
, len
;
2161 if (object_length
< (data_start
- block_start
) + (int) sizeof(frheader
)) {
2162 *err
= WTAP_ERR_BAD_FILE
;
2163 *err_info
= ws_strdup("blf: FLEXRAY_MESSAGE: not enough bytes for flexrayheader in object");
2164 ws_debug("not enough bytes for flexrayheader in object");
2168 if (!blf_read_bytes(params
, data_start
, &frheader
, sizeof(frheader
), err
, err_info
)) {
2169 ws_debug("not enough bytes for flexrayheader header in file");
2172 fix_endianness_blf_flexraymessage(&frheader
);
2174 payload_length
= frheader
.length
;
2175 payload_length_valid
= payload_length
;
2177 if ((frheader
.length
& 0x01) == 0x01) {
2178 ws_debug("reading odd length in FlexRay!?");
2181 if (payload_length_valid
> object_length
- (data_start
- block_start
) - sizeof(frheader
)) {
2182 ws_debug("shortening FlexRay payload because buffer is too short!");
2183 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
) - sizeof(frheader
));
2186 if (frheader
.channel
!= 0 && frheader
.channel
!= 1) {
2187 ws_debug("FlexRay supports only two channels.");
2190 /* Measurement Header */
2191 if (frheader
.channel
== 0) {
2192 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
;
2194 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
| BLF_FLEXRAYDATA_CHANNEL_B
;
2201 tmpbuf
[2] = ((0x0700 & frheader
.frameId
) >> 8);
2202 if ((frheader
.frameState
& BLF_FLEXRAYMESSAGE_STATE_PPI
) == BLF_FLEXRAYMESSAGE_STATE_PPI
) {
2203 tmpbuf
[2] |= BLF_DLT_FLEXRAY_PPI
;
2206 if ((frheader
.frameState
& BLF_FLEXRAYMESSAGE_STATE_SFI
) == BLF_FLEXRAYMESSAGE_STATE_SFI
) {
2207 tmpbuf
[2] |= BLF_DLT_FLEXRAY_SFI
;
2210 if ((frheader
.frameState
& BLF_FLEXRAYMESSAGE_STATE_NFI
) != BLF_FLEXRAYMESSAGE_STATE_NFI
) {
2211 /* NFI needs to be inversed !? */
2212 tmpbuf
[2] |= BLF_DLT_FLEXRAY_NFI
;
2215 if ((frheader
.frameState
& BLF_FLEXRAYMESSAGE_STATE_STFI
) == BLF_FLEXRAYMESSAGE_STATE_STFI
) {
2216 tmpbuf
[2] |= BLF_DLT_FLEXRAY_STFI
;
2219 tmpbuf
[3] = 0x00ff & frheader
.frameId
;
2220 tmpbuf
[4] = (0xfe & frheader
.length
) | ((frheader
.headerCrc
& 0x0400) >> 10);
2221 tmpbuf
[5] = (0x03fc & frheader
.headerCrc
) >> 2;
2222 tmpbuf
[6] = ((0x0003 & frheader
.headerCrc
) << 6) | (0x3f & frheader
.cycle
);
2224 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length_valid
);
2225 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2226 caplen
= sizeof(tmpbuf
) + payload_length_valid
;
2227 len
= sizeof(tmpbuf
) + payload_length
;
2229 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
)) {
2230 ws_debug("copying flexray payload failed");
2233 params
->buf
->first_free
+= payload_length_valid
;
2235 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_FLEXRAY
, frheader
.channel
, UINT16_MAX
, caplen
, len
);
2236 blf_add_direction_option(params
, frheader
.dir
);
2242 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
) {
2243 blf_flexrayrcvmessage_t frheader
;
2245 uint16_t payload_length
;
2246 uint16_t payload_length_valid
;
2248 int frheadersize
= sizeof(frheader
);
2249 unsigned caplen
, len
;
2255 if ((int64_t)object_length
< (data_start
- block_start
) + frheadersize
) {
2256 *err
= WTAP_ERR_BAD_FILE
;
2257 *err_info
= ws_strdup_printf("blf: %s: not enough bytes for flexrayheader in object",
2258 ext
? "FLEXRAY_RCVMESSAGE_EX" : "FLEXRAY_RCVMESSAGE");
2259 ws_debug("not enough bytes for flexrayheader in object");
2263 if (!blf_read_bytes(params
, data_start
, &frheader
, sizeof(frheader
), err
, err_info
)) {
2264 ws_debug("not enough bytes for flexrayheader header in file");
2267 fix_endianness_blf_flexrayrcvmessage(&frheader
);
2270 frheader
.dir
&= 0xff;
2271 frheader
.cycle
&= 0xff;
2274 payload_length
= frheader
.payloadLength
;
2275 payload_length_valid
= frheader
.payloadLengthValid
;
2277 if ((frheader
.payloadLength
& 0x01) == 0x01) {
2278 ws_debug("reading odd length in FlexRay!?");
2281 if (payload_length_valid
> object_length
- (data_start
- block_start
) - frheadersize
) {
2282 ws_debug("shortening FlexRay payload because buffer is too short!");
2283 payload_length_valid
= (uint8_t)(object_length
- (data_start
- block_start
) - frheadersize
);
2286 /* Measurement Header */
2287 /* TODO: It seems that this format support both channels at the same time!? */
2288 if (frheader
.channelMask
== BLF_FLEXRAYRCVMSG_CHANNELMASK_A
) {
2289 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
;
2291 tmpbuf
[0] = BLF_FLEXRAYDATA_FRAME
| BLF_FLEXRAYDATA_CHANNEL_B
;
2298 tmpbuf
[2] = ((0x0700 & frheader
.frameId
) >> 8);
2299 if ((frheader
.frameFlags
& BLF_FLEXRAYRCVMSG_FRAME_FLAG_PAYLOAD_PREAM
) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_PAYLOAD_PREAM
) {
2300 tmpbuf
[2] |= BLF_DLT_FLEXRAY_PPI
;
2303 if ((frheader
.frameFlags
& BLF_FLEXRAYRCVMSG_FRAME_FLAG_SYNC
) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_SYNC
) {
2304 tmpbuf
[2] |= BLF_DLT_FLEXRAY_SFI
;
2307 if ((frheader
.frameFlags
& BLF_FLEXRAYRCVMSG_FRAME_FLAG_NULL_FRAME
) != BLF_FLEXRAYRCVMSG_FRAME_FLAG_NULL_FRAME
) {
2308 /* NFI needs to be inversed !? */
2309 tmpbuf
[2] |= BLF_DLT_FLEXRAY_NFI
;
2312 if ((frheader
.frameFlags
& BLF_FLEXRAYRCVMSG_FRAME_FLAG_STARTUP
) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_STARTUP
) {
2313 tmpbuf
[2] |= BLF_DLT_FLEXRAY_STFI
;
2316 tmpbuf
[3] = 0x00ff & frheader
.frameId
;
2317 tmpbuf
[4] = (0xfe & frheader
.payloadLength
) | ((frheader
.headerCrc1
& 0x0400) >> 10);
2318 tmpbuf
[5] = (0x03fc & frheader
.headerCrc1
) >> 2;
2319 tmpbuf
[6] = ((0x0003 & frheader
.headerCrc1
) << 6) | (0x3f & frheader
.cycle
);
2321 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length_valid
);
2322 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2323 caplen
= sizeof(tmpbuf
) + payload_length_valid
;
2324 len
= sizeof(tmpbuf
) + payload_length
;
2326 if (payload_length_valid
> 0 && !blf_read_bytes(params
, data_start
+ frheadersize
, ws_buffer_end_ptr(params
->buf
), payload_length_valid
, err
, err_info
)) {
2327 ws_debug("copying flexray payload failed");
2330 params
->buf
->first_free
+= payload_length_valid
;
2332 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_FLEXRAY
, frheader
.channelMask
, UINT16_MAX
, caplen
, len
);
2333 blf_add_direction_option(params
, frheader
.dir
);
2339 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
) {
2340 blf_linmessage_t linmessage
;
2342 uint8_t payload_length
;
2345 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2346 *err
= WTAP_ERR_BAD_FILE
;
2347 *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");
2348 ws_debug("not enough bytes for %s in object", crc_error
? "lincrcerror" : "linmessage");
2352 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2353 ws_debug("not enough bytes for %s in file", crc_error
? "lincrcerror" : "linmessage");
2356 fix_endianness_blf_linmessage(&linmessage
);
2358 linmessage
.dlc
&= 0x0f;
2359 linmessage
.id
&= 0x3f;
2361 payload_length
= MIN(linmessage
.dlc
, 8);
2364 tmpbuf
[0] = 1; /* message format rev = 1 */
2365 tmpbuf
[1] = 0; /* reserved */
2366 tmpbuf
[2] = 0; /* reserved */
2367 tmpbuf
[3] = 0; /* reserved */
2368 tmpbuf
[4] = linmessage
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2369 tmpbuf
[5] = linmessage
.id
; /* parity (2bit) | id (6bit) */
2370 tmpbuf
[6] = (uint8_t)(linmessage
.crc
& 0xff); /* checksum */
2371 tmpbuf
[7] = 0; /* errors */
2377 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length
);
2378 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2379 ws_buffer_append(params
->buf
, linmessage
.data
, payload_length
);
2380 len
= sizeof(tmpbuf
) + payload_length
;
2382 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.channel
, UINT16_MAX
, len
, len
);
2383 blf_add_direction_option(params
, linmessage
.dir
);
2389 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
) {
2390 blf_linrcverror_t linmessage
;
2392 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2393 *err
= WTAP_ERR_BAD_FILE
;
2394 *err_info
= ws_strdup("blf: LIN_RCV_ERROR: not enough bytes for linrcverror in object");
2395 ws_debug("not enough bytes for linrcverror in object");
2399 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2400 ws_debug("not enough bytes for linrcverror in file");
2403 linmessage
.channel
= GUINT16_FROM_LE(linmessage
.channel
);
2405 linmessage
.dlc
&= 0x0f;
2406 linmessage
.id
&= 0x3f;
2409 tmpbuf
[0] = 1; /* message format rev = 1 */
2410 tmpbuf
[1] = 0; /* reserved */
2411 tmpbuf
[2] = 0; /* reserved */
2412 tmpbuf
[3] = 0; /* reserved */
2413 tmpbuf
[4] = linmessage
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2414 tmpbuf
[5] = linmessage
.id
; /* parity (2bit) | id (6bit) */
2415 tmpbuf
[6] = 0; /* checksum */
2416 /* XXX - This object can represent many different error types.
2417 * For now we always treat it as framing error,
2418 * but in the future we should expand it. */
2419 tmpbuf
[7] = 0x02; /* errors */
2421 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2422 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2424 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2430 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
) {
2431 blf_linsenderror_t linmessage
;
2433 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2434 *err
= WTAP_ERR_BAD_FILE
;
2435 *err_info
= ws_strdup("blf: LIN_SND_ERROR: not enough bytes for linsenderror in object");
2436 ws_debug("not enough bytes for linsenderror in object");
2440 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2441 ws_debug("not enough bytes for linsenderror in file");
2444 linmessage
.channel
= GUINT16_FROM_LE(linmessage
.channel
);
2446 linmessage
.dlc
&= 0x0f;
2447 linmessage
.id
&= 0x3f;
2450 tmpbuf
[0] = 1; /* message format rev = 1 */
2451 tmpbuf
[1] = 0; /* reserved */
2452 tmpbuf
[2] = 0; /* reserved */
2453 tmpbuf
[3] = 0; /* reserved */
2454 tmpbuf
[4] = linmessage
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2455 tmpbuf
[5] = linmessage
.id
; /* parity (2bit) | id (6bit) */
2456 tmpbuf
[6] = 0; /* checksum */
2457 tmpbuf
[7] = 0x01; /* errors */
2459 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2460 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2462 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2468 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
) {
2469 blf_linwakeupevent_t linevent
;
2471 if (object_length
< (data_start
- block_start
) + (int)sizeof(linevent
)) {
2472 *err
= WTAP_ERR_BAD_FILE
;
2473 *err_info
= ws_strdup("blf: LIN_WAKEUP: not enough bytes for linwakeup in object");
2474 ws_debug("not enough bytes for linwakeup in object");
2478 if (!blf_read_bytes(params
, data_start
, &linevent
, sizeof(linevent
), err
, err_info
)) {
2479 ws_debug("not enough bytes for linwakeup in file");
2482 linevent
.channel
= GUINT16_FROM_LE(linevent
.channel
);
2484 uint8_t tmpbuf
[12]; /* LIN events have a fixed length of 12 bytes */
2485 tmpbuf
[0] = 1; /* message format rev = 1 */
2486 tmpbuf
[1] = 0; /* reserved */
2487 tmpbuf
[2] = 0; /* reserved */
2488 tmpbuf
[3] = 0; /* reserved */
2489 tmpbuf
[4] = 3 << 2; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2490 tmpbuf
[5] = 0; /* parity (2bit) | id (6bit) */
2491 tmpbuf
[6] = 0; /* checksum */
2492 tmpbuf
[7] = 0; /* errors */
2500 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2501 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2503 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linevent
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2509 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
) {
2510 blf_linmessage2_t linmessage
;
2512 uint8_t payload_length
;
2515 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2516 *err
= WTAP_ERR_BAD_FILE
;
2517 *err_info
= ws_strdup("blf: LIN_MESSAGE2: not enough bytes for linmessage2 in object");
2518 ws_debug("not enough bytes for linmessage2 in object");
2522 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2523 ws_debug("not enough bytes for linmessage2 in file");
2526 fix_endianness_blf_linmessage2(&linmessage
);
2528 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
&= 0x0f;
2529 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
&= 0x3f;
2531 payload_length
= MIN(linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
, 8);
2534 tmpbuf
[0] = 1; /* message format rev = 1 */
2535 tmpbuf
[1] = 0; /* reserved */
2536 tmpbuf
[2] = 0; /* reserved */
2537 tmpbuf
[3] = 0; /* reserved */
2538 tmpbuf
[4] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2539 if (object_version
>= 1) { /* The 'checksumModel' field is valid only if objectVersion >= 1 */
2540 switch (linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.checksumModel
) {
2542 tmpbuf
[4] |= 1; /* Classic */
2545 tmpbuf
[4] |= 2; /* Enhanced */
2551 tmpbuf
[5] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
; /* parity (2bit) | id (6bit) */
2552 tmpbuf
[6] = (uint8_t)(linmessage
.crc
& 0xff); /* checksum */
2553 tmpbuf
[7] = 0; /* errors */
2555 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length
);
2556 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2557 ws_buffer_append(params
->buf
, linmessage
.data
, payload_length
);
2558 len
= sizeof(tmpbuf
) + payload_length
;
2560 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.linSynchFieldEvent
.linBusEvent
.channel
, UINT16_MAX
, len
, len
);
2561 blf_add_direction_option(params
, linmessage
.dir
);
2567 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
) {
2568 blf_lincrcerror2_t linmessage
;
2570 uint8_t payload_length
;
2573 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2574 *err
= WTAP_ERR_BAD_FILE
;
2575 *err_info
= ws_strdup("blf: LIN_CRC_ERROR2: not enough bytes for lincrcerror2 in object");
2576 ws_debug("not enough bytes for lincrcerror2 in object");
2580 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2581 ws_debug("not enough bytes for lincrcerror2 in file");
2584 fix_endianness_blf_lincrcerror2(&linmessage
);
2586 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
&= 0x0f;
2587 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
&= 0x3f;
2589 payload_length
= MIN(linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
, 8);
2592 tmpbuf
[0] = 1; /* message format rev = 1 */
2593 tmpbuf
[1] = 0; /* reserved */
2594 tmpbuf
[2] = 0; /* reserved */
2595 tmpbuf
[3] = 0; /* reserved */
2596 tmpbuf
[4] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2597 if (object_version
>= 1) { /* The 'checksumModel' field is valid only if objectVersion >= 1 */
2598 switch (linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.checksumModel
) {
2600 tmpbuf
[4] |= 1; /* Classic */
2603 tmpbuf
[4] |= 2; /* Enhanced */
2609 tmpbuf
[5] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
; /* parity (2bit) | id (6bit) */
2610 tmpbuf
[6] = (uint8_t)(linmessage
.crc
& 0xff); /* checksum */
2611 tmpbuf
[7] = 0x08; /* errors */
2613 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length
);
2614 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2615 ws_buffer_append(params
->buf
, linmessage
.data
, payload_length
);
2616 len
= sizeof(tmpbuf
) + payload_length
;
2618 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.linSynchFieldEvent
.linBusEvent
.channel
, UINT16_MAX
, len
, len
);
2619 blf_add_direction_option(params
, linmessage
.dir
);
2625 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
) {
2626 blf_linrcverror2_t linmessage
;
2628 uint8_t payload_length
;
2631 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2632 *err
= WTAP_ERR_BAD_FILE
;
2633 *err_info
= ws_strdup("blf: LIN_RCV_ERROR2: not enough bytes for linrcverror2 in object");
2634 ws_debug("not enough bytes for linrcverror2 in object");
2638 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2639 ws_debug("not enough bytes for linrcverror2 in file");
2642 fix_endianness_blf_linrcverror2(&linmessage
);
2644 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
&= 0x0f;
2645 linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
&= 0x3f;
2647 if (linmessage
.hasDataBytes
) {
2648 payload_length
= MIN(linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
, 8);
2655 tmpbuf
[0] = 1; /* message format rev = 1 */
2656 tmpbuf
[1] = 0; /* reserved */
2657 tmpbuf
[2] = 0; /* reserved */
2658 tmpbuf
[3] = 0; /* reserved */
2659 tmpbuf
[4] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2660 if (object_version
>= 1) { /* The 'checksumModel' field is valid only if objectVersion >= 1 */
2661 switch (linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.checksumModel
) {
2663 tmpbuf
[4] |= 1; /* Classic */
2666 tmpbuf
[4] |= 2; /* Enhanced */
2672 tmpbuf
[5] = linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.id
; /* parity (2bit) | id (6bit) */
2673 tmpbuf
[6] = 0; /* checksum */
2674 /* XXX - This object can represent many different error types.
2675 * For now we always treat it as framing error,
2676 * but in the future we should expand it. */
2677 tmpbuf
[7] = 0x02; /* errors */
2679 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
) + payload_length
);
2680 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2681 if (payload_length
> 0) {
2682 ws_buffer_append(params
->buf
, linmessage
.data
, payload_length
);
2684 len
= sizeof(tmpbuf
) + payload_length
;
2686 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.linDataByteTimestampEvent
.linMessageDescriptor
.linSynchFieldEvent
.linBusEvent
.channel
, UINT16_MAX
, len
, len
);
2692 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
) {
2693 blf_linsenderror2_t linmessage
;
2695 if (object_length
< (data_start
- block_start
) + (int)sizeof(linmessage
)) {
2696 *err
= WTAP_ERR_BAD_FILE
;
2697 *err_info
= ws_strdup("blf: LIN_SND_ERROR2: not enough bytes for linsenderror2 in object");
2698 ws_debug("not enough bytes for linsenderror2 in object");
2702 if (!blf_read_bytes(params
, data_start
, &linmessage
, sizeof(linmessage
), err
, err_info
)) {
2703 ws_debug("not enough bytes for linsenderror2 in file");
2706 fix_endianness_blf_linsenderror2(&linmessage
);
2708 linmessage
.linMessageDescriptor
.dlc
&= 0x0f;
2709 linmessage
.linMessageDescriptor
.id
&= 0x3f;
2712 tmpbuf
[0] = 1; /* message format rev = 1 */
2713 tmpbuf
[1] = 0; /* reserved */
2714 tmpbuf
[2] = 0; /* reserved */
2715 tmpbuf
[3] = 0; /* reserved */
2716 tmpbuf
[4] = linmessage
.linMessageDescriptor
.dlc
<< 4; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2717 if (object_version
>= 1) { /* The 'checksumModel' field is valid only if objectVersion >= 1 */
2718 switch (linmessage
.linMessageDescriptor
.checksumModel
) {
2720 tmpbuf
[4] |= 1; /* Classic */
2723 tmpbuf
[4] |= 2; /* Enhanced */
2729 tmpbuf
[5] = linmessage
.linMessageDescriptor
.id
; /* parity (2bit) | id (6bit) */
2730 tmpbuf
[6] = 0; /* checksum */
2731 tmpbuf
[7] = 0x01; /* errors */
2733 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2734 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2736 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linmessage
.linMessageDescriptor
.linSynchFieldEvent
.linBusEvent
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2742 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
) {
2743 blf_linwakeupevent2_t linevent
;
2745 if (object_length
< (data_start
- block_start
) + (int)sizeof(linevent
)) {
2746 *err
= WTAP_ERR_BAD_FILE
;
2747 *err_info
= ws_strdup("blf: LIN_WAKEUP2: not enough bytes for linwakeup2 in object");
2748 ws_debug("not enough bytes for linwakeup2 in object");
2752 if (!blf_read_bytes(params
, data_start
, &linevent
, sizeof(linevent
), err
, err_info
)) {
2753 ws_debug("not enough bytes for linwakeup2 in file");
2756 fix_endianness_blf_linwakeupevent2(&linevent
);
2758 uint8_t tmpbuf
[12]; /* LIN events have a fixed length of 12 bytes */
2759 tmpbuf
[0] = 1; /* message format rev = 1 */
2760 tmpbuf
[1] = 0; /* reserved */
2761 tmpbuf
[2] = 0; /* reserved */
2762 tmpbuf
[3] = 0; /* reserved */
2763 tmpbuf
[4] = 3 << 2; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2764 tmpbuf
[5] = 0; /* parity (2bit) | id (6bit) */
2765 tmpbuf
[6] = 0; /* checksum */
2766 tmpbuf
[7] = 0; /* errors */
2774 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2775 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2777 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linevent
.linBusEvent
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2783 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
) {
2784 blf_linsleepmodeevent_t linevent
;
2786 if (object_length
< (data_start
- block_start
) + (int)sizeof(linevent
)) {
2787 *err
= WTAP_ERR_BAD_FILE
;
2788 *err_info
= ws_strdup("blf: LIN_SLEEP: not enough bytes for linsleep in object");
2789 ws_debug("not enough bytes for linsleep in object");
2793 if (!blf_read_bytes(params
, data_start
, &linevent
, sizeof(linevent
), err
, err_info
)) {
2794 ws_debug("not enough bytes for linsleep in file");
2797 linevent
.channel
= GUINT16_FROM_LE(linevent
.channel
);
2799 uint8_t tmpbuf
[12]; /* LIN events have a fixed length of 12 bytes */
2800 tmpbuf
[0] = 1; /* message format rev = 1 */
2801 tmpbuf
[1] = 0; /* reserved */
2802 tmpbuf
[2] = 0; /* reserved */
2803 tmpbuf
[3] = 0; /* reserved */
2804 tmpbuf
[4] = 3 << 2; /* dlc (4bit) | type (2bit) | checksum type (2bit) */
2805 tmpbuf
[5] = 0; /* parity (2bit) | id (6bit) */
2806 tmpbuf
[6] = 0; /* checksum */
2807 tmpbuf
[7] = 0; /* errors */
2809 switch (linevent
.reason
) {
2810 case BLF_LIN_SLEEP_REASON_GO_TO_SLEEP_FRAME
:
2811 /* Go-to-Sleep event by Go-to-Sleep frame */
2817 case BLF_LIN_SLEEP_REASON_BUS_IDLE_TIMEOUT
:
2818 case BLF_LIN_SLEEP_REASON_SILENT_SLEEPMODE_CMD
:
2819 /* Go-to-Sleep event by Inactivity for more than 4s */
2825 case BLF_LIN_WU_REASON_EXTERNAL_WAKEUP_SIG
:
2826 case BLF_LIN_WU_REASON_INTERNAL_WAKEUP_SIG
:
2827 case BLF_LIN_WU_REASON_BUS_TRAFFIC
: /* There's no "wake-up by bus traffic" event in the LIN packet. */
2828 /* Wake-up event by Wake-up signal */
2834 case BLF_LIN_WU_SLEEP_REASON_START_STATE
:
2835 case BLF_LIN_NO_SLEEP_REASON_BUS_TRAFFIC
:
2836 /* If we're just reporting on the initial state,
2837 * or the interface doesn't want to go to sleep,
2838 * report the current state as "event". */
2839 if (linevent
.flags
& 0x2) {
2840 /* Wake-up event by Wake-up signal */
2847 /* Go-to-Sleep event by Inactivity for more than 4s */
2862 ws_buffer_assure_space(params
->buf
, sizeof(tmpbuf
));
2863 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(tmpbuf
));
2865 blf_init_rec(params
, flags
, object_timestamp
, WTAP_ENCAP_LIN
, linevent
.channel
, UINT16_MAX
, sizeof(tmpbuf
), sizeof(tmpbuf
));
2870 uint16_t blf_get_xml_channel_number(const char* start
, const char* end
) {
2875 if (start
== NULL
|| end
== NULL
|| end
<= start
) {
2879 len
= (size_t)(end
- start
);
2880 text
= g_try_malloc(len
+ 1); /* Accommodate '\0' */
2882 ws_debug("cannot allocate memory");
2885 memcpy(text
, start
, len
);
2888 if (!ws_strtou16(text
, NULL
, &res
)) {
2896 char* blf_get_xml_channel_name(const char* start
, const char* end
) {
2900 if (start
== NULL
|| end
== NULL
|| end
<= start
) {
2904 len
= (size_t)(end
- start
);
2905 text
= g_try_malloc(len
+ 1); /* Accommodate '\0' */
2907 ws_debug("cannot allocate memory");
2910 memcpy(text
, start
, len
);
2916 bool blf_parse_xml_port(const char* start
, const char* end
, char** name
, uint16_t* hwchannel
, bool* simulated
) {
2917 static const char name_magic
[] = "name=";
2918 static const char hwchannel_magic
[] = "hwchannel=";
2919 static const char simulated_magic
[] = "simulated=";
2926 if (start
== NULL
|| end
== NULL
|| name
== NULL
|| end
<= start
) {
2930 len
= (size_t)(end
- start
);
2931 text
= g_try_malloc(len
+ 1); /* Accommodate '\0' */
2933 ws_debug("cannot allocate memory");
2936 memcpy(text
, start
, len
);
2939 tokens
= g_strsplit_set(text
, ";", -1);
2941 if (tokens
== NULL
) {
2942 ws_debug("cannot split XML port data");
2947 *hwchannel
= UINT16_MAX
;
2950 for (int i
= 0; tokens
[i
] != NULL
; i
++) {
2952 if (strncmp(token
, name_magic
, strlen(name_magic
)) == 0) {
2953 if (*name
== NULL
) { /* Avoid memory leak in case of malformed string */
2954 *name
= ws_strdup(token
+ strlen(name_magic
));
2957 else if (strncmp(token
, hwchannel_magic
, strlen(hwchannel_magic
)) == 0) {
2958 if (!ws_strtou16(token
+ strlen(hwchannel_magic
), NULL
, hwchannel
)) {
2959 *hwchannel
= UINT16_MAX
;
2962 else if (strncmp(token
, simulated_magic
, strlen(simulated_magic
)) == 0) {
2963 if (strlen(token
) > strlen(simulated_magic
) && token
[strlen(simulated_magic
)] != '0') {
2964 *simulated
= true; /* TODO: Find a way to use this information */
2974 int blf_get_xml_pkt_encap(const char* start
, const char* end
) {
2977 if (start
== NULL
|| end
== NULL
|| end
<= start
) {
2981 len
= (size_t)(end
- start
);
2983 if (strncmp(start
, "CAN", len
) == 0) {
2984 return WTAP_ENCAP_SOCKETCAN
;
2986 if (strncmp(start
, "FlexRay", len
) == 0) {
2987 return WTAP_ENCAP_FLEXRAY
;
2989 if (strncmp(start
, "LIN", len
) == 0) {
2990 return WTAP_ENCAP_LIN
;
2992 if (strncmp(start
, "Ethernet", len
) == 0) {
2993 return WTAP_ENCAP_ETHERNET
;
2995 if (strncmp(start
, "WLAN", len
) == 0) { /* Not confirmed with a real capture */
2996 return WTAP_ENCAP_IEEE_802_11
;
3002 /** Finds a NULL-terminated string in a block of memory.
3004 * 'start' points to the first byte of the block of memory.
3005 * 'end' points to the first byte after the end of the block of memory,
3006 * so that the size of the block is end-start.
3007 * 'str' is a NULL-terminated string.
3009 const char* blf_strmem(const char* start
, const char* end
, const char* str
) {
3010 if (start
== NULL
|| end
== NULL
|| str
== NULL
|| end
<= start
) {
3014 return ws_memmem(start
, end
- start
, str
, strlen(str
));
3017 /** Extracts the channel and port names from a channels XML.
3019 * A sample channels XML looks like this:
3021 * <?xml version="1.0" encoding="UTF-8"?>
3022 * <channels version="1">
3023 * <channel number="1" type="CAN" network="CAN01">
3025 * <database file="DB.arxml" path="C:\...\" cluster="CAN01" />
3026 * <database file="DB.dbc" path="C:\...\" cluster="General" />
3029 * <channel number="1" type="LIN" network="LIN01">
3031 * <database file="DB.dbc" path="C:\...\" cluster="General" />
3032 * <database file="DB.ldf" path="C:\...\" cluster="LIN01" />
3035 * <channel number="1" type="Ethernet" network="ETH01">
3037 * <database file="DB.dbc" path="C:\...\" cluster="General" />
3039 * <channel_properties>
3040 * <elist name="ports">
3041 * <eli name="port">name=Port1;hwchannel=11;simulated=1</eli>
3042 * <eli name="port">name=Port2;hwchannel=12;simulated=0</eli>
3044 * </channel_properties>
3049 blf_set_xml_channels(blf_params_t
* params
, const char* text
, size_t len
) {
3050 static const char xml_magic
[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
3051 static const char channels_start_magic
[] = "<channels ";
3052 static const char channels_end_magic
[] = "</channels>";
3053 static const char channel_start_magic
[] = "<channel ";
3054 static const char channel_end_magic
[] = "</channel>";
3055 static const char number_start_magic
[] = "number=\"";
3056 static const char number_end_magic
[] = "\"";
3057 static const char type_start_magic
[] = "type=\"";
3058 static const char type_end_magic
[] = "\"";
3059 static const char network_start_magic
[] = "network=\"";
3060 static const char network_end_magic
[] = "\"";
3061 static const char ports_start_magic
[] = "<elist name=\"ports\">";
3062 static const char ports_end_magic
[] = "</elist>";
3063 static const char port_start_magic
[] = "<eli name=\"port\">";
3064 static const char port_end_magic
[] = "</eli>";
3066 const char* xml_start
;
3067 const char* channels_start
;
3068 const char* channels_end
;
3069 const char* channel_start
;
3070 const char* channel_end
;
3071 const char* number_start
;
3072 const char* number_end
;
3073 const char* type_start
;
3074 const char* type_end
;
3075 const char* network_start
;
3076 const char* network_end
;
3077 const char* ports_start
;
3078 const char* ports_end
;
3079 const char* port_start
;
3080 const char* port_end
;
3082 const char* search_start
;
3087 uint16_t hwchannel
= UINT16_MAX
;
3088 char* channel_name
= NULL
;
3089 char* port_name
= NULL
;
3090 bool simulated
= false;
3091 char* iface_name
= NULL
;
3093 if (text
== NULL
|| len
< strlen(xml_magic
)) {
3097 xml_start
= blf_strmem(text
, text
+ len
, xml_magic
);
3098 if (xml_start
== NULL
) {
3099 ws_debug("no valid xml magic found");
3102 search_start
= xml_start
+ strlen(xml_magic
);
3104 channels_start
= blf_strmem(search_start
, text
+ len
, channels_start_magic
);
3105 channels_end
= blf_strmem(search_start
, text
+ len
, channels_end_magic
);
3106 if (channels_start
== NULL
|| channels_end
== NULL
|| channels_end
<= channels_start
+ strlen(channels_start_magic
)) {
3107 ws_debug("no channels tag found in xml");
3110 search_start
= channels_start
+ strlen(channels_start_magic
);
3112 while (search_start
< channels_end
) {
3113 channel_start
= blf_strmem(search_start
, channels_end
, channel_start_magic
);
3114 search_start
= search_start
+ strlen(channel_start_magic
);
3115 channel_end
= blf_strmem(search_start
, channels_end
, channel_end_magic
);
3116 if (channel_start
== NULL
|| channel_end
== NULL
|| channel_end
<= channel_start
+ strlen(channel_start_magic
)) {
3117 ws_debug("found end of channel list");
3121 number_start
= blf_strmem(channel_start
, channel_end
, number_start_magic
);
3122 if (number_start
== NULL
) {
3123 ws_debug("channel without number found in xml");
3124 search_start
= channel_end
+ strlen(channel_end_magic
);
3128 number_end
= blf_strmem(number_start
+ strlen(number_start_magic
), channel_end
, number_end_magic
);
3129 if (number_end
== NULL
) {
3130 ws_debug("channel with malformed number attribute found in xml");
3131 search_start
= channel_end
+ strlen(channel_end_magic
);
3135 channel
= blf_get_xml_channel_number(number_start
+ strlen(number_start_magic
), number_end
);
3136 if (channel
== UINT16_MAX
) {
3137 ws_debug("invalid channel number found in xml");
3138 search_start
= channel_end
+ strlen(channel_end_magic
);
3142 type_start
= blf_strmem(channel_start
, channel_end
, type_start_magic
);
3143 if (type_start
== NULL
) {
3144 ws_debug("channel without type found in xml");
3145 search_start
= channel_end
+ strlen(channel_end_magic
);
3149 type_end
= blf_strmem(type_start
+ strlen(type_start_magic
), channel_end
, type_end_magic
);
3150 if (type_end
== NULL
) {
3151 ws_debug("channel with malformed type attribute found in xml");
3152 search_start
= channel_end
+ strlen(channel_end_magic
);
3156 pkt_encap
= blf_get_xml_pkt_encap(type_start
+ strlen(type_start_magic
), type_end
);
3158 network_start
= blf_strmem(channel_start
, channel_end
, network_start_magic
);
3159 if (network_start
== NULL
) {
3160 ws_debug("channel without name found in xml");
3161 search_start
= channel_end
+ strlen(channel_end_magic
);
3165 network_end
= blf_strmem(network_start
+ strlen(network_start_magic
), channel_end
, network_end_magic
);
3166 if (network_end
== NULL
) {
3167 ws_debug("channel with malformed network attribute found in xml");
3168 search_start
= channel_end
+ strlen(channel_end_magic
);
3172 channel_name
= blf_get_xml_channel_name(network_start
+ strlen(network_start_magic
), network_end
);
3173 if (channel_name
== NULL
|| strlen(channel_name
) == 0) {
3174 ws_debug("channel with empty name found in xml");
3176 g_free(channel_name
);
3177 channel_name
= NULL
;
3179 search_start
= channel_end
+ strlen(channel_end_magic
);
3183 ws_debug("Found channel in XML: PKT_ENCAP: %d, ID: %u, name: %s", pkt_encap
, channel
, channel_name
);
3184 blf_prepare_interface_name(params
, pkt_encap
, channel
, UINT16_MAX
, channel_name
, true);
3186 search_start
= MAX(MAX(number_end
+ strlen(number_end_magic
), type_end
+ strlen(type_end_magic
)), network_end
+ strlen(network_end_magic
));
3188 ports_start
= blf_strmem(search_start
, channel_end
, ports_start_magic
);
3189 if (ports_start
== NULL
) {
3190 /* Not an error, channel has no ports */
3191 g_free(channel_name
);
3192 channel_name
= NULL
;
3193 search_start
= channel_end
+ strlen(channel_end_magic
);
3197 search_start
= ports_start
+ strlen(ports_start_magic
);
3199 ports_end
= blf_strmem(search_start
, channel_end
, ports_end_magic
);
3200 if (ports_end
== NULL
) {
3201 ws_debug("channel with malformed ports tag found in xml");
3202 g_free(channel_name
);
3203 channel_name
= NULL
;
3204 search_start
= channel_end
+ strlen(channel_end_magic
);
3208 while (search_start
< ports_end
) {
3209 port_start
= blf_strmem(search_start
, ports_end
, port_start_magic
);
3210 port_end
= blf_strmem(search_start
+ strlen(port_start_magic
), ports_end
, port_end_magic
);
3211 if (port_start
== NULL
|| port_end
== NULL
|| port_end
<= port_start
+ strlen(port_start_magic
)) {
3212 ws_debug("found end of ports list");
3213 search_start
= ports_end
+ strlen(ports_end_magic
);
3217 res
= blf_parse_xml_port(port_start
+ strlen(port_start_magic
), port_end
, &port_name
, &hwchannel
, &simulated
);
3218 if (!res
|| port_name
== NULL
|| hwchannel
== UINT16_MAX
) {
3223 ws_debug("port with missing or malformed info found in xml");
3224 search_start
= port_end
+ strlen(port_end_magic
);
3228 iface_name
= ws_strdup_printf("%s::%s", channel_name
, port_name
);
3229 ws_debug("Found channel in XML: PKT_ENCAP: %d, ID: %u, HW ID: %u, name: %s", pkt_encap
, channel
, hwchannel
, iface_name
);
3230 blf_prepare_interface_name(params
, pkt_encap
, channel
, hwchannel
, iface_name
, true);
3238 search_start
= port_end
+ strlen(port_end_magic
);
3241 g_free(channel_name
);
3242 channel_name
= NULL
;
3244 search_start
= channel_end
+ strlen(channel_end_magic
);
3251 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
) {
3252 blf_apptext_t apptextheader
;
3254 if (object_length
< (data_start
- block_start
) + (int)sizeof(apptextheader
)) {
3255 *err
= WTAP_ERR_BAD_FILE
;
3256 *err_info
= ws_strdup("blf: APP_TEXT: not enough bytes for apptext header in object");
3257 ws_debug("not enough bytes for apptext header in object");
3258 return BLF_APPTEXT_FAILED
;
3261 if (!blf_read_bytes(params
, data_start
, &apptextheader
, sizeof(apptextheader
), err
, err_info
)) {
3262 ws_debug("not enough bytes for apptext header in file");
3263 return BLF_APPTEXT_FAILED
;
3265 fix_endianness_blf_apptext_header(&apptextheader
);
3267 if (metadata_cont
&& apptextheader
.source
!= BLF_APPTEXT_METADATA
) {
3268 /* If we're in the middle of a sequence of metadata objects,
3269 * but we get an AppText object from another source,
3270 * skip the previously incomplete object and start fresh.
3275 /* Add an extra byte for a terminating '\0' */
3276 char* text
= g_try_malloc((size_t)apptextheader
.textLength
+ 1);
3278 ws_debug("cannot allocate memory");
3279 return BLF_APPTEXT_FAILED
;
3282 if (!blf_read_bytes(params
, data_start
+ sizeof(apptextheader
), text
, apptextheader
.textLength
, err
, err_info
)) {
3283 ws_debug("not enough bytes for apptext text in file");
3285 return BLF_APPTEXT_FAILED
;
3287 text
[apptextheader
.textLength
] = '\0'; /* Here's the '\0' */
3289 switch (apptextheader
.source
) {
3290 case BLF_APPTEXT_CHANNEL
:
3293 /* returns a NULL terminated array of NULL terminates strings */
3294 char** tokens
= g_strsplit_set(text
, ";", -1);
3296 if (tokens
== NULL
|| tokens
[0] == NULL
|| tokens
[1] == NULL
) {
3297 if (tokens
!= NULL
) {
3301 return BLF_APPTEXT_CHANNEL
;
3304 uint16_t channel
= (apptextheader
.reservedAppText1
>> 8) & 0xff;
3307 switch ((apptextheader
.reservedAppText1
>> 16) & 0xff) {
3308 case BLF_BUSTYPE_CAN
:
3309 pkt_encap
= WTAP_ENCAP_SOCKETCAN
;
3312 case BLF_BUSTYPE_FLEXRAY
:
3313 pkt_encap
= WTAP_ENCAP_FLEXRAY
;
3316 case BLF_BUSTYPE_LIN
:
3317 pkt_encap
= WTAP_ENCAP_LIN
;
3320 case BLF_BUSTYPE_ETHERNET
:
3321 pkt_encap
= WTAP_ENCAP_ETHERNET
;
3324 case BLF_BUSTYPE_WLAN
:
3325 pkt_encap
= WTAP_ENCAP_IEEE_802_11
;
3329 pkt_encap
= 0xffffffff;
3333 /* we use lookup to create interface, if not existing yet */
3334 blf_prepare_interface_name(params
, pkt_encap
, channel
, UINT16_MAX
, tokens
[1], false);
3338 return BLF_APPTEXT_CHANNEL
;
3340 case BLF_APPTEXT_METADATA
:
3341 if (metadata_cont
) {
3342 /* Set the buffer pointer to the end of the previous object */
3343 params
->buf
->first_free
= metadata_cont
;
3346 /* First object of a sequence of one or more */
3347 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_DISSECTOR_NAME
, "data-text-lines");
3348 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_COL_PROT_TEXT
, "BLF App text");
3349 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_COL_INFO_TEXT
, "Metadata");
3350 wtap_buffer_append_epdu_end(params
->buf
);
3353 ws_buffer_assure_space(params
->buf
, apptextheader
.textLength
);
3354 ws_buffer_append(params
->buf
, text
, apptextheader
.textLength
);
3357 if ((apptextheader
.reservedAppText1
& 0x00ffffff) > apptextheader
.textLength
) {
3358 /* Continues in the next object */
3359 return BLF_APPTEXT_CONT
;
3362 if (((apptextheader
.reservedAppText1
>> 24) & 0xff) == BLF_APPTEXT_XML_CHANNELS
) {
3363 blf_set_xml_channels(params
, params
->buf
->data
, ws_buffer_length(params
->buf
));
3366 /* 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. */
3367 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
));
3368 return BLF_APPTEXT_METADATA
;
3369 case BLF_APPTEXT_COMMENT
:
3370 case BLF_APPTEXT_ATTACHMENT
:
3371 case BLF_APPTEXT_TRACELINE
:
3373 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_DISSECTOR_NAME
, "data-text-lines");
3374 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_COL_PROT_TEXT
, "BLF App text");
3376 char* info_line
= NULL
;
3377 switch (apptextheader
.source
) {
3378 case BLF_APPTEXT_COMMENT
:
3379 info_line
= ws_strdup_printf("Comment: %s", text
);
3381 case BLF_APPTEXT_ATTACHMENT
:
3382 info_line
= ws_strdup_printf("Attachment: %s", text
);
3384 case BLF_APPTEXT_TRACELINE
:
3385 info_line
= ws_strdup_printf("Trace line%s: %s", (apptextheader
.reservedAppText1
& 0x00000010) ? "" : " (hidden)", text
);
3391 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_COL_INFO_TEXT
, info_line
);
3392 wtap_buffer_append_epdu_end(params
->buf
);
3394 size_t text_length
= strlen(text
); /* The string can contain '\0' before textLength bytes */
3395 ws_buffer_assure_space(params
->buf
, text_length
); /* The dissector doesn't need NULL-terminated strings */
3396 ws_buffer_append(params
->buf
, text
, text_length
);
3398 /* We'll write this as a WS UPPER PDU packet with a text blob */
3399 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
));
3404 return apptextheader
.source
;
3408 return BLF_APPTEXT_CHANNEL
; /* Cheat - no block to write */;
3410 return BLF_APPTEXT_CHANNEL
; /* Cheat - no block to write */
3414 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
) {
3415 blf_ethernet_status_t ethernet_status_header
;
3417 uint64_t linkUpDuration
;
3419 if (object_length
< (data_start
- block_start
) + (int)sizeof(ethernet_status_header
) + (int)(object_version
>= 1 ? 8 : 0)) {
3420 *err
= WTAP_ERR_BAD_FILE
;
3421 *err_info
= ws_strdup("blf: ETHERNET_STATUS: not enough bytes for ethernet status header in object");
3422 ws_debug("not enough bytes for ethernet status header in object");
3426 if (!blf_read_bytes(params
, data_start
, ðernet_status_header
, sizeof(ethernet_status_header
), err
, err_info
)) {
3427 ws_debug("not enough bytes for ethernet_status_header header in file");
3431 if (object_version
>= 1) {
3432 if (!blf_read_bytes(params
, data_start
+ sizeof(ethernet_status_header
), &linkUpDuration
, 8, err
, err_info
)) {
3433 ws_debug("not enough bytes for ethernet_status_header header in file");
3436 linkUpDuration
= GUINT64_FROM_LE(linkUpDuration
);
3439 fix_endianness_blf_ethernet_status_header(ðernet_status_header
);
3441 tmpbuf
[0] = (ethernet_status_header
.channel
& 0xff00) >> 8;
3442 tmpbuf
[1] = (ethernet_status_header
.channel
& 0x00ff);
3443 tmpbuf
[2] = (ethernet_status_header
.flags
& 0xff00) >> 8;
3444 tmpbuf
[3] = (ethernet_status_header
.flags
& 0x00ff);
3445 tmpbuf
[4] = (ethernet_status_header
.linkStatus
);
3446 tmpbuf
[5] = (ethernet_status_header
.ethernetPhy
);
3447 tmpbuf
[6] = (ethernet_status_header
.duplex
);
3448 tmpbuf
[7] = (ethernet_status_header
.mdi
);
3449 tmpbuf
[8] = (ethernet_status_header
.connector
);
3450 tmpbuf
[9] = (ethernet_status_header
.clockMode
);
3451 tmpbuf
[10] = (ethernet_status_header
.pairs
);
3452 tmpbuf
[11] = (ethernet_status_header
.hardwareChannel
);
3453 tmpbuf
[12] = (ethernet_status_header
.bitrate
& 0xff000000) >> 24;
3454 tmpbuf
[13] = (ethernet_status_header
.bitrate
& 0x00ff0000) >> 16;
3455 tmpbuf
[14] = (ethernet_status_header
.bitrate
& 0x0000ff00) >> 8;
3456 tmpbuf
[15] = (ethernet_status_header
.bitrate
& 0x000000ff);
3458 if (object_version
>= 1) {
3459 tmpbuf
[16] = (uint8_t)((linkUpDuration
& UINT64_C(0xff00000000000000)) >> 56);
3460 tmpbuf
[17] = (uint8_t)((linkUpDuration
& UINT64_C(0x00ff000000000000)) >> 48);
3461 tmpbuf
[18] = (uint8_t)((linkUpDuration
& UINT64_C(0x0000ff0000000000)) >> 40);
3462 tmpbuf
[19] = (uint8_t)((linkUpDuration
& UINT64_C(0x000000ff00000000)) >> 32);
3463 tmpbuf
[20] = (uint8_t)((linkUpDuration
& UINT64_C(0x00000000ff000000)) >> 24);
3464 tmpbuf
[21] = (uint8_t)((linkUpDuration
& UINT64_C(0x0000000000ff0000)) >> 16);
3465 tmpbuf
[22] = (uint8_t)((linkUpDuration
& UINT64_C(0x000000000000ff00)) >> 8);
3466 tmpbuf
[23] = (uint8_t)((linkUpDuration
& UINT64_C(0x00000000000000ff)));
3469 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_DISSECTOR_NAME
, "blf-ethernetstatus-obj");
3470 wtap_buffer_append_epdu_end(params
->buf
);
3472 ws_buffer_assure_space(params
->buf
, sizeof(ethernet_status_header
));
3473 ws_buffer_append(params
->buf
, tmpbuf
, (size_t)(object_version
>= 1 ? 24 : 16));
3475 /* We'll write this as a WS UPPER PDU packet with a data blob */
3476 /* This will create an interface with the "name" of the matching
3477 * WTAP_ENCAP_ETHERNET interface with the same channel and hardware
3478 * channel prefixed with "STATUS" and with a different interface ID,
3479 * because IDBs in pcapng can only have one linktype.
3480 * The other option would be to write everything as UPPER_PDU, including
3481 * the Ethernet data (with one of the "eth_" dissectors.)
3483 char* iface_name
= ws_strdup_printf("STATUS-ETH-%u-%u", ethernet_status_header
.channel
, ethernet_status_header
.hardwareChannel
);
3484 blf_lookup_interface(params
, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, ethernet_status_header
.channel
, ethernet_status_header
.hardwareChannel
, iface_name
);
3486 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
));
3488 if ((ethernet_status_header
.flags
& BLF_ETH_STATUS_HARDWARECHANNEL
) == BLF_ETH_STATUS_HARDWARECHANNEL
) {
3489 /* If HW channel valid */
3490 wtap_block_add_uint32_option(params
->rec
->block
, OPT_PKT_QUEUE
, ethernet_status_header
.hardwareChannel
);
3497 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
) {
3498 blf_ethernet_phystate_t ethernet_phystate_header
;
3501 if (object_length
< (data_start
- block_start
) + (int)sizeof(ethernet_phystate_header
)) {
3502 *err
= WTAP_ERR_BAD_FILE
;
3503 *err_info
= ws_strdup("blf: ETHERNET_PHY_STATE: not enough bytes for ethernet phystate header in object");
3504 ws_debug("not enough bytes for ethernet phystate header in object");
3508 if (!blf_read_bytes(params
, data_start
, ðernet_phystate_header
, sizeof(ethernet_phystate_header
), err
, err_info
)) {
3509 ws_debug("not enough bytes for ethernet phystate header in file");
3513 fix_endianness_blf_ethernet_phystate_header(ðernet_phystate_header
);
3515 tmpbuf
[0] = (ethernet_phystate_header
.channel
& 0xff00) >> 8;
3516 tmpbuf
[1] = (ethernet_phystate_header
.channel
& 0x00ff);
3517 tmpbuf
[2] = (ethernet_phystate_header
.flags
& 0xff00) >> 8;
3518 tmpbuf
[3] = (ethernet_phystate_header
.flags
& 0x00ff);
3519 tmpbuf
[4] = (ethernet_phystate_header
.phyState
);
3520 tmpbuf
[5] = (ethernet_phystate_header
.phyEvent
);
3521 tmpbuf
[6] = (ethernet_phystate_header
.hardwareChannel
);
3522 tmpbuf
[7] = (ethernet_phystate_header
.res1
);
3524 wtap_buffer_append_epdu_string(params
->buf
, EXP_PDU_TAG_DISSECTOR_NAME
, "blf-ethernetphystate-obj");
3525 wtap_buffer_append_epdu_end(params
->buf
);
3527 ws_buffer_assure_space(params
->buf
, sizeof(ethernet_phystate_header
));
3528 ws_buffer_append(params
->buf
, tmpbuf
, sizeof(ethernet_phystate_header
));
3530 /* We'll write this as a WS UPPER PDU packet with a data blob */
3531 /* This will create an interface with the "name" of the matching
3532 * WTAP_ENCAP_ETHERNET interface with the same channel and hardware
3533 * channel prefixed with "STATUS" and with a different interface ID,
3534 * because IDBs in pcapng can only have one linktype.
3535 * The other option would be to write everything as UPPER_PDU, including
3536 * the Ethernet data (with one of the "eth_" dissectors.)
3538 char* iface_name
= ws_strdup_printf("STATUS-ETH-%u-%u", ethernet_phystate_header
.channel
, ethernet_phystate_header
.hardwareChannel
);
3539 blf_lookup_interface(params
, WTAP_ENCAP_WIRESHARK_UPPER_PDU
, ethernet_phystate_header
.channel
, ethernet_phystate_header
.hardwareChannel
, iface_name
);
3541 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
));
3543 if ((ethernet_phystate_header
.flags
& BLF_PHY_STATE_HARDWARECHANNEL
) == BLF_PHY_STATE_HARDWARECHANNEL
) {
3544 /* If HW channel valid */
3545 wtap_block_add_uint32_option(params
->rec
->block
, OPT_PKT_QUEUE
, ethernet_phystate_header
.hardwareChannel
);
3552 blf_read_block(blf_params_t
*params
, int64_t start_pos
, int *err
, char **err_info
) {
3553 blf_blockheader_t header
;
3554 blf_logobjectheader_t logheader
;
3555 blf_logobjectheader2_t logheader2
;
3556 blf_logobjectheader3_t logheader3
;
3558 uint64_t object_timestamp
;
3559 uint16_t object_version
;
3560 int64_t last_metadata_start
= 0;
3561 size_t metadata_cont
= 0;
3566 /* Resetting buffer */
3567 params
->buf
->first_free
= params
->buf
->start
;
3570 if (!blf_read_bytes_or_eof(params
, start_pos
, &header
, sizeof header
, err
, err_info
)) {
3571 ws_debug("not enough bytes for block header or unsupported file");
3572 if (*err
== WTAP_ERR_SHORT_READ
) {
3573 /* we have found the end that is not a short read therefore. */
3581 fix_endianness_blf_blockheader(&header
);
3583 if (memcmp(header
.magic
, blf_obj_magic
, sizeof(blf_obj_magic
))) {
3584 ws_debug("object magic is not LOBJ (pos: 0x%" PRIx64
")", start_pos
);
3590 /* we are moving back and try again but 1 byte later */
3591 /* TODO: better understand how this paddings works... */
3594 params
->blf_data
->start_of_last_obj
= start_pos
;
3596 if (!params
->random
) {
3597 /* Make sure that we start after this object next time,
3598 * but only if it's a linear read. We can have random reads
3599 * during the linear read, so we have to make sure we don't
3600 * lose track of our position.
3602 params
->blf_data
->current_real_seek_pos
= start_pos
+ MAX(MAX(16, header
.object_length
), header
.header_length
);
3605 switch (header
.header_type
) {
3606 case BLF_HEADER_TYPE_DEFAULT
:
3607 if (!blf_read_log_object_header(params
, err
, err_info
, start_pos
+ sizeof(blf_blockheader_t
), start_pos
+ header
.header_length
, &logheader
)) {
3610 flags
= logheader
.flags
;
3611 object_timestamp
= logheader
.object_timestamp
;
3612 object_version
= logheader
.object_version
;
3615 case BLF_HEADER_TYPE_2
:
3616 if (!blf_read_log_object_header2(params
, err
, err_info
, start_pos
+ sizeof(blf_blockheader_t
), start_pos
+ header
.header_length
, &logheader2
)) {
3619 flags
= logheader2
.flags
;
3620 object_timestamp
= logheader2
.object_timestamp
;
3621 object_version
= logheader2
.object_version
;
3624 case BLF_HEADER_TYPE_3
:
3625 if (!blf_read_log_object_header3(params
, err
, err_info
, start_pos
+ sizeof(blf_blockheader_t
), start_pos
+ header
.header_length
, &logheader3
)) {
3628 flags
= logheader3
.flags
;
3629 object_timestamp
= logheader3
.object_timestamp
;
3630 object_version
= logheader3
.object_version
;
3634 *err
= WTAP_ERR_UNSUPPORTED
;
3635 *err_info
= ws_strdup_printf("blf: unknown header type %u", header
.header_type
);
3636 ws_debug("unknown header type");
3640 if (metadata_cont
&& header
.object_type
!= BLF_OBJTYPE_APP_TEXT
) {
3641 /* If we're in the middle of a sequence of AppText metadata objects,
3642 * but we get an AppText object from another source,
3643 * skip the previous incomplete packet and start fresh.
3646 last_metadata_start
= 0;
3649 switch (header
.object_type
) {
3650 case BLF_OBJTYPE_LOG_CONTAINER
:
3651 *err
= WTAP_ERR_UNSUPPORTED
;
3652 *err_info
= ws_strdup("blf: log container in log container not supported");
3653 ws_debug("log container in log container not supported");
3656 case BLF_OBJTYPE_ETHERNET_FRAME
:
3657 return blf_read_ethernetframe(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3659 case BLF_OBJTYPE_ETHERNET_FRAME_EX
:
3660 return blf_read_ethernetframe_ext(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3662 case BLF_OBJTYPE_ETHERNET_RX_ERROR
:
3663 return blf_read_ethernet_rxerror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3665 case BLF_OBJTYPE_ETHERNET_ERROR_EX
:
3666 return blf_read_ethernetframe_ext(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3668 case BLF_OBJTYPE_WLAN_FRAME
:
3669 return blf_read_wlanframe(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3671 case BLF_OBJTYPE_CAN_MESSAGE
:
3672 return blf_read_canmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3674 case BLF_OBJTYPE_CAN_ERROR
:
3675 return blf_read_canerror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3677 case BLF_OBJTYPE_CAN_OVERLOAD
:
3678 return blf_read_canerror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3680 case BLF_OBJTYPE_CAN_MESSAGE2
:
3681 return blf_read_canmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3683 case BLF_OBJTYPE_CAN_ERROR_EXT
:
3684 return blf_read_canerrorext(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3686 case BLF_OBJTYPE_CAN_FD_MESSAGE
:
3687 return blf_read_canfdmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3689 case BLF_OBJTYPE_CAN_FD_MESSAGE_64
:
3690 return blf_read_canfdmessage64(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3692 case BLF_OBJTYPE_CAN_FD_ERROR_64
:
3693 return blf_read_canfderror64(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3695 case BLF_OBJTYPE_FLEXRAY_DATA
:
3696 return blf_read_flexraydata(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3698 case BLF_OBJTYPE_FLEXRAY_MESSAGE
:
3699 return blf_read_flexraymessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3701 case BLF_OBJTYPE_FLEXRAY_RCVMESSAGE
:
3702 return blf_read_flexrayrcvmessageex(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3704 case BLF_OBJTYPE_FLEXRAY_RCVMESSAGE_EX
:
3705 return blf_read_flexrayrcvmessageex(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3707 case BLF_OBJTYPE_LIN_MESSAGE
:
3708 return blf_read_linmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, false);
3710 case BLF_OBJTYPE_LIN_CRC_ERROR
:
3711 return blf_read_linmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, true);
3713 case BLF_OBJTYPE_LIN_RCV_ERROR
:
3714 return blf_read_linrcverror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3716 case BLF_OBJTYPE_LIN_SND_ERROR
:
3717 return blf_read_linsenderror(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3719 case BLF_OBJTYPE_LIN_WAKEUP
:
3720 return blf_read_linwakeupevent(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3722 case BLF_OBJTYPE_LIN_MESSAGE2
:
3723 return blf_read_linmessage2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3725 case BLF_OBJTYPE_LIN_CRC_ERROR2
:
3726 return blf_read_lincrcerror2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3728 case BLF_OBJTYPE_LIN_RCV_ERROR2
:
3729 return blf_read_linrcverror2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3731 case BLF_OBJTYPE_LIN_SND_ERROR2
:
3732 return blf_read_linsenderror2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3734 case BLF_OBJTYPE_LIN_WAKEUP2
:
3735 return blf_read_linwakeupevent2(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3737 case BLF_OBJTYPE_LIN_SLEEP
:
3738 return blf_read_linsleepmodeevent(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3740 case BLF_OBJTYPE_APP_TEXT
:
3742 int result
= blf_read_apptextmessage(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, metadata_cont
);
3743 if (result
== BLF_APPTEXT_CONT
) {
3744 if (!metadata_cont
) {
3745 /* First object of a sequence, save its start position */
3746 last_metadata_start
= start_pos
;
3748 /* Save a pointer to the end of the buffer */
3749 metadata_cont
= params
->buf
->first_free
;
3752 if (result
== BLF_APPTEXT_METADATA
&& metadata_cont
) {
3753 /* Last object of a sequence, restore the start position of the first object */
3754 params
->blf_data
->start_of_last_obj
= last_metadata_start
;
3756 /* Reset everything and start fresh */
3757 last_metadata_start
= 0;
3761 case BLF_APPTEXT_FAILED
:
3763 case BLF_APPTEXT_COMMENT
:
3764 case BLF_APPTEXT_METADATA
:
3765 case BLF_APPTEXT_ATTACHMENT
:
3766 case BLF_APPTEXT_TRACELINE
:
3768 case BLF_APPTEXT_CHANNEL
:
3769 case BLF_APPTEXT_CONT
:
3771 /* we do not return since there is no packet to show here */
3772 start_pos
+= MAX(MAX(16, header
.object_length
), header
.header_length
);
3778 case BLF_OBJTYPE_ETHERNET_STATUS
:
3779 return blf_read_ethernet_status(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
, object_version
);
3781 case BLF_OBJTYPE_ETHERNET_PHY_STATE
:
3782 return blf_read_ethernet_phystate(params
, err
, err_info
, start_pos
, start_pos
+ header
.header_length
, header
.object_length
, flags
, object_timestamp
);
3784 case BLF_OBJTYPE_ENV_INTEGER
:
3785 case BLF_OBJTYPE_ENV_DOUBLE
:
3786 case BLF_OBJTYPE_ENV_STRING
:
3787 case BLF_OBJTYPE_ENV_DATA
:
3788 case BLF_OBJTYPE_SYS_VARIABLE
:
3789 case BLF_OBJTYPE_RESERVED5
: /* Despite the name, this is actually used. Maybe it's worth investigating the content. */
3790 case BLF_OBJTYPE_TEST_STRUCTURE
:
3791 ws_debug("skipping unsupported object type 0x%04x", header
.object_type
);
3792 start_pos
+= MAX(MAX(16, header
.object_length
), header
.header_length
);
3795 ws_info("unknown object type 0x%04x", header
.object_type
);
3796 start_pos
+= MAX(MAX(16, header
.object_length
), header
.header_length
);
3803 static bool blf_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
, int64_t *data_offset
) {
3804 blf_params_t blf_tmp
;
3807 blf_tmp
.fh
= wth
->fh
;
3808 blf_tmp
.random
= false;
3809 blf_tmp
.pipe
= wth
->ispipe
;
3812 blf_tmp
.blf_data
= (blf_t
*)wth
->priv
;
3814 if (!blf_read_block(&blf_tmp
, blf_tmp
.blf_data
->current_real_seek_pos
, err
, err_info
)) {
3817 *data_offset
= blf_tmp
.blf_data
->start_of_last_obj
;
3822 static bool blf_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
) {
3823 blf_params_t blf_tmp
;
3826 blf_tmp
.fh
= wth
->random_fh
;
3827 blf_tmp
.random
= true;
3828 blf_tmp
.pipe
= wth
->ispipe
;
3831 blf_tmp
.blf_data
= (blf_t
*)wth
->priv
;
3833 if (!blf_read_block(&blf_tmp
, seek_off
, err
, err_info
)) {
3834 ws_debug("couldn't read packet block (err=%d).", *err
);
3841 static void blf_free(blf_t
*blf
) {
3843 if (blf
->log_containers
!= NULL
) {
3844 for (unsigned i
= 0; i
< blf
->log_containers
->len
; i
++) {
3845 blf_log_container_t
* log_container
= &g_array_index(blf
->log_containers
, blf_log_container_t
, i
);
3846 if (log_container
->real_data
!= NULL
) {
3847 g_free(log_container
->real_data
);
3850 g_array_free(blf
->log_containers
, true);
3851 blf
->log_containers
= NULL
;
3853 if (blf
->channel_to_iface_ht
!= NULL
) {
3854 g_hash_table_destroy(blf
->channel_to_iface_ht
);
3855 blf
->channel_to_iface_ht
= NULL
;
3857 if (blf
->channel_to_name_ht
!= NULL
) {
3858 g_hash_table_destroy(blf
->channel_to_name_ht
);
3859 blf
->channel_to_name_ht
= NULL
;
3864 static void blf_close(wtap
*wth
) {
3865 blf_free((blf_t
*)wth
->priv
);
3867 /* TODO: do we need to reverse the wtap_add_idb? how? */
3870 wtap_open_return_val
3871 blf_open(wtap
*wth
, int *err
, char **err_info
) {
3872 blf_fileheader_t header
;
3875 ws_debug("opening file");
3877 if (!wtap_read_bytes_or_eof(wth
->fh
, &header
, sizeof(blf_fileheader_t
), err
, err_info
)) {
3879 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err
);
3880 if (*err
== 0 || *err
== WTAP_ERR_SHORT_READ
) {
3882 * Short read or EOF.
3884 * We're reading this as part of an open, so
3885 * the file is too short to be a blf file.
3890 return WTAP_OPEN_NOT_MINE
;
3892 return WTAP_OPEN_ERROR
;
3895 fix_endianness_blf_fileheader(&header
);
3897 if (memcmp(header
.magic
, blf_magic
, sizeof(blf_magic
))) {
3898 return WTAP_OPEN_NOT_MINE
;
3901 /* This seems to be an BLF! */
3902 /* Check for a valid header length */
3903 if (header
.header_length
< sizeof(blf_fileheader_t
)) {
3904 *err
= WTAP_ERR_BAD_FILE
;
3905 *err_info
= ws_strdup("blf: file header length too short");
3906 return WTAP_OPEN_ERROR
;
3909 /* skip past the header, which may include padding/reserved space */
3910 if (!wtap_read_bytes(wth
->fh
, NULL
, header
.header_length
- sizeof(blf_fileheader_t
), err
, err_info
)) {
3911 return WTAP_OPEN_ERROR
;
3914 /* Prepare our private context. */
3915 blf
= g_new(blf_t
, 1);
3916 blf
->log_containers
= g_array_new(false, false, sizeof(blf_log_container_t
));
3917 blf
->current_real_seek_pos
= 0;
3918 blf
->start_offset_ns
= blf_get_start_offset_ns(&header
.start_date
);
3920 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
);
3921 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
);
3922 blf
->next_interface_id
= 0;
3924 wth
->priv
= (void *)blf
;
3925 wth
->file_encap
= WTAP_ENCAP_NONE
;
3926 wth
->snapshot_length
= 0;
3927 wth
->file_tsprec
= WTAP_TSPREC_UNKNOWN
;
3928 wth
->subtype_read
= blf_read
;
3929 wth
->subtype_seek_read
= blf_seek_read
;
3930 wth
->subtype_close
= blf_close
;
3931 wth
->file_type_subtype
= blf_file_type_subtype
;
3933 return WTAP_OPEN_MINE
;
3936 /* Options for interface blocks. */
3937 static const struct supported_option_type interface_block_options_supported
[] = {
3938 /* No comments, just an interface name. */
3939 { OPT_IDB_NAME
, ONE_OPTION_SUPPORTED
}
3942 static const struct supported_block_type blf_blocks_supported
[] = {
3943 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
},
3944 { WTAP_BLOCK_IF_ID_AND_INFO
, MULTIPLE_BLOCKS_SUPPORTED
, OPTION_TYPES_SUPPORTED(interface_block_options_supported
) },
3947 static const struct file_type_subtype_info blf_info
= {
3948 "Vector Informatik Binary Logging Format (BLF) logfile", "blf", "blf", NULL
,
3949 false, BLOCKS_SUPPORTED(blf_blocks_supported
),
3953 void register_blf(void)
3955 blf_file_type_subtype
= wtap_register_file_type_subtype(&blf_info
);
3958 * Register name for backwards compatibility with the
3959 * wtap_filetypes table in Lua.
3961 wtap_register_backwards_compatibility_lua_name("BLF", blf_file_type_subtype
);
3965 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3970 * indent-tabs-mode: nil
3973 * vi: set shiftwidth=4 tabstop=8 expandtab:
3974 * :indentSize=4:tabSize=8:noTabs=true: