summaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-17 15:00:51 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-17 15:00:51 +0000
commite27759aa56732ec1423a104333c1d88f5ddd7efb (patch)
tree489b146d4effcec44f246eb0b4d1c9f269c94b43 /wiretap
parentAdding upstream version 4.2.4. (diff)
downloadwireshark-e27759aa56732ec1423a104333c1d88f5ddd7efb.tar.xz
wireshark-e27759aa56732ec1423a104333c1d88f5ddd7efb.zip
Adding upstream version 4.2.5.upstream/4.2.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/CMakeLists.txt2
-rw-r--r--wiretap/blf.c191
-rw-r--r--wiretap/blf.h28
-rw-r--r--wiretap/file_access.c2
-rw-r--r--wiretap/pcapng.c112
-rw-r--r--wiretap/wtap.h3
-rw-r--r--wiretap/wtap_opttypes.c26
-rw-r--r--wiretap/wtap_opttypes.h23
8 files changed, 267 insertions, 120 deletions
diff --git a/wiretap/CMakeLists.txt b/wiretap/CMakeLists.txt
index f267c64..fe5ef69 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 9c08c5e..176db32 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(&params);
+ if (!blf_scan_file_for_logcontainers(&params, 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 d372f95..fb9e117 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 01317da..ca4d2f6 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 85c635f..f5c3b32 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 93bcca4..2b25c03 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 7dfbf1a..98ffe4d 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 f3d9efb..91dafd6 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