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.
This commit is contained in:
parent
510c088ce6
commit
030b06ba3c
|
@ -36,6 +36,7 @@ libwiretap.so.0 libwiretap0 #MINVER#
|
|||
wtap_block_add_ipv4_option@Base 2.1.2
|
||||
wtap_block_add_ipv6_option@Base 2.1.2
|
||||
wtap_block_add_nflx_custom_option@Base 3.5.0
|
||||
wtap_block_add_packet_verdict_option@Base 3.5.1
|
||||
wtap_block_add_string_option@Base 2.1.2
|
||||
wtap_block_add_string_option_format@Base 2.1.2
|
||||
wtap_block_add_uint32_option@Base 3.5.0
|
||||
|
@ -53,15 +54,14 @@ libwiretap.so.0 libwiretap0 #MINVER#
|
|||
wtap_block_get_mandatory_data@Base 2.1.2
|
||||
wtap_block_get_nflx_custom_option@Base 3.5.0
|
||||
wtap_block_get_nth_bytes_option_value@Base 3.5.0
|
||||
wtap_block_get_nth_packet_verdict_option_value@Base 3.5.1
|
||||
wtap_block_get_nth_string_option_value@Base 2.1.2
|
||||
wtap_block_get_options_size_padded@Base 3.5.0
|
||||
wtap_block_get_string_option_value@Base 2.1.2
|
||||
wtap_block_get_type@Base 3.5.0
|
||||
wtap_block_get_uint32_option_value@Base 3.5.0
|
||||
wtap_block_get_uint64_option_value@Base 2.1.2
|
||||
wtap_block_get_uint8_option_value@Base 2.1.2
|
||||
wtap_block_make_copy@Base 3.3.2
|
||||
wtap_block_option_get_value_size@Base 3.5.0
|
||||
wtap_block_ref@Base 3.5.0
|
||||
wtap_block_remove_nth_option_instance@Base 2.2.0
|
||||
wtap_block_remove_option@Base 2.2.0
|
||||
|
@ -70,6 +70,7 @@ libwiretap.so.0 libwiretap0 #MINVER#
|
|||
wtap_block_set_ipv4_option_value@Base 2.1.2
|
||||
wtap_block_set_ipv6_option_value@Base 2.1.2
|
||||
wtap_block_set_nth_bytes_option_value@Base 3.5.0
|
||||
wtap_block_set_nth_packet_verdict_option_value@Base 3.5.1
|
||||
wtap_block_set_nth_string_option_value@Base 2.1.2
|
||||
wtap_block_set_nth_string_option_value_format@Base 3.5.0
|
||||
wtap_block_set_string_option_value@Base 2.1.2
|
||||
|
@ -151,6 +152,7 @@ libwiretap.so.0 libwiretap0 #MINVER#
|
|||
wtap_open_offline@Base 1.9.1
|
||||
wtap_opttypes_initialize@Base 2.1.2
|
||||
wtap_opttypes_cleanup@Base 2.3.0
|
||||
wtap_packet_verdict_free@Base 3.5.1
|
||||
wtap_pcap_encap_to_wtap_encap@Base 1.9.1
|
||||
wtap_pcap_file_type_subtype@Base 3.5.0
|
||||
wtap_pcap_nsec_file_type_subtype@Base 3.5.0
|
||||
|
|
433
wiretap/pcapng.c
433
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);
|
||||
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);
|
||||
default:
|
||||
/* Unknown options - size by datatype? */
|
||||
size = 0;
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
return ok;
|
||||
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 OPT_PKT_DROPCOUNT:
|
||||
if (!pcapng_write_uint64_option(wdh, OPT_EPB_DROPCOUNT, optval, err))
|
||||
return FALSE;
|
||||
break;
|
||||
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 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 */
|
||||
|
|
|
@ -143,6 +143,57 @@ static void if_filter_free(if_filter_opt_t* filter_src)
|
|||
}
|
||||
}
|
||||
|
||||
static packet_verdict_opt_t
|
||||
packet_verdict_dup(packet_verdict_opt_t* verdict_src)
|
||||
{
|
||||
packet_verdict_opt_t verdict_dest;
|
||||
|
||||
memset(&verdict_dest, 0, sizeof(verdict_dest));
|
||||
|
||||
/* Deep copy. */
|
||||
verdict_dest.type = verdict_src->type;
|
||||
switch (verdict_src->type) {
|
||||
|
||||
case packet_verdict_hardware:
|
||||
/* array of octets */
|
||||
verdict_dest.data.verdict_bytes =
|
||||
g_byte_array_new_take((guint8 *)g_memdup2(verdict_src->data.verdict_bytes->data,
|
||||
verdict_src->data.verdict_bytes->len),
|
||||
verdict_src->data.verdict_bytes->len);
|
||||
break;
|
||||
|
||||
case packet_verdict_linux_ebpf_tc:
|
||||
/* eBPF TC_ACT_ value */
|
||||
verdict_dest.data.verdict_linux_ebpf_tc =
|
||||
verdict_src->data.verdict_linux_ebpf_tc;
|
||||
break;
|
||||
|
||||
case packet_verdict_linux_ebpf_xdp:
|
||||
/* xdp_action value */
|
||||
verdict_dest.data.verdict_linux_ebpf_xdp =
|
||||
verdict_src->data.verdict_linux_ebpf_xdp;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return verdict_dest;
|
||||
}
|
||||
|
||||
void wtap_packet_verdict_free(packet_verdict_opt_t* verdict)
|
||||
{
|
||||
switch (verdict->type) {
|
||||
|
||||
case packet_verdict_hardware:
|
||||
/* array of bytes */
|
||||
g_byte_array_free(verdict->data.verdict_bytes, TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wtap_opttype_block_register(wtap_blocktype_t *blocktype)
|
||||
{
|
||||
wtap_block_type_t block_type;
|
||||
|
@ -309,6 +360,10 @@ static void wtap_block_free_option(wtap_block_t block, wtap_option_t *opt)
|
|||
}
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_PACKET_VERDICT:
|
||||
wtap_packet_verdict_free(&opt->value.packet_verdictval);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -449,6 +504,10 @@ wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_PACKET_VERDICT:
|
||||
wtap_block_add_packet_verdict_option(dest_block, src_opt->option_id, &src_opt->value.packet_verdictval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -462,109 +521,6 @@ wtap_block_t wtap_block_make_copy(wtap_block_t block)
|
|||
return block_copy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the (un-padded) size of the given option value, by its type.
|
||||
*/
|
||||
gsize
|
||||
wtap_block_option_get_value_size(wtap_opttype_e option_type, wtap_optval_t *option)
|
||||
{
|
||||
gsize ret_val = 0;
|
||||
|
||||
switch(option_type) {
|
||||
|
||||
case WTAP_OPTTYPE_UINT8:
|
||||
ret_val += 1;
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_UINT32:
|
||||
ret_val += 4;
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_UINT64:
|
||||
ret_val += 8;
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_IPv4:
|
||||
ret_val += 4;
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_IPv6:
|
||||
ret_val += IPv6_ADDR_SIZE;
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_STRING:
|
||||
ret_val += strlen(option->stringval);
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_BYTES:
|
||||
ret_val += g_bytes_get_size(option->byteval);
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_IF_FILTER:
|
||||
switch(option->if_filterval.type) {
|
||||
|
||||
case if_filter_pcap:
|
||||
ret_val += 1 + strlen(option->if_filterval.data.filter_str);
|
||||
break;
|
||||
|
||||
case if_filter_bpf:
|
||||
ret_val += 1 + (8 * option->if_filterval.data.bpf_prog.bpf_prog_len);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WTAP_OPTTYPE_CUSTOM:
|
||||
/* PEN */
|
||||
ret_val += sizeof(guint32);
|
||||
switch (option->custom_opt.pen) {
|
||||
case PEN_NFLX:
|
||||
/* NFLX type */
|
||||
ret_val += sizeof(guint32);
|
||||
ret_val += option->custom_opt.data.nflx_data.custom_data_len;
|
||||
break;
|
||||
default:
|
||||
ret_val += option->custom_opt.data.generic_data.custom_data_len;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the size of all options, padded to a 32-bit boundary.
|
||||
*/
|
||||
gsize
|
||||
wtap_block_get_options_size_padded(wtap_block_t block)
|
||||
{
|
||||
gsize ret_val = 0;
|
||||
gsize opt_size = 0;
|
||||
guint i;
|
||||
wtap_option_t *opt;
|
||||
const wtap_opttype_t *opttype;
|
||||
|
||||
if (block == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < block->options->len; i++)
|
||||
{
|
||||
|
||||
opt = &g_array_index(block->options, wtap_option_t, i);
|
||||
opttype = GET_OPTION_TYPE(block->info->options, opt->option_id);
|
||||
|
||||
opt_size = ROUND_TO_4BYTE(wtap_block_option_get_value_size(opttype->data_type, &opt->value));
|
||||
|
||||
/* pcapng.c silently skips over data that's too big to fit in an option.
|
||||
* Reflect that when calculating the size of our options.
|
||||
*/
|
||||
if (opt_size <= 0xffff) {
|
||||
ret_val += opt_size + 4; // 4 for size of type and length fields themselves
|
||||
}
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
guint
|
||||
wtap_block_count_option(wtap_block_t block, guint option_id)
|
||||
{
|
||||
|
@ -1428,6 +1384,50 @@ wtap_block_add_custom_option(wtap_block_t block, guint option_id, guint32 pen, c
|
|||
return WTAP_OPTTYPE_SUCCESS;
|
||||
}
|
||||
|
||||
wtap_opttype_return_val
|
||||
wtap_block_add_packet_verdict_option(wtap_block_t block, guint option_id, packet_verdict_opt_t* value)
|
||||
{
|
||||
wtap_opttype_return_val ret;
|
||||
wtap_option_t *opt;
|
||||
|
||||
ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_PACKET_VERDICT, &opt);
|
||||
if (ret != WTAP_OPTTYPE_SUCCESS)
|
||||
return ret;
|
||||
opt->value.packet_verdictval = packet_verdict_dup(value);
|
||||
return WTAP_OPTTYPE_SUCCESS;
|
||||
}
|
||||
|
||||
wtap_opttype_return_val
|
||||
wtap_block_set_nth_packet_verdict_option_value(wtap_block_t block, guint option_id, guint idx, packet_verdict_opt_t* value)
|
||||
{
|
||||
wtap_opttype_return_val ret;
|
||||
wtap_optval_t *optval;
|
||||
packet_verdict_opt_t prev_value;
|
||||
|
||||
ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_PACKET_VERDICT, idx, &optval);
|
||||
if (ret != WTAP_OPTTYPE_SUCCESS)
|
||||
return ret;
|
||||
prev_value = optval->packet_verdictval;
|
||||
optval->packet_verdictval = packet_verdict_dup(value);
|
||||
/* Free after memory is duplicated in case structure was manipulated with a "get then set" */
|
||||
wtap_packet_verdict_free(&prev_value);
|
||||
|
||||
return WTAP_OPTTYPE_SUCCESS;
|
||||
}
|
||||
|
||||
wtap_opttype_return_val
|
||||
wtap_block_get_nth_packet_verdict_option_value(wtap_block_t block, guint option_id, guint idx, packet_verdict_opt_t* value)
|
||||
{
|
||||
wtap_opttype_return_val ret;
|
||||
wtap_optval_t *optval;
|
||||
|
||||
ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
|
||||
if (ret != WTAP_OPTTYPE_SUCCESS)
|
||||
return ret;
|
||||
*value = optval->packet_verdictval;
|
||||
return WTAP_OPTTYPE_SUCCESS;
|
||||
}
|
||||
|
||||
wtap_opttype_return_val
|
||||
wtap_block_remove_option(wtap_block_t block, guint option_id)
|
||||
{
|
||||
|
@ -1849,8 +1849,7 @@ void wtap_opttypes_initialize(void)
|
|||
static const wtap_opttype_t pkt_verdict = {
|
||||
"verdict",
|
||||
"Packet Verdict",
|
||||
WTAP_OPTTYPE_BYTES, // maybe replace with a pkt_verdict_opt_t
|
||||
// (or maybe not, packet-frame.c reads the raw bytes)
|
||||
WTAP_OPTTYPE_PACKET_VERDICT,
|
||||
WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED
|
||||
};
|
||||
|
||||
|
|
|
@ -281,7 +281,8 @@ typedef enum {
|
|||
WTAP_OPTTYPE_IPv4,
|
||||
WTAP_OPTTYPE_IPv6,
|
||||
WTAP_OPTTYPE_IF_FILTER,
|
||||
WTAP_OPTTYPE_CUSTOM
|
||||
WTAP_OPTTYPE_CUSTOM,
|
||||
WTAP_OPTTYPE_PACKET_VERDICT
|
||||
} wtap_opttype_e;
|
||||
|
||||
typedef enum {
|
||||
|
@ -346,6 +347,26 @@ typedef struct custom_opt_s {
|
|||
} data;
|
||||
} custom_opt_t;
|
||||
|
||||
/* Packet - packet_verdict option structure */
|
||||
|
||||
/*
|
||||
* Type of verdict.
|
||||
*/
|
||||
typedef enum {
|
||||
packet_verdict_hardware = 0, /* array of octets */
|
||||
packet_verdict_linux_ebpf_tc = 1, /* 64-bit unsigned integer TC_ACT_ value */
|
||||
packet_verdict_linux_ebpf_xdp = 2 /* 64-bit unsigned integer xdp_action value */
|
||||
} packet_verdict_type_e;
|
||||
|
||||
typedef struct packet_verdict_opt_s {
|
||||
packet_verdict_type_e type;
|
||||
union {
|
||||
GByteArray *verdict_bytes;
|
||||
guint64 verdict_linux_ebpf_tc;
|
||||
guint64 verdict_linux_ebpf_xdp;
|
||||
} data;
|
||||
} packet_verdict_opt_t;
|
||||
|
||||
/*
|
||||
* Structure describing a NFLX custom option.
|
||||
*/
|
||||
|
@ -370,6 +391,7 @@ typedef union {
|
|||
GBytes *byteval;
|
||||
if_filter_opt_t if_filterval;
|
||||
custom_opt_t custom_opt;
|
||||
packet_verdict_opt_t packet_verdictval;
|
||||
} wtap_optval_t;
|
||||
|
||||
/*
|
||||
|
@ -977,6 +999,46 @@ wtap_block_get_nflx_custom_option(wtap_block_t block, guint32 nflx_type, char *n
|
|||
WS_DLL_PUBLIC wtap_opttype_return_val
|
||||
wtap_block_add_custom_option(wtap_block_t block, guint option_id, guint32 pen, const char *custom_data, gsize custom_data_len);
|
||||
|
||||
/** Add an packet_verdict option value to a block
|
||||
*
|
||||
* @param[in] block Block to which to add the option
|
||||
* @param[in] option_id Identifier value for option
|
||||
* @param[in] value Value of option
|
||||
* @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
|
||||
* error code otherwise
|
||||
*/
|
||||
WS_DLL_PUBLIC wtap_opttype_return_val
|
||||
wtap_block_add_packet_verdict_option(wtap_block_t block, guint option_id, packet_verdict_opt_t* value);
|
||||
|
||||
/** Set packet_verdict option value for the nth instsance of a particular
|
||||
* option in a block
|
||||
*
|
||||
* @param[in] block Block in which to set the option value
|
||||
* @param[in] option_id Identifier value for option
|
||||
* @param[in] idx Instance number of option with that ID
|
||||
* @param[in] value New value of option
|
||||
* @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
|
||||
* error code otherwise
|
||||
*/
|
||||
WS_DLL_PUBLIC wtap_opttype_return_val
|
||||
wtap_block_set_nth_packet_verdict_option_value(wtap_block_t block, guint option_id, guint idx, packet_verdict_opt_t* value);
|
||||
|
||||
/** Get packet_verdict option value for the nth instance of a particular
|
||||
* option in a block
|
||||
*
|
||||
* @param[in] block Block from which to get the option value
|
||||
* @param[in] option_id Identifier value for option
|
||||
* @param[in] idx Instance number of option with that ID
|
||||
* @param[out] value Returned value of option value
|
||||
* @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
|
||||
* error code otherwise
|
||||
*/
|
||||
WS_DLL_PUBLIC wtap_opttype_return_val
|
||||
wtap_block_get_nth_packet_verdict_option_value(wtap_block_t block, guint option_id, guint idx, packet_verdict_opt_t* value) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
WS_DLL_PUBLIC void
|
||||
wtap_packet_verdict_free(packet_verdict_opt_t* verdict);
|
||||
|
||||
/** Remove an option from a block
|
||||
*
|
||||
* @param[in] block Block from which to remove the option
|
||||
|
@ -998,26 +1060,6 @@ wtap_block_remove_option(wtap_block_t block, guint option_id);
|
|||
WS_DLL_PUBLIC wtap_opttype_return_val
|
||||
wtap_block_remove_nth_option_instance(wtap_block_t block, guint option_id, guint idx);
|
||||
|
||||
/**
|
||||
* Get the original (unpadded) length of an option's value
|
||||
*
|
||||
* @param[in] option_type The `wtap_opttype_e` for this option
|
||||
* @param[in] option The option's value to measure
|
||||
* @return gsize - the number of bytes occupied by the option's value
|
||||
*/
|
||||
WS_DLL_PUBLIC gsize
|
||||
wtap_block_option_get_value_size(wtap_opttype_e option_type, wtap_optval_t *option);
|
||||
|
||||
/** Get the padded length of all options in the block
|
||||
*
|
||||
* @param[in] block Block from which to remove the option instance
|
||||
* @return gsize - size in bytes of all options, each padded to 32 bits
|
||||
* @note The size of any options with values larger than can be held in an option
|
||||
* is NOT included, because pcapng.c skips over such option values.
|
||||
*/
|
||||
WS_DLL_PUBLIC gsize
|
||||
wtap_block_get_options_size_padded(wtap_block_t block);
|
||||
|
||||
/** Copy a block to another.
|
||||
*
|
||||
* Any options that are in the destination but not the source are not removed.
|
||||
|
|
Loading…
Reference in New Issue