diff options
author | Ivan Nardi <nardi.ivan@gmail.com> | 2018-04-17 17:53:42 +0200 |
---|---|---|
committer | Peter Wu <peter@lekensteyn.nl> | 2018-04-20 08:23:13 +0000 |
commit | 79014a50c3f7f06f4e0513c887e4cb1e85edf61c (patch) | |
tree | cc462dcfb06d69e38cc7da1a3b0a6001666fb1de /epan/dissectors/packet-tcp.c | |
parent | ac7e609b9f87d2f53b7dc77574ecd4c269f6d384 (diff) |
TCP: improve handling of unknown TCP options
Create protocol sub-tree, allow filtering for unknown/unsupported TCP options.
Change-Id: I9f51e3ac83e2fa97756a9f3a43f8cd2e15949e67
Reviewed-on: https://code.wireshark.org/review/27020
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'epan/dissectors/packet-tcp.c')
-rw-r--r-- | epan/dissectors/packet-tcp.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index de73fdaf0d..821bc43525 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -132,6 +132,7 @@ static int proto_tcp_option_tfo = -1; static int proto_tcp_option_rvbd_probe = -1; static int proto_tcp_option_rvbd_trpy = -1; static int proto_tcp_option_exp = -1; +static int proto_tcp_option_unknown = -1; static int proto_mptcp = -1; static int hf_tcp_srcport = -1; @@ -207,6 +208,7 @@ 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_unknown_payload = -1; static int hf_tcp_option_rvbd_probe_version1 = -1; static int hf_tcp_option_rvbd_probe_version2 = -1; @@ -572,6 +574,7 @@ static heur_dissector_list_t heur_subdissector_list; static dissector_handle_t data_handle; static dissector_handle_t tcp_handle; static dissector_handle_t sport_handle; +static dissector_handle_t tcp_opt_unknown_handle; static guint32 tcp_stream_count; static guint32 mptcp_stream_count; @@ -3660,6 +3663,24 @@ tcp_option_len_check(proto_item* length_item, packet_info *pinfo, guint len, gui } static int +dissect_tcpopt_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + proto_item *item; + proto_tree *exp_tree; + int offset = 0, optlen = tvb_reported_length(tvb); + + item = proto_tree_add_item(tree, proto_tcp_option_unknown, tvb, offset, -1, ENC_NA); + exp_tree = proto_item_add_subtree(item, ett_tcp_unknown_opt); + + 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 (optlen > 2) + proto_tree_add_item(exp_tree, hf_tcp_option_unknown_payload, tvb, offset + 2, optlen - 2, ENC_NA); + + return tvb_captured_length(tvb); +} + +static int dissect_tcpopt_default_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, int ett) { proto_item *item; @@ -5401,6 +5422,7 @@ tcp_dissect_options(tvbuff_t *tvb, int offset, guint length, int eol, option_dissector = dissector_get_uint_handle(tcp_option_table, opt); if (option_dissector == NULL) { name = wmem_strdup_printf(wmem_packet_scope(), "Unknown (0x%02x)", opt); + option_dissector = tcp_opt_unknown_handle; } else { name = dissector_handle_get_short_name(option_dissector); } @@ -5432,14 +5454,10 @@ tcp_dissect_options(tvbuff_t *tvb, int offset, guint length, int eol, return; } - if (option_dissector == NULL) { - proto_tree_add_subtree_format(opt_tree, tvb, offset, optlen, ett_tcp_unknown_opt, NULL, "%s (%u byte%s)", - name, optlen, plurality(optlen, "", "s")); - } else { - next_tvb = tvb_new_subset_length(tvb, offset, optlen); - call_dissector_with_data(option_dissector, next_tvb, pinfo, opt_tree/* tree */, data); - proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name); - } + next_tvb = tvb_new_subset_length(tvb, offset, optlen); + call_dissector_with_data(option_dissector, next_tvb, pinfo, opt_tree/* tree */, data); + proto_item_append_text(proto_tree_get_parent(opt_tree), ", %s", name); + offset += optlen; length -= (optlen-2); //already accounted for type and len bytes } @@ -6790,6 +6808,10 @@ proto_register_tcp(void) { "Magic Number", "tcp.options.experimental.magic_number", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + { &hf_tcp_option_unknown_payload, + { "Payload", "tcp.options.unknown.payload", FT_BYTES, + BASE_NONE, NULL, 0x0, NULL, HFILL}}, + { &hf_tcp_option_sack_sle, {"TCP SACK Left Edge", "tcp.options.sack_le", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, @@ -7473,6 +7495,7 @@ proto_register_tcp(void) proto_tcp_option_rvbd_probe = proto_register_protocol_in_name_only("TCP Option - Riverbed Probe", "Riverbed Probe", "tcp.options.rvbd.probe", proto_tcp, FT_BYTES); proto_tcp_option_rvbd_trpy = proto_register_protocol_in_name_only("TCP Option - Riverbed Transparency", "Riverbed Transparency", "tcp.options.rvbd.trpy", proto_tcp, FT_BYTES); proto_tcp_option_exp = proto_register_protocol_in_name_only("TCP Option - Experimental", "Experimental", "tcp.options.experimental", proto_tcp, FT_BYTES); + proto_tcp_option_unknown = proto_register_protocol_in_name_only("TCP Option - Unknown", "Unknown", "tcp.options.unknown", proto_tcp, FT_BYTES); register_capture_dissector_table("tcp.port", "TCP"); @@ -7630,6 +7653,8 @@ proto_reg_handoff_tcp(void) dissector_add_uint("tcp.option", TCPOPT_EXP_FD, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp )); dissector_add_uint("tcp.option", TCPOPT_EXP_FE, create_dissector_handle( dissect_tcpopt_exp, proto_tcp_option_exp )); dissector_add_uint("tcp.option", TCPOPT_MPTCP, create_dissector_handle( dissect_tcpopt_mptcp, proto_mptcp )); + /* Common handle for all the unknown/unsupported TCP options */ + tcp_opt_unknown_handle = create_dissector_handle( dissect_tcpopt_unknown, proto_tcp_option_unknown ); mptcp_tap = register_tap("mptcp"); exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4); |