diff options
author | Michael Tuexen <tuexen@wireshark.org> | 2021-08-04 19:57:52 +0200 |
---|---|---|
committer | Michael Tuexen <tuexen@wireshark.org> | 2021-08-27 04:48:21 +0200 |
commit | b17f354304242ac14769f7b4f13b65b077b769a8 (patch) | |
tree | a1cb3b40942fe4b9958a31e854f902cdafcbeece /wiretap | |
parent | 8c4543373ad6a3c870f30d33dedf7bcdc12796ac (diff) |
Add initial support for BBLog files
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/pcapng.c | 391 | ||||
-rw-r--r-- | wiretap/wtap.h | 9 | ||||
-rw-r--r-- | wiretap/wtap_opttypes.c | 240 | ||||
-rw-r--r-- | wiretap/wtap_opttypes.h | 160 |
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 |