pcapng: add support for custom options

This commit is contained in:
Michael Tuexen 2021-06-21 16:56:58 +02:00 committed by Wireshark GitLab Utility
parent c9f4bbc11c
commit 1f0a16e472
6 changed files with 501 additions and 134 deletions

View File

@ -22,6 +22,7 @@ libwiretap.so.0 libwiretap0 #MINVER#
register_pcapng_option_handler@Base 1.99.2
wtap_add_generated_idb@Base 3.3.0
wtap_addrinfo_list_empty@Base 2.5.0
wtap_block_add_custom_option@Base 3.5.0
wtap_block_add_if_filter_option@Base 3.5.0
wtap_block_add_ipv4_option@Base 2.1.2
wtap_block_add_ipv6_option@Base 2.1.2

View File

@ -589,6 +589,59 @@ 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,
const guint8 *option_content,
int *err, gchar **err_info)
{
guint32 pen;
if (option_length < 4) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcapng: option length (%d) too small for custom option",
option_length);
return FALSE;
}
memcpy(&pen, option_content, sizeof(guint32));
if (section_info->byte_swapped) {
pen = GUINT32_SWAP_LE_BE(pen);
}
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)) {
return FALSE;
}
break;
}
return TRUE;
}
#ifdef HAVE_PLUGINS
static gboolean
pcapng_process_unhandled_option(wtapng_block_t *wblock,
@ -712,6 +765,19 @@ pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
/* padding should be ok here, just get out of this */
opt_bytes_remaining = 0;
break;
case(OPT_CUSTOM_STR_COPY):
case(OPT_CUSTOM_BIN_COPY):
case(OPT_CUSTOM_STR_NO_COPY):
case(OPT_CUSTOM_BIN_NO_COPY):
if (!pcapng_process_custom_option(wblock, section_info,
option_code, option_length,
option_ptr,
err, err_info)) {
g_free(option_content);
return FALSE;
}
break;
default:
if (!(*process_option)(wblock, section_info, option_code,
option_length, option_ptr,
@ -1553,6 +1619,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;
/* "(Enhanced) Packet Block" read fixed part */
if (enhanced) {
@ -1742,6 +1810,15 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh,
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;
@ -1790,6 +1867,8 @@ 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?
@ -1889,6 +1968,15 @@ pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh,
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,
@ -3466,6 +3554,25 @@ static guint32 pcapng_compute_option_string_size(char *str)
return size;
}
static guint32 pcapng_compute_custom_option_size(size_t custom_data_len)
{
size_t size, pad;
size = custom_data_len + sizeof(guint32);
if (size > 65535) {
size = 65535;
}
if ((size % 4)) {
pad = 4 - (size % 4);
} else {
pad = 0;
}
size += pad;
return (guint32)size;
}
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;
@ -3479,6 +3586,10 @@ static void compute_shb_option_size(wtap_block_t block _U_, guint option_id, wta
case OPT_SHB_USERAPPL:
size = pcapng_compute_option_string_size(optval->stringval);
break;
case OPT_CUSTOM_STR_COPY:
case OPT_CUSTOM_BIN_COPY:
size = pcapng_compute_custom_option_size(optval->custom_opt.custom_data_len);
break;
default:
/* Unknown options - size by datatype? */
break;
@ -3504,6 +3615,59 @@ typedef struct pcapng_write_block_t
}
pcapng_write_block_t;
static gboolean pcapng_write_custom_option(wtap_dumper *wdh, guint option_id, custom_opt_t *custom_option, int *err)
{
struct pcapng_option_header option_hdr;
const guint32 zero_pad = 0;
size_t pad;
if ((option_id == OPT_CUSTOM_STR_NO_COPY) ||
(option_id == OPT_CUSTOM_BIN_NO_COPY))
return TRUE;
if (custom_option->custom_data_len + sizeof(guint32) > 65535) {
/*
* Too big to fit in the option.
* Don't write anything.
*
* XXX - truncate it? Report an error?
*/
return TRUE;
}
/* write option header */
option_hdr.type = (guint16)option_id;
option_hdr.value_length = (guint16)(custom_option->custom_data_len + sizeof(guint32));
if (!wtap_dump_file_write(wdh, &option_hdr, sizeof(struct pcapng_option_header), err))
return FALSE;
wdh->bytes_dumped += sizeof(struct pcapng_option_header);
/* write PEN */
if (!wtap_dump_file_write(wdh, &custom_option->pen, sizeof(guint32), err))
return FALSE;
wdh->bytes_dumped += sizeof(guint32);
/* write custom data */
if (!wtap_dump_file_write(wdh, custom_option->custom_data, custom_option->custom_data_len, err))
return FALSE;
wdh->bytes_dumped += custom_option->custom_data_len;
/* write padding (if any) */
if ((custom_option->custom_data_len % 4)) {
pad = 4 - (custom_option->custom_data_len % 4);
} else {
pad = 0;
}
if (pad != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, pad, err))
return FALSE;
wdh->bytes_dumped += pad;
}
ws_debug("Wrote custom option: type %u, length %u", option_hdr.type, option_hdr.value_length);
return TRUE;
}
static gboolean pcapng_write_option_string(wtap_dumper *wdh, guint option_id, char *str, int *err)
{
struct pcapng_option_header option_hdr;
@ -3632,6 +3796,13 @@ static void write_wtap_shb_option(wtap_block_t block _U_, guint option_id, wtap_
return;
}
break;
case OPT_CUSTOM_STR_COPY:
case OPT_CUSTOM_BIN_COPY:
if (!pcapng_write_custom_option(write_block->wdh, option_id, &optval->custom_opt, write_block->err)) {
write_block->success = FALSE;
return;
}
break;
default:
/* Unknown options - write by datatype? */
break;
@ -3768,6 +3939,18 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
}
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.custom_opt.custom_data_len) + 4;
}
}
}
if (rec->presence_flags & WTAP_HAS_PACK_FLAGS) {
have_options = TRUE;
options_total_length = options_total_length + 8;
@ -3877,53 +4060,56 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
/* 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.
*
* 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.
* 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 (rec->opt_comment) {
option_hdr.type = OPT_COMMENT;
@ -3949,6 +4135,17 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
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.custom_opt, err);
}
}
}
if (rec->presence_flags & WTAP_HAS_PACK_FLAGS) {
option_hdr.type = OPT_EPB_FLAGS;
option_hdr.value_length = 4;
@ -4346,6 +4543,10 @@ compute_nrb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e
case OPT_NS_DNSNAME:
size = pcapng_compute_option_string_size(optval->stringval);
break;
case OPT_CUSTOM_STR_COPY:
case OPT_CUSTOM_BIN_COPY:
size = pcapng_compute_custom_option_size(optval->custom_opt.custom_data_len);
break;
case OPT_NS_DNSIP4ADDR:
size = 4;
break;
@ -4397,6 +4598,33 @@ put_nrb_option(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_ty
pad = 0;
}
/* put padding (if any) */
if (pad != 0) {
memset(*opt_ptrp, 0, pad);
*opt_ptrp += pad;
}
break;
case OPT_CUSTOM_STR_COPY:
case OPT_CUSTOM_BIN_COPY:
/* Custom options don't consider pad bytes part of the length */
size = (guint32)(optval->custom_opt.custom_data_len + sizeof(guint32)) & 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->custom_opt.pen, sizeof(guint32));
*opt_ptrp += sizeof(guint32);
memcpy(*opt_ptrp, optval->custom_opt.custom_data, 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);
@ -4726,6 +4954,10 @@ static void compute_isb_option_size(wtap_block_t block _U_, guint option_id, wta
case OPT_COMMENT:
size = pcapng_compute_option_string_size(optval->stringval);
break;
case OPT_CUSTOM_STR_COPY:
case OPT_CUSTOM_BIN_COPY:
size = pcapng_compute_custom_option_size(optval->custom_opt.custom_data_len);
break;
case OPT_ISB_STARTTIME:
case OPT_ISB_ENDTIME:
size = 8;
@ -4770,6 +5002,13 @@ static void write_wtap_isb_option(wtap_block_t block _U_, guint option_id, wtap_
return;
}
break;
case OPT_CUSTOM_STR_COPY:
case OPT_CUSTOM_BIN_COPY:
if (!pcapng_write_custom_option(write_block->wdh, option_id, &optval->custom_opt, write_block->err)) {
write_block->success = FALSE;
return;
}
break;
case OPT_ISB_STARTTIME:
case OPT_ISB_ENDTIME:
if (!pcapng_write_option_timestamp(write_block->wdh, option_id, optval->uint64val, write_block->err)) {
@ -4872,6 +5111,10 @@ static void compute_idb_option_size(wtap_block_t block _U_, guint option_id, wta
case OPT_IDB_HARDWARE:
size = pcapng_compute_option_string_size(optval->stringval);
break;
case OPT_CUSTOM_STR_COPY:
case OPT_CUSTOM_BIN_COPY:
size = pcapng_compute_custom_option_size(optval->custom_opt.custom_data_len);
break;
case OPT_IDB_SPEED:
size = 8;
break;
@ -4936,6 +5179,13 @@ static void write_wtap_idb_option(wtap_block_t block _U_, guint option_id, wtap_
return;
}
break;
case OPT_CUSTOM_STR_COPY:
case OPT_CUSTOM_BIN_COPY:
if (!pcapng_write_custom_option(write_block->wdh, option_id, &optval->custom_opt, write_block->err)) {
write_block->success = FALSE;
return;
}
break;
case OPT_IDB_SPEED:
if (!pcapng_write_option_uint64(write_block->wdh, option_id, optval->uint64val, write_block->err)) {
write_block->success = FALSE;
@ -5377,6 +5627,10 @@ gboolean pcapng_encap_is_ft_specific(int encap)
/* Options for section blocks. */
static const struct supported_option_type section_block_options_supported[] = {
{ OPT_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_SHB_HARDWARE, ONE_OPTION_SUPPORTED },
{ OPT_SHB_USERAPPL, ONE_OPTION_SUPPORTED }
};
@ -5384,6 +5638,10 @@ static const struct supported_option_type section_block_options_supported[] = {
/* Options for interface blocks. */
static const struct supported_option_type interface_block_options_supported[] = {
{ OPT_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_IDB_NAME, ONE_OPTION_SUPPORTED },
{ OPT_IDB_DESCR, ONE_OPTION_SUPPORTED },
{ OPT_IDB_IP4ADDR, MULTIPLE_OPTIONS_SUPPORTED },
@ -5403,6 +5661,10 @@ static const struct supported_option_type interface_block_options_supported[] =
/* Options for name resolution blocks. */
static const struct supported_option_type name_resolution_block_options_supported[] = {
{ OPT_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_NS_DNSNAME, ONE_OPTION_SUPPORTED },
{ OPT_NS_DNSIP4ADDR, ONE_OPTION_SUPPORTED },
{ OPT_NS_DNSIP6ADDR, ONE_OPTION_SUPPORTED }
@ -5411,6 +5673,10 @@ static const struct supported_option_type name_resolution_block_options_supporte
/* Options for interface statistics blocks. */
static const struct supported_option_type interface_statistics_block_options_supported[] = {
{ OPT_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED },
{ OPT_ISB_STARTTIME, ONE_OPTION_SUPPORTED },
{ OPT_ISB_ENDTIME, ONE_OPTION_SUPPORTED },
{ OPT_ISB_IFRECV, ONE_OPTION_SUPPORTED },
@ -5422,28 +5688,48 @@ static const struct supported_option_type interface_statistics_block_options_sup
/* Options for decryption secrets blocks. */
static const struct supported_option_type decryption_secrets_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
{ OPT_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED }
};
/* 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_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for file-type-sepcific reports. */
static const struct supported_option_type ft_specific_report_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
{ OPT_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for file-type-sepcific event. */
static const struct supported_option_type ft_specific_event_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
{ OPT_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED }
};
/* Options for systemd journal entry. */
static const struct supported_option_type systemd_journal_export_block_options_supported[] = {
{ OPT_COMMENT, MULTIPLE_OPTIONS_SUPPORTED }
{ OPT_COMMENT, 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 },
{ OPT_CUSTOM_BIN_NO_COPY, MULTIPLE_OPTIONS_SUPPORTED }
};
static const struct supported_block_type pcapng_blocks_supported[] = {

View File

@ -1664,6 +1664,9 @@ wtap_rec_init(wtap_rec *rec)
void
wtap_rec_cleanup(wtap_rec *rec)
{
wtap_option_t option;
guint i;
g_free(rec->opt_comment);
rec->opt_comment = NULL;
ws_buffer_free(&rec->options_buf);
@ -1671,6 +1674,15 @@ wtap_rec_cleanup(wtap_rec *rec)
g_ptr_array_free(rec->packet_verdict, TRUE);
rec->packet_verdict = NULL;
}
if (rec->custom_options != NULL) {
for (i = 0; i < rec->custom_options->len; i++) {
option = g_array_index(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(rec->custom_options, TRUE);
rec->custom_options = NULL;
}
}
gboolean

View File

@ -1352,6 +1352,7 @@ typedef struct {
but due to the way the current code is
reusing the wtap_rec structure, it's
impossible to nicely clean it up. */
GArray *custom_options; /* Array of generic custom options of EPBs */
/*
* We use a Buffer so that we don't have to allocate and free
* a buffer for the options for each record.

View File

@ -117,6 +117,12 @@ static void wtap_opttype_block_register(wtap_blocktype_t *blocktype)
WTAP_OPTTYPE_STRING,
WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED
};
static const wtap_opttype_t opt_custom = {
"opt_custom",
"Custom Option",
WTAP_OPTTYPE_CUSTOM,
WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED
};
block_type = blocktype->block_type;
@ -133,7 +139,8 @@ static void wtap_opttype_block_register(wtap_blocktype_t *blocktype)
/*
* Initialize the set of supported options.
* All blocks that support options at all support OPT_COMMENT.
* All blocks that support options at all support
* OPT_COMMENT and OPT_CUSTOM.
*
* XXX - there's no "g_uint_hash()" or "g_uint_equal()",
* so we use "g_direct_hash()" and "g_direct_equal()".
@ -141,6 +148,14 @@ static void wtap_opttype_block_register(wtap_blocktype_t *blocktype)
blocktype->options = g_hash_table_new(g_direct_hash, g_direct_equal);
g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_COMMENT),
(gpointer)&opt_comment);
g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_CUSTOM_STR_COPY),
(gpointer)&opt_custom);
g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_CUSTOM_BIN_COPY),
(gpointer)&opt_custom);
g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_CUSTOM_STR_NO_COPY),
(gpointer)&opt_custom);
g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_CUSTOM_BIN_NO_COPY),
(gpointer)&opt_custom);
blocktype_list[block_type] = blocktype;
}
@ -226,6 +241,10 @@ static void wtap_block_free_option(wtap_block_t block, wtap_option_t *opt)
if_filter_free(&opt->value.if_filterval);
break;
case WTAP_OPTTYPE_CUSTOM:
g_free(opt->value.custom_opt.custom_data);
break;
default:
break;
}
@ -318,6 +337,10 @@ wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block)
case WTAP_OPTTYPE_IF_FILTER:
wtap_block_add_if_filter_option(dest_block, src_opt->option_id, &src_opt->value.if_filterval);
break;
case WTAP_OPTTYPE_CUSTOM:
wtap_block_add_custom_option(dest_block, src_opt->option_id, src_opt->value.custom_opt.pen, src_opt->value.custom_opt.custom_data, src_opt->value.custom_opt.custom_data_len);
break;
}
}
}
@ -828,6 +851,21 @@ wtap_block_get_if_filter_option_value(wtap_block_t block, guint option_id, if_fi
return WTAP_OPTTYPE_SUCCESS;
}
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)
{
wtap_opttype_return_val ret;
wtap_option_t *opt;
ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_CUSTOM, &opt);
if (ret != WTAP_OPTTYPE_SUCCESS)
return ret;
opt->value.custom_opt.pen = pen;
opt->value.custom_opt.custom_data_len = custom_data_len;
opt->value.custom_opt.custom_data = g_memdup2(custom_data, custom_data_len);
return WTAP_OPTTYPE_SUCCESS;
}
wtap_opttype_return_val
wtap_block_remove_option(wtap_block_t block, guint option_id)
{

View File

@ -23,90 +23,94 @@ extern "C" {
*/
/* Options for all blocks */
#define OPT_EOFOPT 0 /**< Appears in pcapng files, but not in blocks. */
#define OPT_COMMENT 1 /**< A UTF-8 string containing a human-readable comment. */
#define OPT_EOFOPT 0 /**< Appears in pcapng files, but not in blocks. */
#define OPT_COMMENT 1 /**< A UTF-8 string containing a human-readable comment. */
#define OPT_CUSTOM_STR_COPY 2988 /**< A custom option containing a string, copying allowed. */
#define OPT_CUSTOM_BIN_COPY 2989 /**< A custom option containing binary data, copying allowed. */
#define OPT_CUSTOM_STR_NO_COPY 19372 /**< A custom option containing binary data, copying not allowed. */
#define OPT_CUSTOM_BIN_NO_COPY 19373 /**< A custom option containing binary data, copying not allowed. */
/* Section Header block (SHB) */
#define OPT_SHB_HARDWARE 2 /**< A UTF-8 string containing the description of the
* hardware used to create this section.
*/
#define OPT_SHB_OS 3 /**< A UTF-8 string containing the
* name of the operating system used to create this section.
*/
#define OPT_SHB_USERAPPL 4 /**< A UTF-8 string containing the
* name of the application used to create this section.
*/
#define OPT_SHB_HARDWARE 2 /**< A UTF-8 string containing the description of the
* hardware used to create this section.
*/
#define OPT_SHB_OS 3 /**< A UTF-8 string containing the
* name of the operating system used to create this section.
*/
#define OPT_SHB_USERAPPL 4 /**< A UTF-8 string containing the
* name of the application used to create this section.
*/
/* Interface Description block (IDB) */
#define OPT_IDB_NAME 2 /**< A UTF-8 string containing the name
* of the device used to capture data.
* "eth0" / "\Device\NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68}"
*/
#define OPT_IDB_DESCR 3 /**< A UTF-8 string containing the description
* of the device used to capture data.
* "Wi-Fi" / "Local Area Connection" /
* "Wireless Network Connection" /
* "First Ethernet Interface"
*/
#define OPT_IDB_IP4ADDR 4 /**< XXX: if_IPv4addr Interface network address and netmask.
* This option can be repeated multiple times within the same Interface Description Block
* when multiple IPv4 addresses are assigned to the interface.
* 192 168 1 1 255 255 255 0
*/
#define OPT_IDB_IP6ADDR 5 /* XXX: if_IPv6addr Interface network address and prefix length (stored in the last byte).
* This option can be repeated multiple times within the same Interface
* Description Block when multiple IPv6 addresses are assigned to the interface.
* 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as
* "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"*/
#define OPT_IDB_MACADDR 6 /* XXX: if_MACaddr Interface Hardware MAC address (48 bits). */
#define OPT_IDB_EUIADDR 7 /* XXX: if_EUIaddr Interface Hardware EUI address (64 bits) */
#define OPT_IDB_SPEED 8 /**< Interface speed (in bps). 100000000 for 100Mbps
*/
#define OPT_IDB_TSRESOL 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 (e.g. 6 means microsecond resolution, timestamps
* are the number of microseconds since 1/1/1970). If the Most Significant Bit
* is equal to one, the remaining bits indicates the resolution has a
* negative power of 2 (e.g. 10 means 1/1024 of second).
* If this option is not present, a resolution of 10^-6 is assumed
* (i.e. timestamps have the same resolution of the standard 'libpcap' timestamps).
*/
#define OPT_IDB_TZONE 10 /* XXX: if_tzone Time zone for GMT support (TODO: specify better). */
#define OPT_IDB_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).
* More details about this format will be presented in Appendix XXX (TODO).
* (TODO: better use different options for different fields?
* e.g. if_filter_pcap, if_filter_bpf, ...) 00 "tcp port 23 and host 10.0.0.5"
*/
#define OPT_IDB_OS 12 /**< A UTF-8 string containing the name of the operating system of the
* machine in which this interface is installed.
* This can be different from the same information that can be
* contained by the Section Header Block
* (Section 3.1 (Section Header Block (mandatory))) because
* the capture can have been done on a remote machine.
* "Windows XP SP2" / "openSUSE 10.2"
*/
#define OPT_IDB_FCSLEN 13 /**< An integer value that specified the length of the
* Frame Check Sequence (in bits) for this interface.
* For link layers whose FCS length can change during time,
* the Packet Block Flags Word can be used (see Appendix A (Packet Block Flags Word))
*/
#define OPT_IDB_TSOFFSET 14 /**< XXX: 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. The time zone of the offset can be specified with the
* option if_tzone. TODO: won't a if_tsoffset_low for fractional
* second offsets be useful for highly synchronized capture systems?
*/
#define OPT_IDB_HARDWARE 15 /**< A UTF-8 string containing the description
* of the hardware of the device used
* to capture data.
* "Broadcom NetXtreme" /
* "Intel(R) PRO/1000 MT Network Connection" /
* "NETGEAR WNA1000Mv2 N150 Wireless USB Micro Adapter"
*/
#define OPT_IDB_NAME 2 /**< A UTF-8 string containing the name
* of the device used to capture data.
* "eth0" / "\Device\NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68}"
*/
#define OPT_IDB_DESCR 3 /**< A UTF-8 string containing the description
* of the device used to capture data.
* "Wi-Fi" / "Local Area Connection" /
* "Wireless Network Connection" /
* "First Ethernet Interface"
*/
#define OPT_IDB_IP4ADDR 4 /**< XXX: if_IPv4addr Interface network address and netmask.
* This option can be repeated multiple times within the same Interface Description Block
* when multiple IPv4 addresses are assigned to the interface.
* 192 168 1 1 255 255 255 0
*/
#define OPT_IDB_IP6ADDR 5 /**< XXX: if_IPv6addr Interface network address and prefix length (stored in the last byte).
* This option can be repeated multiple times within the same Interface
* Description Block when multiple IPv6 addresses are assigned to the interface.
* 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as
* "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
*/
#define OPT_IDB_MACADDR 6 /**< XXX: if_MACaddr Interface Hardware MAC address (48 bits). */
#define OPT_IDB_EUIADDR 7 /**< XXX: if_EUIaddr Interface Hardware EUI address (64 bits) */
#define OPT_IDB_SPEED 8 /**< Interface speed (in bps). 100000000 for 100Mbps
*/
#define OPT_IDB_TSRESOL 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 (e.g. 6 means microsecond resolution, timestamps
* are the number of microseconds since 1/1/1970). If the Most Significant Bit
* is equal to one, the remaining bits indicates the resolution has a
* negative power of 2 (e.g. 10 means 1/1024 of second).
* If this option is not present, a resolution of 10^-6 is assumed
* (i.e. timestamps have the same resolution of the standard 'libpcap' timestamps).
*/
#define OPT_IDB_TZONE 10 /**< XXX: if_tzone Time zone for GMT support (TODO: specify better). */
#define OPT_IDB_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).
* More details about this format will be presented in Appendix XXX (TODO).
* (TODO: better use different options for different fields?
* e.g. if_filter_pcap, if_filter_bpf, ...) 00 "tcp port 23 and host 10.0.0.5"
*/
#define OPT_IDB_OS 12 /**< A UTF-8 string containing the name of the operating system of the
* machine in which this interface is installed.
* This can be different from the same information that can be
* contained by the Section Header Block
* (Section 3.1 (Section Header Block (mandatory))) because
* the capture can have been done on a remote machine.
* "Windows XP SP2" / "openSUSE 10.2"
*/
#define OPT_IDB_FCSLEN 13 /**< An integer value that specified the length of the
* Frame Check Sequence (in bits) for this interface.
* For link layers whose FCS length can change during time,
* the Packet Block Flags Word can be used (see Appendix A (Packet Block Flags Word))
*/
#define OPT_IDB_TSOFFSET 14 /**< XXX: 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. The time zone of the offset can be specified with the
* option if_tzone. TODO: won't a if_tsoffset_low for fractional
* second offsets be useful for highly synchronized capture systems?
*/
#define OPT_IDB_HARDWARE 15 /**< A UTF-8 string containing the description
* of the hardware of the device used
* to capture data.
* "Broadcom NetXtreme" /
* "Intel(R) PRO/1000 MT Network Connection" /
* "NETGEAR WNA1000Mv2 N150 Wireless USB Micro Adapter"
*/
#define OPT_NS_DNSNAME 2
@ -241,7 +245,8 @@ typedef enum {
WTAP_OPTTYPE_STRING,
WTAP_OPTTYPE_IPv4,
WTAP_OPTTYPE_IPv6,
WTAP_OPTTYPE_IF_FILTER
WTAP_OPTTYPE_IF_FILTER,
WTAP_OPTTYPE_CUSTOM
} wtap_opttype_e;
typedef enum {
@ -282,6 +287,16 @@ typedef struct if_filter_opt_s {
} data;
} if_filter_opt_t;
/*
* Structure describing a custom option.
*/
typedef struct custom_opt_s {
guint32 pen;
gsize custom_data_len;
gchar *custom_data;
} custom_opt_t;
/*
* Structure describing a value of an option.
*/
@ -292,6 +307,7 @@ typedef union {
ws_in6_addr ipv6val;
char *stringval;
if_filter_opt_t if_filterval;
custom_opt_t custom_opt;
} wtap_optval_t;
/*
@ -620,6 +636,19 @@ wtap_block_set_if_filter_option_value(wtap_block_t block, guint option_id, if_fi
WS_DLL_PUBLIC wtap_opttype_return_val
wtap_block_get_if_filter_option_value(wtap_block_t block, guint option_id, if_filter_opt_t* value) G_GNUC_WARN_UNUSED_RESULT;
/** Add an custom option to a block
*
* @param[in] block Block to which to add the option
* @param[in] option_id Identifier value for option
* @param[in] pen PEN
* @param[in] custom_data pointer to the data
* @param[in] custom_data_len length of custom_data
* @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
* error code otherwise
*/
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);
/** Remove an option from a block
*
* @param[in] block Block from which to remove the option