* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
*
- * File format support for pcap-ng file format
+ * File format support for pcapng file format
* Copyright (c) 2007 by Ulf Lamping <ulf.lamping@web.de>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
/* File format specification:
#include <string.h>
#include <errno.h>
+#include <wsutil/ws_printf.h>
#include "wtap-int.h"
#include "file_wrappers.h"
gint64 *data_offset);
static gboolean
pcapng_seek_read(wtap *wth, gint64 seek_off,
- struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
+ wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
static void
pcapng_close(wtap *wth);
-
-/* pcapng: common block header file encoding for every block type */
-typedef struct pcapng_block_header_s {
- guint32 block_type;
- guint32 block_total_length;
- /* x bytes block_body */
- /* guint32 block_total_length */
-} pcapng_block_header_t;
-
/*
* Minimum block size = size of block header + size of block trailer.
*/
#define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
-/*
- * In order to keep from trying to allocate large chunks of memory,
- * which could either fail or, even if it succeeds, chew up so much
- * address space or memory+backing store as not to leave room for
- * anything else, we impose an upper limit on the size of blocks
- * we're willing to handle.
- *
- * For now, we pick an arbitrary limit of 16MB (OK, fine, 16MiB, but
- * don't try saying that on Wikipedia :-) :-) :-)).
- */
-#define MAX_BLOCK_SIZE (16*1024*1024)
-
-/* pcapng: section header block file encoding */
-typedef struct pcapng_section_header_block_s {
- /* pcapng_block_header_t */
- guint32 magic;
- guint16 version_major;
- guint16 version_minor;
- guint64 section_length; /* might be -1 for unknown */
- /* ... Options ... */
-} pcapng_section_header_block_t;
-
/*
* Minimum SHB size = minimum block size + size of fixed length portion of SHB.
*/
#define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
-/* pcapng: interface description block file encoding */
-typedef struct pcapng_interface_description_block_s {
- guint16 linktype;
- guint16 reserved;
- guint32 snaplen;
- /* ... Options ... */
-} pcapng_interface_description_block_t;
-
-/*
- * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
- */
-#define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
-
/* pcapng: packet block file encoding (obsolete) */
typedef struct pcapng_packet_block_s {
guint16 interface_id;
*/
#define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
-/* pcapng: interface statistics block file encoding */
-typedef struct pcapng_interface_statistics_block_s {
- guint32 interface_id;
- guint32 timestamp_high;
- guint32 timestamp_low;
- /* ... Options ... */
-} pcapng_interface_statistics_block_t;
-
/*
* Minimum ISB size = minimum block size + size of fixed length portion of ISB.
*/
/*
* Minimum Sysdig size = minimum block size + packed size of sysdig_event_phdr.
*/
-#define MIN_SYSDIG_EVENT_SIZE ((guint32)(MIN_BLOCK_SIZE)) + ((16 + 64 + 64 + 32 + 16) / 8)
+#define SYSDIG_EVENT_HEADER_SIZE ((16 + 64 + 64 + 32 + 16)/8) /* CPU ID + TS + TID + Event len + Event type */
+#define MIN_SYSDIG_EVENT_SIZE ((guint32)(MIN_BLOCK_SIZE + SYSDIG_EVENT_HEADER_SIZE))
/* pcapng: common option header file encoding for every option type */
typedef struct pcapng_option_header_s {
/* MSBit of option code means "local type" */
#define OPT_LOCAL_FLAG 0x8000
+/*
+ * In order to keep from trying to allocate large chunks of memory,
+ * which could either fail or, even if it succeeds, chew up so much
+ * address space or memory+backing store as not to leave room for
+ * anything else, we impose upper limits on the size of blocks we're
+ * willing to handle.
+ *
+ * We pick a limit of an EPB with a maximum-sized D-Bus packet and 128 KiB
+ * worth of options; we use the maximum D-Bus packet size as that's larger
+ * than the maximum packet size for other link-layer types, and the maximum
+ * packet size for other link-layer types is currently small enough that
+ * the resulting block size would be less than the previous 16 MiB limit.
+ */
+#define MAX_BLOCK_SIZE (MIN_EPB_SIZE + WTAP_MAX_PACKET_SIZE_DBUS + 131072)
+
/* Note: many of the defined structures for block data are defined in wtap.h */
/* Packet data - used for both Enhanced Packet Block and the obsolete Packet Block data */
/* XXX - put the packet data / pseudo_header here as well? */
} wtapng_simple_packet_t;
-/* Block data to be passed between functions during reading */
-typedef struct wtapng_block_s {
- guint32 type; /* block_type as defined by pcapng */
- wtap_optionblock_t block;
-
- /*
- * XXX - currently don't know how to handle these!
- *
- * For one thing, when we're reading a block, they must be
- * writable, i.e. not const, so that we can read into them,
- * but, when we're writing a block, they can be const, and,
- * in fact, they sometimes point to const values.
- */
- struct wtap_pkthdr *packet_header;
- Buffer *frame_buffer;
-} wtapng_block_t;
-
/* Interface data in private struct */
typedef struct interface_info_s {
int wtap_encap;
} interface_info_t;
typedef struct {
- gboolean shb_read; /**< Set when first SHB read, second read will fail */
+ gboolean shb_read; /**< Set when first SHB read */
gboolean byte_swapped;
guint16 version_major;
guint16 version_minor;
{
block_handler *handler;
+ /*
+ * Is this a known block type?
+ */
+ switch (block_type) {
+
+ case BLOCK_TYPE_SHB:
+ case BLOCK_TYPE_IDB:
+ case BLOCK_TYPE_PB:
+ case BLOCK_TYPE_SPB:
+ case BLOCK_TYPE_NRB:
+ case BLOCK_TYPE_ISB:
+ case BLOCK_TYPE_EPB:
+ case BLOCK_TYPE_SYSDIG_EVENT:
+ /*
+ * Yes; we already handle it, and don't allow a replacement to
+ * be registeted (if there's a bug in our code, or there's
+ * something we don't handle in that block, submit a change
+ * to the main Wireshark source).
+ */
+ g_warning("Attempt to register plugin for block type 0x%08x not allowed",
+ block_type);
+ return;
+
+ case BLOCK_TYPE_IRIG_TS:
+ case BLOCK_TYPE_ARINC_429:
+ case BLOCK_TYPE_SYSDIG_EVF:
+ /*
+ * Yes, and we don't already handle it. Allow a plugin to
+ * handle it.
+ *
+ * (But why not submit the plugin source to Wireshark?)
+ */
+ break;
+
+ default:
+ /*
+ * No; is it a local block type?
+ */
+ if (!(block_type & 0x80000000)) {
+ /*
+ * No; don't allow a plugin to be registered for it, as
+ * the block type needs to be registered before it's used.
+ */
+ g_warning("Attempt to register plugin for reserved block type 0x%08x not allowed",
+ block_type);
+ return;
+ }
+
+ /*
+ * Yes; allow the registration.
+ */
+ break;
+ }
+
if (block_handlers == NULL) {
/*
* Create the table of block handlers.
/* jump over potential padding bytes at end of option */
if ( (oh->option_length % 4) != 0) {
- if (!file_skip(fh, 4 - (oh->option_length % 4), err))
+ if (!wtap_read_bytes(fh, NULL, 4 - (oh->option_length % 4), err, err_info))
return -1;
block_read += 4 - (oh->option_length % 4);
}
int *err, gchar **err_info)
{
int bytes_read;
+ gboolean byte_swapped;
+ guint16 version_major;
+ guint16 version_minor;
guint to_read, opt_cont_buf_len;
pcapng_section_header_block_t shb;
pcapng_option_header_t oh;
* This block is too short to be an SHB.
*
* If we're reading this as part of an open,
- * the file is too short to be a pcap-ng file.
+ * the file is too short to be a pcapng file.
*
* If we're not, we treat PCAPNG_BLOCK_NOT_SHB and
* PCAPNG_BLOCK_ERROR the same, so we can just return
switch (shb.magic) {
case(0x1A2B3C4D):
/* this seems pcapng with correct byte order */
- pn->byte_swapped = FALSE;
- pn->version_major = shb.version_major;
- pn->version_minor = shb.version_minor;
+ byte_swapped = FALSE;
+ version_major = shb.version_major;
+ version_minor = shb.version_minor;
- pcapng_debug("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
- pn->version_major, pn->version_minor, bh->block_total_length);
+ pcapng_debug("pcapng_read_section_header_block: SHB (our byte order) V%u.%u, len %u",
+ version_major, version_minor, bh->block_total_length);
break;
case(0x4D3C2B1A):
/* this seems pcapng with swapped byte order */
- pn->byte_swapped = TRUE;
- pn->version_major = GUINT16_SWAP_LE_BE(shb.version_major);
- pn->version_minor = GUINT16_SWAP_LE_BE(shb.version_minor);
+ byte_swapped = TRUE;
+ version_major = GUINT16_SWAP_LE_BE(shb.version_major);
+ version_minor = GUINT16_SWAP_LE_BE(shb.version_minor);
/* tweak the block length to meet current swapping that we know now */
bh->block_total_length = GUINT32_SWAP_LE_BE(bh->block_total_length);
- pcapng_debug("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
- pn->version_major, pn->version_minor, bh->block_total_length);
+ pcapng_debug("pcapng_read_section_header_block: SHB (byte-swapped) V%u.%u, len %u",
+ version_major, version_minor, bh->block_total_length);
break;
default:
/* Not a "pcapng" magic number we know about. */
return PCAPNG_BLOCK_ERROR;
}
- /* OK, at this point we assume it's a pcap-ng file.
+ /* OK, at this point we assume it's a pcapng file.
Don't try to allocate memory for a huge number of options, as
that might fail and, even if it succeeds, it might not leave
We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
We check for this *after* checking the SHB for its byte
- order magic number, so that non-pcap-ng files are less
- likely to be treated as bad pcap-ng files. */
+ order magic number, so that non-pcapng files are less
+ likely to be treated as bad pcapng files. */
if (bh->block_total_length > MAX_BLOCK_SIZE) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcapng_read_section_header_block: total block length %u is too large (> %u)",
return PCAPNG_BLOCK_ERROR;
}
- /* We currently only suport one SHB */
- if (pn->shb_read == TRUE) {
- *err = WTAP_ERR_UNSUPPORTED;
- *err_info = g_strdup_printf("pcapng_read_section_header_block: multiple section header blocks not supported");
- return PCAPNG_BLOCK_ERROR;
- }
-
/* we currently only understand SHB V1.0 */
- if (pn->version_major != 1 || pn->version_minor > 0) {
+ if (version_major != 1 || version_minor > 0) {
*err = WTAP_ERR_UNSUPPORTED;
*err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
pn->version_major, pn->version_minor);
return PCAPNG_BLOCK_ERROR;
}
- wblock->block = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
- section_data = (wtapng_mandatory_section_t*)wtap_optionblock_get_mandatory_data(wblock->block);
+ pn->byte_swapped = byte_swapped;
+ pn->version_major = version_major;
+ pn->version_minor = version_minor;
+
+ wblock->block = wtap_block_create(WTAP_BLOCK_NG_SECTION);
+ section_data = (wtapng_mandatory_section_t*)wtap_block_get_mandatory_data(wblock->block);
/* 64bit section_length (currently unused) */
if (pn->byte_swapped) {
section_data->section_length = GUINT64_SWAP_LE_BE(shb.section_length);
bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info, "section_header");
if (bytes_read <= 0) {
pcapng_debug("pcapng_read_section_header_block: failed to read option");
+ g_free(option_content);
return PCAPNG_BLOCK_ERROR;
}
to_read -= bytes_read;
case(OPT_COMMENT):
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_COMMENT, tmp_content);
+ wtap_block_add_string_option(wblock->block, OPT_COMMENT, option_content, oh.option_length);
pcapng_debug("pcapng_read_section_header_block: opt_comment %s", tmp_content);
g_free(tmp_content);
} else {
case(OPT_SHB_HARDWARE):
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_SHB_HARDWARE, tmp_content);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_string_option(wblock->block, OPT_SHB_HARDWARE, option_content, oh.option_length);
pcapng_debug("pcapng_read_section_header_block: shb_hardware %s", tmp_content);
g_free(tmp_content);
} else {
case(OPT_SHB_OS):
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_SHB_OS, tmp_content);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_string_option(wblock->block, OPT_SHB_OS, option_content, oh.option_length);
pcapng_debug("pcapng_read_section_header_block: shb_os %s", tmp_content);
g_free(tmp_content);
} else {
case(OPT_SHB_USERAPPL):
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_SHB_USERAPPL, tmp_content);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_string_option(wblock->block, OPT_SHB_USERAPPL, option_content, oh.option_length);
pcapng_debug("pcapng_read_section_header_block: shb_user_appl %s", tmp_content);
g_free(tmp_content);
} else {
}
g_free(option_content);
+ /*
+ * We don't return these to the caller in pcapng_read().
+ */
+ wblock->internal = TRUE;
+
return PCAPNG_BLOCK_OK;
}
guint to_read, opt_cont_buf_len;
pcapng_interface_description_block_t idb;
wtapng_if_descr_mandatory_t* if_descr_mand;
+ guint link_type;
pcapng_option_header_t oh;
guint8 *option_content = NULL; /* Allocate as large as the options block */
gchar* tmp_content;
return FALSE;
}
- /* Don't try to allocate memory for a huge number of options, as
- that might fail and, even if it succeeds, it might not leave
- any address space or memory+backing store for anything else.
-
- We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
- We check for this *after* checking the SHB for its byte
- order magic number, so that non-pcap-ng files are less
- likely to be treated as bad pcap-ng files. */
- if (bh->block_total_length > MAX_BLOCK_SIZE) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("pcapng_read_if_descr_block: total block length %u is too large (> %u)",
- bh->block_total_length, MAX_BLOCK_SIZE);
- return FALSE;
- }
-
/* read block content */
if (!wtap_read_bytes(fh, &idb, sizeof idb, err, err_info)) {
pcapng_debug("pcapng_read_if_descr_block: failed to read IDB");
}
/* mandatory values */
- wblock->block = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
- if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(wblock->block);
+ wblock->block = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+ if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
if (pn->byte_swapped) {
- if_descr_mand->link_type = GUINT16_SWAP_LE_BE(idb.linktype);
+ link_type = GUINT16_SWAP_LE_BE(idb.linktype);
if_descr_mand->snap_len = GUINT32_SWAP_LE_BE(idb.snaplen);
} else {
- if_descr_mand->link_type = idb.linktype;
+ link_type = idb.linktype;
if_descr_mand->snap_len = idb.snaplen;
}
- if_descr_mand->wtap_encap = wtap_pcap_encap_to_wtap_encap(if_descr_mand->link_type);
+ if_descr_mand->wtap_encap = wtap_pcap_encap_to_wtap_encap(link_type);
if_descr_mand->time_units_per_second = time_units_per_second;
if_descr_mand->tsprecision = tsprecision;
pcapng_debug("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
- if_descr_mand->link_type,
+ link_type,
wtap_encap_string(if_descr_mand->wtap_encap),
if_descr_mand->snap_len);
- if (if_descr_mand->snap_len > WTAP_MAX_PACKET_SIZE) {
- /* This is unrealistic, but text2pcap currently uses 102400.
+ if (if_descr_mand->snap_len > wtap_max_snaplen_for_encap(if_descr_mand->wtap_encap)) {
+ /*
* We do not use this value, maybe we should check the
* snap_len of the packets against it. For now, only warn.
*/
pcapng_debug("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
if_descr_mand->snap_len);
- /*if_descr_mand->snap_len = WTAP_MAX_PACKET_SIZE;*/
+ /*if_descr_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;*/
}
/* Options */
bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info, "if_descr");
if (bytes_read <= 0) {
pcapng_debug("pcapng_read_if_descr_block: failed to read option");
+ g_free(option_content);
return FALSE;
}
to_read -= bytes_read;
case(OPT_COMMENT): /* opt_comment */
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_COMMENT, tmp_content);
+ wtap_block_add_string_option(wblock->block, oh.option_code, option_content, oh.option_length);
pcapng_debug("pcapng_read_if_descr_block: opt_comment %s", tmp_content);
g_free(tmp_content);
} else {
case(OPT_IDB_NAME): /* if_name */
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_IDB_NAME, tmp_content);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_string_option(wblock->block, oh.option_code, option_content, oh.option_length);
pcapng_debug("pcapng_read_if_descr_block: if_name %s", tmp_content);
g_free(tmp_content);
} else {
case(OPT_IDB_DESCR): /* if_description */
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_IDB_DESCR, tmp_content);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_string_option(wblock->block, oh.option_code, option_content, oh.option_length);
pcapng_debug("pcapng_read_if_descr_block: if_description %s", tmp_content);
g_free(tmp_content);
} else {
memcpy(&tmp64, option_content, sizeof(guint64));
if (pn->byte_swapped)
tmp64 = GUINT64_SWAP_LE_BE(tmp64);
- wtap_optionblock_set_option_uint64(wblock->block, OPT_IDB_SPEED, tmp64);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint64_option(wblock->block, oh.option_code, tmp64);
pcapng_debug("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", tmp64);
} else {
pcapng_debug("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
pcapng_debug("pcapng_open: time conversion might be inaccurate");
}
if_descr_mand->time_units_per_second = time_units_per_second;
- wtap_optionblock_set_option_uint8(wblock->block, OPT_IDB_TSRESOL, if_tsresol);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint8_option(wblock->block, oh.option_code, if_tsresol);
if (time_units_per_second >= 1000000000)
tsprecision = WTAP_TSPREC_NSEC;
else if (time_units_per_second >= 1000000)
pcapng_debug("pcapng_read_if_descr_block: if_filter_str %s oh.option_length %u", if_filter.if_filter_str, oh.option_length);
} else if (option_content[0] == 1) {
if_filter.bpf_filter_len = oh.option_length-1;
- if_filter.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
- memcpy(if_filter.if_filter_bpf_bytes, (char *)option_content+1, oh.option_length-1);
+ if_filter.if_filter_bpf_bytes = (guint8 *)option_content+1;
}
- wtap_optionblock_set_option_custom(wblock->block, OPT_IDB_FILTER, &if_filter);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_custom_option(wblock->block, oh.option_code, &if_filter, sizeof if_filter);
+ g_free(if_filter.if_filter_str);
} else {
pcapng_debug("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
}
*/
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_IDB_OS, tmp_content);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_string_option(wblock->block, oh.option_code, option_content, oh.option_length);
pcapng_debug("pcapng_read_if_descr_block: if_os %s", tmp_content);
g_free(tmp_content);
} else {
break;
case(OPT_IDB_FCSLEN): /* if_fcslen */
if (oh.option_length == 1) {
- wtap_optionblock_set_option_uint8(wblock->block, OPT_IDB_TSRESOL, option_content[0]);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint8_option(wblock->block, oh.option_code, option_content[0]);
pn->if_fcslen = option_content[0];
pcapng_debug("pcapng_read_if_descr_block: if_fcslen %u", pn->if_fcslen);
/* XXX - add sanity check */
pcapng_debug("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
}
break;
+ case(OPT_IDB_HARDWARE): /* if_hardware */
+ if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
+ tmp_content = g_strndup((char *)option_content, oh.option_length);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_string_option(wblock->block, oh.option_code, option_content, oh.option_length);
+ pcapng_debug("pcapng_read_if_descr_block: if_hardware %s", tmp_content);
+ g_free(tmp_content);
+ } else {
+ pcapng_debug("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
+ }
+ break;
/* TODO: process these! */
case(OPT_IDB_IP4ADDR):
}
}
+ /*
+ * We don't return these to the caller in pcapng_read().
+ */
+ wblock->internal = TRUE;
+
return TRUE;
}
option_handler *handler;
#endif
- /* Don't try to allocate memory for a huge number of options, as
- that might fail and, even if it succeeds, it might not leave
- any address space or memory+backing store for anything else.
-
- We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
- We check for this *after* checking the SHB for its byte
- order magic number, so that non-pcap-ng files are less
- likely to be treated as bad pcap-ng files. */
- if (bh->block_total_length > MAX_BLOCK_SIZE) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u is too large (> %u)",
- bh->block_total_length, MAX_BLOCK_SIZE);
- return FALSE;
- }
-
/* "(Enhanced) Packet Block" read fixed part */
if (enhanced) {
/*
}
}
- if (packet.cap_len > WTAP_MAX_PACKET_SIZE) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
- packet.cap_len, WTAP_MAX_PACKET_SIZE);
- return FALSE;
- }
pcapng_debug("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
packet.packet_len,
packet.cap_len,
iface_info = g_array_index(pn->interfaces, interface_info_t,
packet.interface_id);
- wblock->packet_header->rec_type = REC_TYPE_PACKET;
- wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
+ if (packet.cap_len > wtap_max_snaplen_for_encap(iface_info.wtap_encap)) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than %u",
+ packet.cap_len,
+ wtap_max_snaplen_for_encap(iface_info.wtap_encap));
+ return FALSE;
+ }
+
+ wblock->rec->rec_type = REC_TYPE_PACKET;
+ wblock->rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
pcapng_debug("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
iface_info.wtap_encap,
wtap_encap_string(iface_info.wtap_encap),
- pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header));
- wblock->packet_header->interface_id = packet.interface_id;
- wblock->packet_header->pkt_encap = iface_info.wtap_encap;
- wblock->packet_header->pkt_tsprec = iface_info.tsprecision;
+ pcap_get_phdr_size(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header.pseudo_header));
+ wblock->rec->rec_header.packet_header.interface_id = packet.interface_id;
+ wblock->rec->rec_header.packet_header.pkt_encap = iface_info.wtap_encap;
+ wblock->rec->tsprec = iface_info.tsprecision;
- memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
+ memset((void *)&wblock->rec->rec_header.packet_header.pseudo_header, 0, sizeof(union wtap_pseudo_header));
pseudo_header_len = pcap_process_pseudo_header(fh,
WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
iface_info.wtap_encap,
packet.cap_len,
- TRUE,
- wblock->packet_header,
+ wblock->rec,
err,
err_info);
if (pseudo_header_len < 0) {
return FALSE;
}
block_read += pseudo_header_len;
- if (pseudo_header_len != pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header)) {
- pcapng_debug("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
- pseudo_header_len);
- }
- wblock->packet_header->caplen = packet.cap_len - pseudo_header_len;
- wblock->packet_header->len = packet.packet_len - pseudo_header_len;
+ wblock->rec->rec_header.packet_header.caplen = packet.cap_len - pseudo_header_len;
+ wblock->rec->rec_header.packet_header.len = packet.packet_len - pseudo_header_len;
/* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
ts = (((guint64)packet.ts_high) << 32) | ((guint64)packet.ts_low);
- wblock->packet_header->ts.secs = (time_t)(ts / iface_info.time_units_per_second);
- wblock->packet_header->ts.nsecs = (int)(((ts % iface_info.time_units_per_second) * 1000000000) / iface_info.time_units_per_second);
+ wblock->rec->ts.secs = (time_t)(ts / iface_info.time_units_per_second);
+ wblock->rec->ts.nsecs = (int)(((ts % iface_info.time_units_per_second) * 1000000000) / iface_info.time_units_per_second);
/* "(Enhanced) Packet Block" read capture data */
if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
/* jump over potential padding bytes at end of the packet data */
if (padding != 0) {
- if (!file_skip(fh, padding, err))
+ if (!wtap_read_bytes(fh, NULL, padding, err, err_info))
return FALSE;
block_read += padding;
}
/* Option defaults */
- wblock->packet_header->opt_comment = NULL;
- wblock->packet_header->drop_count = -1;
- wblock->packet_header->pack_flags = 0;
+ wblock->rec->opt_comment = NULL;
+ wblock->rec->rec_header.packet_header.drop_count = -1;
+ wblock->rec->rec_header.packet_header.pack_flags = 0;
/* FCS length default */
fcslen = pn->if_fcslen;
/* Allocate enough memory to hold all options */
opt_cont_buf_len = to_read;
- ws_buffer_assure_space(&wblock->packet_header->ft_specific_data, opt_cont_buf_len);
- opt_ptr = ws_buffer_start_ptr(&wblock->packet_header->ft_specific_data);
+ ws_buffer_assure_space(&wblock->rec->options_buf, opt_cont_buf_len);
+ opt_ptr = ws_buffer_start_ptr(&wblock->rec->options_buf);
while (to_read != 0) {
/* read option */
/* XXX - free anything? */
return FALSE;
}
- block_read += bytes_read;
to_read -= bytes_read;
/* handle option content */
break;
case(OPT_COMMENT):
if (oh->option_length > 0 && oh->option_length < opt_cont_buf_len) {
- wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
- wblock->packet_header->opt_comment = g_strndup((char *)option_content, oh->option_length);
- pcapng_debug("pcapng_read_packet_block: length %u opt_comment '%s'", oh->option_length, wblock->packet_header->opt_comment);
+ wblock->rec->presence_flags |= WTAP_HAS_COMMENTS;
+ wblock->rec->opt_comment = g_strndup((char *)option_content, oh->option_length);
+ pcapng_debug("pcapng_read_packet_block: length %u opt_comment '%s'", oh->option_length, wblock->rec->opt_comment);
} else {
pcapng_debug("pcapng_read_packet_block: opt_comment length %u seems strange", oh->option_length);
}
* guint8 * may not point to something that's
* aligned correctly.
*/
- wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
- memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
+ wblock->rec->presence_flags |= WTAP_HAS_PACK_FLAGS;
+ memcpy(&wblock->rec->rec_header.packet_header.pack_flags, option_content, sizeof(guint32));
if (pn->byte_swapped) {
- wblock->packet_header->pack_flags = GUINT32_SWAP_LE_BE(wblock->packet_header->pack_flags);
- memcpy(option_content, &wblock->packet_header->pack_flags, sizeof(guint32));
+ wblock->rec->rec_header.packet_header.pack_flags = GUINT32_SWAP_LE_BE(wblock->rec->rec_header.packet_header.pack_flags);
+ memcpy(option_content, &wblock->rec->rec_header.packet_header.pack_flags, sizeof(guint32));
}
- if (wblock->packet_header->pack_flags & 0x000001E0) {
+ if (wblock->rec->rec_header.packet_header.pack_flags & 0x000001E0) {
/* The FCS length is present */
- fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
+ fcslen = (wblock->rec->rec_header.packet_header.pack_flags & 0x000001E0) >> 5;
}
- pcapng_debug("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
+ pcapng_debug("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->rec->rec_header.packet_header.pack_flags);
break;
case(OPT_EPB_HASH):
pcapng_debug("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
* guint8 * may not point to something that's
* aligned correctly.
*/
- wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
- memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
+ wblock->rec->presence_flags |= WTAP_HAS_DROP_COUNT;
+ memcpy(&wblock->rec->rec_header.packet_header.drop_count, option_content, sizeof(guint64));
if (pn->byte_swapped) {
- wblock->packet_header->drop_count = GUINT64_SWAP_LE_BE(wblock->packet_header->drop_count);
- memcpy(option_content, &wblock->packet_header->drop_count, sizeof(guint64));
+ wblock->rec->rec_header.packet_header.drop_count = GUINT64_SWAP_LE_BE(wblock->rec->rec_header.packet_header.drop_count);
+ memcpy(option_content, &wblock->rec->rec_header.packet_header.drop_count, sizeof(guint64));
}
- pcapng_debug("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
+ pcapng_debug("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->rec->rec_header.packet_header.drop_count);
break;
default:
#ifdef HAVE_PLUGINS
}
pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
- wblock->packet_header, ws_buffer_start_ptr(wblock->frame_buffer),
+ wblock->rec, ws_buffer_start_ptr(wblock->frame_buffer),
pn->byte_swapped, fcslen);
+
+ /*
+ * We return these to the caller in pcapng_read().
+ */
+ wblock->internal = FALSE;
+
return TRUE;
}
return FALSE;
}
- /* Don't try to allocate memory for a huge number of options, as
- that might fail and, even if it succeeds, it might not leave
- any address space or memory+backing store for anything else.
-
- We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
- We check for this *after* checking the SHB for its byte
- order magic number, so that non-pcap-ng files are less
- likely to be treated as bad pcap-ng files. */
- if (bh->block_total_length > MAX_BLOCK_SIZE) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u is too large (> %u)",
- bh->block_total_length, MAX_BLOCK_SIZE);
- return FALSE;
- }
-
/* "Simple Packet Block" read fixed part */
if (!wtap_read_bytes(fh, &spb, sizeof spb, err, err_info)) {
pcapng_debug("pcapng_read_simple_packet_block: failed to read packet data");
if (0 >= pn->interfaces->len) {
*err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("pcapng_read_simple_packet_block: SPB appeared before any IDBs");
+ *err_info = g_strdup("pcapng_read_simple_packet_block: SPB appeared before any IDBs");
return FALSE;
}
iface_info = g_array_index(pn->interfaces, interface_info_t, 0);
/*
* The captured length is not a field in the SPB; it can be
* calculated as the minimum of the snapshot length from the
- * IDB and the packet length, as per the pcap-ng spec. An IDB
+ * IDB and the packet length, as per the pcapng spec. An IDB
* snapshot length of 0 means no limit.
*/
simple_packet.cap_len = simple_packet.packet_len;
return FALSE;
}
- if (simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
+ if (simple_packet.cap_len > wtap_max_snaplen_for_encap(iface_info.wtap_encap)) {
*err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
- simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
+ *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than %u",
+ simple_packet.cap_len,
+ wtap_max_snaplen_for_encap(iface_info.wtap_encap));
return FALSE;
}
pcapng_debug("pcapng_read_simple_packet_block: packet data: packet_len %u",
simple_packet.packet_len);
pcapng_debug("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
- pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header));
+ pcap_get_phdr_size(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header.pseudo_header));
/* No time stamp in a simple packet block; no options, either */
- wblock->packet_header->rec_type = REC_TYPE_PACKET;
- wblock->packet_header->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
- wblock->packet_header->interface_id = 0;
- wblock->packet_header->pkt_encap = iface_info.wtap_encap;
- wblock->packet_header->pkt_tsprec = iface_info.tsprecision;
- wblock->packet_header->ts.secs = 0;
- wblock->packet_header->ts.nsecs = 0;
- wblock->packet_header->interface_id = 0;
- wblock->packet_header->opt_comment = NULL;
- wblock->packet_header->drop_count = 0;
- wblock->packet_header->pack_flags = 0;
-
- memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
+ wblock->rec->rec_type = REC_TYPE_PACKET;
+ wblock->rec->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
+ wblock->rec->rec_header.packet_header.interface_id = 0;
+ wblock->rec->rec_header.packet_header.pkt_encap = iface_info.wtap_encap;
+ wblock->rec->tsprec = iface_info.tsprecision;
+ wblock->rec->ts.secs = 0;
+ wblock->rec->ts.nsecs = 0;
+ wblock->rec->rec_header.packet_header.interface_id = 0;
+ wblock->rec->opt_comment = NULL;
+ wblock->rec->rec_header.packet_header.drop_count = 0;
+ wblock->rec->rec_header.packet_header.pack_flags = 0;
+
+ memset((void *)&wblock->rec->rec_header.packet_header.pseudo_header, 0, sizeof(union wtap_pseudo_header));
pseudo_header_len = pcap_process_pseudo_header(fh,
WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
iface_info.wtap_encap,
simple_packet.cap_len,
- TRUE,
- wblock->packet_header,
+ wblock->rec,
err,
err_info);
if (pseudo_header_len < 0) {
return FALSE;
}
- wblock->packet_header->caplen = simple_packet.cap_len - pseudo_header_len;
- wblock->packet_header->len = simple_packet.packet_len - pseudo_header_len;
- if (pseudo_header_len != pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header)) {
- pcapng_debug("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
- pseudo_header_len);
- }
+ wblock->rec->rec_header.packet_header.caplen = simple_packet.cap_len - pseudo_header_len;
+ wblock->rec->rec_header.packet_header.len = simple_packet.packet_len - pseudo_header_len;
- memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
+ memset((void *)&wblock->rec->rec_header.packet_header.pseudo_header, 0, sizeof(union wtap_pseudo_header));
/* "Simple Packet Block" read capture data */
if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
/* jump over potential padding bytes at end of the packet data */
if ((simple_packet.cap_len % 4) != 0) {
- if (!file_skip(fh, 4 - (simple_packet.cap_len % 4), err))
+ if (!wtap_read_bytes(fh, NULL, 4 - (simple_packet.cap_len % 4), err, err_info))
return FALSE;
}
pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
- wblock->packet_header, ws_buffer_start_ptr(wblock->frame_buffer),
+ wblock->rec, ws_buffer_start_ptr(wblock->frame_buffer),
pn->byte_swapped, pn->if_fcslen);
+
+ /*
+ * We return these to the caller in pcapng_read().
+ */
+ wblock->internal = FALSE;
+
return TRUE;
}
}
static gboolean
-pcapng_read_name_resolution_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock _U_,int *err, gchar **err_info)
+pcapng_read_name_resolution_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
{
int block_read;
int to_read;
return FALSE;
}
- /* Don't try to allocate memory for a huge number of options, as
- that might fail and, even if it succeeds, it might not leave
- any address space or memory+backing store for anything else.
-
- We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
- We check for this *after* checking the SHB for its byte
- order magic number, so that non-pcap-ng files are less
- likely to be treated as bad pcap-ng files. */
- if (bh->block_total_length > MAX_BLOCK_SIZE) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("pcapng_read_name_resolution_block: total block length %u is too large (> %u)",
- bh->block_total_length, MAX_BLOCK_SIZE);
- return FALSE;
- }
-
to_read = bh->block_total_length - 8 - 4; /* We have read the header and should not read the final block_total_length */
pcapng_debug("pcapng_read_name_resolution_block, total %d bytes", bh->block_total_length);
+ /* Ensure we have a name resolution block */
+ if (wblock->block == NULL) {
+ wblock->block = wtap_block_create(WTAP_BLOCK_NG_NRB);
+ }
+
/*
* Start out with a buffer big enough for an IPv6 address and one
* 64-byte name; we'll make the buffer bigger if necessary.
* a 4-byte IPv4 address, hence a minimum
* of 4 bytes.
*
- * (The pcap-NG spec really indicates
+ * (The pcapng spec really indicates
* that it must be at least 5 bytes,
* as there must be at least one name,
* and it really must be at least 6
}
}
- if (!file_skip(fh, PADDING4(nrb.record_len), err)) {
+ if (!wtap_read_bytes(fh, NULL, PADDING4(nrb.record_len), err, err_info)) {
ws_buffer_free(&nrb_rec);
return FALSE;
}
* a 16-byte IPv6 address, hence a minimum
* of 16 bytes.
*
- * (The pcap-NG spec really indicates
+ * (The pcapng spec really indicates
* that it must be at least 17 bytes,
* as there must be at least one name,
* and it really must be at least 18
}
}
- if (!file_skip(fh, PADDING4(nrb.record_len), err)) {
+ if (!wtap_read_bytes(fh, NULL, PADDING4(nrb.record_len), err, err_info)) {
ws_buffer_free(&nrb_rec);
return FALSE;
}
break;
default:
pcapng_debug("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
- if (!file_skip(fh, nrb.record_len + PADDING4(nrb.record_len), err)) {
+ if (!wtap_read_bytes(fh, NULL, nrb.record_len + PADDING4(nrb.record_len), err, err_info)) {
ws_buffer_free(&nrb_rec);
return FALSE;
}
case(OPT_COMMENT):
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_COMMENT, tmp_content);
+ wtap_block_add_string_option(wblock->block, OPT_COMMENT, option_content, oh.option_length);
pcapng_debug("pcapng_read_name_resolution_block: length %u opt_comment '%s'", oh.option_length, tmp_content);
g_free(tmp_content);
} else {
g_free(option_content);
ws_buffer_free(&nrb_rec);
+
+ /*
+ * We don't return these to the caller in pcapng_read().
+ */
+ wblock->internal = TRUE;
+
return TRUE;
}
return FALSE;
}
- /* Don't try to allocate memory for a huge number of options, as
- that might fail and, even if it succeeds, it might not leave
- any address space or memory+backing store for anything else.
-
- We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
- We check for this *after* checking the SHB for its byte
- order magic number, so that non-pcap-ng files are less
- likely to be treated as bad pcap-ng files. */
- if (bh->block_total_length > MAX_BLOCK_SIZE) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too large (> %u)",
- bh->block_total_length, MAX_BLOCK_SIZE);
- return FALSE;
- }
-
/* "Interface Statistics Block" read fixed part */
if (!wtap_read_bytes(fh, &isb, sizeof isb, err, err_info)) {
pcapng_debug("pcapng_read_interface_statistics_block: failed to read packet data");
return FALSE;
}
- wblock->block = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_STATS);
- if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(wblock->block);
+ wblock->block = wtap_block_create(WTAP_BLOCK_IF_STATS);
+ if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
if (pn->byte_swapped) {
if_stats_mand->interface_id = GUINT32_SWAP_LE_BE(isb.interface_id);
if_stats_mand->ts_high = GUINT32_SWAP_LE_BE(isb.timestamp_high);
bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info, "interface_statistics");
if (bytes_read <= 0) {
pcapng_debug("pcapng_read_interface_statistics_block: failed to read option");
+ g_free(option_content);
return FALSE;
}
to_read -= bytes_read;
case(OPT_COMMENT): /* opt_comment */
if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
tmp_content = g_strndup((char *)option_content, oh.option_length);
- wtap_optionblock_set_option_string(wblock->block, OPT_COMMENT, tmp_content);
- g_free(tmp_content);
+ wtap_block_add_string_option(wblock->block, OPT_COMMENT, option_content, oh.option_length);
pcapng_debug("pcapng_read_interface_statistics_block: opt_comment %s", tmp_content);
+ g_free(tmp_content);
} else {
pcapng_debug("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
}
starttime = (guint64)high;
starttime <<= 32;
starttime += (guint64)low;
- wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_STARTTIME, starttime);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint64_option(wblock->block, OPT_ISB_STARTTIME, starttime);
pcapng_debug("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", starttime);
} else {
pcapng_debug("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
endtime = (guint64)high;
endtime <<= 32;
endtime += (guint64)low;
- wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_ENDTIME, endtime);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint64_option(wblock->block, OPT_ISB_ENDTIME, endtime);
pcapng_debug("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", endtime);
} else {
pcapng_debug("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
memcpy(&ifrecv, option_content, sizeof(guint64));
if (pn->byte_swapped)
ifrecv = GUINT64_SWAP_LE_BE(ifrecv);
- wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_IFRECV, ifrecv);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint64_option(wblock->block, OPT_ISB_IFRECV, ifrecv);
pcapng_debug("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", ifrecv);
} else {
pcapng_debug("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
memcpy(&ifdrop, option_content, sizeof(guint64));
if (pn->byte_swapped)
ifdrop = GUINT64_SWAP_LE_BE(ifdrop);
- wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_IFDROP, ifdrop);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint64_option(wblock->block, OPT_ISB_IFDROP, ifdrop);
pcapng_debug("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", ifdrop);
} else {
pcapng_debug("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
memcpy(&filteraccept, option_content, sizeof(guint64));
if (pn->byte_swapped)
filteraccept = GUINT64_SWAP_LE_BE(filteraccept);
- wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_FILTERACCEPT, filteraccept);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint64_option(wblock->block, OPT_ISB_FILTERACCEPT, filteraccept);
pcapng_debug("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", filteraccept);
} else {
pcapng_debug("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
memcpy(&osdrop, option_content, sizeof(guint64));
if (pn->byte_swapped)
osdrop = GUINT64_SWAP_LE_BE(osdrop);
- wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_OSDROP, osdrop);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint64_option(wblock->block, OPT_ISB_OSDROP, osdrop);
pcapng_debug("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", osdrop);
} else {
pcapng_debug("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
memcpy(&usrdeliv, option_content, sizeof(guint64));
if (pn->byte_swapped)
usrdeliv = GUINT64_SWAP_LE_BE(usrdeliv);
- wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_USRDELIV, usrdeliv);
+ /* Fails with multiple options; we silently ignore the failure */
+ wtap_block_add_uint64_option(wblock->block, OPT_ISB_USRDELIV, usrdeliv);
pcapng_debug("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", usrdeliv);
} else {
pcapng_debug("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
g_free(option_content);
+ /*
+ * We don't return these to the caller in pcapng_read().
+ */
+ wblock->internal = TRUE;
+
return TRUE;
}
static gboolean
-pcapng_read_sysdig_event_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_, wtapng_block_t *wblock, int *err, gchar **err_info)
+pcapng_read_sysdig_event_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
{
unsigned block_read;
guint32 block_total_length;
pcapng_debug("pcapng_read_sysdig_event_block: block_total_length %u",
bh->block_total_length);
- wblock->packet_header->rec_type = REC_TYPE_FT_SPECIFIC_EVENT;
- wblock->packet_header->pseudo_header.sysdig_event.record_type = BLOCK_TYPE_SYSDIG_EVENT;
- wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN /*|WTAP_HAS_INTERFACE_ID */;
- wblock->packet_header->pkt_tsprec = WTAP_TSPREC_NSEC;
+ wblock->rec->rec_type = REC_TYPE_SYSCALL;
+ wblock->rec->rec_header.syscall_header.record_type = BLOCK_TYPE_SYSDIG_EVENT;
+ wblock->rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN /*|WTAP_HAS_INTERFACE_ID */;
+ wblock->rec->tsprec = WTAP_TSPREC_NSEC;
block_read = block_total_length;
}
block_read -= MIN_SYSDIG_EVENT_SIZE;
- wblock->packet_header->pseudo_header.sysdig_event.byte_order = G_BYTE_ORDER;
+ wblock->rec->rec_header.syscall_header.byte_order = G_BYTE_ORDER;
+ /* XXX Use Gxxx_FROM_LE macros instead? */
if (pn->byte_swapped) {
- wblock->packet_header->pseudo_header.sysdig_event.byte_order =
- G_BYTE_ORDER == G_LITTLE_ENDIAN ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
- wblock->packet_header->pseudo_header.sysdig_event.cpu_id = GUINT16_SWAP_LE_BE(cpu_id);
+ wblock->rec->rec_header.syscall_header.byte_order =
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ G_BIG_ENDIAN;
+#else
+ G_LITTLE_ENDIAN;
+#endif
+ wblock->rec->rec_header.syscall_header.cpu_id = GUINT16_SWAP_LE_BE(cpu_id);
ts = GUINT64_SWAP_LE_BE(wire_ts);
- wblock->packet_header->pseudo_header.sysdig_event.thread_id = GUINT64_SWAP_LE_BE(thread_id);
- wblock->packet_header->pseudo_header.sysdig_event.event_len = GUINT32_SWAP_LE_BE(event_len);
- wblock->packet_header->pseudo_header.sysdig_event.event_type = GUINT16_SWAP_LE_BE(event_type);
+ wblock->rec->rec_header.syscall_header.thread_id = GUINT64_SWAP_LE_BE(thread_id);
+ wblock->rec->rec_header.syscall_header.event_len = GUINT32_SWAP_LE_BE(event_len);
+ wblock->rec->rec_header.syscall_header.event_type = GUINT16_SWAP_LE_BE(event_type);
} else {
- wblock->packet_header->pseudo_header.sysdig_event.cpu_id = cpu_id;
+ wblock->rec->rec_header.syscall_header.cpu_id = cpu_id;
ts = wire_ts;
- wblock->packet_header->pseudo_header.sysdig_event.thread_id = thread_id;
- wblock->packet_header->pseudo_header.sysdig_event.event_len = event_len;
- wblock->packet_header->pseudo_header.sysdig_event.event_type = event_type;
+ wblock->rec->rec_header.syscall_header.thread_id = thread_id;
+ wblock->rec->rec_header.syscall_header.event_len = event_len;
+ wblock->rec->rec_header.syscall_header.event_type = event_type;
}
- wblock->packet_header->ts.secs = (time_t) (ts / 1000000000);
- wblock->packet_header->ts.nsecs = (int) (ts % 1000000000);
+ wblock->rec->ts.secs = (time_t) (ts / 1000000000);
+ wblock->rec->ts.nsecs = (int) (ts % 1000000000);
- wblock->packet_header->caplen = block_read;
- wblock->packet_header->len = wblock->packet_header->pseudo_header.sysdig_event.event_len;
+ wblock->rec->rec_header.syscall_header.event_filelen = block_read;
/* "Sysdig Event Block" read event data */
if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
block_read, err, err_info))
return FALSE;
+ /* XXX Read comment? */
+
+ /*
+ * We return these to the caller in pcapng_read().
+ */
+ wblock->internal = FALSE;
+
return TRUE;
}
static gboolean
-pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_, wtapng_block_t *wblock _U_, int *err, gchar **err_info)
+pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh,
+#
+#ifdef HAVE_PLUGINS
+ pcapng_t *pn,
+#else
+ pcapng_t *pn _U_,
+#endif
+ wtapng_block_t *wblock,
+ int *err, gchar **err_info)
{
guint32 block_read;
guint32 block_total_length;
(handler = (block_handler *)g_hash_table_lookup(block_handlers,
GUINT_TO_POINTER(bh->block_type))) != NULL) {
/* Yes - call it to read this block type. */
- if (!handler->reader(fh, block_read, pn->byte_swapped,
- wblock->packet_header, wblock->frame_buffer,
+ if (!handler->reader(fh, block_read, pn->byte_swapped, wblock,
err, err_info))
return FALSE;
} else
#endif
{
/* No. Skip over this unknown block. */
- if (!file_skip(fh, block_read, err)) {
+ if (!wtap_read_bytes(fh, NULL, block_read, err, err_info)) {
return FALSE;
}
+
+ /*
+ * We're skipping this, so we won't return these to the caller
+ * in pcapng_read().
+ */
+ wblock->internal = TRUE;
}
return TRUE;
* Short read or EOF.
*
* If we're reading this as part of an open,
- * the file is too short to be a pcap-ng file.
+ * the file is too short to be a pcapng file.
*
* If we're not, we treat PCAPNG_BLOCK_NOT_SHB and
* PCAPNG_BLOCK_ERROR the same, so we can just return
return PCAPNG_BLOCK_ERROR;
}
- if (pn->byte_swapped) {
- bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
- bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length);
- }
-
- wblock->type = bh.block_type;
-
- pcapng_debug("pcapng_read_block: block_type 0x%x", bh.block_type);
-
/*
- * SHBs have to be treated differently from other blocks, as we
- * might be doing an open and attempting to read a block at the
- * beginning of the file to see if it's a pcap-ng file or not.
+ * SHBs have to be treated differently from other blocks, because
+ * the byte order of the fields in the block can only be determined
+ * by looking at the byte-order magic number inside the block, not
+ * by using the byte order of the section to which it belongs, as
+ * it is the block that *defines* the byte order of the section to
+ * which it belongs.
*/
if (bh.block_type == BLOCK_TYPE_SHB) {
+ /*
+ * BLOCK_TYPE_SHB has the same value regardless of byte order,
+ * so we don't need to byte-swap it.
+ *
+ * We *might* need to byte-swap the total length, but we
+ * can't determine whether we do until we look inside the
+ * block and find the byte-order magic number, so we rely
+ * on pcapng_read_section_header_block() to do that and
+ * to swap the total length (as it needs to get the total
+ * length in the right byte order in order to read the
+ * entire block).
+ */
+ wblock->type = bh.block_type;
+
+ pcapng_debug("pcapng_read_block: block_type 0x%x", bh.block_type);
+
ret = pcapng_read_section_header_block(fh, &bh, pn, wblock, err, err_info);
if (ret != PCAPNG_BLOCK_OK) {
return ret;
}
} else {
+ if (pn->byte_swapped) {
+ bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
+ bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length);
+ }
+
+ wblock->type = bh.block_type;
+
+ pcapng_debug("pcapng_read_block: block_type 0x%x", bh.block_type);
+
if (!pn->shb_read) {
/*
* No SHB seen yet, so we're trying to read the first block
* during an open, to see whether it's an SHB; if what we
- * read doesn't look like an SHB, this isn't a pcap-ng file.
+ * read doesn't look like an SHB, this isn't a pcapng file.
*/
*err = 0;
*err_info = NULL;
return PCAPNG_BLOCK_NOT_SHB;
}
+
+ /* Don't try to allocate memory for a huge number of options, as
+ that might fail and, even if it succeeds, it might not leave
+ any address space or memory+backing store for anything else.
+
+ We do that by imposing a maximum block size of MAX_BLOCK_SIZE. */
+ if (bh.block_total_length > MAX_BLOCK_SIZE) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("pcapng_read_block: total block length %u is too large (> %u)",
+ bh.block_total_length, MAX_BLOCK_SIZE);
+ return PCAPNG_BLOCK_ERROR;
+ }
+
switch (bh.block_type) {
case(BLOCK_TYPE_IDB):
if (!pcapng_read_if_descr_block(wth, fh, &bh, pn, wblock, err, err_info))
return PCAPNG_BLOCK_OK;
}
-/* Process an IDB that we've just read. */
+/* Process an IDB that we've just read. The contents of wblock are copied as needed. */
static void
pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
{
- wtap_optionblock_t int_data = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
+ wtap_block_t int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
interface_info_t iface_info;
- wtapng_if_descr_mandatory_t *if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data),
- *wblock_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(wblock->block);
+ wtapng_if_descr_mandatory_t *if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data),
+ *wblock_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
- wtap_optionblock_copy_options(int_data, wblock->block);
+ wtap_block_copy(int_data, wblock->block);
/* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
/* Interface statistics */
/* we don't expect any packet blocks yet */
wblock.frame_buffer = NULL;
- wblock.packet_header = NULL;
+ wblock.rec = NULL;
pcapng_debug("pcapng_open: opening file");
/* read first block */
break;
case PCAPNG_BLOCK_NOT_SHB:
- /* An error indicating that this isn't a pcap-ng file. */
- wtap_optionblock_free(wblock.block);
+ /* This doesn't look like an SHB, so this isn't a pcapng file. */
+ wtap_block_free(wblock.block);
*err = 0;
+ g_free(*err_info);
*err_info = NULL;
return WTAP_OPEN_NOT_MINE;
case PCAPNG_BLOCK_ERROR:
- /* An I/O error, or this probably *is* a pcap-ng file but not a valid one. */
- wtap_optionblock_free(wblock.block);
+ /* An I/O error, or this probably *is* a pcapng file but not a valid one. */
+ wtap_block_free(wblock.block);
return WTAP_OPEN_ERROR;
}
* binary data?
*/
pcapng_debug("pcapng_open: first block type %u not SHB", wblock.type);
- wtap_optionblock_free(wblock.block);
+ wtap_block_free(wblock.block);
return WTAP_OPEN_NOT_MINE;
}
pn.shb_read = TRUE;
/*
- * At this point, we've decided this is a pcap-NG file, not
+ * At this point, we've decided this is a pcapng file, not
* some other type of file, so we can't return WTAP_OPEN_NOT_MINE
* past this point.
*/
- wtap_optionblock_copy_options(wth->shb_hdr, wblock.block);
+ wtap_block_copy(g_array_index(wth->shb_hdrs, wtap_block_t, 0), wblock.block);
+ wtap_block_free(wblock.block);
+ wblock.block = NULL;
wth->file_encap = WTAP_ENCAP_UNKNOWN;
wth->snapshot_length = 0;
break; /* No more IDB:s */
}
if (pcapng_read_block(wth, wth->fh, &pn, &wblock, err, err_info) != PCAPNG_BLOCK_OK) {
+ wtap_block_free(wblock.block);
if (*err == 0) {
pcapng_debug("No more IDBs available...");
- wtap_optionblock_free(wblock.block);
break;
} else {
pcapng_debug("pcapng_open: couldn't read IDB");
- wtap_optionblock_free(wblock.block);
return WTAP_OPEN_ERROR;
}
}
pcapng_process_idb(wth, pcapng, &wblock);
+ wtap_block_free(wblock.block);
pcapng_debug("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i",
wth->interface_data->len, wth->file_encap);
}
{
pcapng_t *pcapng = (pcapng_t *)wth->priv;
wtapng_block_t wblock;
- wtap_optionblock_t wtapng_if_descr = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
- wtap_optionblock_t if_stats = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_STATS);
+ wtap_block_t wtapng_if_descr;
+ wtap_block_t if_stats;
wtapng_if_stats_mandatory_t *if_stats_mand_block, *if_stats_mand;
wtapng_if_descr_mandatory_t *wtapng_if_descr_mand;
- wblock.frame_buffer = wth->frame_buffer;
- wblock.packet_header = &wth->phdr;
+ wblock.frame_buffer = wth->rec_data;
+ wblock.rec = &wth->rec;
pcapng->add_new_ipv4 = wth->add_new_ipv4;
pcapng->add_new_ipv6 = wth->add_new_ipv6;
if (pcapng_read_block(wth, wth->fh, pcapng, &wblock, err, err_info) != PCAPNG_BLOCK_OK) {
pcapng_debug("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
pcapng_debug("pcapng_read: couldn't read packet block");
+ wtap_block_free(wblock.block);
return FALSE;
}
+ if (!wblock.internal) {
+ /*
+ * This is a block type we return to the caller to process.
+ */
+ break;
+ }
+
+ /*
+ * This is a block type we process internally, rather than
+ * returning it for the caller to process.
+ */
switch (wblock.type) {
case(BLOCK_TYPE_SHB):
- /* We don't currently support multi-section files. */
- wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
- wth->phdr.pkt_tsprec = WTAP_TSPREC_UNKNOWN;
- *err = WTAP_ERR_UNSUPPORTED;
- *err_info = g_strdup_printf("pcapng: multi-section files not currently supported");
- return FALSE;
-
- case(BLOCK_TYPE_PB):
- case(BLOCK_TYPE_SPB):
- case(BLOCK_TYPE_EPB):
- case(BLOCK_TYPE_SYSDIG_EVENT):
- case(BLOCK_TYPE_SYSDIG_EVF):
- /* packet block - we've found a packet */
- goto got_packet;
+ pcapng_debug("pcapng_read: another section header block");
+ g_array_append_val(wth->shb_hdrs, wblock.block);
+ break;
case(BLOCK_TYPE_IDB):
/* A new interface */
pcapng_debug("pcapng_read: block type BLOCK_TYPE_IDB");
pcapng_process_idb(wth, pcapng, &wblock);
+ wtap_block_free(wblock.block);
break;
case(BLOCK_TYPE_NRB):
/* More name resolution entries */
pcapng_debug("pcapng_read: block type BLOCK_TYPE_NRB");
+ if (wth->nrb_hdrs == NULL) {
+ wth->nrb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
+ }
+ g_array_append_val(wth->nrb_hdrs, wblock.block);
break;
case(BLOCK_TYPE_ISB):
- /* Another interface statistics report */
+ /*
+ * Another interface statistics report
+ *
+ * XXX - given that they're reports, we should be
+ * supplying them in read calls, and displaying them
+ * in the "packet" list, so you can see what the
+ * statistics were *at the time when the report was
+ * made*.
+ *
+ * The statistics from the *last* ISB could be displayed
+ * in the summary, but if there are packets after the
+ * last ISB, that could be misleading.
+ *
+ * If we only display them if that ISB has an isb_endtime
+ * option, which *should* only appear when capturing ended
+ * on that interface (so there should be no more packet
+ * blocks or ISBs for that interface after that point,
+ * that would be the best way of showing "summary"
+ * statistics.
+ */
pcapng_debug("pcapng_read: block type BLOCK_TYPE_ISB");
- if_stats_mand_block = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(wblock.block);
+ if_stats_mand_block = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(wblock.block);
if (wth->interface_data->len <= if_stats_mand_block->interface_id) {
pcapng_debug("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u >= number_of_interfaces", if_stats_mand_block->interface_id);
} else {
/* Get the interface description */
- wtapng_if_descr = g_array_index(wth->interface_data, wtap_optionblock_t, if_stats_mand_block->interface_id);
- wtapng_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(wtapng_if_descr);
+ wtapng_if_descr = g_array_index(wth->interface_data, wtap_block_t, if_stats_mand_block->interface_id);
+ wtapng_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wtapng_if_descr);
if (wtapng_if_descr_mand->num_stat_entries == 0) {
/* First ISB found, no previous entry */
pcapng_debug("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
- wtapng_if_descr_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+ wtapng_if_descr_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
}
- if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(if_stats);
+ if_stats = wtap_block_create(WTAP_BLOCK_IF_STATS);
+ if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats);
if_stats_mand->interface_id = if_stats_mand_block->interface_id;
if_stats_mand->ts_high = if_stats_mand_block->ts_high;
if_stats_mand->ts_low = if_stats_mand_block->ts_low;
- wtap_optionblock_copy_options(if_stats, wblock.block);
+ wtap_block_copy(if_stats, wblock.block);
g_array_append_val(wtapng_if_descr_mand->interface_statistics, if_stats);
wtapng_if_descr_mand->num_stat_entries++;
}
+ wtap_block_free(wblock.block);
break;
default:
}
}
-got_packet:
-
- /*pcapng_debug("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
+ /*pcapng_debug("Read length: %u Packet length: %u", bytes_read, wth->rec.rec_header.packet_header.caplen);*/
pcapng_debug("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
return TRUE;
/* classic wtap: seek to file position and read packet */
static gboolean
pcapng_seek_read(wtap *wth, gint64 seek_off,
- struct wtap_pkthdr *phdr, Buffer *buf,
+ wtap_rec *rec, Buffer *buf,
int *err, gchar **err_info)
{
pcapng_t *pcapng = (pcapng_t *)wth->priv;
- block_return_val ret;
wtapng_block_t wblock;
pcapng_debug("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
wblock.frame_buffer = buf;
- wblock.packet_header = phdr;
+ wblock.rec = rec;
/* read the block */
- ret = pcapng_read_block(wth, wth->random_fh, pcapng, &wblock, err, err_info);
- wtap_optionblock_free(wblock.block);
- if (ret != PCAPNG_BLOCK_OK) {
+ if (pcapng_read_block(wth, wth->random_fh, pcapng, &wblock, err, err_info) != PCAPNG_BLOCK_OK) {
pcapng_debug("pcapng_seek_read: couldn't read packet block (err=%d).",
*err);
+ wtap_block_free(wblock.block);
return FALSE;
}
- /* block must be a "Packet Block", an "Enhanced Packet Block",
- a "Simple Packet Block", or an event */
- if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
- wblock.type != BLOCK_TYPE_SPB &&
- wblock.type != BLOCK_TYPE_SYSDIG_EVENT && wblock.type != BLOCK_TYPE_SYSDIG_EVF) {
- pcapng_debug("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
+ /* block must not be one we process internally rather than supplying */
+ if (wblock.internal) {
+ pcapng_debug("pcapng_seek_read: block type %u is not one we return",
+ wblock.type);
+ wtap_block_free(wblock.block);
return FALSE;
}
+ wtap_block_free(wblock.block);
return TRUE;
}
g_array_free(pcapng->interfaces, TRUE);
}
+typedef struct pcapng_block_size_t
+{
+ guint32 size;
+} pcapng_block_size_t;
-static gboolean
-pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
+static guint32 pcapng_compute_option_string_size(char *str)
{
- pcapng_block_header_t bh;
- pcapng_section_header_block_t shb;
- const guint32 zero_pad = 0;
- gboolean have_options = FALSE;
- struct option option_hdr; /* guint16 type, guint16 value_length; */
- guint32 options_total_length = 0;
- guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
- guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
- char *opt_comment, *shb_hardware, *shb_os, *shb_user_appl;
+ guint32 size = 0, pad;
- if (wdh->shb_hdr) {
- pcapng_debug("pcapng_write_section_header_block: Have shb_hdr");
- /* Check if we should write comment option */
- wtap_optionblock_get_option_string(wdh->shb_hdr, OPT_COMMENT, &opt_comment);
- if (opt_comment) {
- have_options = TRUE;
- comment_len = (guint32)strlen(opt_comment) & 0xffff;
- if ((comment_len % 4)) {
- comment_pad_len = 4 - (comment_len % 4);
- } else {
- comment_pad_len = 0;
- }
- options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
- }
+ size = (guint32)strlen(str) & 0xffff;
+ if ((size % 4)) {
+ pad = 4 - (size % 4);
+ } else {
+ pad = 0;
+ }
- /* Check if we should write shb_hardware option */
- wtap_optionblock_get_option_string(wdh->shb_hdr, OPT_SHB_HARDWARE, &shb_hardware);
- if (shb_hardware) {
- have_options = TRUE;
- shb_hardware_len = (guint32)strlen(shb_hardware) & 0xffff;
- if ((shb_hardware_len % 4)) {
- shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
- } else {
- shb_hardware_pad_len = 0;
- }
- options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
- }
+ size += pad;
- /* Check if we should write shb_os option */
- wtap_optionblock_get_option_string(wdh->shb_hdr, OPT_SHB_OS, &shb_os);
- if (shb_os) {
- have_options = TRUE;
- shb_os_len = (guint32)strlen(shb_os) & 0xffff;
- if ((shb_os_len % 4)) {
- shb_os_pad_len = 4 - (shb_os_len % 4);
- } else {
- shb_os_pad_len = 0;
- }
- options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
- }
+ return size;
+}
- /* Check if we should write shb_user_appl option */
- wtap_optionblock_get_option_string(wdh->shb_hdr, OPT_SHB_USERAPPL, &shb_user_appl);
- if (shb_user_appl) {
- have_options = TRUE;
- shb_user_appl_len = (guint32)strlen(shb_user_appl) & 0xffff;
- if ((shb_user_appl_len % 4)) {
- shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
- } else {
- shb_user_appl_pad_len = 0;
- }
- options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
- }
+static void compute_shb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t* optval, void* user_data)
+{
+ pcapng_block_size_t* block_size = (pcapng_block_size_t*)user_data;
+ guint32 size = 0;
- if (have_options) {
- /* End-of-options tag */
- options_total_length += 4;
+ switch(option_id)
+ {
+ case OPT_COMMENT:
+ case OPT_SHB_HARDWARE:
+ case OPT_SHB_OS:
+ case OPT_SHB_USERAPPL:
+ size = pcapng_compute_option_string_size(optval->stringval);
+ break;
+ default:
+ /* Unknown options - size by datatype? */
+ break;
+ }
+
+ block_size->size += size;
+ /* Add bytes for option header if option should be written */
+ if (size > 0) {
+ /* Add optional padding to 32 bits */
+ if ((block_size->size & 0x03) != 0)
+ {
+ block_size->size += 4 - (block_size->size & 0x03);
}
+ block_size->size += 4;
}
+}
- /* write block header */
- bh.block_type = BLOCK_TYPE_SHB;
- bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
- pcapng_debug("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
+typedef struct pcapng_write_block_t
+{
+ wtap_dumper *wdh;
+ int *err;
+ gboolean success;
+}
+pcapng_write_block_t;
- if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
- return FALSE;
- wdh->bytes_dumped += sizeof bh;
-
- /* write block fixed content */
- /* XXX - get these values from wblock? */
- shb.magic = 0x1A2B3C4D;
- shb.version_major = 1;
- shb.version_minor = 0;
- shb.section_length = -1;
-
- if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
- return FALSE;
- wdh->bytes_dumped += sizeof shb;
-
- /* XXX - write (optional) block options
- * opt_comment 1
- * shb_hardware 2
- * shb_os 3
- * shb_user_appl 4
- */
-
- if (comment_len) {
- option_hdr.type = OPT_COMMENT;
- option_hdr.value_length = comment_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the comments string */
- pcapng_debug("pcapng_write_section_header_block, comment:'%s' comment_len %u comment_pad_len %u" , opt_comment, comment_len, comment_pad_len);
- if (!wtap_dump_file_write(wdh, opt_comment, comment_len, err))
- return FALSE;
- wdh->bytes_dumped += comment_len;
-
- /* write padding (if any) */
- if (comment_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += comment_pad_len;
- }
- }
-
- if (shb_hardware_len) {
- option_hdr.type = OPT_SHB_HARDWARE;
- option_hdr.value_length = shb_hardware_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the string */
- pcapng_debug("pcapng_write_section_header_block, shb_hardware:'%s' shb_hardware_len %u shb_hardware_pad_len %u" , shb_hardware, shb_hardware_len, shb_hardware_pad_len);
- if (!wtap_dump_file_write(wdh, shb_hardware, shb_hardware_len, err))
- return FALSE;
- wdh->bytes_dumped += shb_hardware_len;
-
- /* write padding (if any) */
- if (shb_hardware_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += shb_hardware_pad_len;
- }
- }
-
- if (shb_os_len) {
- option_hdr.type = OPT_SHB_OS;
- option_hdr.value_length = shb_os_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the string */
- pcapng_debug("pcapng_write_section_header_block, shb_os:'%s' shb_os_len %u shb_os_pad_len %u" , shb_os, shb_os_len, shb_os_pad_len);
- if (!wtap_dump_file_write(wdh, shb_os, shb_os_len, err))
- return FALSE;
- wdh->bytes_dumped += shb_os_len;
-
- /* write padding (if any) */
- if (shb_os_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += shb_os_pad_len;
- }
- }
-
- if (shb_user_appl_len) {
- option_hdr.type = OPT_SHB_USERAPPL;
- option_hdr.value_length = shb_user_appl_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the comments string */
- pcapng_debug("pcapng_write_section_header_block, shb_user_appl:'%s' shb_user_appl_len %u shb_user_appl_pad_len %u" , shb_user_appl, shb_user_appl_len, shb_user_appl_pad_len);
- if (!wtap_dump_file_write(wdh, shb_user_appl, shb_user_appl_len, err))
- return FALSE;
- wdh->bytes_dumped += shb_user_appl_len;
-
- /* write padding (if any) */
- if (shb_user_appl_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += shb_user_appl_pad_len;
- }
- }
-
- /* Write end of options if we have otions */
- if (have_options) {
- option_hdr.type = OPT_EOFOPT;
- option_hdr.value_length = 0;
- if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
- }
-
- /* write block footer */
- if (!wtap_dump_file_write(wdh, &bh.block_total_length,
- sizeof bh.block_total_length, err))
- return FALSE;
- wdh->bytes_dumped += sizeof bh.block_total_length;
-
- return TRUE;
-}
-
-
-static gboolean
-pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_optionblock_t int_data, int *err)
-{
- pcapng_block_header_t bh;
- pcapng_interface_description_block_t idb;
- const guint32 zero_pad = 0;
- gboolean have_options = FALSE;
- struct option option_hdr; /* guint16 type, guint16 value_length; */
- guint32 options_total_length = 0;
- guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
- guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0, if_filter_str_pad_len = 0;
- wtapng_if_descr_mandatory_t* int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
- char *opt_comment, *if_name, *if_description, *if_os;
- guint64 if_speed;
- guint8 if_tsresol, if_fcslen;
- wtapng_if_descr_filter_t* if_filter;
-
- pcapng_debug("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
- int_data_mand->link_type,
- wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data_mand->link_type)),
- int_data_mand->snap_len);
-
- if (int_data_mand->link_type == (guint16)-1) {
- *err = WTAP_ERR_UNWRITABLE_ENCAP;
- return FALSE;
- }
-
- /* Calculate options length */
- wtap_optionblock_get_option_string(int_data, OPT_COMMENT, &opt_comment);
- if (opt_comment) {
- have_options = TRUE;
- comment_len = (guint32)strlen(opt_comment) & 0xffff;
- if ((comment_len % 4)) {
- comment_pad_len = 4 - (comment_len % 4);
- } else {
- comment_pad_len = 0;
- }
- options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
- }
-
- /*
- * if_name 2 A UTF-8 string containing the name of the device used to capture data.
- */
- wtap_optionblock_get_option_string(int_data, OPT_IDB_NAME, &if_name);
- if (if_name) {
- have_options = TRUE;
- if_name_len = (guint32)strlen(if_name) & 0xffff;
- if ((if_name_len % 4)) {
- if_name_pad_len = 4 - (if_name_len % 4);
- } else {
- if_name_pad_len = 0;
- }
- options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
- }
-
- /*
- * if_description 3 A UTF-8 string containing the description of the device used to capture data.
- */
- wtap_optionblock_get_option_string(int_data, OPT_IDB_DESCR, &if_description);
- if (if_description) {
- have_options = TRUE;
- if_description_len = (guint32)strlen(if_description) & 0xffff;
- if ((if_description_len % 4)) {
- if_description_pad_len = 4 - (if_description_len % 4);
- } else {
- if_description_pad_len = 0;
- }
- options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
- }
- /* Currently not handled
- * if_IPv4addr 4 Interface network address and netmask.
- * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
- * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
- * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
- */
- /*
- * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
- */
- wtap_optionblock_get_option_uint64(int_data, OPT_IDB_SPEED, &if_speed);
- if (if_speed != 0) {
- have_options = TRUE;
- options_total_length = options_total_length + 8 + 4;
- }
- /*
- * if_tsresol 9 Resolution of timestamps.
- */
- wtap_optionblock_get_option_uint8(int_data, OPT_IDB_TSRESOL, &if_tsresol);
- if (if_tsresol != 0) {
- have_options = TRUE;
- options_total_length = options_total_length + 4 + 4;
- }
- /* Not used
- * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
- */
- /*
- * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
- * The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more).
- */
- wtap_optionblock_get_option_custom(int_data, OPT_IDB_FILTER, (void**)&if_filter);
- if (if_filter->if_filter_str) {
- have_options = TRUE;
- if_filter_str_len = (guint32)(strlen(if_filter->if_filter_str) + 1) & 0xffff;
- if ((if_filter_str_len % 4)) {
- if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
- } else {
- if_filter_str_pad_len = 0;
- }
- options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
- }
- /*
- * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
- */
- wtap_optionblock_get_option_string(int_data, OPT_IDB_OS, &if_os);
- if (if_os) {
- have_options = TRUE;
- if_os_len = (guint32)strlen(if_os) & 0xffff;
- if ((if_os_len % 4)) {
- if_os_pad_len = 4 - (if_os_len % 4);
- } else {
- if_os_pad_len = 0;
- }
- options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
- }
- /*
- * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
- * -1 if unknown or changes between packets, opt 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
- */
- wtap_optionblock_get_option_uint8(int_data, OPT_IDB_FCSLEN, &if_fcslen);
- if (if_fcslen != 0) {
- }
- /* Not used
- * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
- * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
- */
-
- if (have_options) {
- /* End-of-options tag */
- options_total_length += 4;
- }
-
- /* write block header */
- bh.block_type = BLOCK_TYPE_IDB;
- bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
-
- if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
- return FALSE;
- wdh->bytes_dumped += sizeof bh;
-
- /* write block fixed content */
- idb.linktype = int_data_mand->link_type;
- idb.reserved = 0;
- idb.snaplen = int_data_mand->snap_len;
-
- if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
- return FALSE;
- wdh->bytes_dumped += sizeof idb;
-
- /* XXX - write (optional) block options */
- if (comment_len != 0) {
- option_hdr.type = OPT_COMMENT;
- option_hdr.value_length = comment_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the comments string */
- pcapng_debug("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , opt_comment, comment_len, comment_pad_len);
- if (!wtap_dump_file_write(wdh, opt_comment, comment_len, err))
- return FALSE;
- wdh->bytes_dumped += comment_len;
-
- /* write padding (if any) */
- if (comment_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += comment_pad_len;
- }
- }
- /*
- * if_name 2 A UTF-8 string containing the name of the device used to capture data.
- */
- if (if_name_len !=0) {
- option_hdr.type = OPT_IDB_NAME;
- option_hdr.value_length = if_name_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the comments string */
- pcapng_debug("pcapng_write_if_descr_block, if_name:'%s' if_name_len %u if_name_pad_len %u" , if_name, if_name_len, if_name_pad_len);
- if (!wtap_dump_file_write(wdh, if_name, if_name_len, err))
- return FALSE;
- wdh->bytes_dumped += if_name_len;
-
- /* write padding (if any) */
- if (if_name_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += if_name_pad_len;
- }
- }
- /*
- * if_description 3 A UTF-8 string containing the description of the device used to capture data.
- */
- if (if_description_len != 0) {
- option_hdr.type = OPT_IDB_NAME;
- option_hdr.value_length = if_description_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the comments string */
- pcapng_debug("pcapng_write_if_descr_block, if_description:'%s' if_description_len %u if_description_pad_len %u" , if_description, if_description_len, if_description_pad_len);
- if (!wtap_dump_file_write(wdh, if_description, if_description_len, err))
- return FALSE;
- wdh->bytes_dumped += if_description_len;
-
- /* write padding (if any) */
- if (if_description_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += if_description_pad_len;
- }
- }
- /* Currently not handled
- * if_IPv4addr 4 Interface network address and netmask.
- * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
- * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
- * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
- */
- /*
- * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
- */
- if (if_speed != 0) {
- option_hdr.type = OPT_IDB_SPEED;
- option_hdr.value_length = 8;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the comments string */
- pcapng_debug("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", if_speed);
- if (!wtap_dump_file_write(wdh, &if_speed, sizeof(guint64), err))
- return FALSE;
- wdh->bytes_dumped += 8;
- }
- /*
- * if_tsresol 9 Resolution of timestamps.
- * default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
- * If the Most Significant Bit is equal to zero, the remaining bits indicates
- * the resolution of the timestamp as as a negative power of 10
- */
- if (if_tsresol != 0) {
- option_hdr.type = OPT_IDB_TSRESOL;
- option_hdr.value_length = 1;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the time stamp resolution */
- pcapng_debug("pcapng_write_if_descr_block: if_tsresol %u", if_tsresol);
- if (!wtap_dump_file_write(wdh, &if_tsresol, 1, err))
- return FALSE;
- wdh->bytes_dumped += 1;
- if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
- return FALSE;
- wdh->bytes_dumped += 3;
- }
- /* not used
- * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
- */
- /*
- * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
- */
- /* Libpcap string variant */
- if (if_filter_str_len !=0) {
- option_hdr.type = OPT_IDB_FILTER;
- option_hdr.value_length = if_filter_str_len;
- /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the zero indicating libpcap filter variant */
- if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
- return FALSE;
- wdh->bytes_dumped += 1;
-
- /* Write the comments string */
- pcapng_debug("pcapng_write_if_descr_block, if_filter_str:'%s' if_filter_str_len %u if_filter_str_pad_len %u" , if_filter->if_filter_str, if_filter_str_len, if_filter_str_pad_len);
- /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
- if (!wtap_dump_file_write(wdh, if_filter->if_filter_str, if_filter_str_len-1, err))
- return FALSE;
- wdh->bytes_dumped += if_filter_str_len - 1;
-
- /* write padding (if any) */
- if (if_filter_str_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += if_filter_str_pad_len;
- }
- }
- /*
- * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
- */
- if (if_os_len != 0) {
- option_hdr.type = OPT_IDB_OS;
- option_hdr.value_length = if_os_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
-
- /* Write the comments string */
- pcapng_debug("pcapng_write_if_descr_block, if_os:'%s' if_os_len %u if_os_pad_len %u" , if_os, if_os_len, if_os_pad_len);
- if (!wtap_dump_file_write(wdh, if_os, if_os_len, err))
- return FALSE;
- wdh->bytes_dumped += if_os_len;
-
- /* write padding (if any) */
- if (if_os_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += if_os_pad_len;
- }
- }
-
- if (have_options) {
- option_hdr.type = OPT_EOFOPT;
- option_hdr.value_length = 0;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
- }
-
- /*
- * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
- */
- /*
- * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
- * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
- */
-
- /* write block footer */
- if (!wtap_dump_file_write(wdh, &bh.block_total_length,
- sizeof bh.block_total_length, err))
- return FALSE;
- wdh->bytes_dumped += sizeof bh.block_total_length;
-
- return TRUE;
-}
-
-static gboolean
-pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtap_optionblock_t if_stats, int *err)
-{
-
- pcapng_block_header_t bh;
- pcapng_interface_statistics_block_t isb;
- const guint32 zero_pad = 0;
- gboolean have_options = FALSE;
- struct option option_hdr; /* guint16 type, guint16 value_length; */
- guint32 options_total_length = 0;
- guint32 comment_len = 0;
- guint32 comment_pad_len = 0;
- char *opt_comment;
- guint64 isb_starttime, isb_endtime, isb_ifrecv, isb_ifdrop, isb_filteraccept, isb_osdrop, isb_usrdeliv;
- wtapng_if_stats_mandatory_t* if_stats_mand;
-
- pcapng_debug("pcapng_write_interface_statistics_block");
-
- wtap_optionblock_get_option_string(if_stats, OPT_COMMENT, &opt_comment);
- /* Calculate options length */
- if (opt_comment) {
- have_options = TRUE;
- comment_len = (guint32)strlen(opt_comment) & 0xffff;
- if ((comment_len % 4)) {
- comment_pad_len = 4 - (comment_len % 4);
- } else {
- comment_pad_len = 0;
- }
- options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
- }
-
- wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_STARTTIME, &isb_starttime);
- if (isb_starttime != 0) {
- have_options = TRUE;
- options_total_length = options_total_length + 8 + 4 /* options tag */ ;
- }
- wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_ENDTIME, &isb_endtime);
- if (isb_endtime != 0) {
- have_options = TRUE;
- options_total_length = options_total_length + 8 + 4 /* options tag */ ;
- }
- wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_IFRECV, &isb_ifrecv);
- if (isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- have_options = TRUE;
- options_total_length = options_total_length + 8 + 4 /* options tag */ ;
- }
- wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_IFDROP, &isb_ifdrop);
- if (isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- have_options = TRUE;
- options_total_length = options_total_length + 8 + 4 /* options tag */ ;
- }
- wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_FILTERACCEPT, &isb_filteraccept);
- if (isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- have_options = TRUE;
- options_total_length = options_total_length + 8 + 4 /* options tag */ ;
- }
- wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_OSDROP, &isb_osdrop);
- if (isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- have_options = TRUE;
- options_total_length = options_total_length + 8 + 4 /* options tag */ ;
- }
- wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_USRDELIV, &isb_usrdeliv);
- if (isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- have_options = TRUE;
- options_total_length = options_total_length + 8 + 4 /* options tag */ ;
- }
+static gboolean pcapng_write_option_string(wtap_dumper *wdh, guint option_id, char *str, int *err)
+{
+ struct pcapng_option_header option_hdr;
+ guint32 size = (guint32)strlen(str) & 0xffff;
+ const guint32 zero_pad = 0;
+ guint32 pad;
- /* write block header */
- if (have_options) {
- /* End-of-optios tag */
- options_total_length += 4;
- }
+ if (size == 0)
+ return TRUE;
- /* write block header */
- bh.block_type = BLOCK_TYPE_ISB;
- bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
+ /* String options don't consider pad bytes part of the length */
+ option_hdr.type = (guint16)option_id;
+ option_hdr.value_length = (guint16)size;
+ if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
- if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
+ if (!wtap_dump_file_write(wdh, str, size, err))
return FALSE;
- wdh->bytes_dumped += sizeof bh;
+ wdh->bytes_dumped += size;
- /* write block fixed content */
- if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(if_stats);
+ if ((size % 4)) {
+ pad = 4 - (size % 4);
+ } else {
+ pad = 0;
+ }
- isb.interface_id = if_stats_mand->interface_id;
- isb.timestamp_high = if_stats_mand->ts_high;
- isb.timestamp_low = if_stats_mand->ts_low;
+ /* write padding (if any) */
+ if (pad != 0) {
+ if (!wtap_dump_file_write(wdh, &zero_pad, pad, err))
+ return FALSE;
- if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
- return FALSE;
- wdh->bytes_dumped += sizeof isb;
+ wdh->bytes_dumped += pad;
+ }
- /* write (optional) block options */
- if (comment_len) {
- option_hdr.type = OPT_COMMENT;
- option_hdr.value_length = comment_len;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ return TRUE;
+}
- /* Write the comments string */
- pcapng_debug("pcapng_write_interface_statistics_block, comment:'%s' comment_len %u comment_pad_len %u" , opt_comment, comment_len, comment_pad_len);
- if (!wtap_dump_file_write(wdh, opt_comment, comment_len, err))
- return FALSE;
- wdh->bytes_dumped += comment_len;
+static void write_wtap_shb_option(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
+{
+ pcapng_write_block_t* write_block = (pcapng_write_block_t*)user_data;
- /* write padding (if any) */
- if (comment_pad_len != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
- return FALSE;
- wdh->bytes_dumped += comment_pad_len;
+ /* Don't continue if there has been an error */
+ if (!write_block->success)
+ return;
+
+ switch(option_id)
+ {
+ case OPT_COMMENT:
+ case OPT_SHB_HARDWARE:
+ case OPT_SHB_OS:
+ case OPT_SHB_USERAPPL:
+ if (!pcapng_write_option_string(write_block->wdh, option_id, optval->stringval, write_block->err)) {
+ write_block->success = FALSE;
+ return;
}
+ break;
+ default:
+ /* Unknown options - write by datatype? */
+ break;
}
- /*guint64 isb_starttime */
- if (isb_starttime != 0) {
- guint32 high, low;
+}
- option_hdr.type = OPT_ISB_STARTTIME;
- option_hdr.value_length = 8;
- high = (guint32)((isb_starttime>>32) & 0xffffffff);
- low = (guint32)(isb_starttime & 0xffffffff);
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+/* Write a section header block.
+ * If we don't have a section block header already, create a default
+ * one with no options.
+ */
+static gboolean
+pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
+{
+ pcapng_block_header_t bh;
+ pcapng_section_header_block_t shb;
+ pcapng_block_size_t block_size;
+ struct pcapng_option_header option_hdr;
+ wtap_block_t wdh_shb = NULL;
- /* Write isb_starttime */
- pcapng_debug("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , isb_starttime);
- if (!wtap_dump_file_write(wdh, &high, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
- if (!wtap_dump_file_write(wdh, &low, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ if (wdh->shb_hdrs && (wdh->shb_hdrs->len > 0)) {
+ wdh_shb = g_array_index(wdh->shb_hdrs, wtap_block_t, 0);
}
- /*guint64 isb_endtime */
- if (isb_endtime != 0) {
- guint32 high, low;
- option_hdr.type = OPT_ISB_ENDTIME;
- option_hdr.value_length = 8;
- high = (guint32)((isb_endtime>>32) & 0xffffffff);
- low = (guint32)(isb_endtime & 0xffffffff);
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ block_size.size = 0;
+ bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + 4);
+ if (wdh_shb) {
+ pcapng_debug("pcapng_write_section_header_block: Have shb_hdr");
- /* Write isb_endtime */
- pcapng_debug("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , isb_endtime);
- if (!wtap_dump_file_write(wdh, &high, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
- if (!wtap_dump_file_write(wdh, &low, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
- }
- /*guint64 isb_ifrecv;*/
- if (isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- option_hdr.type = OPT_ISB_IFRECV;
- option_hdr.value_length = 8;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ /* Compute block size */
+ wtap_block_foreach_option(wdh_shb, compute_shb_option_size, &block_size);
- /* Write isb_ifrecv */
- pcapng_debug("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , isb_ifrecv);
- if (!wtap_dump_file_write(wdh, &isb_ifrecv, 8, err))
- return FALSE;
- wdh->bytes_dumped += 8;
- }
- /*guint64 isb_ifdrop;*/
- if (isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- option_hdr.type = OPT_ISB_IFDROP;
- option_hdr.value_length = 8;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ if (block_size.size > 0) {
+ /* End-of-options tag */
+ block_size.size += 4;
+ }
- /* Write isb_ifdrop */
- pcapng_debug("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , isb_ifdrop);
- if (!wtap_dump_file_write(wdh, &isb_ifdrop, 8, err))
- return FALSE;
- wdh->bytes_dumped += 8;
+ bh.block_total_length += block_size.size;
}
- /*guint64 isb_filteraccept;*/
- if (isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- option_hdr.type = OPT_ISB_FILTERACCEPT;
- option_hdr.value_length = 8;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
- /* Write isb_filteraccept */
- pcapng_debug("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , isb_filteraccept);
- if (!wtap_dump_file_write(wdh, &isb_filteraccept, 8, err))
- return FALSE;
- wdh->bytes_dumped += 8;
- }
- /*guint64 isb_osdrop;*/
- if (isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- option_hdr.type = OPT_ISB_OSDROP;
- option_hdr.value_length = 8;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ pcapng_debug("pcapng_write_section_header_block: Total len %u", bh.block_total_length);
- /* Write isb_osdrop */
- pcapng_debug("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , isb_osdrop);
- if (!wtap_dump_file_write(wdh, &isb_osdrop, 8, err))
- return FALSE;
- wdh->bytes_dumped += 8;
- }
- /*guint64 isb_usrdeliv;*/
- if (isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
- option_hdr.type = OPT_ISB_USRDELIV;
- option_hdr.value_length = 8;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ /* write block header */
+ bh.block_type = BLOCK_TYPE_SHB;
- /* Write isb_usrdeliv */
- pcapng_debug("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , isb_usrdeliv);
- if (!wtap_dump_file_write(wdh, &isb_usrdeliv, 8, err))
- return FALSE;
- wdh->bytes_dumped += 8;
+ if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof bh;
+
+ /* write block fixed content */
+ shb.magic = 0x1A2B3C4D;
+ shb.version_major = 1;
+ shb.version_minor = 0;
+ if (wdh_shb) {
+ wtapng_mandatory_section_t* section_data = (wtapng_mandatory_section_t*)wtap_block_get_mandatory_data(wdh_shb);
+ shb.section_length = section_data->section_length;
+ } else {
+ shb.section_length = -1;
}
- if (have_options) {
- option_hdr.type = OPT_EOFOPT;
- option_hdr.value_length = 0;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof shb;
+
+ if (wdh_shb) {
+ pcapng_write_block_t block_data;
+
+ if (block_size.size > 0) {
+ /* Write options */
+ block_data.wdh = wdh;
+ block_data.err = err;
+ block_data.success = TRUE;
+ wtap_block_foreach_option(wdh_shb, write_wtap_shb_option, &block_data);
+
+ if (!block_data.success)
+ return FALSE;
+
+ /* Write end of options */
+ option_hdr.type = OPT_EOFOPT;
+ option_hdr.value_length = 0;
+ if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
+ }
}
/* write block footer */
wdh->bytes_dumped += sizeof bh.block_total_length;
return TRUE;
-
}
-
static gboolean
-pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
- const struct wtap_pkthdr *phdr,
- const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
+pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
+ const guint8 *pd, int *err)
{
+ const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header;
pcapng_block_header_t bh;
pcapng_enhanced_packet_block_t epb;
guint64 ts;
guint32 options_total_length = 0;
struct option option_hdr;
guint32 comment_len = 0, comment_pad_len = 0;
- wtap_optionblock_t int_data;
+ wtap_block_t int_data;
wtapng_if_descr_mandatory_t *int_data_mand;
/* Don't write anything we're not willing to read. */
- if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
+ if (rec->rec_header.packet_header.caplen > wtap_max_snaplen_for_encap(wdh->encap)) {
*err = WTAP_ERR_PACKET_TOO_LARGE;
return FALSE;
}
- phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
- if ((phdr_len + phdr->caplen) % 4) {
- pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
+ phdr_len = (guint32)pcap_get_phdr_size(rec->rec_header.packet_header.pkt_encap, pseudo_header);
+ if ((phdr_len + rec->rec_header.packet_header.caplen) % 4) {
+ pad_len = 4 - ((phdr_len + rec->rec_header.packet_header.caplen) % 4);
} else {
pad_len = 0;
}
/* Check if we should write comment option */
- if (phdr->opt_comment) {
+ if (rec->opt_comment) {
have_options = TRUE;
- comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
+ comment_len = (guint32)strlen(rec->opt_comment) & 0xffff;
if ((comment_len % 4)) {
comment_pad_len = 4 - (comment_len % 4);
} else {
}
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
- if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
+ if (rec->presence_flags & WTAP_HAS_PACK_FLAGS) {
have_options = TRUE;
options_total_length = options_total_length + 8;
}
/* write (enhanced) packet block header */
bh.block_type = BLOCK_TYPE_EPB;
- bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
+ bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + rec->rec_header.packet_header.caplen + pad_len + options_total_length + 4;
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
return FALSE;
wdh->bytes_dumped += sizeof bh;
/* write block fixed content */
- if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
- epb.interface_id = phdr->interface_id;
+ if (rec->presence_flags & WTAP_HAS_INTERFACE_ID)
+ epb.interface_id = rec->rec_header.packet_header.interface_id;
else {
/*
* XXX - we should support writing WTAP_ENCAP_PER_PACKET
- * data to pcap-NG files even if we *don't* have interface
+ * data to pcapng files even if we *don't* have interface
* IDs.
*/
epb.interface_id = 0;
*err = WTAP_ERR_INTERNAL;
return FALSE;
}
- int_data = g_array_index(wdh->interface_data, wtap_optionblock_t,
+ int_data = g_array_index(wdh->interface_data, wtap_block_t,
epb.interface_id);
- int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
- ts = ((guint64)phdr->ts.secs) * int_data_mand->time_units_per_second +
- (((guint64)phdr->ts.nsecs) * int_data_mand->time_units_per_second) / 1000000000;
+ int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
+ ts = ((guint64)rec->ts.secs) * int_data_mand->time_units_per_second +
+ (((guint64)rec->ts.nsecs) * int_data_mand->time_units_per_second) / 1000000000;
epb.timestamp_high = (guint32)(ts >> 32);
epb.timestamp_low = (guint32)ts;
- epb.captured_len = phdr->caplen + phdr_len;
- epb.packet_len = phdr->len + phdr_len;
+ epb.captured_len = rec->rec_header.packet_header.caplen + phdr_len;
+ epb.packet_len = rec->rec_header.packet_header.len + phdr_len;
if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
return FALSE;
wdh->bytes_dumped += sizeof epb;
/* write pseudo header */
- if (!pcap_write_phdr(wdh, phdr->pkt_encap, pseudo_header, err)) {
+ if (!pcap_write_phdr(wdh, rec->rec_header.packet_header.pkt_encap, pseudo_header, err)) {
return FALSE;
}
wdh->bytes_dumped += phdr_len;
/* write packet data */
- if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
+ if (!wtap_dump_file_write(wdh, pd, rec->rec_header.packet_header.caplen, err))
return FALSE;
- wdh->bytes_dumped += phdr->caplen;
+ wdh->bytes_dumped += rec->rec_header.packet_header.caplen;
/* write padding (if any) */
if (pad_len != 0) {
* between this packet and the preceding one.
* opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
*/
- if (phdr->opt_comment) {
+ if (rec->opt_comment) {
option_hdr.type = OPT_COMMENT;
option_hdr.value_length = comment_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
wdh->bytes_dumped += 4;
/* Write the comments string */
- pcapng_debug("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr->opt_comment, comment_len, comment_pad_len);
- if (!wtap_dump_file_write(wdh, phdr->opt_comment, comment_len, err))
+ pcapng_debug("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , rec->opt_comment, comment_len, comment_pad_len);
+ if (!wtap_dump_file_write(wdh, rec->opt_comment, comment_len, err))
return FALSE;
wdh->bytes_dumped += comment_len;
comment_len,
comment_pad_len);
}
- if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
+ if (rec->presence_flags & WTAP_HAS_PACK_FLAGS) {
option_hdr.type = OPT_EPB_FLAGS;
option_hdr.value_length = 4;
- if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
- if (!wtap_dump_file_write(wdh, &phdr->pack_flags, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
- pcapng_debug("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr->pack_flags);
- }
- /* Write end of options if we have options */
- if (have_options) {
- if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
- return FALSE;
- wdh->bytes_dumped += 4;
+ if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
+ if (!wtap_dump_file_write(wdh, &rec->rec_header.packet_header.pack_flags, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
+ pcapng_debug("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", rec->rec_header.packet_header.pack_flags);
+ }
+ /* Write end of options if we have options */
+ if (have_options) {
+ if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
+ }
+
+ /* write block footer */
+ if (!wtap_dump_file_write(wdh, &bh.block_total_length,
+ sizeof bh.block_total_length, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof bh.block_total_length;
+
+ return TRUE;
+}
+
+static gboolean
+pcapng_write_sysdig_event_block(wtap_dumper *wdh, const wtap_rec *rec,
+ const guint8 *pd, int *err)
+{
+ pcapng_block_header_t bh;
+ const guint32 zero_pad = 0;
+ guint32 pad_len;
+#if 0
+ gboolean have_options = FALSE;
+ struct option option_hdr;
+ guint32 comment_len = 0, comment_pad_len = 0;
+#endif
+ guint32 options_total_length = 0;
+ guint16 cpu_id;
+ guint64 hdr_ts;
+ guint64 ts;
+ guint64 thread_id;
+ guint32 event_len;
+ guint16 event_type;
+
+ /* Don't write anything we're not willing to read. */
+ if (rec->rec_header.syscall_header.event_filelen > WTAP_MAX_PACKET_SIZE_STANDARD) {
+ *err = WTAP_ERR_PACKET_TOO_LARGE;
+ return FALSE;
+ }
+
+ if (rec->rec_header.syscall_header.event_filelen % 4) {
+ pad_len = 4 - (rec->rec_header.syscall_header.event_filelen % 4);
+ } else {
+ pad_len = 0;
+ }
+
+#if 0
+ /* Check if we should write comment option */
+ if (rec->opt_comment) {
+ have_options = TRUE;
+ comment_len = (guint32)strlen(rec->opt_comment) & 0xffff;
+ if ((comment_len % 4)) {
+ comment_pad_len = 4 - (comment_len % 4);
+ } else {
+ comment_pad_len = 0;
+ }
+ options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
+ }
+ if (have_options) {
+ /* End-of options tag */
+ options_total_length += 4;
+ }
+#endif
+
+ /* write sysdig event block header */
+ bh.block_type = BLOCK_TYPE_SYSDIG_EVENT;
+ bh.block_total_length = (guint32)sizeof(bh) + SYSDIG_EVENT_HEADER_SIZE + rec->rec_header.syscall_header.event_filelen + pad_len + options_total_length + 4;
+
+ if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof bh;
+
+ /* Sysdig is always LE? */
+ cpu_id = GUINT16_TO_LE(rec->rec_header.syscall_header.cpu_id);
+ hdr_ts = (((guint64)rec->ts.secs) * 1000000000) + rec->ts.nsecs;
+ ts = GUINT64_TO_LE(hdr_ts);
+ thread_id = GUINT64_TO_LE(rec->rec_header.syscall_header.thread_id);
+ event_len = GUINT32_TO_LE(rec->rec_header.syscall_header.event_len);
+ event_type = GUINT16_TO_LE(rec->rec_header.syscall_header.event_type);
+
+ if (!wtap_dump_file_write(wdh, &cpu_id, sizeof cpu_id, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof cpu_id;
+
+ if (!wtap_dump_file_write(wdh, &ts, sizeof ts, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof ts;
+
+ if (!wtap_dump_file_write(wdh, &thread_id, sizeof thread_id, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof thread_id;
+
+ if (!wtap_dump_file_write(wdh, &event_len, sizeof event_len, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof event_len;
+
+ if (!wtap_dump_file_write(wdh, &event_type, sizeof event_type, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof event_type;
+
+ /* write event data */
+ if (!wtap_dump_file_write(wdh, pd, rec->rec_header.syscall_header.event_filelen, err))
+ return FALSE;
+ wdh->bytes_dumped += rec->rec_header.syscall_header.event_filelen;
+
+ /* write padding (if any) */
+ if (pad_len != 0) {
+ if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
+ return FALSE;
+ wdh->bytes_dumped += pad_len;
+ }
+
+ /* XXX Write comment? */
+
+ /* write block footer */
+ if (!wtap_dump_file_write(wdh, &bh.block_total_length,
+ sizeof bh.block_total_length, err))
+ return FALSE;
+
+ return TRUE;
+
+}
+
+/*
+ * libpcap's maximum pcapng block size is currently 16MB.
+ *
+ * The maximum pcapng block size in macOS's private pcapng reading code
+ * is 1MB. (Yes, this means that a program using the standard pcap
+ * code to read pcapng files can handle bigger blocks than can programs
+ * using the private code, such as Apple's tcpdump, can handle.)
+ *
+ * The pcapng reading code here can handle NRBs of arbitrary size (less
+ * than 4GB, obviously), as they read each NRB record independently,
+ * rather than reading the entire block into memory.
+ *
+ * So, for now, we set the maximum NRB block size we write as 1 MB.
+ *
+ * (Yes, for the benefit of the fussy, "MB" is really "MiB".)
+ */
+
+#define NRES_BLOCK_MAX_SIZE (1024*1024)
+
+static void
+compute_nrb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t* optval, void* user_data)
+{
+ pcapng_block_size_t* block_size = (pcapng_block_size_t*)user_data;
+ guint32 size = 0;
+
+ switch(option_id)
+ {
+ case OPT_COMMENT:
+ case OPT_NS_DNSNAME:
+ size = pcapng_compute_option_string_size(optval->stringval);
+ break;
+ case OPT_NS_DNSIP4ADDR:
+ size = 4;
+ break;
+ case OPT_NS_DNSIP6ADDR:
+ size = 16;
+ break;
+ default:
+ /* Unknown options - size by datatype? */
+ break;
+ }
+
+ block_size->size += size;
+ /* Add bytes for option header if option should be written */
+ if (size > 0) {
+ /* Add optional padding to 32 bits */
+ if ((block_size->size & 0x03) != 0)
+ {
+ block_size->size += 4 - (block_size->size & 0x03);
+ }
+ block_size->size += 4;
+ }
+}
+
+static void
+put_nrb_option(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t* optval, void* user_data)
+{
+ guint8 **opt_ptrp = (guint8 **)user_data;
+ guint32 size = 0;
+ struct pcapng_option_header option_hdr;
+ guint32 pad;
+
+ switch(option_id)
+ {
+ case OPT_COMMENT:
+ case OPT_NS_DNSNAME:
+ /* String options don't consider pad bytes part of the length */
+ size = (guint32)strlen(optval->stringval) & 0xffff;
+ option_hdr.type = (guint16)option_id;
+ option_hdr.value_length = (guint16)size;
+ memcpy(*opt_ptrp, &option_hdr, 4);
+ *opt_ptrp += 4;
+
+ memcpy(*opt_ptrp, optval->stringval, size);
+ *opt_ptrp += size;
+
+ if ((size % 4)) {
+ pad = 4 - (size % 4);
+ } else {
+ pad = 0;
+ }
+
+ /* put padding (if any) */
+ if (pad != 0) {
+ memset(*opt_ptrp, 0, pad);
+ *opt_ptrp += pad;
+ }
+ break;
+ case OPT_NS_DNSIP4ADDR:
+ option_hdr.type = (guint16)option_id;
+ option_hdr.value_length = 4;
+ memcpy(*opt_ptrp, &option_hdr, 4);
+ *opt_ptrp += 4;
+
+ memcpy(*opt_ptrp, &optval->ipv4val, 4);
+ *opt_ptrp += 4;
+ break;
+ case OPT_NS_DNSIP6ADDR:
+ option_hdr.type = (guint16)option_id;
+ option_hdr.value_length = 16;
+ memcpy(*opt_ptrp, &option_hdr, 4);
+ *opt_ptrp += 4;
+
+ memcpy(*opt_ptrp, &optval->ipv6val, 16);
+ *opt_ptrp += 16;
+ break;
+ default:
+ /* Unknown options - size by datatype? */
+ break;
}
+}
- /* write block footer */
- if (!wtap_dump_file_write(wdh, &bh.block_total_length,
- sizeof bh.block_total_length, err))
- return FALSE;
- wdh->bytes_dumped += sizeof bh.block_total_length;
+static void
+put_nrb_options(wtap_dumper *wdh, guint8 *opt_ptr)
+{
+ if (wdh->nrb_hdrs && wdh->nrb_hdrs->len > 0) {
+ wtap_block_t nrb_hdr = g_array_index(wdh->nrb_hdrs, wtap_block_t, 0);
+ struct option option_hdr;
- return TRUE;
+ wtap_block_foreach_option(nrb_hdr, put_nrb_option, &opt_ptr);
+
+ /* Put end of options */
+ option_hdr.type = OPT_EOFOPT;
+ option_hdr.value_length = 0;
+ memcpy(opt_ptr, &option_hdr, 4);
+ }
}
-/* Arbitrary. */
-#define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
static gboolean
pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
{
pcapng_block_header_t bh;
pcapng_name_resolution_block_t nrb;
- guint8 *rec_data;
- guint32 rec_off;
+ pcapng_block_size_t opts_size;
+ size_t max_rec_data_size;
+ guint8 *block_data;
+ guint32 block_off;
size_t hostnamelen;
guint16 namelen;
guint32 tot_rec_len;
hashipv6_t *ipv6_hash_list_entry;
int i;
- if ((!wdh->addrinfo_lists) || ((!wdh->addrinfo_lists->ipv4_addr_list)&&(!wdh->addrinfo_lists->ipv6_addr_list))) {
+ if (wtap_addrinfo_list_empty(wdh->addrinfo_lists)) {
+ /*
+ * No name/address pairs to write.
+ * XXX - what if we have options?
+ */
+ return TRUE;
+ }
+
+ /* Calculate the space needed for options. */
+ opts_size.size = 0;
+ if (wdh->nrb_hdrs && wdh->nrb_hdrs->len > 0) {
+ wtap_block_t nrb_hdr = g_array_index(wdh->nrb_hdrs, wtap_block_t, 0);
+
+ wtap_block_foreach_option(nrb_hdr, compute_nrb_option_size, &opts_size);
+ if (opts_size.size > 0) {
+ /* End-of options tag */
+ opts_size.size += 4;
+ }
+ }
+
+ /*
+ * Make sure we can fit at least one maximum-sized record, plus
+ * an end-of-records record, plus the options, into a maximum-sized
+ * block.
+ *
+ * That requires that there be enough space for the block header
+ * (8 bytes), a maximum-sized record (2 bytes of record type, 2
+ * bytes of record value length, 65535 bytes of record value,
+ * and 1 byte of padding), an end-of-records record (4 bytes),
+ * the options (opts_size.size bytes), and the block trailer (4
+ * bytes).
+ */
+ if (8 + 2 + 2 + 65535 + 1 + 4 + opts_size.size + 4 > NRES_BLOCK_MAX_SIZE) {
+ /*
+ * XXX - we can't even fit the options in the largest NRB size
+ * we're willing to write and still have room enough for a
+ * maximum-sized record. Just discard the information for now.
+ */
return TRUE;
}
- rec_off = 8; /* block type + block total length */
+ /*
+ * Allocate a buffer for the largest block we'll write.
+ */
+ block_data = (guint8 *)g_malloc(NRES_BLOCK_MAX_SIZE);
+
+ /*
+ * Calculate the maximum amount of record data we'll be able to
+ * fit into such a block, after taking into account the block header
+ * (8 bytes), the end-of-records record (4 bytes), the options
+ * (opts_size.size bytes), and the block trailer (4 bytes).
+ */
+ max_rec_data_size = NRES_BLOCK_MAX_SIZE - (8 + 4 + opts_size.size + 4);
+
+ block_off = 8; /* block type + block total length */
bh.block_type = BLOCK_TYPE_NRB;
- bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
- rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
+ bh.block_total_length = 12; /* block header + block trailer */
+ /*
+ * Write out the IPv4 resolved addresses, if any.
+ */
if (wdh->addrinfo_lists->ipv4_addr_list){
i = 0;
ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
hostnamelen = strlen(ipv4_hash_list_entry->name);
if (hostnamelen > (G_MAXUINT16 - 4) - 1) {
/*
- * This won't fit in a maximum-sized record; discard it.
+ * This won't fit in the largest possible NRB record;
+ * discard it.
*/
i++;
ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
continue;
}
namelen = (guint16)(hostnamelen + 1);
- nrb.record_len = 4 + namelen;
+ nrb.record_len = 4 + namelen; /* 4 bytes IPv4 address length */
+ /* 2 bytes record type, 2 bytes length field */
tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
- if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
- /* We know the total length now; copy the block header. */
- memcpy(rec_data, &bh, sizeof(bh));
+ if (block_off + tot_rec_len > max_rec_data_size) {
+ /*
+ * This record would overflow our maximum size for Name
+ * Resolution Blocks; write out all the records we created
+ * before it, and start a new NRB.
+ */
+
+ /* Append the end-of-records record */
+ memset(block_data + block_off, 0, 4);
+ block_off += 4;
+ bh.block_total_length += 4;
+
+ /*
+ * Put the options into the block.
+ *
+ * XXX - this puts the same options in all NRBs.
+ */
+ put_nrb_options(wdh, block_data + block_off);
+ block_off += opts_size.size;
+ bh.block_total_length += opts_size.size;
- /* End of record */
- memset(rec_data + rec_off, 0, 4);
- rec_off += 4;
+ /* Copy the block header. */
+ memcpy(block_data, &bh, sizeof(bh));
- memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
+ /* Copy the block trailer. */
+ memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
- pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
+ pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, block_off %u", bh.block_total_length, block_off);
- if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
- g_free(rec_data);
+ if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
+ g_free(block_data);
return FALSE;
}
wdh->bytes_dumped += bh.block_total_length;
/*Start a new NRB */
- rec_off = 8; /* block type + block total length */
+ block_off = 8; /* block type + block total length */
bh.block_type = BLOCK_TYPE_NRB;
- bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
-
+ bh.block_total_length = 12; /* block header + block trailer */
}
bh.block_total_length += tot_rec_len;
- memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
- rec_off += 4;
- memcpy(rec_data + rec_off, &(ipv4_hash_list_entry->addr), 4);
- rec_off += 4;
- memcpy(rec_data + rec_off, ipv4_hash_list_entry->name, namelen);
- rec_off += namelen;
- memset(rec_data + rec_off, 0, PADDING4(namelen));
- rec_off += PADDING4(namelen);
+ memcpy(block_data + block_off, &nrb, sizeof(nrb));
+ block_off += 4;
+ memcpy(block_data + block_off, &(ipv4_hash_list_entry->addr), 4);
+ block_off += 4;
+ memcpy(block_data + block_off, ipv4_hash_list_entry->name, namelen);
+ block_off += namelen;
+ memset(block_data + block_off, 0, PADDING4(namelen));
+ block_off += PADDING4(namelen);
pcapng_debug("NRB: added IPv4 record for %s", ipv4_hash_list_entry->name);
i++;
hostnamelen = strlen(ipv6_hash_list_entry->name);
if (hostnamelen > (G_MAXUINT16 - 16) - 1) {
/*
- * This won't fit in a maximum-sized record; discard it.
+ * This won't fit in the largest possible NRB record;
+ * discard it.
*/
i++;
ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
/* 2 bytes record type, 2 bytes length field */
tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
- if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
+ if (block_off + tot_rec_len > max_rec_data_size) {
/*
* This record would overflow our maximum size for Name
* Resolution Blocks; write out all the records we created
* before it, and start a new NRB.
*/
- /* First, copy the block header. */
- memcpy(rec_data, &bh, sizeof(bh));
+ /* Append the end-of-records record */
+ memset(block_data + block_off, 0, 4);
+ block_off += 4;
+ bh.block_total_length += 4;
- /* End of record */
- memset(rec_data + rec_off, 0, 4);
- rec_off += 4;
+ /*
+ * Put the options into the block.
+ *
+ * XXX - this puts the same options in all NRBs.
+ */
+ put_nrb_options(wdh, block_data + block_off);
+ block_off += opts_size.size;
+ bh.block_total_length += opts_size.size;
+
+ /* Copy the block header. */
+ memcpy(block_data, &bh, sizeof(bh));
- memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
+ /* Copy the block trailer. */
+ memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
- pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
+ pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, block_off %u", bh.block_total_length, block_off);
- if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
- g_free(rec_data);
+ if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
+ g_free(block_data);
return FALSE;
}
wdh->bytes_dumped += bh.block_total_length;
/*Start a new NRB */
- rec_off = 8; /* block type + block total length */
+ block_off = 8; /* block type + block total length */
bh.block_type = BLOCK_TYPE_NRB;
- bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
-
+ bh.block_total_length = 12; /* block header + block trailer */
}
bh.block_total_length += tot_rec_len;
- memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
- rec_off += 4;
- memcpy(rec_data + rec_off, &(ipv6_hash_list_entry->addr), 16);
- rec_off += 16;
- memcpy(rec_data + rec_off, ipv6_hash_list_entry->name, namelen);
- rec_off += namelen;
- memset(rec_data + rec_off, 0, PADDING4(namelen));
- rec_off += PADDING4(namelen);
+ memcpy(block_data + block_off, &nrb, sizeof(nrb));
+ block_off += 4;
+ memcpy(block_data + block_off, &(ipv6_hash_list_entry->addr), 16);
+ block_off += 16;
+ memcpy(block_data + block_off, ipv6_hash_list_entry->name, namelen);
+ block_off += namelen;
+ memset(block_data + block_off, 0, PADDING4(namelen));
+ block_off += PADDING4(namelen);
pcapng_debug("NRB: added IPv6 record for %s", ipv6_hash_list_entry->name);
i++;
wdh->addrinfo_lists->ipv6_addr_list = NULL;
}
- /* add options, if any */
- if (wdh->nrb_hdr) {
- gboolean have_options = FALSE;
- guint32 options_total_length = 0;
- struct option option_hdr;
- guint32 comment_len = 0, comment_pad_len = 0;
- wtap_optionblock_t nrb_hdr = wdh->nrb_hdr;
- guint32 prev_rec_off = rec_off;
- char* opt_comment;
-
- /* get lengths first to make sure we can fit this into the block */
- wtap_optionblock_get_option_string(nrb_hdr, OPT_COMMENT, &opt_comment);
- if (opt_comment) {
- have_options = TRUE;
- comment_len = (guint32)strlen(opt_comment) & 0xffff;
- if ((comment_len % 4)) {
- comment_pad_len = 4 - (comment_len % 4);
- } else {
- comment_pad_len = 0;
+ /* Append the end-of-records record */
+ memset(block_data + block_off, 0, 4);
+ block_off += 4;
+ bh.block_total_length += 4;
+
+ /*
+ * Put the options into the block.
+ */
+ put_nrb_options(wdh, block_data + block_off);
+ block_off += opts_size.size;
+ bh.block_total_length += opts_size.size;
+
+ /* Copy the block header. */
+ memcpy(block_data, &bh, sizeof(bh));
+
+ /* Copy the block trailer. */
+ memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
+
+ pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, block_off %u", bh.block_total_length, block_off);
+
+ if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
+ g_free(block_data);
+ return FALSE;
+ }
+ wdh->bytes_dumped += bh.block_total_length;
+
+ g_free(block_data);
+
+ return TRUE;
+}
+
+static void compute_isb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
+{
+ pcapng_block_size_t* block_size = (pcapng_block_size_t*)user_data;
+ guint32 size = 0;
+
+ switch(option_id)
+ {
+ case OPT_COMMENT:
+ size = pcapng_compute_option_string_size(optval->stringval);
+ break;
+ case OPT_ISB_STARTTIME:
+ case OPT_ISB_ENDTIME:
+ size = 8;
+ break;
+ case OPT_ISB_IFRECV:
+ case OPT_ISB_IFDROP:
+ case OPT_ISB_FILTERACCEPT:
+ case OPT_ISB_OSDROP:
+ case OPT_ISB_USRDELIV:
+ size = 8;
+ break;
+ default:
+ /* Unknown options - size by datatype? */
+ break;
+ }
+
+ block_size->size += size;
+ /* Add bytes for option header if option should be written */
+ if (size > 0) {
+ /* Add optional padding to 32 bits */
+ if ((block_size->size & 0x03) != 0)
+ {
+ block_size->size += 4 - (block_size->size & 0x03);
+ }
+ block_size->size += 4;
+ }
+}
+
+static void write_wtap_isb_option(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
+{
+ pcapng_write_block_t* write_block = (pcapng_write_block_t*)user_data;
+ struct pcapng_option_header option_hdr;
+
+ /* Don't continue if there has been an error */
+ if (!write_block->success)
+ return;
+
+ switch(option_id)
+ {
+ case OPT_COMMENT:
+ if (!pcapng_write_option_string(write_block->wdh, option_id, optval->stringval, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ break;
+ case OPT_ISB_STARTTIME:
+ case OPT_ISB_ENDTIME:
+ {
+ guint32 high, low;
+
+ option_hdr.type = option_id;
+ option_hdr.value_length = 8;
+ if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 4;
+
+ high = (guint32)(optval->uint64val >> 32);
+ low = (guint32)(optval->uint64val >> 0);
+ if (!wtap_dump_file_write(write_block->wdh, &high, sizeof(guint32), write_block->err)) {
+ write_block->success = FALSE;
+ return;
}
- options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
+ write_block->wdh->bytes_dumped += 4;
+ if (!wtap_dump_file_write(write_block->wdh, &low, sizeof(guint32), write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 4;
}
+ break;
+ case OPT_ISB_IFRECV:
+ case OPT_ISB_IFDROP:
+ case OPT_ISB_FILTERACCEPT:
+ case OPT_ISB_OSDROP:
+ case OPT_ISB_USRDELIV:
+ {
+ option_hdr.type = option_id;
+ option_hdr.value_length = 8;
+ if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 4;
- if (have_options) {
- /* End-of options tag */
- options_total_length += 4;
+ if (!wtap_dump_file_write(write_block->wdh, &optval->uint64val, sizeof(guint64), write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 8;
+ }
+ break;
+ default:
+ /* Unknown options - write by datatype? */
+ break;
+ }
+}
- if (rec_off + options_total_length > NRES_REC_MAX_SIZE) {
- /*
- * This record would overflow our maximum size for Name
- * Resolution Blocks; write out all the records we created
- * before it, and start a new NRB.
- */
+static gboolean
+pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtap_block_t if_stats, int *err)
+{
+ pcapng_block_header_t bh;
+ pcapng_interface_statistics_block_t isb;
+ pcapng_block_size_t block_size;
+ pcapng_write_block_t block_data;
+ struct pcapng_option_header option_hdr;
+ wtapng_if_stats_mandatory_t* mand_data = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats);
+
+ pcapng_debug("pcapng_write_interface_statistics_block");
+
+ /* Compute block size */
+ block_size.size = 0;
+ wtap_block_foreach_option(if_stats, compute_isb_option_size, &block_size);
+
+ if (block_size.size > 0) {
+ /* End-of-options tag */
+ block_size.size += 4;
+ }
+
+ /* write block header */
+ bh.block_type = BLOCK_TYPE_ISB;
+ bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + block_size.size + 4);
+ pcapng_debug("pcapng_write_interface_statistics_block: Total len %u", bh.block_total_length);
- /* First, copy the block header. */
- memcpy(rec_data, &bh, sizeof(bh));
+ if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof bh;
- /* End of record */
- memset(rec_data + rec_off, 0, 4);
- rec_off += 4;
+ /* write block fixed content */
+ isb.interface_id = mand_data->interface_id;
+ isb.timestamp_high = mand_data->ts_high;
+ isb.timestamp_low = mand_data->ts_low;
- memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
+ if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof isb;
- pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
+ /* Write options */
+ if (block_size.size > 0) {
+ block_data.wdh = wdh;
+ block_data.err = err;
+ block_data.success = TRUE;
+ wtap_block_foreach_option(if_stats, write_wtap_isb_option, &block_data);
- if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
- g_free(rec_data);
- return FALSE;
+ if (!block_data.success)
+ return FALSE;
+
+ /* Write end of options */
+ option_hdr.type = OPT_EOFOPT;
+ option_hdr.value_length = 0;
+ if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
+ }
+
+ /* write block footer */
+ if (!wtap_dump_file_write(wdh, &bh.block_total_length,
+ sizeof bh.block_total_length, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof bh.block_total_length;
+ return TRUE;
+}
+
+static void compute_idb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
+{
+ pcapng_block_size_t* block_size = (pcapng_block_size_t*)user_data;
+ guint32 size = 0;
+
+ switch(option_id)
+ {
+ case OPT_COMMENT:
+ case OPT_IDB_NAME:
+ case OPT_IDB_DESCR:
+ case OPT_IDB_OS:
+ case OPT_IDB_HARDWARE:
+ size = pcapng_compute_option_string_size(optval->stringval);
+ break;
+ case OPT_IDB_SPEED:
+ size = 8;
+ break;
+ case OPT_IDB_TSRESOL:
+ size = 1;
+ break;
+ case OPT_IDB_FILTER:
+ {
+ wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)optval->customval.data;
+ guint32 pad;
+ if (filter->if_filter_str != NULL) {
+ size = (guint32)(strlen(filter->if_filter_str) + 1) & 0xffff;
+ if ((size % 4)) {
+ pad = 4 - (size % 4);
+ } else {
+ pad = 0;
}
- wdh->bytes_dumped += bh.block_total_length;
- /*Start a new NRB */
- prev_rec_off = rec_off = 8; /* block type + block total length */
- bh.block_type = BLOCK_TYPE_NRB;
- bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
+ size += pad;
}
+ }
+ break;
+ case OPT_IDB_FCSLEN:
+ /* XXX - Not currently writing value */
+ break;
+ default:
+ /* Unknown options - size by datatype? */
+ break;
+ }
- bh.block_total_length += options_total_length;
+ block_size->size += size;
+ /* Add bytes for option header if option should be written */
+ if (size > 0) {
+ /* Add optional padding to 32 bits */
+ if ((block_size->size & 0x03) != 0)
+ {
+ block_size->size += 4 - (block_size->size & 0x03);
+ }
+ block_size->size += 4;
+ }
+}
- if (comment_len > 0) {
- option_hdr.type = OPT_COMMENT;
- option_hdr.value_length = comment_len;
+static void write_wtap_idb_option(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
+{
+ pcapng_write_block_t* write_block = (pcapng_write_block_t*)user_data;
+ struct pcapng_option_header option_hdr;
+ const guint32 zero_pad = 0;
- memcpy(rec_data + rec_off, &option_hdr, sizeof(option_hdr));
- rec_off += (guint32)sizeof(option_hdr);
+ switch(option_id)
+ {
+ case OPT_COMMENT:
+ case OPT_IDB_NAME:
+ case OPT_IDB_DESCR:
+ case OPT_IDB_OS:
+ case OPT_IDB_HARDWARE:
+ if (!pcapng_write_option_string(write_block->wdh, option_id, optval->stringval, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ break;
+ case OPT_IDB_SPEED:
+ option_hdr.type = option_id;
+ option_hdr.value_length = 8;
+ if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 4;
- /* Write the comments string */
- memcpy(rec_data + rec_off, opt_comment, comment_len);
- rec_off += comment_len;
- memset(rec_data + rec_off, 0, comment_pad_len);
- rec_off += comment_pad_len;
+ if (!wtap_dump_file_write(write_block->wdh, &optval->uint64val, sizeof(guint64), write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 8;
+ break;
+ case OPT_IDB_TSRESOL:
+ option_hdr.type = option_id;
+ option_hdr.value_length = 1;
+ if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 4;
- pcapng_debug("pcapng_write_name_resolution_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
- comment_len,
- comment_pad_len);
- }
+ if (!wtap_dump_file_write(write_block->wdh, &optval->uint8val, 1, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 1;
- /* Write end of options */
- memset(rec_data + rec_off, 0, 4);
- rec_off += 4;
+ if (!wtap_dump_file_write(write_block->wdh, &zero_pad, 3, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 3;
+ break;
+ case OPT_IDB_FILTER:
+ {
+ wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)optval->customval.data;
+ guint32 size, pad;
+ if (filter->if_filter_str != NULL) {
+ size = (guint32)(strlen(filter->if_filter_str) + 1) & 0xffff;
+ if ((size % 4)) {
+ pad = 4 - (size % 4);
+ } else {
+ pad = 0;
+ }
+
+ option_hdr.type = option_id;
+ option_hdr.value_length = size;
+ if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 4;
+
+ /* Write the zero indicating libpcap filter variant */
+ if (!wtap_dump_file_write(write_block->wdh, &zero_pad, 1, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += 1;
+
+ /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
+ if (!wtap_dump_file_write(write_block->wdh, filter->if_filter_str, size-1, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += size - 1;
+
+ /* write padding (if any) */
+ if (pad != 0) {
+ if (!wtap_dump_file_write(write_block->wdh, &zero_pad, pad, write_block->err)) {
+ write_block->success = FALSE;
+ return;
+ }
+ write_block->wdh->bytes_dumped += pad;
+ }
- /* sanity check */
- g_assert(options_total_length == rec_off - prev_rec_off);
+ }
}
+ break;
+ case OPT_IDB_FCSLEN:
+ /* XXX - Not currently writing value */
+ break;
+ default:
+ /* Unknown options - size by datatype? */
+ break;
+ }
+}
+
+static gboolean
+pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_block_t int_data, int *err)
+{
+ pcapng_block_header_t bh;
+ pcapng_interface_description_block_t idb;
+ pcapng_block_size_t block_size;
+ pcapng_write_block_t block_data;
+ struct pcapng_option_header option_hdr;
+ wtapng_if_descr_mandatory_t* mand_data = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
+ int link_type;
+
+ pcapng_debug("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
+ mand_data->wtap_encap,
+ wtap_encap_string(mand_data->wtap_encap),
+ mand_data->snap_len);
+
+ link_type = wtap_wtap_encap_to_pcap_encap(mand_data->wtap_encap);
+ if (link_type == -1) {
+ *err = WTAP_ERR_UNWRITABLE_ENCAP;
+ return FALSE;
}
- /* We know the total length now; copy the block header. */
- memcpy(rec_data, &bh, sizeof(bh));
+ /* Compute block size */
+ block_size.size = 0;
+ wtap_block_foreach_option(int_data, compute_idb_option_size, &block_size);
+
+ if (block_size.size > 0) {
+ /* End-of-options tag */
+ block_size.size += 4;
+ }
- /* End of record */
- memset(rec_data + rec_off, 0, 4);
- rec_off += 4;
+ /* write block header */
+ bh.block_type = BLOCK_TYPE_IDB;
+ bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + block_size.size + 4);
+ pcapng_debug("pcapng_write_if_descr_block: Total len %u", bh.block_total_length);
- memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
+ if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof bh;
- pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
+ /* write block fixed content */
+ idb.linktype = link_type;
+ idb.reserved = 0;
+ idb.snaplen = mand_data->snap_len;
- if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
- g_free(rec_data);
+ if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
return FALSE;
+ wdh->bytes_dumped += sizeof idb;
+
+ if (block_size.size > 0) {
+ /* Write options */
+ block_data.wdh = wdh;
+ block_data.err = err;
+ block_data.success = TRUE;
+ wtap_block_foreach_option(int_data, write_wtap_idb_option, &block_data);
+
+ if (!block_data.success)
+ return FALSE;
+
+ /* Write end of options */
+ option_hdr.type = OPT_EOFOPT;
+ option_hdr.value_length = 0;
+ if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
}
- g_free(rec_data);
- wdh->bytes_dumped += bh.block_total_length;
+ /* write block footer */
+ if (!wtap_dump_file_write(wdh, &bh.block_total_length,
+ sizeof bh.block_total_length, err))
+ return FALSE;
+
+ wdh->bytes_dumped += sizeof bh.block_total_length;
return TRUE;
}
static gboolean pcapng_dump(wtap_dumper *wdh,
- const struct wtap_pkthdr *phdr,
+ const wtap_rec *rec,
const guint8 *pd, int *err, gchar **err_info _U_)
{
- const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
#ifdef HAVE_PLUGINS
block_handler *handler;
#endif
pcapng_debug("pcapng_dump: encap = %d (%s)",
- phdr->pkt_encap,
- wtap_encap_string(phdr->pkt_encap));
+ rec->rec_header.packet_header.pkt_encap,
+ wtap_encap_string(rec->rec_header.packet_header.pkt_encap));
- switch (phdr->rec_type) {
+ switch (rec->rec_type) {
case REC_TYPE_PACKET:
- if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
+ /*
+ * XXX - write a Simple Packet Block if there's no time
+ * stamp or other information that doesn't appear in an
+ * SPB?
+ */
+ if (!pcapng_write_enhanced_packet_block(wdh, rec, pd, err)) {
return FALSE;
}
break;
*/
if (block_handlers != NULL &&
(handler = (block_handler *)g_hash_table_lookup(block_handlers,
- GUINT_TO_POINTER(pseudo_header->ftsrec.record_type))) != NULL) {
+ GUINT_TO_POINTER(rec->rec_header.ft_specific_header.record_type))) != NULL) {
/* Yes. Call it to write out this record. */
- if (!handler->writer(wdh, phdr, pd, err))
+ if (!handler->writer(wdh, rec, pd, err))
return FALSE;
} else
#endif
}
break;
+ case REC_TYPE_SYSCALL:
+ if (!pcapng_write_sysdig_event_block(wdh, rec, pd, err)) {
+ return FALSE;
+ }
+ break;
+
default:
/* We don't support writing this record type. */
*err = WTAP_ERR_UNWRITABLE_REC_TYPE;
for (i = 0; i < wdh->interface_data->len; i++) {
/* Get the interface description */
- wtap_optionblock_t int_data;
+ wtap_block_t int_data;
wtapng_if_descr_mandatory_t *int_data_mand;
- int_data = g_array_index(wdh->interface_data, wtap_optionblock_t, i);
- int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+ int_data = g_array_index(wdh->interface_data, wtap_block_t, i);
+ int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
for (j = 0; j < int_data_mand->num_stat_entries; j++) {
- wtap_optionblock_t if_stats;
+ wtap_block_t if_stats;
- if_stats = g_array_index(int_data_mand->interface_statistics, wtap_optionblock_t, j);
- pcapng_debug("pcapng_dump_finish: write ISB for interface %u", ((wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(if_stats))->interface_id);
+ if_stats = g_array_index(int_data_mand->interface_statistics, wtap_block_t, j);
+ pcapng_debug("pcapng_dump_finish: write ISB for interface %u", ((wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats))->interface_id);
if (!pcapng_write_interface_statistics_block(wdh, if_stats, err)) {
return FALSE;
}
for (i = 0; i < wdh->interface_data->len; i++) {
/* Get the interface description */
- wtap_optionblock_t int_data;
+ wtap_block_t idb;
- int_data = g_array_index(wdh->interface_data, wtap_optionblock_t, i);
+ idb = g_array_index(wdh->interface_data, wtap_block_t, i);
- if (!pcapng_write_if_descr_block(wdh, int_data, err)) {
+ if (!pcapng_write_if_descr_block(wdh, idb, err)) {
return FALSE;
}