aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@wireshark.org>2021-08-04 19:57:52 +0200
committerMichael Tuexen <tuexen@wireshark.org>2021-08-27 04:48:21 +0200
commitb17f354304242ac14769f7b4f13b65b077b769a8 (patch)
treea1cb3b40942fe4b9958a31e854f902cdafcbeece /wiretap
parent8c4543373ad6a3c870f30d33dedf7bcdc12796ac (diff)
Add initial support for BBLog files
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/pcapng.c391
-rw-r--r--wiretap/wtap.h9
-rw-r--r--wiretap/wtap_opttypes.c240
-rw-r--r--wiretap/wtap_opttypes.h160
4 files changed, 750 insertions, 50 deletions
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index 811576fdb9..e443b47764 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -233,11 +233,14 @@ typedef struct wtapng_simple_packet_s {
/* Section data in private struct */
typedef struct section_info_t {
- gboolean byte_swapped; /**< TRUE if this section is not in our byte order */
- guint16 version_major; /**< Major version number of this section */
- guint16 version_minor; /**< Minor version number of this section */
- GArray *interfaces; /**< Interfaces found in this section */
- gint64 shb_off; /**< File offset of the SHB for this section */
+ gboolean byte_swapped; /**< TRUE if this section is not in our byte order */
+ guint16 version_major; /**< Major version number of this section */
+ guint16 version_minor; /**< Minor version number of this section */
+ GArray *interfaces; /**< Interfaces found in this section */
+ gint64 shb_off; /**< File offset of the SHB for this section */
+ guint32 bblog_version; /**< BBLog: version used */
+ guint64 bblog_offset_tv_sec; /**< BBLog: UTC offset */
+ guint64 bblog_offset_tv_usec;
} section_info_t;
/* Interface data in private struct */
@@ -613,13 +616,97 @@ pcapng_process_bytes_option(wtapng_block_t *wblock, guint16 option_code,
}
static gboolean
+pcapng_process_nflx_custom_option(wtapng_block_t *wblock,
+ section_info_t *section_info,
+ const guint8 *value, guint16 length)
+{
+ struct nflx_dumpinfo dumpinfo;
+ guint32 type, version;
+ gint64 dumptime, temp;
+
+ if (length < 4) {
+ ws_debug("Length = %u too small", length);
+ return FALSE;
+ }
+ memcpy(&type, value, sizeof(guint32));
+ type = GUINT32_FROM_LE(type);
+ value += 4;
+ length -= 4;
+ ws_debug("Handling type = %u, payload of length = %u", type, length);
+ switch (type) {
+ case NFLX_OPT_TYPE_VERSION:
+ if (length == sizeof(guint32)) {
+ memcpy(&version, value, sizeof(guint32));
+ version = GUINT32_FROM_LE(version);
+ ws_debug("BBLog version: %u", version);
+ section_info->bblog_version = version;
+ } else {
+ ws_debug("BBLog version parameter has strange length: %u", length);
+ }
+ break;
+ case NFLX_OPT_TYPE_TCPINFO:
+ ws_debug("BBLog tcpinfo of length: %u", length);
+ if (wblock->type == BLOCK_TYPE_CB_COPY) {
+ ws_buffer_assure_space(wblock->frame_buffer, length);
+ wblock->rec->rec_header.custom_block_header.length = length + 4;
+ memcpy(ws_buffer_start_ptr(wblock->frame_buffer), value, length);
+ memcpy(&temp, value, sizeof(guint64));
+ temp = GUINT64_FROM_LE(temp);
+ wblock->rec->ts.secs = section_info->bblog_offset_tv_sec + temp;
+ memcpy(&temp, value + sizeof(guint64), sizeof(guint64));
+ temp = GUINT64_FROM_LE(temp);
+ wblock->rec->ts.nsecs = (guint32)(section_info->bblog_offset_tv_usec + temp) * 1000;
+ if (wblock->rec->ts.nsecs >= 1000000000) {
+ wblock->rec->ts.secs += 1;
+ wblock->rec->ts.nsecs -= 1000000000;
+ }
+ wblock->rec->presence_flags = WTAP_HAS_TS;
+ wblock->internal = FALSE;
+ }
+ break;
+ case NFLX_OPT_TYPE_DUMPINFO:
+ if (length == sizeof(struct nflx_dumpinfo)) {
+ memcpy(&dumpinfo, value, sizeof(struct nflx_dumpinfo));
+ section_info->bblog_offset_tv_sec = GUINT64_FROM_LE(dumpinfo.tlh_offset_tv_sec);
+ section_info->bblog_offset_tv_usec = GUINT64_FROM_LE(dumpinfo.tlh_offset_tv_usec);
+ ws_debug("BBLog dumpinfo time offset: %" G_GUINT64_FORMAT, section_info->bblog_offset_tv_sec);
+ } else {
+ ws_debug("BBLog dumpinfo parameter has strange length: %u", length);
+ }
+ break;
+ case NFLX_OPT_TYPE_DUMPTIME:
+ if (length == sizeof(gint64)) {
+ memcpy(&dumptime, value, sizeof(gint64));
+ dumptime = GINT64_FROM_LE(dumptime);
+ ws_debug("BBLog dumpinfo time offset: %" G_GUINT64_FORMAT, dumptime);
+ } else {
+ ws_debug("BBLog dumptime parameter has strange length: %u", length);
+ }
+ break;
+ case NFLX_OPT_TYPE_STACKNAME:
+ if (length >= 2) {
+ ws_debug("BBLog stack name: %.*s(%u)", length - 1, value + 1, *(guint8 *)value);
+ } else {
+ ws_debug("BBLog stack name has strange length: %u)", length);
+ }
+ break;
+ default:
+ ws_debug("Unknown type: %u, length: %u", type, length);
+ break;
+ }
+ return wtap_block_add_nflx_custom_option(wblock->block, type, value, length) == WTAP_OPTTYPE_SUCCESS;
+}
+
+static gboolean
pcapng_process_custom_option(wtapng_block_t *wblock,
- const section_info_t *section_info,
+ section_info_t *section_info,
guint16 option_code, guint16 option_length,
const guint8 *option_content,
+ gboolean little_endian,
int *err, gchar **err_info)
{
guint32 pen;
+ gboolean ret;
if (option_length < 4) {
*err = WTAP_ERR_BAD_FILE;
@@ -628,18 +715,22 @@ pcapng_process_custom_option(wtapng_block_t *wblock,
return FALSE;
}
memcpy(&pen, option_content, sizeof(guint32));
- if (section_info->byte_swapped) {
+ if (little_endian) {
+ pen = GUINT32_FROM_LE(pen);
+ } else if (section_info->byte_swapped) {
pen = GUINT32_SWAP_LE_BE(pen);
}
switch (pen) {
+ case PEN_NFLX:
+ ret = pcapng_process_nflx_custom_option(wblock, section_info, option_content + 4, option_length - 4);
+ break;
default:
+ ret = wtap_block_add_custom_option(wblock->block, option_code, pen, option_content + 4, option_length - 4) == WTAP_OPTTYPE_SUCCESS;
ws_debug("Custom option type 0x%04x with unknown pen %u with custom data of length %u", option_code, pen, option_length - 4);
- if (wtap_block_add_custom_option(wblock->block, option_code, pen, option_content + 4, option_length - 4) != WTAP_OPTTYPE_SUCCESS) {
- return FALSE;
- }
break;
}
- return TRUE;
+ ws_debug("returning %d", ret);
+ return ret;
}
#ifdef HAVE_PLUGINS
@@ -682,13 +773,14 @@ pcapng_process_unhandled_option(wtapng_block_t *wblock _U_,
static gboolean
pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
- const section_info_t *section_info,
+ section_info_t *section_info,
guint opt_cont_buf_len,
gboolean (*process_option)(wtapng_block_t *,
const section_info_t *,
guint16, guint16,
const guint8 *,
int *, gchar **),
+ gboolean little_endian,
int *err, gchar **err_info)
{
guint8 *option_content; /* Allocate as large as the options block */
@@ -738,7 +830,10 @@ pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
}
option_code = oh->option_code;
option_length = oh->option_length;
- if (section_info->byte_swapped) {
+ if (little_endian) {
+ option_code = GUINT16_FROM_LE(option_code);
+ option_length = GUINT16_FROM_LE(option_length);
+ } else if (section_info->byte_swapped) {
option_code = GUINT16_SWAP_LE_BE(option_code);
option_length = GUINT16_SWAP_LE_BE(option_length);
}
@@ -776,6 +871,7 @@ pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
if (!pcapng_process_custom_option(wblock, section_info,
option_code, option_length,
option_ptr,
+ little_endian,
err, err_info)) {
g_free(option_content);
return FALSE;
@@ -783,7 +879,8 @@ pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
break;
default:
- if (!(*process_option)(wblock, section_info, option_code,
+ if (process_option == NULL ||
+ !(*process_option)(wblock, (const section_info_t *)section_info, option_code,
option_length, option_ptr,
err, err_info)) {
g_free(option_content);
@@ -995,7 +1092,7 @@ pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
opt_cont_buf_len = bh->block_total_length - MIN_SHB_SIZE;
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_section_header_block_option,
- err, err_info))
+ FALSE, err, err_info))
return PCAPNG_BLOCK_ERROR;
/*
@@ -1190,7 +1287,7 @@ pcapng_process_if_descr_block_option(wtapng_block_t *wblock,
/* "Interface Description Block" */
static gboolean
pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
- const section_info_t *section_info,
+ section_info_t *section_info,
wtapng_block_t *wblock, int *err, gchar **err_info)
{
guint64 time_units_per_second = 1000000; /* default = 10^6 */
@@ -1258,7 +1355,7 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
opt_cont_buf_len = bh->block_total_length - MIN_IDB_SIZE;
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_if_descr_block_option,
- err, err_info))
+ FALSE, err, err_info))
return FALSE;
/*
@@ -1557,7 +1654,7 @@ pcapng_process_packet_block_option(wtapng_block_t *wblock,
static gboolean
pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh,
- const section_info_t *section_info,
+ section_info_t *section_info,
wtapng_block_t *wblock,
int *err, gchar **err_info, gboolean enhanced)
{
@@ -1763,7 +1860,7 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh,
(int)sizeof(bh->block_total_length);
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_packet_block_option,
- err, err_info))
+ FALSE, err, err_info))
return FALSE;
/*
@@ -2033,7 +2130,7 @@ pcapng_process_name_resolution_block_option(wtapng_block_t *wblock,
static gboolean
pcapng_read_name_resolution_block(FILE_T fh, pcapng_block_header_t *bh,
pcapng_t *pn,
- const section_info_t *section_info,
+ section_info_t *section_info,
wtapng_block_t *wblock,
int *err, gchar **err_info)
{
@@ -2254,7 +2351,7 @@ read_options:
opt_cont_buf_len = to_read;
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_name_resolution_block_option,
- err, err_info))
+ FALSE, err, err_info))
return FALSE;
ws_buffer_free(&nrb_rec);
@@ -2334,7 +2431,7 @@ pcapng_process_interface_statistics_block_option(wtapng_block_t *wblock,
static gboolean
pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh,
- const section_info_t *section_info,
+ section_info_t *section_info,
wtapng_block_t *wblock,
int *err, gchar **err_info)
{
@@ -2386,7 +2483,7 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh,
(MIN_BLOCK_SIZE + (guint)sizeof isb); /* fixed and variable part, including padding */
if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
pcapng_process_interface_statistics_block_option,
- err, err_info))
+ FALSE, err, err_info))
return FALSE;
/*
@@ -2397,6 +2494,71 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh,
return TRUE;
}
+#define NFLX_BLOCK_TYPE_EVENT 1
+#define NFLX_BLOCK_TYPE_SKIP 2
+
+typedef struct pcapng_nflx_custom_block_s {
+ guint32 nflx_type;
+} pcapng_nflx_custom_block_t;
+
+#define MIN_NFLX_CB_SIZE ((guint32)(MIN_CB_SIZE + sizeof(pcapng_nflx_custom_block_t)))
+
+static gboolean
+pcapng_read_nflx_custom_block(FILE_T fh, pcapng_block_header_t *bh,
+ section_info_t *section_info,
+ wtapng_block_t *wblock,
+ int *err, gchar **err_info)
+{
+ pcapng_nflx_custom_block_t nflx_cb;
+ guint opt_cont_buf_len;
+ guint32 type, skipped;
+
+ if (bh->block_total_length < MIN_NFLX_CB_SIZE) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("pcapng_read_nflx_custom_block: total block length %u is too small (< %u)",
+ bh->block_total_length, MIN_NFLX_CB_SIZE);
+ return FALSE;
+ }
+
+ opt_cont_buf_len = bh->block_total_length - MIN_NFLX_CB_SIZE;
+ wblock->rec->rec_type = REC_TYPE_CUSTOM_BLOCK;
+ wblock->rec->rec_header.custom_block_header.pen = PEN_NFLX;
+ /* "NFLX Custom Block" read fixed part */
+ if (!wtap_read_bytes(fh, &nflx_cb, sizeof nflx_cb, err, err_info)) {
+ ws_debug("Failed to read nflx type");
+ return FALSE;
+ }
+ type = GUINT32_FROM_LE(nflx_cb.nflx_type);
+ ws_debug("BBLog type: %u", type);
+ switch (type) {
+ case NFLX_BLOCK_TYPE_EVENT:
+ wblock->rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.type = BBLOG_TYPE_EVENT_BLOCK;
+ opt_cont_buf_len = bh->block_total_length - MIN_NFLX_CB_SIZE;
+ ws_debug("event");
+ break;
+ case NFLX_BLOCK_TYPE_SKIP:
+ wblock->rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.type = BBLOG_TYPE_SKIPPED_BLOCK;
+ if (!wtap_read_bytes(fh, &skipped, sizeof(guint32), err, err_info)) {
+ ws_debug("Failed to read skipped");
+ return FALSE;
+ }
+ wblock->rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.skipped = GUINT32_FROM_LE(skipped);
+ ws_debug("skipped: %u", wblock->rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.skipped);
+ opt_cont_buf_len = bh->block_total_length - MIN_NFLX_CB_SIZE - sizeof(guint32);
+ break;
+ default:
+ ws_debug("Unknown type %u", type);
+ return FALSE;
+ }
+
+ /* Options */
+ if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
+ NULL, TRUE, err, err_info))
+ return FALSE;
+
+ return TRUE;
+}
+
static gboolean
pcapng_handle_generic_custom_block(FILE_T fh, pcapng_block_header_t *bh,
guint32 pen, wtapng_block_t *wblock,
@@ -2425,9 +2587,10 @@ pcapng_handle_generic_custom_block(FILE_T fh, pcapng_block_header_t *bh,
wblock->internal = FALSE;
return TRUE;
}
+
static gboolean
pcapng_read_custom_block(FILE_T fh, pcapng_block_header_t *bh,
- const section_info_t *section_info,
+ section_info_t *section_info,
wtapng_block_t *wblock,
int *err, gchar **err_info)
{
@@ -2445,6 +2608,8 @@ pcapng_read_custom_block(FILE_T fh, pcapng_block_header_t *bh,
return FALSE;
}
+ wblock->block = wtap_block_create(WTAP_BLOCK_CUSTOM);
+
/* Custom block read fixed part */
if (!wtap_read_bytes(fh, &cb, sizeof cb, err, err_info)) {
ws_debug("failed to read pen");
@@ -2458,6 +2623,10 @@ pcapng_read_custom_block(FILE_T fh, pcapng_block_header_t *bh,
ws_debug("pen %u, custom data and option length %u", pen, bh->block_total_length - MIN_CB_SIZE);
switch (pen) {
+ case PEN_NFLX:
+ if (!pcapng_read_nflx_custom_block(fh, bh, section_info, wblock, err, err_info))
+ return FALSE;
+ break;
default:
if (!pcapng_handle_generic_custom_block(fh, bh, pen, wblock, err, err_info)) {
return FALSE;
@@ -2465,6 +2634,9 @@ pcapng_read_custom_block(FILE_T fh, pcapng_block_header_t *bh,
break;
}
+ wblock->rec->block = wblock->block;
+ wblock->block = NULL;
+
return TRUE;
}
@@ -3521,7 +3693,18 @@ static guint32 pcapng_compute_custom_option_size(wtap_optval_t *optval)
{
size_t size, pad;
- size = optval->custom_opt.custom_data_len + sizeof(guint32);
+ /* PEN */
+ size = sizeof(guint32);
+ switch (optval->custom_opt.pen) {
+ case PEN_NFLX:
+ /* PEN */
+ size += sizeof(guint32);
+ size += optval->custom_opt.data.nflx_data.custom_data_len;
+ break;
+ default:
+ size += optval->custom_opt.data.generic_data.custom_data_len;
+ break;
+ }
if (size > 65535) {
size = 65535;
}
@@ -3957,13 +4140,28 @@ static gboolean pcapng_write_if_filter_option(wtap_dumper *wdh, guint option_id,
static gboolean pcapng_write_custom_option(wtap_dumper *wdh, guint option_id, wtap_optval_t *optval, int *err)
{
struct pcapng_option_header option_hdr;
+ gsize pad;
+ gsize size;
const guint32 zero_pad = 0;
- size_t pad;
+ guint32 pen, type;
+ gboolean use_little_endian;
if ((option_id == OPT_CUSTOM_STR_NO_COPY) ||
(option_id == OPT_CUSTOM_BIN_NO_COPY))
return TRUE;
- if (optval->custom_opt.custom_data_len + sizeof(guint32) > 65535) {
+ ws_debug("PEN %d", optval->custom_opt.pen);
+ switch (optval->custom_opt.pen) {
+ case PEN_NFLX:
+ size = sizeof(guint32) + sizeof(guint32) + optval->custom_opt.data.nflx_data.custom_data_len;
+ use_little_endian = optval->custom_opt.data.nflx_data.use_little_endian;
+ break;
+ default:
+ size = sizeof(guint32) + optval->custom_opt.data.generic_data.custom_data_len;
+ use_little_endian = false;
+ break;
+ }
+ ws_debug("use_little_endian %d", use_little_endian);
+ if (size > 65535) {
/*
* Too big to fit in the option.
* Don't write anything.
@@ -3975,30 +4173,57 @@ static gboolean pcapng_write_custom_option(wtap_dumper *wdh, guint option_id, wt
/* write option header */
option_hdr.type = (guint16)option_id;
- option_hdr.value_length = (guint16)(optval->custom_opt.custom_data_len + sizeof(guint32));
+ option_hdr.value_length = (guint16)size;
+ if (use_little_endian) {
+ option_hdr.type = GUINT16_TO_LE(option_hdr.type);
+ option_hdr.value_length = GUINT16_TO_LE(option_hdr.value_length);
+ }
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, &optval->custom_opt.pen, sizeof(guint32), err))
+ pen = optval->custom_opt.pen;
+ if (use_little_endian) {
+ pen = GUINT32_TO_LE(pen);
+ }
+ if (!wtap_dump_file_write(wdh, &pen, sizeof(guint32), err))
return FALSE;
wdh->bytes_dumped += sizeof(guint32);
- /* write custom data */
- if (!wtap_dump_file_write(wdh, optval->custom_opt.custom_data, optval->custom_opt.custom_data_len, err))
- return FALSE;
- wdh->bytes_dumped += optval->custom_opt.custom_data_len;
+ switch (optval->custom_opt.pen) {
+ case PEN_NFLX:
+ /* write NFLX type */
+ type = GUINT32_TO_LE(optval->custom_opt.data.nflx_data.type);
+ ws_debug("type=%d", type);
+ if (!wtap_dump_file_write(wdh, &type, sizeof(guint32), err))
+ return FALSE;
+ wdh->bytes_dumped += sizeof(guint32);
+ /* write custom data */
+ if (!wtap_dump_file_write(wdh, optval->custom_opt.data.nflx_data.custom_data, optval->custom_opt.data.nflx_data.custom_data_len, err)) {
+ return FALSE;
+ }
+ wdh->bytes_dumped += optval->custom_opt.data.nflx_data.custom_data_len;
+ break;
+ default:
+ /* write custom data */
+ if (!wtap_dump_file_write(wdh, optval->custom_opt.data.generic_data.custom_data, optval->custom_opt.data.generic_data.custom_data_len, err)) {
+ return FALSE;
+ }
+ wdh->bytes_dumped += optval->custom_opt.data.generic_data.custom_data_len;
+ break;
+ }
/* write padding (if any) */
- if ((optval->custom_opt.custom_data_len % 4)) {
- pad = 4 - (optval->custom_opt.custom_data_len % 4);
+ if (size % 4 != 0) {
+ pad = 4 - (size % 4);
} else {
pad = 0;
}
if (pad != 0) {
- if (!wtap_dump_file_write(wdh, &zero_pad, pad, err))
+ 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);
@@ -4591,9 +4816,9 @@ pcapng_write_custom_block(wtap_dumper *wdh, const wtap_rec *rec,
/* write block header */
bh.block_type = BLOCK_TYPE_CB_COPY;
bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(cb) + rec->rec_header.custom_block_header.length + pad_len + 4;
- ws_debug("writing %u bytes, %u padded",
+ ws_debug("writing %u bytes, %u padded, PEN %u",
rec->rec_header.custom_block_header.length,
- bh.block_total_length);
+ bh.block_total_length, rec->rec_header.custom_block_header.pen);
if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err)) {
return FALSE;
}
@@ -4605,6 +4830,7 @@ pcapng_write_custom_block(wtap_dumper *wdh, const wtap_rec *rec,
return FALSE;
}
wdh->bytes_dumped += sizeof cb;
+ ws_debug("wrote PEN = %u", cb.pen);
/* write custom data */
if (!wtap_dump_file_write(wdh, pd, rec->rec_header.custom_block_header.length, err)) {
@@ -4625,6 +4851,76 @@ pcapng_write_custom_block(wtap_dumper *wdh, const wtap_rec *rec,
sizeof bh.block_total_length, err)) {
return FALSE;
}
+ wdh->bytes_dumped += sizeof bh.block_total_length;
+
+ return TRUE;
+}
+
+static gboolean
+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 pen, skipped, type;
+
+ options_len = wtap_block_get_options_size_padded(rec->block) + 4;
+
+ /* write block header */
+ bh.block_type = BLOCK_TYPE_CB_COPY;
+ bh.block_total_length = (guint32)(sizeof(bh) + sizeof(guint32) + sizeof(guint32) + options_len + 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);
+ }
+ ws_debug("writing %u bytes, type %u",
+ bh.block_total_length, rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.type);
+ if (!wtap_dump_file_write(wdh, &bh, sizeof(bh), err)) {
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof bh;
+
+ /* write PEN */
+ pen = PEN_NFLX;
+ if (!wtap_dump_file_write(wdh, &pen, sizeof(guint32), err)) {
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(guint32);
+ ws_debug("wrote PEN = %u", pen);
+
+ /* write type */
+ type = GUINT32_TO_LE(rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.type);
+ if (!wtap_dump_file_write(wdh, &type, sizeof(guint32), err)) {
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(guint32);
+ ws_debug("wrote type = %u", rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.type);
+
+ if (rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.type == BBLOG_TYPE_SKIPPED_BLOCK) {
+ skipped = GUINT32_TO_LE(rec->rec_header.custom_block_header.custom_data_header.nflx_custom_data_header.skipped);
+ if (!wtap_dump_file_write(wdh, &skipped, sizeof(guint32), err)) {
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(guint32);
+ 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 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;
}
@@ -4752,7 +5048,7 @@ put_nrb_option(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_ty
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;
+ size = (guint32)(optval->custom_opt.data.generic_data.custom_data_len + sizeof(guint32)) & 0xffff;
option_hdr.type = (guint16)option_id;
option_hdr.value_length = (guint16)size;
memcpy(*opt_ptrp, &option_hdr, 4);
@@ -4761,8 +5057,8 @@ put_nrb_option(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_ty
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;
+ memcpy(*opt_ptrp, optval->custom_opt.data.generic_data.custom_data, optval->custom_opt.data.generic_data.custom_data_len);
+ *opt_ptrp += optval->custom_opt.data.generic_data.custom_data_len;
if ((size % 4)) {
pad = 4 - (size % 4);
@@ -5398,8 +5694,17 @@ static gboolean pcapng_dump(wtap_dumper *wdh,
break;
case REC_TYPE_CUSTOM_BLOCK:
- if (!pcapng_write_custom_block(wdh, rec, pd, err)) {
- return FALSE;
+ switch (rec->rec_header.custom_block_header.pen) {
+ case PEN_NFLX:
+ if (!pcapng_write_bblog_block(wdh, rec, pd, err)) {
+ return FALSE;
+ }
+ break;
+ default:
+ if (!pcapng_write_custom_block(wdh, rec, pd, err)) {
+ return FALSE;
+ }
+ break;
}
break;
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index d10e6856c1..a332e66f13 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -1323,8 +1323,17 @@ typedef struct {
guint32 length; /* length of the record */
guint32 pen; /* private enterprise number */
gboolean copy_allowed; /* CB can be written */
+ union {
+ struct nflx {
+ guint32 type; /* block type */
+ guint32 skipped; /* Used if type == BBLOG_TYPE_SKIPPED_BLOCK */
+ } nflx_custom_data_header;
+ } custom_data_header;
} wtap_custom_block_header;
+#define BBLOG_TYPE_EVENT_BLOCK 1
+#define BBLOG_TYPE_SKIPPED_BLOCK 2
+
typedef struct {
guint rec_type; /* what type of record is this? */
guint32 presence_flags; /* what stuff do we have? */
diff --git a/wiretap/wtap_opttypes.c b/wiretap/wtap_opttypes.c
index dfbab29f32..928b64b2d5 100644
--- a/wiretap/wtap_opttypes.c
+++ b/wiretap/wtap_opttypes.c
@@ -299,7 +299,14 @@ static void wtap_block_free_option(wtap_block_t block, wtap_option_t *opt)
break;
case WTAP_OPTTYPE_CUSTOM:
- g_free(opt->value.custom_opt.custom_data);
+ switch (opt->value.custom_opt.pen) {
+ case PEN_NFLX:
+ g_free(opt->value.custom_opt.data.nflx_data.custom_data);
+ break;
+ default:
+ g_free(opt->value.custom_opt.data.generic_data.custom_data);
+ break;
+ }
break;
default:
@@ -433,7 +440,14 @@ wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block)
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);
+ switch (src_opt->value.custom_opt.pen) {
+ case PEN_NFLX:
+ wtap_block_add_nflx_custom_option(dest_block, src_opt->value.custom_opt.data.nflx_data.type, src_opt->value.custom_opt.data.nflx_data.custom_data, src_opt->value.custom_opt.data.nflx_data.custom_data_len);
+ break;
+ default:
+ wtap_block_add_custom_option(dest_block, src_opt->option_id, src_opt->value.custom_opt.pen, src_opt->value.custom_opt.data.generic_data.custom_data, src_opt->value.custom_opt.data.generic_data.custom_data_len);
+ break;
+ }
break;
}
}
@@ -500,7 +514,18 @@ wtap_block_option_get_value_size(wtap_opttype_e option_type, wtap_optval_t *opti
break;
case WTAP_OPTTYPE_CUSTOM:
- ret_val += sizeof(guint32) + option->custom_opt.custom_data_len;
+ /* 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;
@@ -1205,6 +1230,190 @@ wtap_block_get_if_filter_option_value(wtap_block_t block, guint option_id, if_fi
}
wtap_opttype_return_val
+wtap_block_add_nflx_custom_option(wtap_block_t block, guint32 type, const char *custom_data, gsize custom_data_len)
+{
+ wtap_opttype_return_val ret;
+ wtap_option_t *opt;
+
+ ret = wtap_block_add_option_common(block, OPT_CUSTOM_BIN_COPY, WTAP_OPTTYPE_CUSTOM, &opt);
+ if (ret != WTAP_OPTTYPE_SUCCESS)
+ return ret;
+ opt->value.custom_opt.pen = PEN_NFLX;
+ opt->value.custom_opt.data.nflx_data.type = type;
+ opt->value.custom_opt.data.nflx_data.custom_data_len = custom_data_len;
+ opt->value.custom_opt.data.nflx_data.custom_data = g_memdup2(custom_data, custom_data_len);
+ opt->value.custom_opt.data.nflx_data.use_little_endian = (block->info->block_type == WTAP_BLOCK_CUSTOM);
+ return WTAP_OPTTYPE_SUCCESS;
+}
+
+wtap_opttype_return_val
+wtap_block_get_nflx_custom_option(wtap_block_t block, guint32 nflx_type, char *nflx_custom_data _U_, gsize nflx_custom_data_len)
+{
+ const wtap_opttype_t *opttype;
+ wtap_option_t *opt;
+ guint i;
+
+ if (block == NULL) {
+ return WTAP_OPTTYPE_BAD_BLOCK;
+ }
+ opttype = GET_OPTION_TYPE(block->info->options, OPT_CUSTOM_BIN_COPY);
+ if (opttype == NULL) {
+ return WTAP_OPTTYPE_NO_SUCH_OPTION;
+ }
+ if (opttype->data_type != WTAP_OPTTYPE_CUSTOM) {
+ return WTAP_OPTTYPE_TYPE_MISMATCH;
+ }
+
+ for (i = 0; i < block->options->len; i++) {
+ opt = &g_array_index(block->options, wtap_option_t, i);
+ if ((opt->option_id == OPT_CUSTOM_BIN_COPY) &&
+ (opt->value.custom_opt.pen == PEN_NFLX) &&
+ (opt->value.custom_opt.data.nflx_data.type == nflx_type)) {
+ break;
+ }
+ }
+ if (i == block->options->len) {
+ return WTAP_OPTTYPE_NOT_FOUND;
+ }
+ if (nflx_custom_data_len < opt->value.custom_opt.data.nflx_data.custom_data_len) {
+ return WTAP_OPTTYPE_TYPE_MISMATCH;
+ }
+ switch (nflx_type) {
+ case NFLX_OPT_TYPE_VERSION: {
+ guint32 *src, *dst;
+
+ ws_assert(nflx_custom_data_len == sizeof(guint32));
+ src = (guint32 *)opt->value.custom_opt.data.nflx_data.custom_data;
+ dst = (guint32 *)nflx_custom_data;
+ *dst = GUINT32_FROM_LE(*src);
+ break;
+ }
+ case NFLX_OPT_TYPE_TCPINFO: {
+ struct nflx_tcpinfo *src, *dst;
+
+ ws_assert(nflx_custom_data_len == sizeof(struct nflx_tcpinfo));
+ src = (struct nflx_tcpinfo *)opt->value.custom_opt.data.nflx_data.custom_data;
+ dst = (struct nflx_tcpinfo *)nflx_custom_data;
+ dst->tlb_tv_sec = GUINT64_FROM_LE(src->tlb_tv_sec);
+ dst->tlb_tv_usec = GUINT64_FROM_LE(src->tlb_tv_usec);
+ dst->tlb_ticks = GUINT32_FROM_LE(src->tlb_ticks);
+ dst->tlb_sn = GUINT32_FROM_LE(src->tlb_sn);
+ dst->tlb_stackid = src->tlb_stackid;
+ dst->tlb_eventid = src->tlb_eventid;
+ dst->tlb_eventflags = GUINT16_FROM_LE(src->tlb_eventflags);
+ dst->tlb_errno = GINT32_FROM_LE(src->tlb_errno);
+ dst->tlb_rxbuf_tls_sb_acc = GUINT32_FROM_LE(src->tlb_rxbuf_tls_sb_acc);
+ dst->tlb_rxbuf_tls_sb_ccc = GUINT32_FROM_LE(src->tlb_rxbuf_tls_sb_ccc);
+ dst->tlb_rxbuf_tls_sb_spare = GUINT32_FROM_LE(src->tlb_rxbuf_tls_sb_spare);
+ dst->tlb_txbuf_tls_sb_acc = GUINT32_FROM_LE(src->tlb_txbuf_tls_sb_acc);
+ dst->tlb_txbuf_tls_sb_ccc = GUINT32_FROM_LE(src->tlb_txbuf_tls_sb_ccc);
+ dst->tlb_txbuf_tls_sb_spare = GUINT32_FROM_LE(src->tlb_txbuf_tls_sb_spare);
+ dst->tlb_state = GINT32_FROM_LE(src->tlb_state);
+ dst->tlb_starttime = GUINT32_FROM_LE(src->tlb_starttime);
+ dst->tlb_iss = GUINT32_FROM_LE(src->tlb_iss);
+ dst->tlb_flags = GUINT32_FROM_LE(src->tlb_flags);
+ dst->tlb_snd_una = GUINT32_FROM_LE(src->tlb_snd_una);
+ dst->tlb_snd_max = GUINT32_FROM_LE(src->tlb_snd_max);
+ dst->tlb_snd_cwnd = GUINT32_FROM_LE(src->tlb_snd_cwnd);
+ dst->tlb_snd_nxt = GUINT32_FROM_LE(src->tlb_snd_nxt);
+ dst->tlb_snd_recover = GUINT32_FROM_LE(src->tlb_snd_recover);
+ dst->tlb_snd_wnd = GUINT32_FROM_LE(src->tlb_snd_wnd);
+ dst->tlb_snd_ssthresh = GUINT32_FROM_LE(src->tlb_snd_ssthresh);
+ dst->tlb_srtt = GUINT32_FROM_LE(src->tlb_srtt);
+ dst->tlb_rttvar = GUINT32_FROM_LE(src->tlb_rttvar);
+ dst->tlb_rcv_up = GUINT32_FROM_LE(src->tlb_rcv_up);
+ dst->tlb_rcv_adv = GUINT32_FROM_LE(src->tlb_rcv_adv);
+ dst->tlb_flags2 = GUINT32_FROM_LE(src->tlb_flags2);
+ dst->tlb_rcv_nxt = GUINT32_FROM_LE(src->tlb_rcv_nxt);
+ dst->tlb_rcv_wnd = GUINT32_FROM_LE(src->tlb_rcv_wnd);
+ dst->tlb_dupacks = GUINT32_FROM_LE(src->tlb_dupacks);
+ dst->tlb_segqlen = GINT32_FROM_LE(src->tlb_segqlen);
+ dst->tlb_snd_numholes = GINT32_FROM_LE(src->tlb_snd_numholes);
+ dst->tlb_flex1 = GUINT32_FROM_LE(src->tlb_flex1);
+ dst->tlb_flex2 = GUINT32_FROM_LE(src->tlb_flex2);
+ dst->tlb_fbyte_in = GUINT32_FROM_LE(src->tlb_fbyte_in);
+ dst->tlb_fbyte_out = GUINT32_FROM_LE(src->tlb_fbyte_out);
+ dst->tlb_snd_scale = src->tlb_snd_scale;
+ dst->tlb_rcv_scale = src->tlb_rcv_scale;
+ for (i = 0; i < 3; i++) {
+ dst->_pad[i] = src->_pad[i];
+ }
+ dst->tlb_stackinfo_bbr_cur_del_rate = GUINT64_FROM_LE(src->tlb_stackinfo_bbr_cur_del_rate);
+ dst->tlb_stackinfo_bbr_delRate = GUINT64_FROM_LE(src->tlb_stackinfo_bbr_delRate);
+ dst->tlb_stackinfo_bbr_rttProp = GUINT64_FROM_LE(src->tlb_stackinfo_bbr_rttProp);
+ dst->tlb_stackinfo_bbr_bw_inuse = GUINT64_FROM_LE(src->tlb_stackinfo_bbr_bw_inuse);
+ dst->tlb_stackinfo_bbr_inflight = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_inflight);
+ dst->tlb_stackinfo_bbr_applimited = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_applimited);
+ dst->tlb_stackinfo_bbr_delivered = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_delivered);
+ dst->tlb_stackinfo_bbr_timeStamp = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_timeStamp);
+ dst->tlb_stackinfo_bbr_epoch = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_epoch);
+ dst->tlb_stackinfo_bbr_lt_epoch = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_lt_epoch);
+ dst->tlb_stackinfo_bbr_pkts_out = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_pkts_out);
+ dst->tlb_stackinfo_bbr_flex1 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex1);
+ dst->tlb_stackinfo_bbr_flex2 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex2);
+ dst->tlb_stackinfo_bbr_flex3 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex3);
+ dst->tlb_stackinfo_bbr_flex4 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex4);
+ dst->tlb_stackinfo_bbr_flex5 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex5);
+ dst->tlb_stackinfo_bbr_flex6 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex6);
+ dst->tlb_stackinfo_bbr_lost = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_lost);
+ dst->tlb_stackinfo_bbr_pacing_gain = GUINT16_FROM_LE(src->tlb_stackinfo_bbr_lost);
+ dst->tlb_stackinfo_bbr_cwnd_gain = GUINT16_FROM_LE(src->tlb_stackinfo_bbr_lost);
+ dst->tlb_stackinfo_bbr_flex7 = GUINT16_FROM_LE(src->tlb_stackinfo_bbr_flex7);
+ dst->tlb_stackinfo_bbr_bbr_state = src->tlb_stackinfo_bbr_bbr_state;
+ dst->tlb_stackinfo_bbr_bbr_substate = src->tlb_stackinfo_bbr_bbr_substate;
+ dst->tlb_stackinfo_bbr_inhpts = src->tlb_stackinfo_bbr_inhpts;
+ dst->tlb_stackinfo_bbr_ininput = src->tlb_stackinfo_bbr_ininput;
+ dst->tlb_stackinfo_bbr_use_lt_bw = src->tlb_stackinfo_bbr_use_lt_bw;
+ dst->tlb_stackinfo_bbr_flex8 = src->tlb_stackinfo_bbr_flex8;
+ dst->tlb_stackinfo_bbr_pkt_epoch = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_pkt_epoch);
+ dst->tlb_len = GUINT32_FROM_LE(src->tlb_len);
+ break;
+ }
+ case NFLX_OPT_TYPE_DUMPINFO: {
+ struct nflx_dumpinfo *src, *dst;
+
+ ws_assert(nflx_custom_data_len == sizeof(struct nflx_dumpinfo));
+ src = (struct nflx_dumpinfo *)opt->value.custom_opt.data.nflx_data.custom_data;
+ dst = (struct nflx_dumpinfo *)nflx_custom_data;
+ dst->tlh_version = GUINT32_FROM_LE(src->tlh_version);
+ dst->tlh_type = GUINT32_FROM_LE(src->tlh_type);
+ dst->tlh_length = GUINT64_FROM_LE(src->tlh_length);
+ dst->tlh_ie_fport = src->tlh_ie_fport;
+ dst->tlh_ie_lport = src->tlh_ie_lport;
+ for (i = 0; i < 4; i++) {
+ dst->tlh_ie_faddr_addr32[i] = src->tlh_ie_faddr_addr32[i];
+ dst->tlh_ie_laddr_addr32[i] = src->tlh_ie_laddr_addr32[i];
+ }
+ dst->tlh_ie_zoneid = src->tlh_ie_zoneid;
+ dst->tlh_offset_tv_sec = GUINT64_FROM_LE(src->tlh_offset_tv_sec);
+ dst->tlh_offset_tv_usec = GUINT64_FROM_LE(src->tlh_offset_tv_usec);
+ memcpy(dst->tlh_id, src->tlh_id, 64);
+ memcpy(dst->tlh_reason, src->tlh_reason, 32);
+ memcpy(dst->tlh_tag, src->tlh_tag, 32);
+ dst->tlh_af = src->tlh_af;
+ memcpy(dst->_pad, src->_pad, 7);
+ break;
+ }
+ case NFLX_OPT_TYPE_DUMPTIME: {
+ guint64 *src, *dst;
+
+ ws_assert(nflx_custom_data_len == sizeof(guint64));
+ src = (guint64 *)opt->value.custom_opt.data.nflx_data.custom_data;
+ dst = (guint64 *)nflx_custom_data;
+ *dst = GUINT64_FROM_LE(*src);
+ break;
+ }
+ case NFLX_OPT_TYPE_STACKNAME:
+ ws_assert(nflx_custom_data_len >= 2);
+ memcpy(nflx_custom_data, opt->value.custom_opt.data.nflx_data.custom_data, nflx_custom_data_len);
+ break;
+ default:
+ return WTAP_OPTTYPE_NOT_FOUND;
+ }
+ 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;
@@ -1214,8 +1423,8 @@ wtap_block_add_custom_option(wtap_block_t block, guint option_id, guint32 pen, c
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);
+ opt->value.custom_opt.data.generic_data.custom_data_len = custom_data_len;
+ opt->value.custom_opt.data.generic_data.custom_data = g_memdup2(custom_data, custom_data_len);
return WTAP_OPTTYPE_SUCCESS;
}
@@ -1414,6 +1623,12 @@ static void pkt_create(wtap_block_t block)
block->mandatory_data = NULL;
}
+static void cb_create(wtap_block_t block)
+{
+ /* Ensure this is null, so when g_free is called on it, it simply returns */
+ block->mandatory_data = NULL;
+}
+
void wtap_opttypes_initialize(void)
{
static wtap_blocktype_t shb_block = {
@@ -1639,6 +1854,16 @@ void wtap_opttypes_initialize(void)
WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED
};
+ static wtap_blocktype_t cb_block = {
+ WTAP_BLOCK_CUSTOM, /* block_type */
+ "CB", /* name */
+ "Packet Block", /* description */
+ cb_create, /* create */
+ NULL, /* free_mand */
+ NULL, /* copy_mand */
+ NULL /* options */
+ };
+
/*
* Register the SHB and the options that can appear in it.
*/
@@ -1699,6 +1924,11 @@ void wtap_opttypes_initialize(void)
wtap_opttype_option_register(&pkt_block, OPT_PKT_HASH, &pkt_hash);
wtap_opttype_option_register(&pkt_block, OPT_PKT_VERDICT, &pkt_verdict);
+ /*
+ * Register the CB and the options that can appear in it.
+ */
+ wtap_opttype_block_register(&cb_block);
+
#ifdef DEBUG_COUNT_REFS
memset(blocks_active, 0, sizeof(blocks_active));
#endif
diff --git a/wiretap/wtap_opttypes.h b/wiretap/wtap_opttypes.h
index e9c11fd9df..e0fadac663 100644
--- a/wiretap/wtap_opttypes.h
+++ b/wiretap/wtap_opttypes.h
@@ -323,17 +323,41 @@ typedef struct if_filter_opt_s {
} data;
} if_filter_opt_t;
+/* https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers */
+#define PEN_NFLX 10949
+
/*
* Structure describing a custom option.
*/
typedef struct custom_opt_s {
guint32 pen;
- gsize custom_data_len;
- gchar *custom_data;
+ union {
+ struct generic_custom_opt_data {
+ gsize custom_data_len;
+ gchar *custom_data;
+ } generic_data;
+ struct nflx_custom_opt_data {
+ guint32 type;
+ gsize custom_data_len;
+ gchar *custom_data;
+ gboolean use_little_endian;
+ } nflx_data;
+ } data;
} custom_opt_t;
/*
+ * Structure describing a NFLX custom option.
+ */
+
+typedef struct nflx_custom_opt_s {
+ gboolean nflx_use_little_endian;
+ guint32 nflx_type;
+ gsize nflx_custom_data_len;
+ gchar *nflx_custom_data;
+} nflx_custom_opt_t;
+
+/*
* Structure describing a value of an option.
*/
typedef union {
@@ -356,6 +380,114 @@ typedef struct {
wtap_optval_t value; /**< value */
} wtap_option_t;
+#define NFLX_OPT_TYPE_VERSION 1
+#define NFLX_OPT_TYPE_TCPINFO 2
+#define NFLX_OPT_TYPE_DUMPINFO 4
+#define NFLX_OPT_TYPE_DUMPTIME 5
+#define NFLX_OPT_TYPE_STACKNAME 6
+
+struct nflx_dumpinfo {
+ guint32 tlh_version;
+ guint32 tlh_type;
+ guint64 tlh_length;
+ guint16 tlh_ie_fport;
+ guint16 tlh_ie_lport;
+ guint32 tlh_ie_faddr_addr32[4];
+ guint32 tlh_ie_laddr_addr32[4];
+ guint32 tlh_ie_zoneid;
+ guint64 tlh_offset_tv_sec;
+ guint64 tlh_offset_tv_usec;
+ char tlh_id[64];
+ char tlh_reason[32];
+ char tlh_tag[32];
+ guint8 tlh_af;
+ guint8 _pad[7];
+};
+
+/* Flags used in tlb_eventflags */
+#define NFLX_TLB_FLAG_RXBUF 0x0001 /* Includes receive buffer info */
+#define NFLX_TLB_FLAG_TXBUF 0x0002 /* Includes send buffer info */
+#define NFLX_TLB_FLAG_HDR 0x0004 /* Includes a TCP header */
+#define NFLX_TLB_FLAG_VERBOSE 0x0008 /* Includes function/line numbers */
+#define NFLX_TLB_FLAG_STACKINFO 0x0010 /* Includes stack-specific info */
+
+struct nflx_tcpinfo {
+ guint64 tlb_tv_sec;
+ guint64 tlb_tv_usec;
+ guint32 tlb_ticks;
+ guint32 tlb_sn;
+ guint8 tlb_stackid;
+ guint8 tlb_eventid;
+ guint16 tlb_eventflags;
+ gint32 tlb_errno;
+ guint32 tlb_rxbuf_tls_sb_acc;
+ guint32 tlb_rxbuf_tls_sb_ccc;
+ guint32 tlb_rxbuf_tls_sb_spare;
+ guint32 tlb_txbuf_tls_sb_acc;
+ guint32 tlb_txbuf_tls_sb_ccc;
+ guint32 tlb_txbuf_tls_sb_spare;
+ gint32 tlb_state;
+ guint32 tlb_starttime;
+ guint32 tlb_iss;
+ guint32 tlb_flags;
+ guint32 tlb_snd_una;
+ guint32 tlb_snd_max;
+ guint32 tlb_snd_cwnd;
+ guint32 tlb_snd_nxt;
+ guint32 tlb_snd_recover;
+ guint32 tlb_snd_wnd;
+ guint32 tlb_snd_ssthresh;
+ guint32 tlb_srtt;
+ guint32 tlb_rttvar;
+ guint32 tlb_rcv_up;
+ guint32 tlb_rcv_adv;
+ guint32 tlb_flags2;
+ guint32 tlb_rcv_nxt;
+ guint32 tlb_rcv_wnd;
+ guint32 tlb_dupacks;
+ gint32 tlb_segqlen;
+ gint32 tlb_snd_numholes;
+ guint32 tlb_flex1;
+ guint32 tlb_flex2;
+ guint32 tlb_fbyte_in;
+ guint32 tlb_fbyte_out;
+ guint8 tlb_snd_scale:4,
+ tlb_rcv_scale:4;
+ guint8 _pad[3];
+
+ /* The following fields might become part of a union */
+ guint64 tlb_stackinfo_bbr_cur_del_rate;
+ guint64 tlb_stackinfo_bbr_delRate;
+ guint64 tlb_stackinfo_bbr_rttProp;
+ guint64 tlb_stackinfo_bbr_bw_inuse;
+ guint32 tlb_stackinfo_bbr_inflight;
+ guint32 tlb_stackinfo_bbr_applimited;
+ guint32 tlb_stackinfo_bbr_delivered;
+ guint32 tlb_stackinfo_bbr_timeStamp;
+ guint32 tlb_stackinfo_bbr_epoch;
+ guint32 tlb_stackinfo_bbr_lt_epoch;
+ guint32 tlb_stackinfo_bbr_pkts_out;
+ guint32 tlb_stackinfo_bbr_flex1;
+ guint32 tlb_stackinfo_bbr_flex2;
+ guint32 tlb_stackinfo_bbr_flex3;
+ guint32 tlb_stackinfo_bbr_flex4;
+ guint32 tlb_stackinfo_bbr_flex5;
+ guint32 tlb_stackinfo_bbr_flex6;
+ guint32 tlb_stackinfo_bbr_lost;
+ guint16 tlb_stackinfo_bbr_pacing_gain;
+ guint16 tlb_stackinfo_bbr_cwnd_gain;
+ guint16 tlb_stackinfo_bbr_flex7;
+ guint8 tlb_stackinfo_bbr_bbr_state;
+ guint8 tlb_stackinfo_bbr_bbr_substate;
+ guint8 tlb_stackinfo_bbr_inhpts;
+ guint8 tlb_stackinfo_bbr_ininput;
+ guint8 tlb_stackinfo_bbr_use_lt_bw;
+ guint8 tlb_stackinfo_bbr_flex8;
+ guint32 tlb_stackinfo_bbr_pkt_epoch;
+
+ guint32 tlb_len;
+};
+
struct wtap_dumper;
typedef void (*wtap_block_create_func)(wtap_block_t block);
@@ -808,6 +940,30 @@ 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 NFLX custom option to a block
+ *
+ * @param[in] block Block to which to add the option
+ * @param[in] nflx_type NFLX option type
+ * @param[in] nflx_custom_data pointer to the data
+ * @param[in] nflx_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_nflx_custom_option(wtap_block_t block, guint32 nflx_type, const char *nflx_custom_data, gsize nflx_custom_data_len);
+
+/** Get an if_filter option value from a block
+ *
+ * @param[in] block Block from which to get the option value
+ * @param[in] nflx_type type of the option
+ * @param[out] nflx_custom_data Returned value of NFLX custom option value
+ * @param[in] nflx_custom_data_len size of buffer provided in nflx_custom_data
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_get_nflx_custom_option(wtap_block_t block, guint32 nflx_type, char *nflx_custom_data, gsize nflx_custom_data_len);
+
/** Add an custom option to a block
*
* @param[in] block Block to which to add the option