diff options
author | David Perry <boolean263@protonmail.com> | 2021-04-29 07:23:21 -0400 |
---|---|---|
committer | Guy Harris <gharris@sonic.net> | 2021-07-07 18:40:24 +0000 |
commit | 73087d6fb486a61e8eb0886a02e6c6403534fa36 (patch) | |
tree | 2cee7a922a2225628103bb247818a8bb2db133b3 /wiretap/pcapng.c | |
parent | 20f38c06eab3f9a995468141cdfb14ec821a6503 (diff) |
Use wtap_blocks for packet comments
Mostly functioning proof of concept for #14329. This work is intended to
allow Wireshark to support multiple packet comments per packet.
Uses and expands upon the `wtap_block` API in `wiretap/wtap_opttypes.h`.
It attaches a `wtap_block` structure to `wtap_rec` in place of its
current `opt_comment` and `packet_verdict` members to hold OPT_COMMENT
and OPT_PKT_VERDICT option values.
Diffstat (limited to 'wiretap/pcapng.c')
-rw-r--r-- | wiretap/pcapng.c | 428 |
1 files changed, 232 insertions, 196 deletions
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index ad076724ab..df91b7a619 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -518,6 +518,13 @@ pcapng_process_string_option(wtapng_block_t *wblock, guint16 option_code, } static void +pcapng_process_bytes_option(wtapng_block_t *wblock, guint16 option_code, + guint16 option_length, const guint8 *option_content) +{ + wtap_block_add_bytes_option(wblock->block, option_code, (const char *)option_content, option_length); +} + +static void pcapng_process_uint8_option(wtapng_block_t *wblock, guint16 option_code, guint16 option_length, const guint8 *option_content) @@ -590,29 +597,6 @@ pcapng_process_uint64_option(wtapng_block_t *wblock, } static gboolean -pcap_process_generic_custom_option(wtapng_block_t *wblock, - guint16 option_code, guint16 option_length, - guint32 pen, - const guint8 *option_content) -{ - wtap_option_t option; - - if (wblock->type == BLOCK_TYPE_EPB) { - if (wblock->rec->custom_options == NULL) { - wblock->rec->custom_options = g_array_new (FALSE, FALSE, sizeof(wtap_option_t)); - } - option.option_id = option_code; - option.value.custom_opt.pen = pen; - option.value.custom_opt.custom_data_len = option_length - 4; - option.value.custom_opt.custom_data = g_memdup2(option_content + 4, option_length - 4); - g_array_append_val(wblock->rec->custom_options, option); - } else { - wtap_block_add_custom_option(wblock->block, option_code, pen, option_content + 4, option_length - 4); - } - return TRUE; -} - -static gboolean pcapng_process_custom_option(wtapng_block_t *wblock, const section_info_t *section_info, guint16 option_code, guint16 option_length, @@ -634,7 +618,7 @@ pcapng_process_custom_option(wtapng_block_t *wblock, switch (pen) { default: ws_debug("Custom option type 0x%04x with unknown pen %u with custom data of length %u", option_code, pen, option_length - 4); - if (!pcap_process_generic_custom_option(wblock, option_code, option_length, pen, option_content)) { + if (wtap_block_add_custom_option(wblock->block, option_code, pen, option_content + 4, option_length - 4) != WTAP_OPTTYPE_SUCCESS) { return FALSE; } break; @@ -1420,7 +1404,6 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock, { guint32 tmp32; guint64 tmp64; - guint8 *option_content_copy; /* * Handle option content. @@ -1441,16 +1424,7 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock, */ switch (option_code) { case(OPT_COMMENT): - if (option_length != 0) { - wblock->rec->presence_flags |= WTAP_HAS_COMMENTS; - g_free(wblock->rec->opt_comment); - wblock->rec->opt_comment = g_strndup((char *)option_content, option_length); - ws_debug("length %u opt_comment '%s'", - option_length, wblock->rec->opt_comment); - } else { - ws_debug("opt_comment length %u seems strange", - option_length); - } + pcapng_process_string_option(wblock, option_code, option_length, option_content); break; case(OPT_EPB_FLAGS): if (option_length != 4) { @@ -1543,7 +1517,7 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock, switch (option_content[0]) { case(OPT_VERDICT_TYPE_HW): - option_content_copy = g_memdup2(option_content, option_length); + /* No byte swapping needed */ break; case(OPT_VERDICT_TYPE_TC): @@ -1554,11 +1528,10 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock, /* XXX - free anything? */ return FALSE; } - option_content_copy = g_memdup2(option_content, option_length); if (section_info->byte_swapped) { - memcpy(&tmp64, option_content_copy + 1, sizeof(tmp64)); + memcpy(&tmp64, option_content + 1, sizeof(tmp64)); tmp64 = GUINT64_SWAP_LE_BE(tmp64); - memcpy(option_content_copy + 1, &tmp64, sizeof(tmp64)); + memcpy((void *)(option_content + 1), &tmp64, sizeof(tmp64)); } break; @@ -1570,11 +1543,10 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock, /* XXX - free anything? */ return FALSE; } - option_content_copy = g_memdup2(option_content, option_length); if (section_info->byte_swapped) { - memcpy(&tmp64, option_content_copy + 1, sizeof(tmp64)); + memcpy(&tmp64, option_content + 1, sizeof(tmp64)); tmp64 = GUINT64_SWAP_LE_BE(tmp64); - memcpy(option_content_copy + 1, &tmp64, sizeof(tmp64)); + memcpy((void*)(option_content + 1), &tmp64, sizeof(tmp64)); } break; @@ -1582,16 +1554,7 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock, /* Silently ignore unknown verdict types */ return TRUE; } - if (wblock->rec->packet_verdict == NULL) { - wblock->rec->presence_flags |= WTAP_HAS_VERDICT; - wblock->rec->packet_verdict = g_ptr_array_new_with_free_func((GDestroyNotify) g_bytes_unref); - } - - g_ptr_array_add(wblock->rec->packet_verdict, - g_bytes_new_with_free_func(option_content_copy, - option_length, - g_free, - option_content_copy)); + pcapng_process_bytes_option(wblock, option_code, option_length, (void*)option_content); ws_debug("verdict type %u, data len %u", option_content[0], option_length - 1); break; @@ -1619,8 +1582,8 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, guint64 ts; int pseudo_header_len; int fcslen; - wtap_option_t option; - guint i; + + wblock->block = wtap_block_create(WTAP_BLOCK_PACKET); /* "(Enhanced) Packet Block" read fixed part */ if (enhanced) { @@ -1800,25 +1763,10 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, } /* Option defaults */ - g_free(wblock->rec->opt_comment); /* Free memory from an earlier read. */ - wblock->rec->opt_comment = NULL; wblock->rec->rec_header.packet_header.drop_count = -1; wblock->rec->rec_header.packet_header.pack_flags = 0; wblock->rec->rec_header.packet_header.packet_id = 0; wblock->rec->rec_header.packet_header.interface_queue = 0; - if (wblock->rec->packet_verdict != NULL) { - g_ptr_array_free(wblock->rec->packet_verdict, TRUE); - wblock->rec->packet_verdict = NULL; - } - if (wblock->rec->custom_options != NULL) { - for (i = 0; i < wblock->rec->custom_options->len; i++) { - option = g_array_index(wblock->rec->custom_options, wtap_option_t, i); - g_free(option.value.custom_opt.custom_data); - option.value.custom_opt.custom_data = NULL; - } - g_array_free(wblock->rec->custom_options, TRUE); - wblock->rec->custom_options = NULL; - } /* FCS length default */ fcslen = iface_info.fcslen; @@ -1852,6 +1800,15 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, */ wblock->internal = FALSE; + /* + * We want dissectors (particularly packet_frame) to be able to + * access packet comments and whatnot that are in the block. wblock->block + * will be unref'd by pcapng_seek_read(), so move the block to where + * dissectors can find it. + */ + wblock->rec->block = wblock->block; + wblock->block = NULL; + return TRUE; } @@ -1867,8 +1824,6 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, wtapng_simple_packet_t simple_packet; guint32 padding; int pseudo_header_len; - wtap_option_t option; - guint i; /* * Is this block long enough to be an SPB? @@ -1958,25 +1913,10 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, wblock->rec->ts.secs = 0; wblock->rec->ts.nsecs = 0; wblock->rec->rec_header.packet_header.interface_id = 0; - g_free(wblock->rec->opt_comment); /* Free memory from an earlier read. */ - wblock->rec->opt_comment = NULL; wblock->rec->rec_header.packet_header.drop_count = 0; wblock->rec->rec_header.packet_header.pack_flags = 0; wblock->rec->rec_header.packet_header.packet_id = 0; wblock->rec->rec_header.packet_header.interface_queue = 0; - if (wblock->rec->packet_verdict != NULL) { - g_ptr_array_free(wblock->rec->packet_verdict, TRUE); - wblock->rec->packet_verdict = NULL; - } - if (wblock->rec->custom_options != NULL) { - for (i = 0; i < wblock->rec->custom_options->len; i++) { - option = g_array_index(wblock->rec->custom_options, wtap_option_t, i); - g_free(option.value.custom_opt.custom_data); - option.value.custom_opt.custom_data = NULL; - } - g_array_free(wblock->rec->custom_options, TRUE); - wblock->rec->custom_options = NULL; - } memset((void *)&wblock->rec->rec_header.packet_header.pseudo_header, 0, sizeof(union wtap_pseudo_header)); pseudo_header_len = pcap_process_pseudo_header(fh, @@ -3136,14 +3076,14 @@ pcapng_open(wtap *wth, int *err, gchar **err_info) case PCAPNG_BLOCK_NOT_SHB: /* This doesn't look like an SHB, so this isn't a pcapng file. */ - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); *err = 0; g_free(*err_info); *err_info = NULL; return WTAP_OPEN_NOT_MINE; case PCAPNG_BLOCK_ERROR: - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); if (*err == WTAP_ERR_SHORT_READ) { /* * Short read. @@ -3165,7 +3105,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info) */ if (!pcapng_read_and_check_block_trailer(wth->fh, &bh, &first_section, err, err_info)) { /* Not readable or not valid. */ - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); return WTAP_OPEN_ERROR; } @@ -3178,7 +3118,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info) * SHBs for this file. */ wtap_block_copy(g_array_index(wth->shb_hdrs, wtap_block_t, 0), wblock.block); - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); wblock.block = NULL; wth->file_encap = WTAP_ENCAP_UNKNOWN; @@ -3264,7 +3204,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info) if (!pcapng_read_block(wth, wth->fh, pcapng, current_section, &new_section, &wblock, err, err_info)) { - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); if (*err == 0) { ws_debug("No more IDBs available..."); break; @@ -3274,7 +3214,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info) } } pcapng_process_idb(wth, current_section, &wblock); - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); ws_debug("Read IDB number_of_interfaces %u, wtap_encap %i", wth->interface_data->len, wth->file_encap); } @@ -3319,7 +3259,7 @@ pcapng_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, &new_section, &wblock, err, err_info)) { ws_debug("data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset); ws_debug("couldn't read packet block"); - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); return FALSE; } @@ -3360,7 +3300,7 @@ pcapng_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, /* A new interface */ ws_debug("block type BLOCK_TYPE_IDB"); pcapng_process_idb(wth, current_section, &wblock); - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); break; case(BLOCK_TYPE_DSB): @@ -3425,7 +3365,7 @@ pcapng_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, g_array_append_val(wtapng_if_descr_mand->interface_statistics, if_stats); wtapng_if_descr_mand->num_stat_entries++; } - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); break; default: @@ -3497,7 +3437,7 @@ pcapng_seek_read(wtap *wth, gint64 seek_off, if (!pcapng_read_block(wth, wth->random_fh, pcapng, section_info, &new_section, &wblock, err, err_info)) { ws_debug("couldn't read packet block (err=%d).", *err); - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); return FALSE; } @@ -3505,11 +3445,11 @@ pcapng_seek_read(wtap *wth, gint64 seek_off, if (wblock.internal) { ws_debug("block type 0x%08x is not one we return", wblock.type); - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); return FALSE; } - wtap_block_free(wblock.block); + wtap_block_unref(wblock.block); return TRUE; } @@ -3557,6 +3497,24 @@ static guint32 pcapng_compute_string_option_size(wtap_optval_t *optval) return size; } +#if 0 +static guint32 pcapng_compute_bytes_option_size(wtap_optval_t *optval) +{ + guint32 size = 0, pad; + + size = (guint32)g_bytes_get_size(optval->byteval) & 0xffff; + if ((size % 4)) { + pad = 4 - (size % 4); + } else { + pad = 0; + } + + size += pad; + + return size; +} +#endif + static guint32 pcapng_compute_if_filter_option_size(wtap_optval_t *optval) { if_filter_opt_t* filter = &optval->if_filterval; @@ -3741,6 +3699,40 @@ static gboolean pcapng_write_uint8_option(wtap_dumper *wdh, guint option_id, wta return TRUE; } +static gboolean pcapng_write_uint32_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err) +{ + struct pcapng_option_header option_hdr; + + option_hdr.type = (guint16)option_id; + option_hdr.value_length = (guint16)4; + if (!wtap_dump_file_write(wdh, &option_hdr, 4, err)) + return FALSE; + wdh->bytes_dumped += 4; + + if (!wtap_dump_file_write(wdh, &optval->uint32val, 1, err)) + return FALSE; + wdh->bytes_dumped += 4; + + return TRUE; +} + +static gboolean pcapng_write_ipv4_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err) +{ + struct pcapng_option_header option_hdr; + + option_hdr.type = (guint16)option_id; + option_hdr.value_length = (guint16)4; + if (!wtap_dump_file_write(wdh, &option_hdr, 4, err)) + return FALSE; + wdh->bytes_dumped += 4; + + if (!wtap_dump_file_write(wdh, &optval->ipv4val, 1, err)) + return FALSE; + wdh->bytes_dumped += 4; + + return TRUE; +} + static gboolean pcapng_write_uint64_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err) { struct pcapng_option_header option_hdr; @@ -3758,6 +3750,23 @@ static gboolean pcapng_write_uint64_option(wtap_dumper *wdh, guint option_id, wt return TRUE; } +static gboolean pcapng_write_ipv6_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err) +{ + struct pcapng_option_header option_hdr; + + option_hdr.type = (guint16)option_id; + option_hdr.value_length = (guint16)IPv6_ADDR_SIZE; + if (!wtap_dump_file_write(wdh, &option_hdr, 4, err)) + return FALSE; + wdh->bytes_dumped += 4; + + if (!wtap_dump_file_write(wdh, &optval->ipv6val.bytes, IPv6_ADDR_SIZE, err)) + return FALSE; + wdh->bytes_dumped += IPv6_ADDR_SIZE; + + return TRUE; +} + static gboolean pcapng_write_timestamp_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err) { struct pcapng_option_header option_hdr; @@ -3828,6 +3837,53 @@ static gboolean pcapng_write_string_option(wtap_dumper *wdh, guint option_id, wt return TRUE; } +static gboolean pcapng_write_bytes_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err) +{ + struct pcapng_option_header option_hdr; + size_t size = g_bytes_get_size(optval->byteval); + const guint32 zero_pad = 0; + guint32 pad; + + if (size == 0) + return TRUE; + if (size > 65535) { + /* + * Too big to fit in the option. + * Don't write anything. + * + * XXX - truncate it? Report an error? + */ + return TRUE; + } + + /* Bytes 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, optval->stringval, size, err)) + return FALSE; + wdh->bytes_dumped += size; + + if ((size % 4)) { + pad = 4 - (size % 4); + } else { + pad = 0; + } + + /* write padding (if any) */ + if (pad != 0) { + if (!wtap_dump_file_write(wdh, &zero_pad, pad, err)) + return FALSE; + + wdh->bytes_dumped += pad; + } + + return TRUE; +} + static gboolean pcapng_write_if_filter_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err) { if_filter_opt_t* filter = &optval->if_filterval; @@ -4109,6 +4165,68 @@ 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. + */ +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) +{ + pcapng_write_block_t* write_block = (pcapng_write_block_t*)user_data; + gboolean ok = TRUE; + + /* The functions below write their option type and length fields, and any needed padding. */ + switch(option_type) + { + + case WTAP_OPTTYPE_UINT8: + ok = pcapng_write_uint8_option(write_block->wdh, option_id, option, write_block->err); + break; + + case WTAP_OPTTYPE_UINT32: + ok = pcapng_write_uint32_option(write_block->wdh, option_id, option, write_block->err); + break; + + case WTAP_OPTTYPE_UINT64: + ok = pcapng_write_uint64_option(write_block->wdh, option_id, option, write_block->err); + 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); + break; + + case WTAP_OPTTYPE_IPv6: + ok = pcapng_write_ipv6_option(write_block->wdh, option_id, option, write_block->err); + break; + + case WTAP_OPTTYPE_STRING: + ok = pcapng_write_string_option(write_block->wdh, option_id, option, write_block->err); + break; + + case WTAP_OPTTYPE_BYTES: + ok = pcapng_write_bytes_option(write_block->wdh, option_id, option, write_block->err); + break; + + case WTAP_OPTTYPE_IF_FILTER: + ok = pcapng_write_if_filter_option(write_block->wdh, option_id, option, write_block->err); + break; + + case WTAP_OPTTYPE_CUSTOM: + ok = pcapng_write_custom_option(write_block->wdh, option_id, option, write_block->err); + break; + } + + return ok; +} + static gboolean pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec, const guint8 *pd, int *err, gchar **err_info) @@ -4123,9 +4241,13 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec, gboolean have_options = FALSE; guint32 options_total_length = 0; struct option option_hdr; - guint32 comment_len = 0, comment_pad_len = 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)) { @@ -4139,30 +4261,17 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec, } else { pad_len = 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; + if (rec->block != NULL) { + // Current options expected to be here: comments, verdicts, custom. + // 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; } - options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ; } - if (rec->custom_options != NULL) { - have_options = TRUE; - for (guint i = 0; i < rec->custom_options->len; i++) { - wtap_option_t option; - option = g_array_index(rec->custom_options, wtap_option_t, i); - if ((option.option_id == OPT_CUSTOM_STR_COPY) || - (option.option_id == OPT_CUSTOM_BIN_COPY)) { - options_total_length += pcapng_compute_custom_option_size(&option.value) + 4; - } - } - } if (rec->presence_flags & WTAP_HAS_PACK_FLAGS) { have_options = TRUE; options_total_length = options_total_length + 8; @@ -4179,17 +4288,6 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec, have_options = TRUE; options_total_length = options_total_length + 8; } - if (rec->presence_flags & WTAP_HAS_VERDICT && rec->packet_verdict != NULL) { - - for(guint i = 0; i < rec->packet_verdict->len; i++) { - gsize len; - GBytes *verdict = (GBytes *) g_ptr_array_index(rec->packet_verdict, i); - - if (g_bytes_get_data(verdict, &len) && len != 0) - options_total_length += ROUND_TO_4BYTE(4 + len); - } - have_options = TRUE; - } if (have_options) { /* End-of options tag */ options_total_length += 4; @@ -4323,40 +4421,8 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec, * 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 (rec->opt_comment) { - 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 */ - ws_debug("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; - - /* 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; - } - - ws_debug("Wrote Options comments: comment_len %u, comment_pad_len %u", - comment_len, comment_pad_len); - } - if (rec->custom_options != NULL) { - for (guint i = 0; i < rec->custom_options->len; i++) { - wtap_option_t option; - - option = g_array_index(rec->custom_options, wtap_option_t, i); - if ((option.option_id == OPT_CUSTOM_STR_COPY) || - (option.option_id == OPT_CUSTOM_BIN_COPY)) { - pcapng_write_custom_option(wdh, option.option_id, &option.value, err); - } - } + if (!wtap_block_foreach_option(rec->block, pcapng_write_option_cb, &block_data)) { + return FALSE; } if (rec->presence_flags & WTAP_HAS_PACK_FLAGS) { option_hdr.type = OPT_EPB_FLAGS; @@ -4406,36 +4472,6 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec, ws_debug("Wrote Options queue: %u", rec->rec_header.packet_header.interface_queue); } - if (rec->presence_flags & WTAP_HAS_VERDICT && rec->packet_verdict != NULL) { - - for(guint i = 0; i < rec->packet_verdict->len; i++) { - gsize len; - GBytes *verdict = (GBytes *) g_ptr_array_index(rec->packet_verdict, i); - const guint8 *verdict_data = (const guint8 *) g_bytes_get_data(verdict, &len); - - if (verdict_data && len != 0) { - - option_hdr.type = OPT_EPB_VERDICT; - option_hdr.value_length = (guint16) len; - if (!wtap_dump_file_write(wdh, &option_hdr, 4, err)) - return FALSE; - wdh->bytes_dumped += 4; - if (!wtap_dump_file_write(wdh, verdict_data, len, err)) - return FALSE; - wdh->bytes_dumped += len; - - if (ROUND_TO_4BYTE(len) != len) { - size_t plen = ROUND_TO_4BYTE(len) - len; - - if (!wtap_dump_file_write(wdh, &zero_pad, plen, err)) - return FALSE; - wdh->bytes_dumped += plen; - } - ws_debug("Wrote Options verdict: %u", - verdict_data[0]); - } - } - } /* Write end of options if we have options */ if (have_options) { if (!pcapng_write_option_eofopt(wdh, err)) @@ -5668,8 +5704,8 @@ static const struct supported_option_type decryption_secrets_block_options_suppo /* Options for packet blocks. */ static const struct supported_option_type packet_block_options_supported[] = { - /* XXX - pending use of wtap_block_t's for packets */ { OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }, + { OPT_EPB_VERDICT, MULTIPLE_OPTIONS_SUPPORTED }, { OPT_CUSTOM_STR_COPY, MULTIPLE_OPTIONS_SUPPORTED }, { OPT_CUSTOM_BIN_COPY, MULTIPLE_OPTIONS_SUPPORTED }, { OPT_CUSTOM_STR_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED }, |