diff options
Diffstat (limited to '')
-rw-r--r-- | wiretap/CMakeLists.txt | 2 | ||||
-rw-r--r-- | wiretap/blf.c | 191 | ||||
-rw-r--r-- | wiretap/blf.h | 28 | ||||
-rw-r--r-- | wiretap/file_access.c | 2 | ||||
-rw-r--r-- | wiretap/pcapng.c | 112 | ||||
-rw-r--r-- | wiretap/wtap.h | 3 | ||||
-rw-r--r-- | wiretap/wtap_opttypes.c | 26 | ||||
-rw-r--r-- | wiretap/wtap_opttypes.h | 23 |
8 files changed, 267 insertions, 120 deletions
diff --git a/wiretap/CMakeLists.txt b/wiretap/CMakeLists.txt index f267c647..fe5ef693 100644 --- a/wiretap/CMakeLists.txt +++ b/wiretap/CMakeLists.txt @@ -175,7 +175,7 @@ set_target_properties(wiretap PROPERTIES PREFIX "lib" COMPILE_DEFINITIONS "WS_BUILD_DLL" LINK_FLAGS "${WS_LINK_FLAGS}" - VERSION "14.1.4" SOVERSION 14 + VERSION "14.1.5" SOVERSION 14 FOLDER "DLLs" INSTALL_RPATH "${LIBRARY_INSTALL_RPATH}" ) diff --git a/wiretap/blf.c b/wiretap/blf.c index 9c08c5ec..176db32f 100644 --- a/wiretap/blf.c +++ b/wiretap/blf.c @@ -5,7 +5,7 @@ * * File format support for the Binary Log File (BLF) file format from * Vector Informatik decoder - * Copyright (c) 2021-2022 by Dr. Lars Voelker <lars.voelker@technica-engineering.de> + * Copyright (c) 2021-2024 by Dr. Lars Voelker <lars.voelker@technica-engineering.de> * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -420,15 +420,11 @@ fix_endianness_blf_flexrayrcvmessage(blf_flexrayrcvmessage_t *header) { } static void -fix_endianness_blf_linmessage(blf_linmessage_t *header) { - header->channel = GUINT16_FROM_LE(header->channel); -} - -static void -fix_endianness_blf_linmessage_trailer(blf_linmessage_trailer_t *header) { - header->crc = GUINT16_FROM_LE(header->crc); +fix_endianness_blf_linmessage(blf_linmessage_t* message) { + message->channel = GUINT16_FROM_LE(message->channel); + message->crc = GUINT16_FROM_LE(message->crc); /* skip the optional part - header->res2 = GUINT32_FROM_LE(header->res2); + message->res2 = GUINT32_FROM_LE(message->res2); */ } @@ -877,14 +873,11 @@ blf_read_bytes(blf_params_t *params, guint64 real_pos, void *target_buffer, unsi /* this is only called once on open to figure out the layout of the file */ static gboolean -blf_scan_file_for_logcontainers(blf_params_t *params) { +blf_scan_file_for_logcontainers(blf_params_t *params, int *err, gchar **err_info) { blf_blockheader_t header; blf_logcontainerheader_t logcontainer_header; blf_log_container_t tmp; - int err; - gchar *err_info; - guint64 current_start_pos; guint64 current_real_start = 0; @@ -893,15 +886,16 @@ blf_scan_file_for_logcontainers(blf_params_t *params) { /* Find Object */ while (1) { - if (!wtap_read_bytes_or_eof(params->fh, &header, sizeof header, &err, &err_info)) { + if (!wtap_read_bytes_or_eof(params->fh, &header, sizeof header, err, err_info)) { ws_debug("we found end of file"); /* lets ignore some bytes at the end since some implementations think it is ok to add a few zero bytes */ - if (err == WTAP_ERR_SHORT_READ) { - err = 0; + if (*err == WTAP_ERR_SHORT_READ) { + *err = 0; } - return TRUE; + /* Either succeed on an EOF or fail. */ + return *err == 0; } fix_endianness_blf_blockheader(&header); @@ -912,36 +906,53 @@ blf_scan_file_for_logcontainers(blf_params_t *params) { break; } - /* we are moving back and try again but 1 byte later */ - /* TODO: better understand how this paddings works... */ + /* + * we are moving back and try again but 1 byte later + * TODO: better understand how this paddings works... + * Note that, in at least one capture - the Example.blf + * file attached to + * https://gitlab.com/wireshark/wireshark/-/issues/19269 - + * one of the log container objects is aligned on a 2-byte + * bundary but *not* on a 4-byte boundary, with 3 bytes + * of padding. + */ current_start_pos++; - if (file_seek(params->fh, current_start_pos, SEEK_SET, &err) < 0) { + if (file_seek(params->fh, current_start_pos, SEEK_SET, err) < 0) { return FALSE; } } + if (header.header_length < sizeof(blf_blockheader_t)) { + *err = WTAP_ERR_BAD_FILE; + *err_info = ws_strdup("blf: log container header length too short"); + return FALSE; + } + if (header.header_type != BLF_HEADER_TYPE_DEFAULT) { - ws_debug("unknown header type, I know only BLF_HEADER_TYPE_DEFAULT (1)"); + *err = WTAP_ERR_UNSUPPORTED; + *err_info = ws_strdup_printf("blf: unknown header type (%u), I know only BLF_HEADER_TYPE_DEFAULT (1)", header.header_type); + return FALSE; + } + + if (header.object_length < header.header_length) { + *err = WTAP_ERR_BAD_FILE; + *err_info = ws_strdup("blf: log container header object length less than log container header length"); return FALSE; } switch (header.object_type) { case BLF_OBJTYPE_LOG_CONTAINER: - if (header.header_length < sizeof(blf_blockheader_t)) { - ws_debug("log container header length too short"); - return FALSE; - } - /* skip unknown header part if needed */ if (header.header_length - sizeof(blf_blockheader_t) > 0) { /* seek over unknown header part */ - if (file_seek(params->fh, current_start_pos + header.header_length, SEEK_SET, &err) < 0) { + if (file_seek(params->fh, current_start_pos + header.header_length, SEEK_SET, err) < 0) { ws_debug("cannot seek file for skipping unknown header bytes in log container"); return FALSE; } } - if (!wtap_read_bytes_or_eof(params->fh, &logcontainer_header, sizeof(blf_logcontainerheader_t), &err, &err_info)) { + /* Read the log container header */ + if (!wtap_read_bytes_or_eof(params->fh, &logcontainer_header, sizeof(blf_logcontainerheader_t), err, err_info)) { ws_debug("not enough bytes for log container header"); return FALSE; } @@ -961,7 +972,7 @@ blf_scan_file_for_logcontainers(blf_params_t *params) { /* set up next start position */ current_real_start += logcontainer_header.uncompressed_size; - if (file_seek(params->fh, current_start_pos + MAX(MAX(16, header.object_length), header.header_length), SEEK_SET, &err) < 0) { + if (file_seek(params->fh, current_start_pos + MAX(MAX(16, header.object_length), header.header_length), SEEK_SET, err) < 0) { ws_debug("cannot seek file for skipping log container bytes"); return FALSE; } @@ -973,7 +984,7 @@ blf_scan_file_for_logcontainers(blf_params_t *params) { ws_debug("we found a non BLF log container on top level. this is unexpected."); /* TODO: maybe create "fake Log Container" for this */ - if (file_seek(params->fh, current_start_pos + MAX(MAX(16, header.object_length), header.header_length), SEEK_SET, &err) < 0) { + if (file_seek(params->fh, current_start_pos + MAX(MAX(16, header.object_length), header.header_length), SEEK_SET, err) < 0) { return FALSE; } } @@ -1261,7 +1272,7 @@ static guint8 canfd_dlc_to_length[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 2 static gboolean blf_can_fill_buf_and_rec(blf_params_t *params, int *err, gchar **err_info, guint32 canid, guint8 payload_length, guint8 payload_length_valid, guint64 start_position, - guint32 flags, guint64 object_timestamp, guint16 channel) { + guint32 flags, guint64 object_timestamp, guint16 channel, guint8 canfd_flags) { guint8 tmpbuf[8]; guint caplen, len; @@ -1270,7 +1281,7 @@ blf_can_fill_buf_and_rec(blf_params_t *params, int *err, gchar **err_info, guint tmpbuf[2] = (canid & 0x0000ff00) >> 8; tmpbuf[3] = (canid & 0x000000ff); tmpbuf[4] = payload_length; - tmpbuf[5] = 0; + tmpbuf[5] = canfd_flags; tmpbuf[6] = 0; tmpbuf[7] = 0; @@ -1327,7 +1338,7 @@ blf_read_canmessage(blf_params_t *params, int *err, gchar **err_info, gint64 blo payload_length = 0; } - 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)) { + 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)) { return FALSE; } @@ -1359,6 +1370,7 @@ blf_read_canfdmessage(blf_params_t *params, int *err, gchar **err_info, gint64 b guint32 canid; guint8 payload_length; guint8 payload_length_valid; + guint8 canfd_flags; if (object_length < (data_start - block_start) + (int) sizeof(canheader)) { *err = WTAP_ERR_BAD_FILE; @@ -1378,11 +1390,13 @@ blf_read_canfdmessage(blf_params_t *params, int *err, gchar **err_info, gint64 b canfd = (canheader.canfdflags & BLF_CANFDMESSAGE_CANFDFLAG_EDL) == BLF_CANFDMESSAGE_CANFDFLAG_EDL; if (canfd) { payload_length = canfd_dlc_to_length[canheader.dlc]; + canfd_flags = (canheader.canfdflags & BLF_CANFDMESSAGE_CANFDFLAG_EDL) << 2 | (canheader.canfdflags & BLF_CANFDMESSAGE_CANFDFLAG_ESI) >> 1 | (canheader.canfdflags & BLF_CANFDMESSAGE_CANFDFLAG_BRS) >> 1; } else { if (canheader.dlc > 8) { ws_debug("regular CAN tries more than 8 bytes?"); } payload_length = can_dlc_to_length[canheader.dlc]; + canfd_flags = 0; } if (payload_length > canheader.validDataBytes) { @@ -1404,7 +1418,7 @@ blf_read_canfdmessage(blf_params_t *params, int *err, gchar **err_info, gint64 b payload_length_valid = (guint8)(object_length - (data_start - block_start)); } - 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)) { + 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)) { return FALSE; } @@ -1421,6 +1435,7 @@ blf_read_canfdmessage64(blf_params_t *params, int *err, gchar **err_info, gint64 guint32 canid; guint8 payload_length; guint8 payload_length_valid; + guint8 canfd_flags; if (object_length < (data_start - block_start) + (int) sizeof(canheader)) { *err = WTAP_ERR_BAD_FILE; @@ -1440,11 +1455,13 @@ blf_read_canfdmessage64(blf_params_t *params, int *err, gchar **err_info, gint64 canfd = (canheader.flags & BLF_CANFDMESSAGE64_FLAG_EDL) == BLF_CANFDMESSAGE64_FLAG_EDL; if (canfd) { payload_length = canfd_dlc_to_length[canheader.dlc]; + canfd_flags = (canheader.flags & BLF_CANFDMESSAGE64_FLAG_EDL) >> 10 | (canheader.flags & BLF_CANFDMESSAGE64_FLAG_ESI) >> 13 | (canheader.flags & BLF_CANFDMESSAGE64_FLAG_BRS) >> 13; } else { if (canheader.dlc > 8) { ws_debug("regular CAN tries more than 8 bytes?"); } payload_length = can_dlc_to_length[canheader.dlc]; + canfd_flags = 0; } if (payload_length > canheader.validDataBytes) { @@ -1466,7 +1483,7 @@ blf_read_canfdmessage64(blf_params_t *params, int *err, gchar **err_info, gint64 payload_length_valid = (guint8)(object_length - (data_start - block_start)); } - 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)) { + 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)) { return FALSE; } @@ -1680,6 +1697,7 @@ blf_read_canfderror64(blf_params_t *params, int *err, gchar **err_info, gint64 b tmpbuf[2] = (canid & 0x0000ff00) >> 8; tmpbuf[3] = (canid & 0x000000ff); tmpbuf[4] = payload_length; + // Don't set FDF, ESI and BRS flags, since error messages are always encapsulated in Classic CAN frames ws_buffer_assure_space(params->buf, sizeof(tmpbuf)); ws_buffer_append(params->buf, tmpbuf, sizeof(tmpbuf)); @@ -1911,20 +1929,20 @@ blf_read_flexrayrcvmessageex(blf_params_t *params, int *err, gchar **err_info, g /* Frame Header */ tmpbuf[2] = ((0x0700 & frheader.frameId) >> 8); - if ((frheader.data & BLF_FLEXRAYRCVMSG_DATA_FLAG_PAYLOAD_PREAM) == BLF_FLEXRAYRCVMSG_DATA_FLAG_PAYLOAD_PREAM) { + if ((frheader.frameFlags & BLF_FLEXRAYRCVMSG_FRAME_FLAG_PAYLOAD_PREAM) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_PAYLOAD_PREAM) { tmpbuf[2] |= BLF_DLT_FLEXRAY_PPI; } - if ((frheader.data & BLF_FLEXRAYRCVMSG_DATA_FLAG_SYNC) == BLF_FLEXRAYRCVMSG_DATA_FLAG_SYNC) { + if ((frheader.frameFlags & BLF_FLEXRAYRCVMSG_FRAME_FLAG_SYNC) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_SYNC) { tmpbuf[2] |= BLF_DLT_FLEXRAY_SFI; } - if ((frheader.data & BLF_FLEXRAYRCVMSG_DATA_FLAG_NULL_FRAME) != BLF_FLEXRAYRCVMSG_DATA_FLAG_NULL_FRAME) { + if ((frheader.frameFlags & BLF_FLEXRAYRCVMSG_FRAME_FLAG_NULL_FRAME) != BLF_FLEXRAYRCVMSG_FRAME_FLAG_NULL_FRAME) { /* NFI needs to be inversed !? */ tmpbuf[2] |= BLF_DLT_FLEXRAY_NFI; } - if ((frheader.data & BLF_FLEXRAYRCVMSG_DATA_FLAG_STARTUP) == BLF_FLEXRAYRCVMSG_DATA_FLAG_STARTUP) { + if ((frheader.frameFlags & BLF_FLEXRAYRCVMSG_FRAME_FLAG_STARTUP) == BLF_FLEXRAYRCVMSG_FRAME_FLAG_STARTUP) { tmpbuf[2] |= BLF_DLT_FLEXRAY_STFI; } @@ -1951,75 +1969,47 @@ blf_read_flexrayrcvmessageex(blf_params_t *params, int *err, gchar **err_info, g } static gboolean -blf_read_linmessage(blf_params_t *params, int *err, gchar **err_info, gint64 block_start, gint64 data_start, gint64 object_length, guint32 flags, guint64 object_timestamp) { - blf_linmessage_t linheader; - blf_linmessage_trailer_t lintrailer; +blf_read_linmessage(blf_params_t* params, int* err, gchar** err_info, gint64 block_start, gint64 data_start, gint64 object_length, guint32 flags, guint64 object_timestamp) { + blf_linmessage_t linmessage; guint8 payload_length; - guint8 payload_length_valid; - guint caplen, len; + guint len; - if (object_length < (data_start - block_start) + (int)sizeof(linheader)) { + if (object_length < (data_start - block_start) + (int)sizeof(linmessage)) { *err = WTAP_ERR_BAD_FILE; - *err_info = ws_strdup_printf("blf: LIN_MESSAGE: not enough bytes for linmessage header in object"); - ws_debug("not enough bytes for linmessage header in object"); + *err_info = ws_strdup_printf("blf: LIN_MESSAGE: not enough bytes for linmessage in object"); + ws_debug("not enough bytes for linmessage in object"); return FALSE; } - if (!blf_read_bytes(params, data_start, &linheader, sizeof(linheader), err, err_info)) { - ws_debug("not enough bytes for linmessage header in file"); + if (!blf_read_bytes(params, data_start, &linmessage, sizeof(linmessage), err, err_info)) { + ws_debug("not enough bytes for linmessage in file"); return FALSE; } - fix_endianness_blf_linmessage(&linheader); + fix_endianness_blf_linmessage(&linmessage); - if (linheader.dlc > 15) { - linheader.dlc = 15; - } - - payload_length = linheader.dlc; - payload_length_valid = payload_length; + linmessage.dlc &= 0x0f; + linmessage.id &= 0x3f; - if (payload_length_valid > object_length - (data_start - block_start)) { - ws_debug("shortening LIN payload because buffer is too short!"); - payload_length_valid = (guint8)(object_length - (data_start - block_start)); - } + payload_length = MIN(linmessage.dlc, 8); guint8 tmpbuf[8]; tmpbuf[0] = 1; /* message format rev = 1 */ tmpbuf[1] = 0; /* reserved */ tmpbuf[2] = 0; /* reserved */ tmpbuf[3] = 0; /* reserved */ - tmpbuf[4] = (linheader.dlc << 4) | 0; /* dlc (4bit) | type (2bit) | checksum type (2bit) */ - tmpbuf[5] = linheader.id; - tmpbuf[6] = 0; /* checksum */ + tmpbuf[4] = (linmessage.dlc << 4) | 0; /* dlc (4bit) | type (2bit) | checksum type (2bit) */ + tmpbuf[5] = linmessage.id; /* parity (2bit) | id (6bit) */ + tmpbuf[6] = (guint8)(linmessage.crc & 0xff); /* checksum */ tmpbuf[7] = 0; /* errors */ - ws_buffer_assure_space(params->buf, sizeof(tmpbuf) + payload_length_valid); + ws_buffer_assure_space(params->buf, sizeof(tmpbuf) + payload_length); ws_buffer_append(params->buf, tmpbuf, sizeof(tmpbuf)); - caplen = sizeof(tmpbuf) + payload_length_valid; + ws_buffer_append(params->buf, linmessage.data, payload_length); len = sizeof(tmpbuf) + payload_length; - if (payload_length_valid > 0 && !blf_read_bytes(params, data_start + 4, ws_buffer_end_ptr(params->buf), payload_length_valid, err, err_info)) { - ws_debug("copying can payload failed"); - return FALSE; - } - params->buf->first_free += payload_length_valid; - - if (object_length < (data_start - block_start) + (int)sizeof(linheader) + payload_length_valid + (int)sizeof(lintrailer)) { - *err = WTAP_ERR_BAD_FILE; - *err_info = ws_strdup_printf("blf: LIN_MESSAGE: not enough bytes for linmessage trailer"); - ws_debug("not enough bytes for linmessage trailer"); - return FALSE; - } - if (!blf_read_bytes(params, data_start + sizeof(linheader) + payload_length_valid, &lintrailer, sizeof(lintrailer), err, err_info)) { - ws_debug("not enough bytes for linmessage trailer in file"); - return FALSE; - } - fix_endianness_blf_linmessage_trailer(&lintrailer); - /* we are not using it right now since the CRC is too big to convert */ - - blf_init_rec(params, flags, object_timestamp, WTAP_ENCAP_LIN, linheader.channel, UINT16_MAX, caplen, len); - blf_add_direction_option(params, lintrailer.dir); + blf_init_rec(params, flags, object_timestamp, WTAP_ENCAP_LIN, linmessage.channel, UINT16_MAX, len, len); + blf_add_direction_option(params, linmessage.dir); return TRUE; } @@ -2404,9 +2394,7 @@ static gboolean blf_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer return TRUE; } -static void blf_close(wtap *wth) { - blf_t *blf = (blf_t *)wth->priv; - +static void blf_free(blf_t *blf) { if (blf != NULL && blf->log_containers != NULL) { for (guint i = 0; i < blf->log_containers->len; i++) { blf_log_container_t *log_container = &g_array_index(blf->log_containers, blf_log_container_t, i); @@ -2422,10 +2410,12 @@ static void blf_close(wtap *wth) { g_hash_table_destroy(blf->channel_to_iface_ht); blf->channel_to_iface_ht = NULL; } +} - /* TODO: do we need to reverse the wtap_add_idb? how? */ +static void blf_close(wtap *wth) { + blf_free((blf_t *)wth->priv); - return; + /* TODO: do we need to reverse the wtap_add_idb? how? */ } wtap_open_return_val @@ -2461,8 +2451,17 @@ blf_open(wtap *wth, int *err, gchar **err_info) { } /* This seems to be an BLF! */ - /* skip unknown part of header */ - file_seek(wth->fh, header.header_length, SEEK_SET, err); + /* Check for a valid header length */ + if (header.header_length < sizeof(blf_blockheader_t)) { + *err = WTAP_ERR_BAD_FILE; + *err_info = ws_strdup("blf: file header length too short"); + return WTAP_OPEN_ERROR; + } + + /* skip past the header, which may include padding/reserved space */ + if (file_seek(wth->fh, header.header_length, SEEK_SET, err) < 0) { + return WTAP_OPEN_ERROR; + } struct tm timestamp; timestamp.tm_year = (header.start_date.year > 1970) ? header.start_date.year - 1900 : 70; @@ -2493,7 +2492,11 @@ blf_open(wtap *wth, int *err, gchar **err_info) { params.blf_data->current_real_seek_pos = 0; /* lets check out the layout of all log containers */ - blf_scan_file_for_logcontainers(¶ms); + if (!blf_scan_file_for_logcontainers(¶ms, err, err_info)) { + /* That didn't work. */ + blf_free(blf); + return WTAP_OPEN_ERROR; + } wth->priv = (void *)blf; wth->file_encap = WTAP_ENCAP_NONE; diff --git a/wiretap/blf.h b/wiretap/blf.h index d372f952..fb9e117c 100644 --- a/wiretap/blf.h +++ b/wiretap/blf.h @@ -3,7 +3,7 @@ * Binary Log File (BLF) file format from Vector Informatik decoder * for the Wiretap library. * - * Copyright (c) 2021-2022 by Dr. Lars Voelker <lars.voelker@technica-engineering.de> + * Copyright (c) 2021-2024 by Dr. Lars Voelker <lars.voelker@technica-engineering.de> * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -276,6 +276,10 @@ typedef struct blf_canerrorext { /* see https://bitbucket.org/tobylorenz/vector_blf/src/master/src/Vector/BLF/CanFdErrorFrame64.h */ +#define BLF_CANERROR64_FLAG_FDF 0x01 +#define BLF_CANERROR65_FLAG_BRS 0x02 +#define BLF_CANERROR65_FLAG_ESI 0x04 + typedef struct blf_canfderror64 { guint8 channel; guint8 dlc; @@ -367,14 +371,14 @@ typedef struct blf_flexraymessage { #define BLF_FLEXRAYRCVMSG_CHANNELMASK_B 0x02 #define BLF_FLEXRAYRCVMSG_CHANNELMASK_AB 0x03 -#define BLF_FLEXRAYRCVMSG_DATA_FLAG_NULL_FRAME 0x00000001 -#define BLF_FLEXRAYRCVMSG_DATA_FLAG_VALID_DATA 0x00000002 -#define BLF_FLEXRAYRCVMSG_DATA_FLAG_SYNC 0x00000004 -#define BLF_FLEXRAYRCVMSG_DATA_FLAG_STARTUP 0x00000008 -#define BLF_FLEXRAYRCVMSG_DATA_FLAG_PAYLOAD_PREAM 0x00000010 -#define BLF_FLEXRAYRCVMSG_DATA_FLAG_RES_20 0x00000020 -#define BLF_FLEXRAYRCVMSG_DATA_FLAG_ERROR 0x00000040 -#define BLF_FLEXRAYRCVMSG_DATA_FLAG_RES_80 0x00000080 +#define BLF_FLEXRAYRCVMSG_FRAME_FLAG_NULL_FRAME 0x00000001 +#define BLF_FLEXRAYRCVMSG_FRAME_FLAG_VALID_DATA 0x00000002 +#define BLF_FLEXRAYRCVMSG_FRAME_FLAG_SYNC 0x00000004 +#define BLF_FLEXRAYRCVMSG_FRAME_FLAG_STARTUP 0x00000008 +#define BLF_FLEXRAYRCVMSG_FRAME_FLAG_PAYLOAD_PREAM 0x00000010 +#define BLF_FLEXRAYRCVMSG_FRAME_FLAG_RES_20 0x00000020 +#define BLF_FLEXRAYRCVMSG_FRAME_FLAG_ERROR 0x00000040 +#define BLF_FLEXRAYRCVMSG_FRAME_FLAG_RES_80 0x00000080 typedef struct blf_flexrayrcvmessage { guint16 channel; @@ -443,9 +447,7 @@ typedef struct blf_linmessage { guint16 channel; guint8 id; guint8 dlc; -} blf_linmessage_t; - -typedef struct blf_linmessage_trailer { + guint8 data[8]; guint8 fsmId; guint8 fsmState; guint8 headerTime; @@ -456,7 +458,7 @@ typedef struct blf_linmessage_trailer { /* This field is optional and skipping does not hurt us. guint32 res2; */ -} blf_linmessage_trailer_t; +} blf_linmessage_t; /* see https://bitbucket.org/tobylorenz/vector_blf/src/master/src/Vector/BLF/AppText.h */ diff --git a/wiretap/file_access.c b/wiretap/file_access.c index 01317da0..ca4d2f69 100644 --- a/wiretap/file_access.c +++ b/wiretap/file_access.c @@ -2680,7 +2680,7 @@ wtap_dump_close(wtap_dumper *wdh, gboolean *needs_reload, *needs_reload = wdh->needs_reload; g_free(wdh->priv); wtap_block_array_free(wdh->interface_data); - wtap_block_array_free(wdh->dsbs_initial); + wtap_block_array_unref(wdh->dsbs_initial); g_free(wdh); return ret; } diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index 85c635fc..f5c3b320 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -16,10 +16,10 @@ */ #include "config.h" -#include "wtap_opttypes.h" - #define WS_LOG_DOMAIN LOG_DOMAIN_WIRETAP +#include "wtap_opttypes.h" + #include <stdlib.h> #include <string.h> #include <errno.h> @@ -4368,7 +4368,6 @@ static guint32 pcapng_compute_packet_hash_option_size(wtap_optval_t *optval) { packet_hash_opt_t* hash = &optval->packet_hash; guint32 size; - guint32 pad; switch (hash->type) { case OPT_HASH_CRC32: @@ -4388,12 +4387,25 @@ static guint32 pcapng_compute_packet_hash_option_size(wtap_optval_t *optval) size = hash->hash_bytes->len; break; } + /* XXX - What if the size of the hash bytes doesn't match the + * expected size? We can: + * 1) Return 0, and omit it when writing + * 2) Return hash_bytes->len, and write it out exactly as we have it + * 3) Return the correct size here, and when writing err or possibly + * truncate. + */ + /* Account for the size of the algorithm type field. */ + size += 1; +#if 0 + /* compute_block_option_size() handles padding. */ + uint32_t pad; if ((size % 4)) { pad = 4 - (size % 4); } else { pad = 0; } size += pad; +#endif return size; } @@ -4401,7 +4413,6 @@ static guint32 pcapng_compute_packet_verdict_option_size(wtap_optval_t *optval) { packet_verdict_opt_t* verdict = &optval->packet_verdictval; guint32 size; - guint32 pad; switch (verdict->type) { @@ -4410,23 +4421,31 @@ static guint32 pcapng_compute_packet_verdict_option_size(wtap_optval_t *optval) break; case packet_verdict_linux_ebpf_tc: - size = 9; + size = 8; break; case packet_verdict_linux_ebpf_xdp: - size = 9; + size = 8; break; default: size = 0; break; } + /* Account for the type octet */ + if (size) { + size += 1; + } +#if 0 + /* compute_block_option_size() handles padding. */ + uint32_t pad; if ((size % 4)) { pad = 4 - (size % 4); } else { pad = 0; } size += pad; +#endif return size; } @@ -4468,6 +4487,15 @@ compute_block_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_ /* * Are we writing this option? */ + /* + * XXX: The option length field is 16 bits. If size > 65535 (how? + * was the block was obtained from some format other than pcapng?), + * are we going to silently omit the option (in which case we shouldn't + * add the size here), or err out when writing it (in which case + * it's probably fine to add the size or not?) Adding it here and + * then omitting it when writing, as some of the routines do, means + * creating a corrupt file. + */ if (size != 0) { /* * Yes. Add the size of the option header to the size of the @@ -4922,7 +4950,8 @@ static gboolean pcapng_write_packet_verdict_option(wtap_dumper *wdh, guint optio switch (verdict->type) { case packet_verdict_hardware: - size = verdict->data.verdict_bytes->len; + /* Include type octet */ + size = verdict->data.verdict_bytes->len + 1; if (size > 65535) { /* * Too big to fit in the option. @@ -4941,8 +4970,8 @@ static gboolean pcapng_write_packet_verdict_option(wtap_dumper *wdh, guint optio if (!wtap_dump_file_write(wdh, &type, sizeof(guint8), err)) return FALSE; - if (!wtap_dump_file_write(wdh, verdict->data.verdict_bytes->data, size, - err)) + if (!wtap_dump_file_write(wdh, verdict->data.verdict_bytes->data, + verdict->data.verdict_bytes->len, err)) return FALSE; break; @@ -4992,6 +5021,63 @@ static gboolean pcapng_write_packet_verdict_option(wtap_dumper *wdh, guint optio return TRUE; } +static gboolean pcapng_write_packet_hash_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err) +{ + packet_hash_opt_t* hash = &optval->packet_hash; + struct pcapng_option_header option_hdr; + uint8_t type; + size_t size; + const uint32_t zero_pad = 0; + uint32_t pad; + + size = pcapng_compute_packet_hash_option_size(optval); + + if (size > 65535) { + /* + * Too big to fit in the option. + * Don't write anything. + * + * XXX - truncate it? Report an error? + */ + return TRUE; + } + + if (size > hash->hash_bytes->len + 1) { + /* + * We don't have enough bytes to write. + * pcapng_compute_packet_hash_option_size() should return 0 if + * we want to silently omit the option instead, or should return + * the length if we want to blindly copy it. + * XXX - Is this the best error type? + */ + *err = WTAP_ERR_UNWRITABLE_REC_DATA; + return FALSE; + } + + type = hash->type; + + option_hdr.type = option_id; + /* Include type byte */ + option_hdr.value_length = (uint16_t)size; + if (!wtap_dump_file_write(wdh, &option_hdr, 4, err)) + return FALSE; + + if (!wtap_dump_file_write(wdh, &type, sizeof(uint8_t), err)) + return FALSE; + + if (!wtap_dump_file_write(wdh, hash->hash_bytes->data, size - 1, + err)) + return FALSE; + + /* write padding (if any) */ + if ((size % 4)) { + pad = 4 - (size % 4); + if (!wtap_dump_file_write(wdh, &zero_pad, pad, err)) + return FALSE; + } + return TRUE; +} + static gboolean write_block_option(wtap_block_t block, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data) { write_options_t* options = (write_options_t*)user_data; @@ -5231,8 +5317,14 @@ static gboolean write_wtap_epb_option(wtap_dumper *wdh, wtap_block_t block _U_, return FALSE; break; case OPT_PKT_VERDICT: - if (!pcapng_write_packet_verdict_option(wdh, OPT_EPB_QUEUE, optval, + if (!pcapng_write_packet_verdict_option(wdh, OPT_EPB_VERDICT, optval, err)) + return false; + break; + case OPT_PKT_HASH: + if (!pcapng_write_packet_hash_option(wdh, OPT_EPB_HASH, optval, + err)) + return false; break; default: /* Unknown options - write by datatype? */ diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 93bcca42..2b25c03f 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -1478,7 +1478,8 @@ typedef struct addrinfo_lists { * @note The shb_hdr and idb_inf arguments will be used until * wtap_dump_close() is called, but will not be free'd by the dumper. If * you created them, you must free them yourself after wtap_dump_close(). - * dsbs_initial will be freed by wtap_dump_close(), + * dsbs_initial will be unreferenced by wtap_dump_close(), so to reuse + * them for another dump file, call wtap_block_array_ref() before closing. * dsbs_growing typically refers to another wth->dsbs. * nrbs_growing typically refers to another wth->nrbs. * diff --git a/wiretap/wtap_opttypes.c b/wiretap/wtap_opttypes.c index 7dfbf1a1..98ffe4dd 100644 --- a/wiretap/wtap_opttypes.c +++ b/wiretap/wtap_opttypes.c @@ -466,6 +466,32 @@ void wtap_block_array_free(GArray* block_array) g_array_free(block_array, TRUE); } +void wtap_block_array_ref(GArray* block_array) +{ + unsigned block; + + if (block_array == NULL) + return; + + for (block = 0; block < block_array->len; block++) { + wtap_block_ref(g_array_index(block_array, wtap_block_t, block)); + } + g_array_ref(block_array); +} + +void wtap_block_array_unref(GArray* block_array) +{ + unsigned block; + + if (block_array == NULL) + return; + + for (block = 0; block < block_array->len; block++) { + wtap_block_unref(g_array_index(block_array, wtap_block_t, block)); + } + g_array_unref(block_array); +} + /* * Make a copy of a block. */ diff --git a/wiretap/wtap_opttypes.h b/wiretap/wtap_opttypes.h index f3d9efbd..91dafd6c 100644 --- a/wiretap/wtap_opttypes.h +++ b/wiretap/wtap_opttypes.h @@ -615,6 +615,29 @@ wtap_block_unref(wtap_block_t block); WS_DLL_PUBLIC void wtap_block_array_free(GArray* block_array); +/** Decrement the reference count of an array of blocks + * + * Decrement the reference count of each block in the array + * and the GArray itself. Any element whose reference count + * drops to 0 will be freed. If the GArray and every block + * has a reference count of 1, this is the same as + * wtap_block_array_free(). + * + * @param[in] block_array Array of blocks to be dereferenced + */ +WS_DLL_PUBLIC void +wtap_block_array_unref(GArray* block_array); + +/** Increment the reference count of an array of blocks + * + * Increment the reference count of each block in the array + * and the GArray itself. + * + * @param[in] block_array Array of blocks to be referenced + */ +WS_DLL_PUBLIC void +wtap_block_array_ref(GArray* block_array); + /** Provide type of a block * * @param[in] block Block from which to retrieve mandatory data |