Add initial support for BBLog files

This commit is contained in:
Michael Tuexen 2021-08-04 19:57:52 +02:00
parent 8c4543373a
commit b17f354304
10 changed files with 1286 additions and 78 deletions

View File

@ -28,6 +28,7 @@ libwiretap.so.0 libwiretap0 #MINVER#
wtap_block_add_if_filter_option@Base 3.5.0
wtap_block_add_ipv4_option@Base 2.1.2
wtap_block_add_ipv6_option@Base 2.1.2
wtap_block_add_nflx_custom_option@Base 3.5.0
wtap_block_add_string_option@Base 2.1.2
wtap_block_add_string_option_format@Base 2.1.2
wtap_block_add_uint32_option@Base 3.5.0
@ -43,6 +44,7 @@ libwiretap.so.0 libwiretap0 #MINVER#
wtap_block_get_ipv4_option_value@Base 2.1.2
wtap_block_get_ipv6_option_value@Base 2.1.2
wtap_block_get_mandatory_data@Base 2.1.2
wtap_block_get_nflx_custom_option@Base 3.5.0
wtap_block_get_nth_bytes_option_value@Base 3.5.0
wtap_block_get_nth_string_option_value@Base 2.1.2
wtap_block_get_options_size_padded@Base 3.5.0

View File

