aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap/pcapng.c
diff options
context:
space:
mode:
authorGuy Harris <gharris@sonic.net>2021-08-30 14:36:44 -0700
committerGuy Harris <gharris@sonic.net>2021-08-30 16:29:04 -0700
commit030b06ba3c80c795a12053510eee11260d04fbec (patch)
tree01a2a36e1a0f01a202857ccc4a5dfe864b696b83 /wiretap/pcapng.c
parent510c088ce60a1bd5e57bee68f9faee9568f9bf0e (diff)
pcapng: write packet and Netflix custom blocks the same as other blocks.
Use compute_options_size() to get the total size of all the options, and use write_options() to write out the options for those blocks, as we do for other blocks. Get rid of wtap_block_option_get_value_size() and wtap_block_get_options_size_padded(); they're no longer needed, and their notion of an option's "size" is "size in a pcapng file", so that doesn't belong in code that's intended to support all file types.
Diffstat (limited to 'wiretap/pcapng.c')
-rw-r--r--wiretap/pcapng.c427
1 files changed, 275 insertions, 152 deletions
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index 383c037214..ed6dabfd49 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -1639,6 +1639,7 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock,
int *err, gchar **err_info)
{
guint64 tmp64;
+ packet_verdict_opt_t packet_verdict;
/*
* Handle option content.
@@ -1725,7 +1726,11 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock,
switch (option_content[0]) {
case(OPT_VERDICT_TYPE_HW):
- /* No byte swapping needed */
+ packet_verdict.type = packet_verdict_hardware;
+ packet_verdict.data.verdict_bytes =
+ g_byte_array_new_take((guint8 *)g_memdup2(&option_content[1],
+ option_length - 1),
+ option_length - 1);
break;
case(OPT_VERDICT_TYPE_TC):
@@ -1736,11 +1741,15 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock,
/* XXX - free anything? */
return FALSE;
}
- if (section_info->byte_swapped) {
- memcpy(&tmp64, option_content + 1, sizeof(tmp64));
+ /* Don't cast a guint8 * into a guint64 *--the
+ * guint8 * may not point to something that's
+ * aligned correctly.
+ */
+ memcpy(&tmp64, &option_content[1], sizeof(guint64));
+ if (section_info->byte_swapped)
tmp64 = GUINT64_SWAP_LE_BE(tmp64);
- memcpy((void *)(option_content + 1), &tmp64, sizeof(tmp64));
- }
+ packet_verdict.type = packet_verdict_linux_ebpf_tc;
+ packet_verdict.data.verdict_linux_ebpf_tc = tmp64;
break;
case(OPT_VERDICT_TYPE_XDP):
@@ -1751,24 +1760,32 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock,
/* XXX - free anything? */
return FALSE;
}
- if (section_info->byte_swapped) {
- memcpy(&tmp64, option_content + 1, sizeof(tmp64));
+ /* Don't cast a guint8 * into a guint64 *--the
+ * guint8 * may not point to something that's
+ * aligned correctly.
+ */
+ memcpy(&tmp64, &option_content[1], sizeof(guint64));
+ if (section_info->byte_swapped)
tmp64 = GUINT64_SWAP_LE_BE(tmp64);
- memcpy((void*)(option_content + 1), &tmp64, sizeof(tmp64));
- }
+ packet_verdict.type = packet_verdict_linux_ebpf_xdp;
+ packet_verdict.data.verdict_linux_ebpf_xdp = tmp64;
break;
default:
/* Silently ignore unknown verdict types */
return TRUE;
}
- pcapng_process_bytes_option(wblock, option_code, option_length, (void*)option_content);
+ wtap_block_add_packet_verdict_option(wblock->block, option_code, &packet_verdict);
+ wtap_packet_verdict_free(&packet_verdict);
ws_debug("verdict type %u, data len %u",
option_content[0], option_length - 1);
break;
default:
- ws_debug("unknown option %u - ignoring %u bytes",
- option_code, option_length);
+ if (!pcapng_process_unhandled_option(wblock, BT_INDEX_PBS,
+ section_info, option_code,
+ option_length, option_content,
+ err, err_info))
+ return FALSE;
break;
}
return TRUE;
@@ -3829,7 +3846,7 @@ static guint32 pcapng_compute_custom_option_size(wtap_optval_t *optval)
size = sizeof(guint32);
switch (optval->custom_opt.pen) {
case PEN_NFLX:
- /* PEN */
+ /* NFLX type */
size += sizeof(guint32);
size += optval->custom_opt.data.nflx_data.custom_data_len;
break;
@@ -3851,6 +3868,39 @@ static guint32 pcapng_compute_custom_option_size(wtap_optval_t *optval)
return (guint32)size;
}
+static guint32 pcapng_compute_packet_verdict_option_size(wtap_optval_t *optval)
+{
+ packet_verdict_opt_t* verdict = &optval->packet_verdictval;
+ guint32 size;
+ guint32 pad;
+
+ switch (verdict->type) {
+
+ case packet_verdict_hardware:
+ size = verdict->data.verdict_bytes->len;
+ break;
+
+ case packet_verdict_linux_ebpf_tc:
+ size = 9;
+ break;
+
+ case packet_verdict_linux_ebpf_xdp:
+ size = 9;
+ break;
+
+ default:
+ size = 0;
+ break;
+ }
+ if ((size % 4)) {
+ pad = 4 - (size % 4);
+ } else {
+ pad = 0;
+ }
+ size += pad;
+ return size;
+}
+
static gboolean
compute_block_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type, wtap_optval_t *optval, void *user_data)
{
@@ -4097,6 +4147,7 @@ static gboolean pcapng_write_string_option(wtap_dumper *wdh, guint option_id, wt
return TRUE;
}
+#if 0
static gboolean pcapng_write_bytes_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err)
{
struct pcapng_option_header option_hdr;
@@ -4177,6 +4228,7 @@ static gboolean pcapng_write_ipv6_option(wtap_dumper *wdh, guint option_id, wtap
return TRUE;
}
+#endif
static gboolean pcapng_write_if_filter_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err)
{
@@ -4363,6 +4415,99 @@ static gboolean pcapng_write_custom_option(wtap_dumper *wdh, guint option_id, wt
return TRUE;
}
+static gboolean pcapng_write_packet_verdict_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err)
+{
+ packet_verdict_opt_t* verdict = &optval->packet_verdictval;
+ struct pcapng_option_header option_hdr;
+ guint8 type;
+ size_t size;
+ const guint32 zero_pad = 0;
+ guint32 pad;
+
+ switch (verdict->type) {
+
+ case packet_verdict_hardware:
+ size = verdict->data.verdict_bytes->len;
+ if (size > 65535) {
+ /*
+ * Too big to fit in the option.
+ * Don't write anything.
+ *
+ * XXX - truncate it? Report an error?
+ */
+ return TRUE;
+ }
+ option_hdr.type = option_id;
+ option_hdr.value_length = (guint16)size;
+ if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
+
+ type = packet_verdict_hardware;
+ if (!wtap_dump_file_write(wdh, &type, sizeof(guint8), err))
+ return FALSE;
+ wdh->bytes_dumped += 1;
+
+ if (!wtap_dump_file_write(wdh, verdict->data.verdict_bytes->data, size,
+ err))
+ return FALSE;
+ wdh->bytes_dumped += size;
+ break;
+
+ case packet_verdict_linux_ebpf_tc:
+ size = 9;
+ option_hdr.type = option_id;
+ option_hdr.value_length = (guint16)size;
+ if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
+
+ type = packet_verdict_linux_ebpf_tc;
+ if (!wtap_dump_file_write(wdh, &type, sizeof(guint8), err))
+ return FALSE;
+ wdh->bytes_dumped += 1;
+
+ if (!wtap_dump_file_write(wdh, &verdict->data.verdict_linux_ebpf_tc,
+ sizeof(guint64), err))
+ return FALSE;
+ wdh->bytes_dumped += 8;
+ break;
+
+ case packet_verdict_linux_ebpf_xdp:
+ size = 9;
+ option_hdr.type = option_id;
+ option_hdr.value_length = (guint16)size;
+ if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
+ return FALSE;
+ wdh->bytes_dumped += 4;
+
+ type = packet_verdict_linux_ebpf_xdp;
+ if (!wtap_dump_file_write(wdh, &type, sizeof(guint8), err))
+ return FALSE;
+ wdh->bytes_dumped += 1;
+
+ if (!wtap_dump_file_write(wdh, &verdict->data.verdict_linux_ebpf_xdp,
+ sizeof(guint64), err))
+ return FALSE;
+ wdh->bytes_dumped += 8;
+ break;
+
+ default:
+ /* Unknown - don't write it out. */
+ return TRUE;
+ }
+
+ /* write padding (if any) */
+ if ((size % 4)) {
+ pad = 4 - (size % 4);
+ if (!wtap_dump_file_write(wdh, &zero_pad, pad, err))
+ return FALSE;
+
+ wdh->bytes_dumped += pad;
+ }
+ return TRUE;
+}
+
static gboolean write_block_option(wtap_block_t block, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
{
write_options_t* write_options = (write_options_t*)user_data;
@@ -4393,8 +4538,9 @@ static gboolean write_block_option(wtap_block_t block, guint option_id, wtap_opt
*/
break;
default:
- /* Block-type dependent; call the callback. */
- if (!(*write_options->write_option)(write_options->wdh, block, option_id, option_type, optval, write_options->err))
+ /* Block-type dependent; call the callback, if we have one. */
+ if (write_options->write_option != NULL &&
+ !(*write_options->write_option)(write_options->wdh, block, option_id, option_type, optval, write_options->err))
return FALSE;
break;
}
@@ -4485,8 +4631,8 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
wdh->bytes_dumped += sizeof shb;
if (wdh_shb) {
+ /* Write options, if we have any */
if (options_size != 0) {
- /* Write options */
if (!write_options(wdh, wdh_shb, write_wtap_shb_option, err))
return FALSE;
}
@@ -4501,67 +4647,114 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
return TRUE;
}
-typedef struct pcapng_write_block_s
-{
- wtap_dumper *wdh;
- int *err;
-}
-pcapng_write_block_t;
-
-/* Helper function used in pcapng_write_enhanced_packet_block().
- * Meant to be generic enough to be used elsewhere too, but currently,
- * only WTAP_OPTTYPE_STRING and WTAP_OPTTYPE_BYTES are exercised (and thus tested).
- * This is a wtap_block_foreach_func.
+/* options defined in Section 2.5 (Options)
+ * Name Code Length Description
+ * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
+ *
+ * Enhanced Packet Block options
+ * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
+ * the allowed flags can be found in Appendix A (Packet Block Flags Word).
+ * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
+ * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
+ * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
+ * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
+ * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
+ * The hash covers only the packet, not the header added by the capture driver:
+ * this gives the possibility to calculate it inside the network card.
+ * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
+ * data acquisition system and the capture library.
+ * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
+ * between this packet and the preceding one.
+ * epb_packetid 5 8 The epb_packetid option is a 64-bit unsigned integer that
+ * uniquely identifies the packet. If the same packet is seen
+ * by multiple interfaces and there is a way for the capture
+ * application to correlate them, the same epb_packetid value
+ * must be used. An example could be a router that captures
+ * packets on all its interfaces in both directions. When a
+ * packet hits interface A on ingress, an EPB entry gets
+ * created, TTL gets decremented, and right before it egresses
+ * on interface B another EPB entry gets created in the trace
+ * file. In this case, two packets are in the capture file,
+ * which are not identical but the epb_packetid can be used to
+ * correlate them.
+ * epb_queue 6 4 The epb_queue option is a 32-bit unsigned integer that
+ * identifies on which queue of the interface the specific
+ * packet was received.
+ * epb_verdict 7 variable The epb_verdict option stores a verdict of the packet. The
+ * verdict indicates what would be done with the packet after
+ * processing it. For example, a firewall could drop the
+ * packet. This verdict can be set by various components, i.e.
+ * Hardware, Linux's eBPF TC or XDP framework, etc. etc. The
+ * first octet specifies the verdict type, while the following
+ * octets contain the actual verdict data, whose size depends on
+ * the verdict type, and hence from the value in the first
+ * octet. The verdict type can be: Hardware (type octet = 0,
+ * size = variable), Linux_eBPF_TC (type octet = 1, size = 8
+ * (64-bit unsigned integer), value = TC_ACT_* as defined in the
+ * Linux pck_cls.h include), Linux_eBPF_XDP (type octet = 2,
+ * size = 8 (64-bit unsigned integer), value = xdp_action as
+ * defined in the Linux pbf.h include).
+ * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
*/
-static gboolean
-pcapng_write_option_cb(wtap_block_t block _U_, guint option_id _U_, wtap_opttype_e option_type, wtap_optval_t *option, void *user_data)
+static guint32
+compute_epb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t* optval)
{
- pcapng_write_block_t* write_block = (pcapng_write_block_t*)user_data;
- gboolean ok = TRUE;
+ guint32 size;
- /* The functions below write their option type and length fields, and any needed padding. */
- switch(option_type)
+ switch(option_id)
{
-
- case WTAP_OPTTYPE_UINT8:
- ok = pcapng_write_uint8_option(write_block->wdh, option_id, option, write_block->err);
+ case OPT_EPB_FLAGS:
+ size = 4;
break;
-
- case WTAP_OPTTYPE_UINT32:
- ok = pcapng_write_uint32_option(write_block->wdh, option_id, option, write_block->err);
+ case OPT_EPB_DROPCOUNT:
+ size = 8;
break;
-
- case WTAP_OPTTYPE_UINT64:
- ok = pcapng_write_uint64_option(write_block->wdh, option_id, option, write_block->err);
+ case OPT_EPB_PACKETID:
+ size = 8;
break;
-
- case WTAP_OPTTYPE_IPv4:
- // wtap_opttypes.h implies this is stored in network byte order
- ok = pcapng_write_ipv4_option(write_block->wdh, option_id, option, write_block->err);
+ case OPT_EPB_QUEUE:
+ size = 4;
break;
-
- case WTAP_OPTTYPE_IPv6:
- ok = pcapng_write_ipv6_option(write_block->wdh, option_id, option, write_block->err);
+ case OPT_EPB_VERDICT:
+ size = pcapng_compute_packet_verdict_option_size(optval);
break;
-
- case WTAP_OPTTYPE_STRING:
- ok = pcapng_write_string_option(write_block->wdh, option_id, option, write_block->err);
+ default:
+ /* Unknown options - size by datatype? */
+ size = 0;
break;
+ }
+ return size;
+}
- case WTAP_OPTTYPE_BYTES:
- ok = pcapng_write_bytes_option(write_block->wdh, option_id, option, write_block->err);
+static gboolean write_wtap_epb_option(wtap_dumper *wdh, wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, int *err)
+{
+ switch(option_id)
+ {
+ case OPT_PKT_FLAGS:
+ if (!pcapng_write_uint32_option(wdh, OPT_EPB_FLAGS, optval, err))
+ return FALSE;
break;
-
- case WTAP_OPTTYPE_IF_FILTER:
- ok = pcapng_write_if_filter_option(write_block->wdh, option_id, option, write_block->err);
+ case OPT_PKT_DROPCOUNT:
+ if (!pcapng_write_uint64_option(wdh, OPT_EPB_DROPCOUNT, optval, err))
+ return FALSE;
break;
-
- case WTAP_OPTTYPE_CUSTOM:
- ok = pcapng_write_custom_option(write_block->wdh, option_id, option, write_block->err);
+ case OPT_PKT_PACKETID:
+ if (!pcapng_write_uint64_option(wdh, OPT_EPB_PACKETID, optval, err))
+ return FALSE;
+ break;
+ case OPT_PKT_QUEUE:
+ if (!pcapng_write_uint32_option(wdh, OPT_EPB_QUEUE, optval, err))
+ return FALSE;
+ break;
+ case OPT_PKT_VERDICT:
+ if (!pcapng_write_packet_verdict_option(wdh, OPT_EPB_QUEUE, optval,
+ err))
+ break;
+ default:
+ /* Unknown options - write by datatype? */
break;
}
-
- return ok;
+ return TRUE; /* success */
}
static gboolean
@@ -4571,19 +4764,14 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
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;
+ guint32 options_size = 0;
guint64 ts;
const guint32 zero_pad = 0;
guint32 pad_len;
guint32 phdr_len;
- gboolean have_options = FALSE;
guint32 options_total_length = 0;
- gsize options_len = 0;
wtap_block_t int_data;
wtapng_if_descr_mandatory_t *int_data_mand;
- pcapng_write_block_t block_data;
-
- block_data.wdh = wdh;
- block_data.err = err;
/* Don't write anything we're not willing to read. */
if (rec->rec_header.packet_header.caplen > wtap_max_snaplen_for_encap(wdh->encap)) {
@@ -4597,24 +4785,15 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
} else {
pad_len = 0;
}
- if (rec->block != NULL) {
- // Remember to also add newly-supported option types to packet_block_options_supported
- // below.
- options_len = wtap_block_get_options_size_padded(rec->block);
- if (options_len > 0) {
- have_options = TRUE;
- options_total_length += (guint32)options_len;
- }
- }
- if (have_options) {
- /* End-of options tag */
- options_total_length += 4;
+ if (rec->block != NULL) {
+ /* Compute size of all the options */
+ options_size = compute_options_size(rec->block, compute_epb_option_size);
}
/* write (enhanced) packet block header */
bh.block_type = BLOCK_TYPE_EPB;
- bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + rec->rec_header.packet_header.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 + options_size + 4;
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
return FALSE;
@@ -4687,65 +4866,9 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
wdh->bytes_dumped += pad_len;
}
- /* XXX - write (optional) block options */
- /* options defined in Section 2.5 (Options)
- * Name Code Length Description
- * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
- * opt_custom 2988 variable A UTF-8 string which can be copied.
- * opt_custom 2989 variable Binary octets which can be copied.
- * opt_custom 19372 variable A UTF-8 string which should not be copied.
- * opt_custom 19373 variable Binary octets which should not be copied.
- * Enhanced Packet Block options
- * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
- * the allowed flags can be found in Appendix A (Packet Block Flags Word).
- * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
- * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
- * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
- * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
- * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
- * The hash covers only the packet, not the header added by the capture driver:
- * this gives the possibility to calculate it inside the network card.
- * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
- * data acquisition system and the capture library.
- * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
- * between this packet and the preceding one.
- * epb_packetid 5 8 The epb_packetid option is a 64-bit unsigned integer that
- * uniquely identifies the packet. If the same packet is seen
- * by multiple interfaces and there is a way for the capture
- * application to correlate them, the same epb_packetid value
- * must be used. An example could be a router that captures
- * packets on all its interfaces in both directions. When a
- * packet hits interface A on ingress, an EPB entry gets
- * created, TTL gets decremented, and right before it egresses
- * on interface B another EPB entry gets created in the trace
- * file. In this case, two packets are in the capture file,
- * which are not identical but the epb_packetid can be used to
- * correlate them.
- * epb_queue 6 4 The epb_queue option is a 32-bit unsigned integer that
- * identifies on which queue of the interface the specific
- * packet was received.
- * epb_verdict 7 variable The epb_verdict option stores a verdict of the packet. The
- * verdict indicates what would be done with the packet after
- * processing it. For example, a firewall could drop the
- * packet. This verdict can be set by various components, i.e.
- * Hardware, Linux's eBPF TC or XDP framework, etc. etc. The
- * first octet specifies the verdict type, while the following
- * octets contain the actual verdict data, whose size depends on
- * the verdict type, and hence from the value in the first
- * octet. The verdict type can be: Hardware (type octet = 0,
- * size = variable), Linux_eBPF_TC (type octet = 1, size = 8
- * (64-bit unsigned integer), value = TC_ACT_* as defined in the
- * Linux pck_cls.h include), Linux_eBPF_XDP (type octet = 2,
- * size = 8 (64-bit unsigned integer), value = xdp_action as
- * defined in the Linux pbf.h include).
- * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
- */
- if (!wtap_block_foreach_option(rec->block, pcapng_write_option_cb, &block_data)) {
- return FALSE;
- }
- /* Write end of options if we have options */
- if (have_options) {
- if (!pcapng_write_option_eofopt(wdh, err))
+ /* Write options, if we have any */
+ if (options_size != 0) {
+ if (!write_options(wdh, rec->block, write_wtap_epb_option, err))
return FALSE;
}
@@ -4994,15 +5117,15 @@ pcapng_write_bblog_block(wtap_dumper *wdh, const wtap_rec *rec,
const guint8 *pd _U_, int *err)
{
pcapng_block_header_t bh;
- pcapng_write_block_t block_data;
- gsize options_len;
+ guint32 options_size = 0;
guint32 pen, skipped, type;
- options_len = wtap_block_get_options_size_padded(rec->block) + 4;
+ /* Compute size of all the options */
+ options_size = compute_options_size(rec->block, compute_epb_option_size);
/* write block header */
bh.block_type = BLOCK_TYPE_CB_COPY;
- bh.block_total_length = (guint32)(sizeof(bh) + sizeof(guint32) + sizeof(guint32) + options_len + 4);
+ bh.block_total_length = (guint32)(sizeof(bh) + sizeof(guint32) + sizeof(guint32) + options_size + 4);
if (rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.type == BBLOG_TYPE_SKIPPED_BLOCK) {
bh.block_total_length += (guint32)sizeof(guint32);
}
@@ -5038,14 +5161,14 @@ pcapng_write_bblog_block(wtap_dumper *wdh, const wtap_rec *rec,
ws_debug("wrote skipped = %u", rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.skipped);
}
- block_data.wdh = wdh;
- block_data.err = err;
- if (!wtap_block_foreach_option(rec->block, pcapng_write_option_cb, &block_data)) {
- return FALSE;
- }
- /* Write end of options if we have options */
- if (!pcapng_write_option_eofopt(wdh, err)) {
- return FALSE;
+ /* Write options, if we have any */
+ if (options_size != 0) {
+ /*
+ * This block type supports only comments and custom options,
+ * so it doesn't need a callback.
+ */
+ if (!write_options(wdh, rec->block, NULL, err))
+ return FALSE;
}
/* write block footer */