diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index 83b0447ad5..f61e3bb12b 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -233,7 +233,7 @@ static int hf_tcp_option_ao_mac = -1; static int hf_tcp_option_qs_rate = -1; static int hf_tcp_option_qs_ttl_diff = -1; static int hf_tcp_option_exp_data = -1; -static int hf_tcp_option_exp_magic_number = -1; +static int hf_tcp_option_exp_exid = -1; static int hf_tcp_option_unknown_payload = -1; static int hf_tcp_option_rvbd_probe_version1 = -1; @@ -469,13 +469,14 @@ static gboolean tcp_no_subdissector_on_error = TRUE; static gboolean tcp_reassemble_out_of_order = FALSE; /* - * FF: (draft-ietf-tcpm-experimental-options-03) + * FF: https://www.rfc-editor.org/rfc/rfc6994.html * With this flag set we assume the option structure for experimental - * codepoints (253, 254) has a magic number field (first field after the - * Kind and Length). The magic number is used to differentiate different - * experiments and thus will be used in data dissection. + * codepoints (253, 254) has an Experiment Identifier (ExID), which is + * the first 16-bit field after the Kind and Length. + * The ExID is used to differentiate different experiments and thus will + * be used in data dissection. */ -static gboolean tcp_exp_options_with_magic = TRUE; +static gboolean tcp_exp_options_rfc6994 = TRUE; /* * This flag indicates which of Fast Retransmission or Out-of-Order @@ -547,7 +548,28 @@ static gboolean read_seq_as_syn_cookie = FALSE; #define TCPOLEN_TFO_MIN 2 #define TCPOLEN_RVBD_PROBE_MIN 3 #define TCPOLEN_RVBD_TRPY_MIN 16 -#define TCPOLEN_EXP_MIN 2 +#define TCPOLEN_EXP_MIN 4 + +/* + * TCP Experimental Option Experiment Identifiers (TCP ExIDs) + * See: https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-exids + * Wireshark only supports 16-bit ExIDs + */ + +#define TCPEXID_TARR 0x00ac +#define TCPEXID_HOST_ID 0x0348 +#define TCPEXID_ASC 0x0a0d +#define TCPEXID_CAPABILITY 0x0ca0 +#define TCPEXID_EDO 0x0ed0 +#define TCPEXID_ENO 0x454e +#define TCPEXID_SNO 0x5323 +#define TCPEXID_TS_INTERVAL 0x75ec /* 32-bit ExID: 0x75ecffee */ +#define TCPEXID_ACC_ECN_0 0xacc0 +#define TCPEXID_ACC_ECN_1 0xacc1 +#define TCPEXID_ACC_ECN 0xacce +#define TCPEXID_SMC_R 0xe2d4 /* 32-bit ExID: 0xe2d4c3d9 */ +#define TCPEXID_FO 0xf989 +#define TCPEXID_LOW_LATENCY 0xf990 /* * Multipath TCP subtypes @@ -617,6 +639,24 @@ static const value_string tcp_option_kind_vs[] = { }; static value_string_ext tcp_option_kind_vs_ext = VALUE_STRING_EXT_INIT(tcp_option_kind_vs); +static const value_string tcp_exid_vs[] = { + { TCPEXID_TARR, "TCP ACK Rate Request" }, + { TCPEXID_HOST_ID, "Host ID" }, + { TCPEXID_ASC, "Autonomous System Compensation" }, + { TCPEXID_CAPABILITY, "Capability Option" }, + { TCPEXID_EDO, "Extended Data Offset" }, + { TCPEXID_ENO, "Encryption Negotiation" }, + { TCPEXID_SNO, "Service Number" }, + { TCPEXID_TS_INTERVAL, "Timestamp Interval" }, + { TCPEXID_ACC_ECN_0, "Accurate ECN - Order 0" }, + { TCPEXID_ACC_ECN_1, "Accurate ECN - Order 1" }, + { TCPEXID_ACC_ECN, "Accurate ECN" }, + { TCPEXID_SMC_R, "Shared Memory communications over RMDA protocol" }, + { TCPEXID_FO, "Fast Open" }, + { TCPEXID_LOW_LATENCY, "Low Latency" }, + { 0, NULL } +}; + /* not all of the hf_fields below make sense for TCP but we have to provide them anyways to comply with the API (which was aimed for IP fragment reassembly) */ @@ -4728,6 +4768,12 @@ tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val) col_append_str_uint(pinfo->cinfo, COL_INFO, abbrev, val, " "); } +static void +tcp_info_append_hex_uint(packet_info *pinfo, const char *abbrev, guint32 val) +{ + col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%X", abbrev, val); +} + static gboolean tcp_option_len_check(proto_item* length_item, packet_info *pinfo, guint len, guint optlen) { @@ -4842,32 +4888,44 @@ dissect_tcpopt_tfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* da static int dissect_tcpopt_exp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { - proto_item *item; + proto_item *length_item, *item; proto_tree *exp_tree; - guint16 magic; + guint16 exid; + guint8 kind; gint offset = 0, optlen = tvb_reported_length(tvb); item = proto_tree_add_item(tree, proto_tcp_option_exp, tvb, offset, -1, ENC_NA); exp_tree = proto_item_add_subtree(item, ett_tcp_option_exp); - proto_tree_add_item(exp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); - if (tcp_exp_options_with_magic && ((optlen - 2) > 0)) { - magic = tvb_get_ntohs(tvb, offset + 2); - proto_tree_add_item(exp_tree, hf_tcp_option_exp_magic_number, tvb, - offset + 2, 2, ENC_BIG_ENDIAN); - switch (magic) { - case 0xf989: /* RFC7413, TCP Fast Open */ - dissect_tcpopt_tfo_payload(tvb, offset+2, optlen-2, pinfo, exp_tree, data); - break; - default: - /* Unknown magic number */ - break; + kind = tvb_get_guint8(tvb, offset); + length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + if (tcp_exp_options_rfc6994) { + if (optlen >= TCPOLEN_EXP_MIN) { + exid = tvb_get_ntohs(tvb, offset + 2); + proto_tree_add_item(exp_tree, hf_tcp_option_exp_exid, tvb, + offset + 2, 2, ENC_BIG_ENDIAN); + proto_item_append_text(item, ": %s", val_to_str_const(exid, tcp_exid_vs, "Unknown")); + switch (exid) { + case TCPEXID_FO: + dissect_tcpopt_tfo_payload(tvb, offset + 2, optlen - 2, pinfo, exp_tree, data); + break; + default: + if (optlen > TCPOLEN_EXP_MIN) { + proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb, + offset + TCPOLEN_EXP_MIN, + optlen - TCPOLEN_EXP_MIN, ENC_NA); + } + tcp_info_append_hex_uint(pinfo, "ExID", exid); + break; + } + } else { + expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, + "option length %u smaller than 4", optlen); } } else { proto_tree_add_item(exp_tree, hf_tcp_option_exp_data, tvb, offset + 2, optlen - 2, ENC_NA); - tcp_info_append_uint(pinfo, "Expxx", TRUE); + tcp_info_append_uint(pinfo, "Exp", (kind == TCPOPT_EXP_FD) ? 1 : 2); } return tvb_captured_length(tvb); } @@ -8256,9 +8314,9 @@ proto_register_tcp(void) { "Data", "tcp.options.experimental.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, - { &hf_tcp_option_exp_magic_number, - { "Magic Number", "tcp.options.experimental.magic_number", FT_UINT16, - BASE_HEX, NULL, 0x0, NULL, HFILL}}, + { &hf_tcp_option_exp_exid, + { "Experiment Identifier", "tcp.options.experimental.exid", FT_UINT16, + BASE_HEX, &tcp_exid_vs, 0x0, NULL, HFILL}}, { &hf_tcp_option_unknown_payload, { "Payload", "tcp.options.unknown.payload", FT_BYTES, @@ -9118,10 +9176,10 @@ proto_register_tcp(void) "Do not call any subdissectors for Retransmitted or OutOfOrder segments", &tcp_no_subdissector_on_error); - prefs_register_bool_preference(tcp_module, "dissect_experimental_options_with_magic", - "TCP Experimental Options with a Magic Number", - "Assume TCP Experimental Options (253, 254) have a Magic Number and use it for dissection", - &tcp_exp_options_with_magic); + prefs_register_bool_preference(tcp_module, "dissect_experimental_options_rfc6994", + "TCP Experimental Options using the format of RFC 6994", + "Assume TCP Experimental Options (253, 254) have an Experiment Identifier and use it for dissection", + &tcp_exp_options_rfc6994); prefs_register_bool_preference(tcp_module, "display_process_info_from_ipfix", "Display process information via IPFIX", diff --git a/epan/prefs.c b/epan/prefs.c index 905902e43e..6f55769ed4 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -5808,6 +5808,8 @@ set_pref(gchar *pref_name, const gchar *value, void *private_data _U_, pref = prefs_find_preference(module, "analyze_sequence_numbers"); else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0) pref = prefs_find_preference(module, "relative_sequence_numbers"); + else if (strcmp(dotp, "dissect_experimental_options_with_magic") == 0) + pref = prefs_find_preference(module, "dissect_experimental_options_rfc6994"); } else if (strcmp(module->name, "udp") == 0) { /* Handle old names for UDP preferences. */ if (strcmp(dotp, "udp_summary_in_tree") == 0) diff --git a/test/captures/tcp-exp-option-tarr.pcap.gz b/test/captures/tcp-exp-option-tarr.pcap.gz new file mode 100644 index 0000000000..12f5ec361e Binary files /dev/null and b/test/captures/tcp-exp-option-tarr.pcap.gz differ