Improve wiretap block capabilities.

Make a more formal method for registering options within a block and do it all with a single function (wtap_optionblock_add_block).
Add ability for block to be able to write itself, refactored out of pcapng.c.  This was implemented for SHB, ISB, and IDB blocks.  Name resolution (NRB), while possible, seemed a little messy for the moment.

Change-Id: Ie855c8550c7c7d96cfc188c0cd90bfbc4d5f0ee8
Reviewed-on: https://code.wireshark.org/review/14357
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
Michael Mann 2016-03-04 08:52:48 -05:00
parent 32d60ac2f5
commit f2de3c7778
4 changed files with 733 additions and 1072 deletions

View File

@ -56,15 +56,6 @@ pcapng_seek_read(wtap *wth, gint64 seek_off,
static void
pcapng_close(wtap *wth);
/* pcapng: common block header file encoding for every block type */
typedef struct pcapng_block_header_s {
guint32 block_type;
guint32 block_total_length;
/* x bytes block_body */
/* guint32 block_total_length */
} pcapng_block_header_t;
/*
* Minimum block size = size of block header + size of block trailer.
*/
@ -82,34 +73,11 @@ typedef struct pcapng_block_header_s {
*/
#define MAX_BLOCK_SIZE (16*1024*1024)
/* pcapng: section header block file encoding */
typedef struct pcapng_section_header_block_s {
/* pcapng_block_header_t */
guint32 magic;
guint16 version_major;
guint16 version_minor;
guint64 section_length; /* might be -1 for unknown */
/* ... Options ... */
} pcapng_section_header_block_t;
/*
* Minimum SHB size = minimum block size + size of fixed length portion of SHB.
*/
#define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
/* pcapng: interface description block file encoding */
typedef struct pcapng_interface_description_block_s {
guint16 linktype;
guint16 reserved;
guint32 snaplen;
/* ... Options ... */
} pcapng_interface_description_block_t;
/*
* Minimum IDB size = minimum block size + size of fixed length portion of IDB.
*/
#define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
/* pcapng: packet block file encoding (obsolete) */
typedef struct pcapng_packet_block_s {
guint16 interface_id;
@ -170,14 +138,6 @@ typedef struct pcapng_name_resolution_block_s {
*/
#define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
/* pcapng: interface statistics block file encoding */
typedef struct pcapng_interface_statistics_block_s {
guint32 interface_id;
guint32 timestamp_high;
guint32 timestamp_low;
/* ... Options ... */
} pcapng_interface_statistics_block_t;
/*
* Minimum ISB size = minimum block size + size of fixed length portion of ISB.
*/
@ -2739,85 +2699,25 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
{
pcapng_block_header_t bh;
pcapng_section_header_block_t shb;
const guint32 zero_pad = 0;
gboolean have_options = FALSE;
struct option option_hdr; /* guint16 type, guint16 value_length; */
guint32 options_total_length = 0;
guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
char *opt_comment, *shb_hardware, *shb_os, *shb_user_appl;
if (wdh->shb_hdr) {
pcapng_debug("pcapng_write_section_header_block: Have shb_hdr");
/* Check if we should write comment option */
wtap_optionblock_get_option_string(wdh->shb_hdr, OPT_COMMENT, &opt_comment);
if (opt_comment) {
have_options = TRUE;
comment_len = (guint32)strlen(opt_comment) & 0xffff;
if ((comment_len % 4)) {
comment_pad_len = 4 - (comment_len % 4);
} else {
comment_pad_len = 0;
}
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
/* Check if we should write shb_hardware option */
wtap_optionblock_get_option_string(wdh->shb_hdr, OPT_SHB_HARDWARE, &shb_hardware);
if (shb_hardware) {
have_options = TRUE;
shb_hardware_len = (guint32)strlen(shb_hardware) & 0xffff;
if ((shb_hardware_len % 4)) {
shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
} else {
shb_hardware_pad_len = 0;
}
options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
}
/* Check if we should write shb_os option */
wtap_optionblock_get_option_string(wdh->shb_hdr, OPT_SHB_OS, &shb_os);
if (shb_os) {
have_options = TRUE;
shb_os_len = (guint32)strlen(shb_os) & 0xffff;
if ((shb_os_len % 4)) {
shb_os_pad_len = 4 - (shb_os_len % 4);
} else {
shb_os_pad_len = 0;
}
options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
}
/* Check if we should write shb_user_appl option */
wtap_optionblock_get_option_string(wdh->shb_hdr, OPT_SHB_USERAPPL, &shb_user_appl);
if (shb_user_appl) {
have_options = TRUE;
shb_user_appl_len = (guint32)strlen(shb_user_appl) & 0xffff;
if ((shb_user_appl_len % 4)) {
shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
} else {
shb_user_appl_pad_len = 0;
}
options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
}
if (have_options) {
/* End-of-options tag */
options_total_length += 4;
}
return wtap_optionblock_write(wdh, wdh->shb_hdr, err);
}
/* we don't have a section block header already, so create a default one with no options */
/* write block header */
bh.block_type = BLOCK_TYPE_SHB;
bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
pcapng_debug("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + 4);
pcapng_debug("pcapng_write_section_header_block: Total len %u", bh.block_total_length);
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
return FALSE;
wdh->bytes_dumped += sizeof bh;
/* write block fixed content */
/* XXX - get these values from wblock? */
shb.magic = 0x1A2B3C4D;
shb.version_major = 1;
shb.version_minor = 0;
@ -2827,106 +2727,6 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
return FALSE;
wdh->bytes_dumped += sizeof shb;
/* XXX - write (optional) block options
* opt_comment 1
* shb_hardware 2
* shb_os 3
* shb_user_appl 4
*/
if (comment_len) {
option_hdr.type = OPT_COMMENT;
option_hdr.value_length = comment_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the comments string */
pcapng_debug("pcapng_write_section_header_block, comment:'%s' comment_len %u comment_pad_len %u" , opt_comment, comment_len, comment_pad_len);
if (!wtap_dump_file_write(wdh, opt_comment, comment_len, err))
return FALSE;
wdh->bytes_dumped += comment_len;
/* write padding (if any) */
if (comment_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
return FALSE;
wdh->bytes_dumped += comment_pad_len;
}
}
if (shb_hardware_len) {
option_hdr.type = OPT_SHB_HARDWARE;
option_hdr.value_length = shb_hardware_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the string */
pcapng_debug("pcapng_write_section_header_block, shb_hardware:'%s' shb_hardware_len %u shb_hardware_pad_len %u" , shb_hardware, shb_hardware_len, shb_hardware_pad_len);
if (!wtap_dump_file_write(wdh, shb_hardware, shb_hardware_len, err))
return FALSE;
wdh->bytes_dumped += shb_hardware_len;
/* write padding (if any) */
if (shb_hardware_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
return FALSE;
wdh->bytes_dumped += shb_hardware_pad_len;
}
}
if (shb_os_len) {
option_hdr.type = OPT_SHB_OS;
option_hdr.value_length = shb_os_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the string */
pcapng_debug("pcapng_write_section_header_block, shb_os:'%s' shb_os_len %u shb_os_pad_len %u" , shb_os, shb_os_len, shb_os_pad_len);
if (!wtap_dump_file_write(wdh, shb_os, shb_os_len, err))
return FALSE;
wdh->bytes_dumped += shb_os_len;
/* write padding (if any) */
if (shb_os_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
return FALSE;
wdh->bytes_dumped += shb_os_pad_len;
}
}
if (shb_user_appl_len) {
option_hdr.type = OPT_SHB_USERAPPL;
option_hdr.value_length = shb_user_appl_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the comments string */
pcapng_debug("pcapng_write_section_header_block, shb_user_appl:'%s' shb_user_appl_len %u shb_user_appl_pad_len %u" , shb_user_appl, shb_user_appl_len, shb_user_appl_pad_len);
if (!wtap_dump_file_write(wdh, shb_user_appl, shb_user_appl_len, err))
return FALSE;
wdh->bytes_dumped += shb_user_appl_len;
/* write padding (if any) */
if (shb_user_appl_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
return FALSE;
wdh->bytes_dumped += shb_user_appl_pad_len;
}
}
/* Write end of options if we have otions */
if (have_options) {
option_hdr.type = OPT_EOFOPT;
option_hdr.value_length = 0;
if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
}
/* write block footer */
if (!wtap_dump_file_write(wdh, &bh.block_total_length,
sizeof bh.block_total_length, err))
@ -2936,603 +2736,6 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
return TRUE;
}
static gboolean
pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_optionblock_t int_data, int *err)
{
pcapng_block_header_t bh;
pcapng_interface_description_block_t idb;
const guint32 zero_pad = 0;
gboolean have_options = FALSE;
struct option option_hdr; /* guint16 type, guint16 value_length; */
guint32 options_total_length = 0;
guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0, if_filter_str_pad_len = 0;
wtapng_if_descr_mandatory_t* int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
char *opt_comment, *if_name, *if_description, *if_os;
guint64 if_speed;
guint8 if_tsresol, if_fcslen;
wtapng_if_descr_filter_t* if_filter;
pcapng_debug("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
int_data_mand->link_type,
wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data_mand->link_type)),
int_data_mand->snap_len);
if (int_data_mand->link_type == (guint16)-1) {
*err = WTAP_ERR_UNWRITABLE_ENCAP;
return FALSE;
}
/* Calculate options length */
wtap_optionblock_get_option_string(int_data, OPT_COMMENT, &opt_comment);
if (opt_comment) {
have_options = TRUE;
comment_len = (guint32)strlen(opt_comment) & 0xffff;
if ((comment_len % 4)) {
comment_pad_len = 4 - (comment_len % 4);
} else {
comment_pad_len = 0;
}
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
/*
* if_name 2 A UTF-8 string containing the name of the device used to capture data.
*/
wtap_optionblock_get_option_string(int_data, OPT_IDB_NAME, &if_name);
if (if_name) {
have_options = TRUE;
if_name_len = (guint32)strlen(if_name) & 0xffff;
if ((if_name_len % 4)) {
if_name_pad_len = 4 - (if_name_len % 4);
} else {
if_name_pad_len = 0;
}
options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
}
/*
* if_description 3 A UTF-8 string containing the description of the device used to capture data.
*/
wtap_optionblock_get_option_string(int_data, OPT_IDB_DESCR, &if_description);
if (if_description) {
have_options = TRUE;
if_description_len = (guint32)strlen(if_description) & 0xffff;
if ((if_description_len % 4)) {
if_description_pad_len = 4 - (if_description_len % 4);
} else {
if_description_pad_len = 0;
}
options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
}
/* Currently not handled
* if_IPv4addr 4 Interface network address and netmask.
* if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
* if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
* if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
*/
/*
* if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
*/
wtap_optionblock_get_option_uint64(int_data, OPT_IDB_SPEED, &if_speed);
if (if_speed != 0) {
have_options = TRUE;
options_total_length = options_total_length + 8 + 4;
}
/*
* if_tsresol 9 Resolution of timestamps.
*/
wtap_optionblock_get_option_uint8(int_data, OPT_IDB_TSRESOL, &if_tsresol);
if (if_tsresol != 0) {
have_options = TRUE;
options_total_length = options_total_length + 4 + 4;
}
/* Not used
* if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
*/
/*
* if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more).
*/
wtap_optionblock_get_option_custom(int_data, OPT_IDB_FILTER, (void**)&if_filter);
if (if_filter->if_filter_str) {
have_options = TRUE;
if_filter_str_len = (guint32)(strlen(if_filter->if_filter_str) + 1) & 0xffff;
if ((if_filter_str_len % 4)) {
if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
} else {
if_filter_str_pad_len = 0;
}
options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
}
/*
* if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
*/
wtap_optionblock_get_option_string(int_data, OPT_IDB_OS, &if_os);
if (if_os) {
have_options = TRUE;
if_os_len = (guint32)strlen(if_os) & 0xffff;
if ((if_os_len % 4)) {
if_os_pad_len = 4 - (if_os_len % 4);
} else {
if_os_pad_len = 0;
}
options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
}
/*
* if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
* -1 if unknown or changes between packets, opt 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
*/
wtap_optionblock_get_option_uint8(int_data, OPT_IDB_FCSLEN, &if_fcslen);
if (if_fcslen != 0) {
}
/* Not used
* if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
* to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
*/
if (have_options) {
/* End-of-options tag */
options_total_length += 4;
}
/* write block header */
bh.block_type = BLOCK_TYPE_IDB;
bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
return FALSE;
wdh->bytes_dumped += sizeof bh;
/* write block fixed content */
idb.linktype = int_data_mand->link_type;
idb.reserved = 0;
idb.snaplen = int_data_mand->snap_len;
if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
return FALSE;
wdh->bytes_dumped += sizeof idb;
/* XXX - write (optional) block options */
if (comment_len != 0) {
option_hdr.type = OPT_COMMENT;
option_hdr.value_length = comment_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the comments string */
pcapng_debug("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , opt_comment, comment_len, comment_pad_len);
if (!wtap_dump_file_write(wdh, opt_comment, comment_len, err))
return FALSE;
wdh->bytes_dumped += comment_len;
/* write padding (if any) */
if (comment_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
return FALSE;
wdh->bytes_dumped += comment_pad_len;
}
}
/*
* if_name 2 A UTF-8 string containing the name of the device used to capture data.
*/
if (if_name_len !=0) {
option_hdr.type = OPT_IDB_NAME;
option_hdr.value_length = if_name_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the comments string */
pcapng_debug("pcapng_write_if_descr_block, if_name:'%s' if_name_len %u if_name_pad_len %u" , if_name, if_name_len, if_name_pad_len);
if (!wtap_dump_file_write(wdh, if_name, if_name_len, err))
return FALSE;
wdh->bytes_dumped += if_name_len;
/* write padding (if any) */
if (if_name_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
return FALSE;
wdh->bytes_dumped += if_name_pad_len;
}
}
/*
* if_description 3 A UTF-8 string containing the description of the device used to capture data.
*/
if (if_description_len != 0) {
option_hdr.type = OPT_IDB_NAME;
option_hdr.value_length = if_description_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the comments string */
pcapng_debug("pcapng_write_if_descr_block, if_description:'%s' if_description_len %u if_description_pad_len %u" , if_description, if_description_len, if_description_pad_len);
if (!wtap_dump_file_write(wdh, if_description, if_description_len, err))
return FALSE;
wdh->bytes_dumped += if_description_len;
/* write padding (if any) */
if (if_description_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
return FALSE;
wdh->bytes_dumped += if_description_pad_len;
}
}
/* Currently not handled
* if_IPv4addr 4 Interface network address and netmask.
* if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
* if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
* if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
*/
/*
* if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
*/
if (if_speed != 0) {
option_hdr.type = OPT_IDB_SPEED;
option_hdr.value_length = 8;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the comments string */
pcapng_debug("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", if_speed);
if (!wtap_dump_file_write(wdh, &if_speed, sizeof(guint64), err))
return FALSE;
wdh->bytes_dumped += 8;
}
/*
* if_tsresol 9 Resolution of timestamps.
* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
* If the Most Significant Bit is equal to zero, the remaining bits indicates
* the resolution of the timestamp as as a negative power of 10
*/
if (if_tsresol != 0) {
option_hdr.type = OPT_IDB_TSRESOL;
option_hdr.value_length = 1;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the time stamp resolution */
pcapng_debug("pcapng_write_if_descr_block: if_tsresol %u", if_tsresol);
if (!wtap_dump_file_write(wdh, &if_tsresol, 1, err))
return FALSE;
wdh->bytes_dumped += 1;
if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
return FALSE;
wdh->bytes_dumped += 3;
}
/* not used
* if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
*/
/*
* if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
*/
/* Libpcap string variant */
if (if_filter_str_len !=0) {
option_hdr.type = OPT_IDB_FILTER;
option_hdr.value_length = if_filter_str_len;
/* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the zero indicating libpcap filter variant */
if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
return FALSE;
wdh->bytes_dumped += 1;
/* Write the comments string */
pcapng_debug("pcapng_write_if_descr_block, if_filter_str:'%s' if_filter_str_len %u if_filter_str_pad_len %u" , if_filter->if_filter_str, if_filter_str_len, if_filter_str_pad_len);
/* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
if (!wtap_dump_file_write(wdh, if_filter->if_filter_str, if_filter_str_len-1, err))
return FALSE;
wdh->bytes_dumped += if_filter_str_len - 1;
/* write padding (if any) */
if (if_filter_str_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
return FALSE;
wdh->bytes_dumped += if_filter_str_pad_len;
}
}
/*
* if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
*/
if (if_os_len != 0) {
option_hdr.type = OPT_IDB_OS;
option_hdr.value_length = if_os_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the comments string */
pcapng_debug("pcapng_write_if_descr_block, if_os:'%s' if_os_len %u if_os_pad_len %u" , if_os, if_os_len, if_os_pad_len);
if (!wtap_dump_file_write(wdh, if_os, if_os_len, err))
return FALSE;
wdh->bytes_dumped += if_os_len;
/* write padding (if any) */
if (if_os_pad_len != 0) {
if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
return FALSE;
wdh->bytes_dumped += if_os_pad_len;
}
}
if (have_options) {
option_hdr.type = OPT_EOFOPT;
option_hdr.value_length = 0;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
}
/*
* if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
*/
/*
* if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
* to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
*/
/* write block footer */
if (!wtap_dump_file_write(wdh, &bh.block_total_length,
sizeof bh.block_total_length, err))
return FALSE;
wdh->bytes_dumped += sizeof bh.block_total_length;
return TRUE;
}
static gboolean
pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtap_optionblock_t if_stats, int *err)
{
pcapng_block_header_t bh;
pcapng_interface_statistics_block_t isb;
const guint32 zero_pad = 0;
gboolean have_options = FALSE;
struct option option_hdr; /* guint16 type, guint16 value_length; */
guint32 options_total_length = 0;
guint32 comment_len = 0;
guint32 comment_pad_len = 0;
char *opt_comment;
guint64 isb_starttime, isb_endtime, isb_ifrecv, isb_ifdrop, isb_filteraccept, isb_osdrop, isb_usrdeliv;
wtapng_if_stats_mandatory_t* if_stats_mand;
pcapng_debug("pcapng_write_interface_statistics_block");
wtap_optionblock_get_option_string(if_stats, OPT_COMMENT, &opt_comment);
/* Calculate options length */
if (opt_comment) {
have_options = TRUE;
comment_len = (guint32)strlen(opt_comment) & 0xffff;
if ((comment_len % 4)) {
comment_pad_len = 4 - (comment_len % 4);
} else {
comment_pad_len = 0;
}
options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
}
wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_STARTTIME, &isb_starttime);
if (isb_starttime != 0) {
have_options = TRUE;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_ENDTIME, &isb_endtime);
if (isb_endtime != 0) {
have_options = TRUE;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_IFRECV, &isb_ifrecv);
if (isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
have_options = TRUE;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_IFDROP, &isb_ifdrop);
if (isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
have_options = TRUE;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_FILTERACCEPT, &isb_filteraccept);
if (isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
have_options = TRUE;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_OSDROP, &isb_osdrop);
if (isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
have_options = TRUE;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_USRDELIV, &isb_usrdeliv);
if (isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
have_options = TRUE;
options_total_length = options_total_length + 8 + 4 /* options tag */ ;
}
/* write block header */
if (have_options) {
/* End-of-optios tag */
options_total_length += 4;
}
/* write block header */
bh.block_type = BLOCK_TYPE_ISB;
bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
return FALSE;
wdh->bytes_dumped += sizeof bh;
/* write block fixed content */
if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(if_stats);
isb.interface_id = if_stats_mand->interface_id;
isb.timestamp_high = if_stats_mand->ts_high;
isb.timestamp_low = if_stats_mand->ts_low;
if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
return FALSE;
wdh->bytes_dumped += sizeof isb;
/* write (optional) block options */
if (comment_len) {
option_hdr.type = OPT_COMMENT;
option_hdr.value_length = comment_len;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write the comments string */
pcapng_debug("pcapng_write_interface_statistics_block, comment:'%s' comment_len %u comment_pad_len %u" , opt_comment, comment_len, comment_pad_len);
if (!wtap_dump_file_write(wdh, opt_comment, comment_len, err))
return FALSE;
wdh->bytes_dumped += comment_len;
/* 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;
}
}
/*guint64 isb_starttime */
if (isb_starttime != 0) {
guint32 high, low;
option_hdr.type = OPT_ISB_STARTTIME;
option_hdr.value_length = 8;
high = (guint32)((isb_starttime>>32) & 0xffffffff);
low = (guint32)(isb_starttime & 0xffffffff);
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write isb_starttime */
pcapng_debug("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , isb_starttime);
if (!wtap_dump_file_write(wdh, &high, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
if (!wtap_dump_file_write(wdh, &low, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
}
/*guint64 isb_endtime */
if (isb_endtime != 0) {
guint32 high, low;
option_hdr.type = OPT_ISB_ENDTIME;
option_hdr.value_length = 8;
high = (guint32)((isb_endtime>>32) & 0xffffffff);
low = (guint32)(isb_endtime & 0xffffffff);
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write isb_endtime */
pcapng_debug("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , isb_endtime);
if (!wtap_dump_file_write(wdh, &high, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
if (!wtap_dump_file_write(wdh, &low, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
}
/*guint64 isb_ifrecv;*/
if (isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
option_hdr.type = OPT_ISB_IFRECV;
option_hdr.value_length = 8;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write isb_ifrecv */
pcapng_debug("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , isb_ifrecv);
if (!wtap_dump_file_write(wdh, &isb_ifrecv, 8, err))
return FALSE;
wdh->bytes_dumped += 8;
}
/*guint64 isb_ifdrop;*/
if (isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
option_hdr.type = OPT_ISB_IFDROP;
option_hdr.value_length = 8;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write isb_ifdrop */
pcapng_debug("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , isb_ifdrop);
if (!wtap_dump_file_write(wdh, &isb_ifdrop, 8, err))
return FALSE;
wdh->bytes_dumped += 8;
}
/*guint64 isb_filteraccept;*/
if (isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
option_hdr.type = OPT_ISB_FILTERACCEPT;
option_hdr.value_length = 8;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write isb_filteraccept */
pcapng_debug("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , isb_filteraccept);
if (!wtap_dump_file_write(wdh, &isb_filteraccept, 8, err))
return FALSE;
wdh->bytes_dumped += 8;
}
/*guint64 isb_osdrop;*/
if (isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
option_hdr.type = OPT_ISB_OSDROP;
option_hdr.value_length = 8;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write isb_osdrop */
pcapng_debug("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , isb_osdrop);
if (!wtap_dump_file_write(wdh, &isb_osdrop, 8, err))
return FALSE;
wdh->bytes_dumped += 8;
}
/*guint64 isb_usrdeliv;*/
if (isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
option_hdr.type = OPT_ISB_USRDELIV;
option_hdr.value_length = 8;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
/* Write isb_usrdeliv */
pcapng_debug("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , isb_usrdeliv);
if (!wtap_dump_file_write(wdh, &isb_usrdeliv, 8, err))
return FALSE;
wdh->bytes_dumped += 8;
}
if (have_options) {
option_hdr.type = OPT_EOFOPT;
option_hdr.value_length = 0;
if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
return FALSE;
wdh->bytes_dumped += 4;
}
/* write block footer */
if (!wtap_dump_file_write(wdh, &bh.block_total_length,
sizeof bh.block_total_length, err))
return FALSE;
wdh->bytes_dumped += sizeof bh.block_total_length;
return TRUE;
}
static gboolean
pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
const struct wtap_pkthdr *phdr,
@ -4056,7 +3259,7 @@ static gboolean pcapng_dump_finish(wtap_dumper *wdh, int *err)
if_stats = g_array_index(int_data_mand->interface_statistics, wtap_optionblock_t, j);
pcapng_debug("pcapng_dump_finish: write ISB for interface %u", ((wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(if_stats))->interface_id);
if (!pcapng_write_interface_statistics_block(wdh, if_stats, err)) {
if (!wtap_optionblock_write(wdh, if_stats, err)) {
return FALSE;
}
}
@ -4098,11 +3301,11 @@ pcapng_dump_open(wtap_dumper *wdh, int *err)
for (i = 0; i < wdh->interface_data->len; i++) {
/* Get the interface description */
wtap_optionblock_t int_data;
wtap_optionblock_t idb;
int_data = g_array_index(wdh->interface_data, wtap_optionblock_t, i);
idb = g_array_index(wdh->interface_data, wtap_optionblock_t, i);
if (!pcapng_write_if_descr_block(wdh, int_data, err)) {
if (!wtap_optionblock_write(wdh, idb, err)) {
return FALSE;
}

View File

@ -112,6 +112,50 @@
#define OPT_ISB_OSDROP 0x0007
#define OPT_ISB_USRDELIV 0x0008
/* pcapng: common block header file encoding for every block type */
typedef struct pcapng_block_header_s {
guint32 block_type;
guint32 block_total_length;
/* x bytes block_body */
/* guint32 block_total_length */
} pcapng_block_header_t;
/* pcapng: section header block file encoding */
typedef struct pcapng_section_header_block_s {
/* pcapng_block_header_t */
guint32 magic;
guint16 version_major;
guint16 version_minor;
guint64 section_length; /* might be -1 for unknown */
/* ... Options ... */
} pcapng_section_header_block_t;
/* pcapng: interface description block file encoding */
typedef struct pcapng_interface_description_block_s {
guint16 linktype;
guint16 reserved;
guint32 snaplen;
/* ... Options ... */
} pcapng_interface_description_block_t;
/* pcapng: interface statistics block file encoding */
typedef struct pcapng_interface_statistics_block_s {
guint32 interface_id;
guint32 timestamp_high;
guint32 timestamp_low;
/* ... Options ... */
} pcapng_interface_statistics_block_t;
struct pcapng_option_header {
guint16 type;
guint16 value_length;
};
/*
* Minimum IDB size = minimum block size + size of fixed length portion of IDB.
*/
#define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
wtap_open_return_val pcapng_open(wtap *wth, int *err, gchar **err_info);
gboolean pcapng_dump_open(wtap_dumper *wdh, int *err);
int pcapng_dump_can_write_encap(int encap);

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,9 @@
#include "ws_symbol_export.h"
struct wtap_optionblock;
typedef struct wtap_optionblock *wtap_optionblock_t;
/* Currently supported option blocks */
typedef enum {
WTAP_OPTION_BLOCK_IF_DESCR = 0,
@ -57,27 +60,27 @@ struct wtap_opttype_custom
wtap_opttype_free_custom_func free_func;
};
typedef struct wtap_opttype {
typedef union {
guint8 uint8val;
guint64 uint64val;
char *stringval;
struct wtap_opttype_custom customval;
} wtap_option_type;
struct wtap_dumper;
typedef guint32 (*wtap_opttype_option_write_size)(wtap_option_type* data); /**< does the option have data worth writing (Ex string option != NULL */
typedef gboolean (*wtap_opttype_option_write)(struct wtap_dumper* wdh, wtap_option_type* data, int *err); /**< does the option have data worth writing (Ex string option != NULL */
typedef struct wtap_optblock_reg {
const char *name; /**< name of option */
const char *description; /**< human-readable description of option */
guint number; /**< Option index */
wtap_opttype_e type; /**< type of that option */
union {
guint8 uint8val;
guint64 uint64val;
char *stringval;
struct wtap_opttype_custom customval;
} option; /**< pointer to variable storing the value */
union {
guint8 uint8val;
guint64 uint64val;
char *stringval;
struct wtap_opttype_custom customval;
} default_val; /**< the default value of the option */
} wtap_opttype_t;
struct wtap_optionblock;
typedef struct wtap_optionblock *wtap_optionblock_t;
wtap_opttype_option_write_size write_size_func; /**< Size of option in file (0 to not write option) */
wtap_opttype_option_write write_func; /**< write option data to dumper */
wtap_option_type option; /**< pointer to variable storing the value */
wtap_option_type default_val; /**< the default value of the option */
} wtap_optblock_reg_t;
/** Initialize option block types.
*
@ -111,132 +114,86 @@ WS_DLL_PUBLIC void wtap_optionblock_free(wtap_optionblock_t block);
*/
WS_DLL_PUBLIC void* wtap_optionblock_get_mandatory_data(wtap_optionblock_t block);
/** Add a string option to the option block
/** Add an option to the option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[in] name Name of option
* @param[in] description Description of option
* @param[in] opt_value Current value of option
* @param[in] default_value Default value of option
* @param[in] option structure explaining it
* @return 0 if successful
*/
int wtap_optionblock_add_option_string(wtap_optionblock_t block, guint option_id,
const char *name, const char *description, char* opt_value, char* default_value);
int wtap_optionblock_add_option(wtap_optionblock_t block, guint option_id, wtap_optblock_reg_t* option);
/** Set string option value to an option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[in] opt_value New value of option
* @param[in] value New value of option
* @return 0 if successful
*/
WS_DLL_PUBLIC int wtap_optionblock_set_option_string(wtap_optionblock_t block, guint option_id, char* opt_value);
WS_DLL_PUBLIC int wtap_optionblock_set_option_string(wtap_optionblock_t block, guint option_id, char* value);
/** Get string option value from an option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[out] opt_value Returned value of option
* @param[out] value Returned value of option
* @return 0 if successful
*/
WS_DLL_PUBLIC int wtap_optionblock_get_option_string(wtap_optionblock_t block, guint option_id, char** opt_value);
/** Add UINT64 option to the option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[in] name Name of option
* @param[in] description Description of option
* @param[in] opt_value Current value of option
* @param[in] default_value Default value of option
* @return 0 if successful
*/
int wtap_optionblock_add_option_uint64(wtap_optionblock_t block, guint option_id,
const char *name, const char *description, guint64 opt_value, guint64 default_value);
WS_DLL_PUBLIC int wtap_optionblock_get_option_string(wtap_optionblock_t block, guint option_id, char** value);
/** Set UINT64 option value to an option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[in] opt_value New value of option
* @param[in] value New value of option
* @return 0 if successful
*/
WS_DLL_PUBLIC int wtap_optionblock_set_option_uint64(wtap_optionblock_t block, guint option_id, guint64 opt_value);
WS_DLL_PUBLIC int wtap_optionblock_set_option_uint64(wtap_optionblock_t block, guint option_id, guint64 value);
/** Get UINT64 option value from an option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[out] opt_value Returned value of option
* @param[out] value Returned value of option
* @return 0 if successful
*/
WS_DLL_PUBLIC int wtap_optionblock_get_option_uint64(wtap_optionblock_t block, guint option_id, guint64* opt_value);
/** Add UINT8 option to the option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[in] name Name of option
* @param[in] description Description of option
* @param[in] opt_value Current value of option
* @param[in] default_value Default value of option
* @return 0 if successful
*/
int wtap_optionblock_add_option_uint8(wtap_optionblock_t block, guint option_id,
const char *name, const char *description, guint8 opt_value, guint8 default_value);
WS_DLL_PUBLIC int wtap_optionblock_get_option_uint64(wtap_optionblock_t block, guint option_id, guint64* value);
/** Set UINT8 option value to an option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[in] opt_value New value of option
* @param[in] value New value of option
* @return 0 if successful
*/
WS_DLL_PUBLIC int wtap_optionblock_set_option_uint8(wtap_optionblock_t block, guint option_id, guint8 opt_value);
WS_DLL_PUBLIC int wtap_optionblock_set_option_uint8(wtap_optionblock_t block, guint option_id, guint8 value);
/** Get UINT8 option value from an option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[out] opt_value Returned value of option
* @param[out] value Returned value of option
* @return 0 if successful
*/
WS_DLL_PUBLIC int wtap_optionblock_get_option_uint8(wtap_optionblock_t block, guint option_id, guint8* opt_value);
/** Add a "custom" option to the option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[in] name Name of option
* @param[in] description Description of option
* @param[in] opt_value Current value of option
* @param[in] default_value Default value of option
* @param[in] size Size of the option structure
* @param[in] free_func Function to free to the option structure
* @return 0 if successful
*/
int wtap_optionblock_add_option_custom(wtap_optionblock_t block, guint option_id,
const char *name, const char *description, void* opt_value, void* default_value,
guint size, wtap_opttype_free_custom_func free_func);
WS_DLL_PUBLIC int wtap_optionblock_get_option_uint8(wtap_optionblock_t block, guint option_id, guint8* value);
/** Set a "custom" option value to an option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[in] opt_value New value of option
* @param[in] value New value of option
* @return 0 if successful
*/
WS_DLL_PUBLIC int wtap_optionblock_set_option_custom(wtap_optionblock_t block, guint option_id, void* opt_value);
WS_DLL_PUBLIC int wtap_optionblock_set_option_custom(wtap_optionblock_t block, guint option_id, void* value);
/** Get a "custom" option value from an option block
*
* @param[in] block Block to add option
* @param[in] option_id Identifier value for option
* @param[out] opt_value Returned value of option
* @param[out] value Returned value of option
* @return 0 if successful
*/
WS_DLL_PUBLIC int wtap_optionblock_get_option_custom(wtap_optionblock_t block, guint option_id, void** opt_value);
WS_DLL_PUBLIC int wtap_optionblock_get_option_custom(wtap_optionblock_t block, guint option_id, void** value);
/** Copy an option block to another.
*
@ -248,5 +205,31 @@ WS_DLL_PUBLIC int wtap_optionblock_get_option_custom(wtap_optionblock_t block, g
*/
void wtap_optionblock_copy_options(wtap_optionblock_t dest_block, wtap_optionblock_t src_block);
/** Write an option block
*
* Will write all mandatory data as well as "valid" options
*
* @param[in] wdh writing assistant
* @param[in] block Block to be written
* @param[in] err Any errors that occurred
* @return TRUE if successful, FALSE will populate err
*/
gboolean wtap_optionblock_write(struct wtap_dumper *wdh, wtap_optionblock_t block, int *err);
/* Some utility functions for option types */
guint32 wtap_opttype_write_size_string(wtap_option_type* data);
gboolean wtap_opttype_write_data_string(struct wtap_dumper* wdh, wtap_option_type* data, int *err);
/* if option value = 0, write size = 0, otherwise 4 */
guint32 wtap_opttype_write_uint8_not0(wtap_option_type* data);
gboolean wtap_opttype_write_data_uint8(struct wtap_dumper* wdh, wtap_option_type* data, int *err);
/* if option value = 0, write size = 0, otherwise 8 */
guint32 wtap_opttype_write_uint64_not0(wtap_option_type* data);
/* if option value = -1 (0xFFFFFFFFFFFFFFFF), write size = 0, otherwise 8 */
guint32 wtap_opttype_write_uint64_not_minus1(wtap_option_type* data);
gboolean wtap_opttype_write_data_uint64(struct wtap_dumper* wdh, wtap_option_type* data, int *err);
#endif /* WTAP_OPT_TYPES_H */