@ -734,6 +734,7 @@ set(DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-banana.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bat.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-batadv.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bblog.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bctp.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-beep.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-bencode.c

View File

@ -0,0 +1,419 @@
/* packet-bblog.c
* Routines for Black Box Log dissection
* Copyright 2021 Michael Tuexen <tuexen [AT] wireshark.org>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <epan/packet.h>
void proto_register_bblog_event(void);
void proto_reg_handoff_bblog(void);
static int proto_bblog = -1;
static int hf_ticks = -1;
static int hf_serial_nr = -1;
static int hf_stack_id = -1;
static int hf_event_id = -1;
static int hf_event_flags = -1;
static int hf_event_flags_rxbuf = -1;
static int hf_event_flags_txbuf = -1;
static int hf_event_flags_hdr = -1;
static int hf_event_flags_verbose = -1;
static int hf_event_flags_stack = -1;
static int hf_errno = -1;
static int hf_rxb_acc = -1;
static int hf_rxb_ccc = -1;
static int hf_rxb_spare = -1;
static int hf_txb_acc = -1;
static int hf_txb_ccc = -1;
static int hf_txb_spare = -1;
static int hf_state = -1;
static int hf_starttime = -1;
static int hf_iss = -1;
static int hf_flags = -1;
static int hf_snd_una = -1;
static int hf_snd_max = -1;
static int hf_snd_cwnd = -1;
static int hf_snd_nxt = -1;
static int hf_snd_recover = -1;
static int hf_snd_wnd = -1;
static int hf_snd_ssthresh = -1;
static int hf_srtt = -1;
static int hf_rttvar = -1;
static int hf_rcv_up = -1;
static int hf_rcv_adv = -1;
static int hf_flags2 = -1;
static int hf_rcv_nxt = -1;
static int hf_rcv_wnd = -1;
static int hf_dupacks = -1;
static int hf_seg_qlen = -1;
static int hf_snd_num_holes = -1;
static int hf_flex_1 = -1;
static int hf_flex_2 = -1;
static int hf_first_byte_in = -1;
static int hf_first_byte_out = -1;
static int hf_snd_scale = -1;
static int hf_rcv_scale = -1;
static int hf_pad_1 = -1;
static int hf_pad_2 = -1;
static int hf_pad_3 = -1;
static int hf_payload_len = -1;
static gint ett_bblog = -1;
static gint ett_bblog_flags = -1;
#define TCP_LOG_IN 1
#define TCP_LOG_OUT 2
#define TCP_LOG_RTO 3
#define TCP_LOG_SB_WAKE 4
#define TCP_LOG_BAD_RETRAN 5
#define TCP_LOG_PRR 6
#define TCP_LOG_REORDER 7
#define TCP_LOG_HPTS 8
#define BBR_LOG_BBRUPD 9
#define BBR_LOG_BBRSND 10
#define BBR_LOG_ACKCLEAR 11
#define BBR_LOG_INQUEUE 12
#define BBR_LOG_TIMERSTAR 13
#define BBR_LOG_TIMERCANC 14
#define BBR_LOG_ENTREC 15
#define BBR_LOG_EXITREC 16
#define BBR_LOG_CWND 17
#define BBR_LOG_BWSAMP 18
#define BBR_LOG_MSGSIZE 19
#define BBR_LOG_BBRRTT 20
#define BBR_LOG_JUSTRET 21
#define BBR_LOG_STATE 22
#define BBR_LOG_PKT_EPOCH 23
#define BBR_LOG_PERSIST 24
#define TCP_LOG_FLOWEND 25
#define BBR_LOG_RTO 26
#define BBR_LOG_DOSEG_DONE 27
#define BBR_LOG_EXIT_GAIN 28
#define BBR_LOG_THRESH_CALC 29
#define TCP_LOG_MAPCHG 30
#define TCP_LOG_USERSEND 31
#define BBR_RSM_CLEARED 32
#define BBR_LOG_STATE_TARGET 33
#define BBR_LOG_TIME_EPOCH 34
#define BBR_LOG_TO_PROCESS 35
#define BBR_LOG_BBRTSO 36
#define BBR_LOG_HPTSDIAG 37
#define BBR_LOG_LOWGAIN 38
#define BBR_LOG_PROGRESS 39
#define TCP_LOG_SOCKET_OPT 40
#define BBR_LOG_TIMERPREP 41
#define BBR_LOG_ENOBUF_JMP 42
#define BBR_LOG_HPTSI_CALC 43
#define BBR_LOG_RTT_SHRINKS 44
#define BBR_LOG_BW_RED_EV 45
#define BBR_LOG_REDUCE 46
#define TCP_LOG_RTT 47
#define BBR_LOG_SETTINGS_CHG 48
#define BBR_LOG_SRTT_GAIN_EVENT 49
#define TCP_LOG_REASS 50
#define TCP_HDWR_TLS 51
#define BBR_LOG_HDWR_PACE 52
#define BBR_LOG_TSTMP_VAL 53
#define TCP_LOG_CONNEND 54
#define TCP_LOG_LRO 55
#define TCP_SACK_FILTER_RES 56
#define TCP_SAD_DETECTION 57
#define TCP_TIMELY_WORK 58
#define TCP_LOG_USER_EVENT 59
#define TCP_LOG_SENDFILE 60
#define TCP_LOG_HTTP_T 61
#define TCP_LOG_ACCOUNTING 62
#define TCP_LOG_FSB 63
static const value_string event_identifier_values[] = {
{ TCP_LOG_IN, "Incoming packet" },
{ TCP_LOG_OUT, "Transmit (without other event)" },
{ TCP_LOG_RTO, "Retransmit timeout" },
{ TCP_LOG_SB_WAKE, "Awaken socket buffer" },
{ TCP_LOG_BAD_RETRAN, "Detected bad retransmission" },
{ TCP_LOG_PRR, "Doing PRR" },
{ TCP_LOG_REORDER, "Detected reorder" },
{ TCP_LOG_HPTS, "Hpts sending a packet" },
{ BBR_LOG_BBRUPD, "We updated BBR info" },
{ BBR_LOG_BBRSND, "We did a slot calculation and sending is done" },
{ BBR_LOG_ACKCLEAR, "A ack clears all outstanding" },
{ BBR_LOG_INQUEUE, "The tcb had a packet input to it" },
{ BBR_LOG_TIMERSTAR, "Start a timer" },
{ BBR_LOG_TIMERCANC, "Cancel a timer" },
{ BBR_LOG_ENTREC, "Entered recovery" },
{ BBR_LOG_EXITREC, "Exited recovery" },
{ BBR_LOG_CWND, "Cwnd change" },
{ BBR_LOG_BWSAMP, "LT B/W sample has been made" },
{ BBR_LOG_MSGSIZE, "We received a EMSGSIZE error" },
{ BBR_LOG_BBRRTT, "BBR RTT is updated" },
{ BBR_LOG_JUSTRET, "We just returned out of output" },
{ BBR_LOG_STATE, "A BBR state change occured" },
{ BBR_LOG_PKT_EPOCH, "A BBR packet epoch occured" },
{ BBR_LOG_PERSIST, "BBR changed to/from a persists" },
{ TCP_LOG_FLOWEND, "End of a flow" },
{ BBR_LOG_RTO, "BBR's timeout includes BBR info" },
{ BBR_LOG_DOSEG_DONE, "hpts do_segment completes" },
{ BBR_LOG_EXIT_GAIN, "hpts do_segment completes" },
{ BBR_LOG_THRESH_CALC, "Doing threshold calculation" },
{ TCP_LOG_MAPCHG, "Map Changes to the sendmap" },
{ TCP_LOG_USERSEND, "User level sends data" },
{ BBR_RSM_CLEARED, "RSM cleared of ACK flags" },
{ BBR_LOG_STATE_TARGET, "Log of target at state" },
{ BBR_LOG_TIME_EPOCH, "A timed based Epoch occured" },
{ BBR_LOG_TO_PROCESS, "A to was processed" },
{ BBR_LOG_BBRTSO, "TSO update" },
{ BBR_LOG_HPTSDIAG, "Hpts diag insert" },
{ BBR_LOG_LOWGAIN, "Low gain accounting" },
{ BBR_LOG_PROGRESS, "Progress timer event" },
{ TCP_LOG_SOCKET_OPT, "A socket option is set" },
{ BBR_LOG_TIMERPREP, "A BBR var to debug out TLP issues" },
{ BBR_LOG_ENOBUF_JMP, "We had a enobuf jump" },
{ BBR_LOG_HPTSI_CALC, "calc the hptsi time" },
{ BBR_LOG_RTT_SHRINKS, "We had a log reduction of rttProp" },
{ BBR_LOG_BW_RED_EV, "B/W reduction events" },
{ BBR_LOG_REDUCE, "old bbr log reduce for 4.1 and earlier" },
{ TCP_LOG_RTT, "A rtt (in useconds) is being sampled and applied to the srtt algo" },
{ BBR_LOG_SETTINGS_CHG, "Settings changed for loss response 48" },
{ BBR_LOG_SRTT_GAIN_EVENT, "SRTT gaining -- now not used" },
{ TCP_LOG_REASS, "Reassembly buffer logging" },
{ TCP_HDWR_TLS, "TCP Hardware TLS logs" },
{ BBR_LOG_HDWR_PACE, "TCP Hardware pacing log" },
{ BBR_LOG_TSTMP_VAL, "Temp debug timestamp validation" },
{ TCP_LOG_CONNEND, "End of connection" },
{ TCP_LOG_LRO, "LRO entry" },
{ TCP_SACK_FILTER_RES, "Results of SACK Filter" },
{ TCP_SAD_DETECTION, "Sack Attack Detection" },
{ TCP_TIMELY_WORK, "Logs regarding Timely CC tweaks" },
{ TCP_LOG_USER_EVENT, "User space event data" },
{ TCP_LOG_SENDFILE, "sendfile() logging for TCP connections" },
{ TCP_LOG_HTTP_T, "logging of http request tracking" },
{ TCP_LOG_ACCOUNTING, "Log of TCP Accounting data" },
{ TCP_LOG_FSB, "FSB information 63" },
{ 0, NULL } };
static const value_string tcp_state_values[] = {
{ 0, "CLOSED" },
{ 1, "LISTEN" },
{ 2, "SYN SENT" },
{ 3, "SYN RECEIVED" },
{ 4, "ESTABLISHED" },
{ 5, "CLOSE WAIT" },
{ 6, "FIN WAIT 1" },
{ 7, "CLOSING" },
{ 8, "LAST ACK" },
{ 9, "FIN WAIT 2" },
{ 10, "TIME WAIT" },
{ 0, NULL } };
#define EVENT_FLAG_RXBUF 0x0001
#define EVENT_FLAG_TXBUF 0x0002
#define EVENT_FLAG_HDR 0x0004
#define EVENT_FLAG_VERBOSE 0x0008
#define EVENT_FLAG_STACKINFO 0x0010
static const true_false_string event_flags_rxbuf = {
"Receive buffer information available",
"Receive buffer information not available"
};
static const true_false_string event_flags_txbuf = {
"Send buffer information available",
"Send buffer information not available"
};
static const true_false_string event_flags_hdr = {
"TCP header available",
"TCP header not available"
};
static const true_false_string event_flags_verbose = {
"Additional information available",
"Additional information not available"
};
static const true_false_string event_flags_stack = {
"Stack specific information available",
"Stack specific information not available"
};
#define SND_SCALE_MASK 0xf0
#define RCV_SCALE_MASK 0x0f
/*
* The structures used here are defined in
* https://cgit.freebsd.org/src/tree/sys/netinet/tcp_log_buf.h
*/
static int
dissect_bblog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
proto_item *bblog_item, *event_flags_item;
proto_tree *bblog_tree, *event_flags_tree;
guint16 event_flags;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "BBLog");
col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_const(tvb_get_guint8(tvb, 25), event_identifier_values, "Unknown"));
bblog_item = proto_tree_add_item(tree, proto_bblog, tvb, 0, -1, ENC_NA);
bblog_tree = proto_item_add_subtree(bblog_item, ett_bblog);
proto_tree_add_item(bblog_tree, hf_ticks, tvb, 16, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_serial_nr, tvb, 20, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_stack_id, tvb, 24, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_event_id, tvb, 25, 1, ENC_LITTLE_ENDIAN);
event_flags = tvb_get_letohs(tvb, 26);
event_flags_item = proto_tree_add_item(bblog_tree, hf_event_flags, tvb, 26, 2, ENC_LITTLE_ENDIAN);
event_flags_tree = proto_item_add_subtree(event_flags_item, ett_bblog_flags);
proto_tree_add_item(event_flags_tree, hf_event_flags_rxbuf, tvb, 26, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(event_flags_tree, hf_event_flags_txbuf, tvb, 26, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(event_flags_tree, hf_event_flags_hdr, tvb, 26, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(event_flags_tree, hf_event_flags_verbose, tvb, 26, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(event_flags_tree, hf_event_flags_stack, tvb, 26, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_errno, tvb, 28, 4, ENC_LITTLE_ENDIAN);
if (event_flags & EVENT_FLAG_RXBUF) {
proto_tree_add_item(bblog_tree, hf_rxb_acc, tvb, 32, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_rxb_ccc, tvb, 36, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_rxb_spare, tvb, 40, 4, ENC_LITTLE_ENDIAN);
}
if (event_flags & EVENT_FLAG_TXBUF) {
proto_tree_add_item(bblog_tree, hf_txb_acc, tvb, 44, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_txb_ccc, tvb, 48, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_txb_spare, tvb, 52, 4, ENC_LITTLE_ENDIAN);
}
proto_tree_add_item(bblog_tree, hf_state, tvb, 56, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_starttime, tvb, 60, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_iss, tvb, 64, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_flags, tvb, 68, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_una, tvb, 72, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_max, tvb, 76, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_cwnd, tvb, 80, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_nxt, tvb, 84, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_recover, tvb, 88, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_wnd, tvb, 92, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_ssthresh, tvb, 96, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_srtt, tvb, 100, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_rttvar, tvb, 104, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_rcv_up, tvb, 108, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_rcv_adv, tvb, 112, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_flags2, tvb, 116, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_rcv_nxt, tvb, 120, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_rcv_wnd, tvb, 124, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_dupacks, tvb, 128, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_seg_qlen, tvb, 132, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_num_holes, tvb, 136, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_flex_1, tvb, 140, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_flex_2, tvb, 144, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_first_byte_in, tvb, 148, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_first_byte_out, tvb, 152, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_snd_scale, tvb, 156, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_rcv_scale, tvb, 156, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_pad_1, tvb, 157, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_pad_2, tvb, 158, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bblog_tree, hf_pad_3, tvb, 159, 1, ENC_LITTLE_ENDIAN);
if (event_flags & EVENT_FLAG_STACKINFO) {
/* stack specific data */
}
proto_tree_add_item(bblog_tree, hf_payload_len, tvb, 264, 4, ENC_LITTLE_ENDIAN);
return tvb_captured_length(tvb);
}
void
proto_register_bblog(void)
{
static hf_register_info hf[] = {
{ &hf_ticks, { "Ticks", "bblog.ticks", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_serial_nr, { "Serial Number", "bblog.serial_nr", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_stack_id, { "Stack Identifier", "bblog.stack_id", FT_UINT8, BASE_DEC, NULL , 0x0, NULL, HFILL} },
{ &hf_event_id, { "Event Identifier", "bblog.event_id", FT_UINT8, BASE_DEC, VALS(event_identifier_values), 0x0, NULL, HFILL} },
{ &hf_event_flags, { "Event Flags", "bblog.event_flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL} },
{ &hf_event_flags_rxbuf, { "Bit", "bblog.event_flags_rxbuf", FT_BOOLEAN, 8, TFS(&event_flags_rxbuf), EVENT_FLAG_RXBUF, NULL, HFILL} },
{ &hf_event_flags_txbuf, { "Bit", "bblog.event_flags_txbuf", FT_BOOLEAN, 8, TFS(&event_flags_txbuf), EVENT_FLAG_TXBUF, NULL, HFILL} },
{ &hf_event_flags_hdr, { "Bit", "bblog.event_flags_hdr", FT_BOOLEAN, 8, TFS(&event_flags_hdr), EVENT_FLAG_HDR, NULL, HFILL} },
{ &hf_event_flags_verbose, { "Bit", "bblog.event_flags_verbose", FT_BOOLEAN, 8, TFS(&event_flags_verbose), EVENT_FLAG_VERBOSE, NULL, HFILL} },
{ &hf_event_flags_stack, { "Bit", "bblog.event_flags_stack", FT_BOOLEAN, 8, TFS(&event_flags_stack), EVENT_FLAG_STACKINFO, NULL, HFILL} },
{ &hf_errno, { "Error Number", "bblog.errno", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_rxb_acc, { "Receive Buffer ACC", "bblog.rxb_acc", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_rxb_ccc, { "Receive Buffer CCC", "bblog.rxb_ccc", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_rxb_spare, { "Receive Buffer Spare", "bblog.rxb_spare", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_txb_acc, { "Send Buffer ACC", "bblog.txb_acc", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_txb_ccc, { "Send Buffer CCC", "bblog.txb_accs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_txb_spare, { "Send Buffer Spare", "bblog.txb_spare", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_state, { "TCP State", "bblog.state", FT_UINT32, BASE_DEC, VALS(tcp_state_values), 0x0, NULL, HFILL} },
{ &hf_starttime, { "Starttime", "bblog.starttime", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_iss, { "Initial Sending Sequence Number (ISS)", "bblog.iss", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_flags, { "TCB Flags", "bblog.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_una, { "Oldest Unacknowledged Sequence Number (SND.UNA)", "bblog.snd_una", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_max, { "Newest Sequence Number Sent (SND.MAX)", "bblog.snd_max", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_cwnd, { "Congestion Window", "bblog.snd_cwnd", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_nxt, { "Next Sequence Number (SND.NXT)", "bblog.snd_nxt", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_recover, { "Recovery Sequence Number (SND.RECOVER)", "bblog.snd_recover", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_wnd, { "Send Window (SND.WND)", "bblog.snd_wnd", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_ssthresh, { "Slowstart Threshold (SSTHREASH)", "bblog.snd_ssthresh", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_srtt, { "Smoothed Round Trip Time (SRTT)", "bblog.srtt", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_rttvar, { "Round Trip Timer Variance (RTTVAR)", "bblog.rttvar", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_rcv_up, { "Receive Urgent Pointer (RCV.UP)", "bblog.rcv_up", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_rcv_adv, { "Receive Advanced (RCV.ADV)", "bblog.rcv_adv", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_flags2, { "TCB Flags2", "bblog.flags2", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} },
{ &hf_rcv_nxt, { "Receive Next (RCV.NXT)", "bblog.rcv_nxt", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_rcv_wnd, { "Receive Window (RCV.WND)", "bblog.rcv_wnd", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_dupacks, { "Duplicate Acknowledgements", "bblog.dupacks", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_seg_qlen, { "Segment Queue Length", "bblog.seg_qlen", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_num_holes, { "Number of Holes", "bblog.snd_num_holes", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_flex_1, { "Flex 1", "bblog.flex_1", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_flex_2, { "Flex 2", "bblog.flex_2", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_first_byte_in, { "Time of First Byte In", "bblog.first_byte_in", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_first_byte_out, { "Time of First Byte Out", "bblog.first_byte_out", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_snd_scale, { "Shift Count for Send Window", "bblog.snd_shift", FT_UINT8, BASE_DEC, NULL, SND_SCALE_MASK, NULL, HFILL} },
{ &hf_rcv_scale, { "Shift Count for Receive Window", "bblog.rcv_shift", FT_UINT8, BASE_DEC, NULL, RCV_SCALE_MASK, NULL, HFILL} },
{ &hf_pad_1, { "Padding", "bblog.pad_1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_pad_2, { "Padding", "bblog.pad_2", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_pad_3, { "Padding", "bblog.pad_3", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} },
{ &hf_payload_len, { "TCP Payload Length", "bblog.payload_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} },
};
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_bblog,
&ett_bblog_flags
};
/* Register the protocol name and description */
proto_bblog = proto_register_protocol("Black Box Log", "BBLog", "bblog");
/* Required function calls to register the header fields and subtrees */
proto_register_field_array(proto_bblog, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("bblog", dissect_bblog, proto_bblog);
}
void
proto_reg_handoff_bblog(void)
{
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -47,6 +47,7 @@ void proto_reg_handoff_frame(void);
static int proto_frame = -1;
static int proto_pkt_comment = -1;
static int proto_syscall = -1;
static int proto_bblog = -1;
static int hf_frame_arrival_time = -1;
static int hf_frame_shift_offset = -1;
@ -94,6 +95,9 @@ static int hf_frame_pack_symbol_error = -1;
static int hf_frame_wtap_encap = -1;
static int hf_frame_cb_pen = -1;
static int hf_frame_cb_copy_allowed = -1;
static int hf_frame_bblog = -1;
static int hf_frame_bblog_ticks = -1;
static int hf_frame_bblog_serial_nr = -1;
static int hf_comments_text = -1;
static gint ett_frame = -1;
@ -101,6 +105,7 @@ static gint ett_ifname = -1;
static gint ett_flags = -1;
static gint ett_comments = -1;
static gint ett_verdict = -1;
static gint ett_bblog = -1;
static expert_field ei_comments_text = EI_INIT;
static expert_field ei_arrive_time_out_of_range = EI_INIT;
@ -111,6 +116,7 @@ static int frame_tap = -1;
static dissector_handle_t docsis_handle;
static dissector_handle_t sysdig_handle;
static dissector_handle_t systemd_journal_handle;
static dissector_handle_t bblog_handle;
/* Preferences */
static gboolean show_file_off = FALSE;
@ -350,6 +356,7 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
const color_filter_t *color_filter;
dissector_handle_t dissector_handle;
fr_foreach_t fr_user_data;
struct nflx_tcpinfo tcpinfo;
tree=parent_tree;
@ -451,7 +458,14 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
break;
case REC_TYPE_CUSTOM_BLOCK:
pinfo->current_proto = "PCAPNG Custom Block";
switch (pinfo->rec->rec_header.custom_block_header.pen) {
case PEN_NFLX:
pinfo->current_proto = "Black Box Log";
break;
default:
pinfo->current_proto = "PCAPNG Custom Block";
break;
}
break;
default:
@ -581,18 +595,28 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
break;
case REC_TYPE_CUSTOM_BLOCK:
ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb),
"PCAPNG Custom Block %u: %u byte%s",
pinfo->num, frame_len, frame_plurality);
if (generate_bits_field) {
proto_item_append_text(ti, " (%u bits)", frame_len * 8);
switch (pinfo->rec->rec_header.custom_block_header.pen) {
case PEN_NFLX:
ti = proto_tree_add_protocol_format(tree, proto_bblog, tvb, 0, tvb_captured_length(tvb),
"Black Box Log %u: %u byte%s",
pinfo->num, frame_len, frame_plurality);
break;
default:
ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb),
"PCAPNG Custom Block %u: %u byte%s",
pinfo->num, frame_len, frame_plurality);
if (generate_bits_field) {
proto_item_append_text(ti, " (%u bits)", frame_len * 8);
}
proto_item_append_text(ti, " of custom data and options, PEN %s (%u)",
enterprises_lookup(pinfo->rec->rec_header.custom_block_header.pen, "Unknown"),
pinfo->rec->rec_header.custom_block_header.pen);
proto_item_append_text(ti, ", copying%s allowed",
pinfo->rec->rec_header.custom_block_header.copy_allowed ? "" : " not");
break;
}
proto_item_append_text(ti, " of custom data and options, PEN %s (%u)",
enterprises_lookup(pinfo->rec->rec_header.custom_block_header.pen, "Unknown"),
pinfo->rec->rec_header.custom_block_header.pen);
proto_item_append_text(ti, ", copying%s allowed",
pinfo->rec->rec_header.custom_block_header.copy_allowed ? "" : " not");
break;
}
fh_tree = proto_item_add_subtree(ti, ett_frame);
@ -763,6 +787,15 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
proto_tree_add_uint(fh_tree, hf_link_number, tvb,
0, 0, pinfo->link_number);
}
if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_nflx_custom_option(fr_data->pkt_block, NFLX_OPT_TYPE_TCPINFO, (char *)&tcpinfo, sizeof(struct nflx_tcpinfo))) {
proto_tree *bblog_tree;
proto_item *bblog_item;
bblog_item = proto_tree_add_string(fh_tree, hf_frame_bblog, tvb, 0, 0, "");
bblog_tree = proto_item_add_subtree(bblog_item, ett_bblog);
proto_tree_add_uint(bblog_tree, hf_frame_bblog_ticks, tvb, 0, 0, tcpinfo.tlb_ticks);
proto_tree_add_uint(bblog_tree, hf_frame_bblog_serial_nr, tvb, 0, 0, tcpinfo.tlb_sn);
}
}
if (show_file_off) {
@ -874,19 +907,29 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void*
break;
case REC_TYPE_CUSTOM_BLOCK:
col_set_str(pinfo->cinfo, COL_PROTOCOL, "PCAPNG");
proto_tree_add_uint_format_value(fh_tree, hf_frame_cb_pen, tvb, 0, 0,
pinfo->rec->rec_header.custom_block_header.pen,
"%s (%u)",
enterprises_lookup(pinfo->rec->rec_header.custom_block_header.pen, "Unknown"),
pinfo->rec->rec_header.custom_block_header.pen);
proto_tree_add_boolean(fh_tree, hf_frame_cb_copy_allowed, tvb, 0, 0, pinfo->rec->rec_header.custom_block_header.copy_allowed);
col_add_fstr(pinfo->cinfo, COL_INFO, "Custom Block: PEN = %s (%d), will%s be copied",
enterprises_lookup(pinfo->rec->rec_header.custom_block_header.pen, "Unknown"),
pinfo->rec->rec_header.custom_block_header.pen,
pinfo->rec->rec_header.custom_block_header.copy_allowed ? "" : " not");
call_data_dissector(tvb, pinfo, parent_tree);
switch (pinfo->rec->rec_header.custom_block_header.pen) {
case PEN_NFLX:
call_dissector_with_data(bblog_handle,
tvb, pinfo, parent_tree,
(void *)pinfo->pseudo_header);
break;
default:
col_set_str(pinfo->cinfo, COL_PROTOCOL, "PCAPNG");
proto_tree_add_uint_format_value(fh_tree, hf_frame_cb_pen, tvb, 0, 0,
pinfo->rec->rec_header.custom_block_header.pen,
"%s (%u)",
enterprises_lookup(pinfo->rec->rec_header.custom_block_header.pen, "Unknown"),
pinfo->rec->rec_header.custom_block_header.pen);
proto_tree_add_boolean(fh_tree, hf_frame_cb_copy_allowed, tvb, 0, 0, pinfo->rec->rec_header.custom_block_header.copy_allowed);
col_add_fstr(pinfo->cinfo, COL_INFO, "Custom Block: PEN = %s (%d), will%s be copied",
enterprises_lookup(pinfo->rec->rec_header.custom_block_header.pen, "Unknown"),
pinfo->rec->rec_header.custom_block_header.pen,
pinfo->rec->rec_header.custom_block_header.copy_allowed ? "" : " not");
call_data_dissector(tvb, pinfo, parent_tree);
break;
}
break;
}
#ifdef _MSC_VER
} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
@ -1283,6 +1326,22 @@ proto_register_frame(void)
{ "Copying", "frame.cb_copy",
FT_BOOLEAN, BASE_DEC, TFS(&tfs_allowed_not_allowed), 0x0,
"Whether the custom block will be written or not", HFILL }},
{ &hf_frame_bblog,
{ "Black Box Log", "frame.bblog",
FT_STRING, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
{ &hf_frame_bblog_ticks,
{ "Ticks", "frame.bblog.ticks",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_frame_bblog_serial_nr,
{ "Serial Number", "frame.bblog.serial_nr",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
};
static hf_register_info hf_encap =
@ -1297,6 +1356,7 @@ proto_register_frame(void)
&ett_flags,
&ett_comments,
&ett_verdict,
&ett_bblog
};
static ei_register_info ei[] = {
@ -1326,6 +1386,7 @@ proto_register_frame(void)
proto_frame = proto_register_protocol("Frame", "Frame", "frame");
proto_pkt_comment = proto_register_protocol_in_name_only("Packet comments", "Pkt_Comment", "pkt_comment", proto_frame, FT_PROTOCOL);
proto_syscall = proto_register_protocol("System Call", "Syscall", "syscall");
proto_bblog = proto_get_id_by_filter_name("bblog");
proto_register_field_array(proto_frame, hf, array_length(hf));
proto_register_field_array(proto_frame, &hf_encap, 1);
@ -1378,6 +1439,7 @@ proto_reg_handoff_frame(void)
docsis_handle = find_dissector_add_dependency("docsis", proto_frame);
sysdig_handle = find_dissector_add_dependency("sysdig", proto_frame);
systemd_journal_handle = find_dissector_add_dependency("systemd_journal", proto_frame);
bblog_handle = find_dissector_add_dependency("bblog", proto_frame);
}
/*

View File

@ -207,9 +207,18 @@ frame_data_init(frame_data *fdata, guint32 num, const wtap_rec *rec,
/*
* XXX - is cum_bytes supposed to count non-packet bytes?
*/
fdata->pkt_len = rec->rec_header.custom_block_header.length;
fdata->cum_bytes = cum_bytes + rec->rec_header.custom_block_header.length;
fdata->cap_len = rec->rec_header.custom_block_header.length;
switch (rec->rec_header.custom_block_header.pen) {
case PEN_NFLX:
fdata->pkt_len = rec->rec_header.custom_block_header.length - 4;
fdata->cum_bytes = cum_bytes + rec->rec_header.custom_block_header.length - 4;
fdata->cap_len = rec->rec_header.custom_block_header.length - 4;
break;
default:
fdata->pkt_len = rec->rec_header.custom_block_header.length;
fdata->cum_bytes = cum_bytes + rec->rec_header.custom_block_header.length;
fdata->cap_len = rec->rec_header.custom_block_header.length;
break;
}
break;
}

View File

@ -508,7 +508,14 @@ dissect_record(epan_dissect_t *edt, int file_type_subtype,
break;
case REC_TYPE_CUSTOM_BLOCK:
record_type = "PCAPNG Custom Block";
switch (rec->rec_header.custom_block_header.pen) {
case PEN_NFLX:
record_type = "Black Box Log Block";
break;
default:
record_type = "PCAPNG Custom Block";
break;
}
break;
default:
@ -560,8 +567,16 @@ dissect_record(epan_dissect_t *edt, int file_type_subtype,
break;
case REC_TYPE_CUSTOM_BLOCK:
edt->pi.pseudo_header = NULL;
switch (rec->rec_header.custom_block_header.pen) {
case PEN_NFLX:
edt->pi.pseudo_header = NULL;
break;
default:
edt->pi.pseudo_header = NULL;
break;
}
break;
}
edt->pi.fd = fd;

View File

@ -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 */
@ -612,14 +615,98 @@ pcapng_process_bytes_option(wtapng_block_t *wblock, guint16 option_code,
wtap_block_add_bytes_option(wblock->block, option_code, (const char *)option_content, option_length);
}
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;

View File

@ -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? */

View File

@ -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;
@ -1204,6 +1229,190 @@ wtap_block_get_if_filter_option_value(wtap_block_t block, guint option_id, if_fi
return WTAP_OPTTYPE_SUCCESS;
}
wtap_opttype_return_val
wtap_block_add_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)
{
@ -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

View File

@ -323,16 +323,40 @@ 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.
*/
@ -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