diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index 03f6185a10..de73fdaf0d 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -330,6 +330,7 @@ static gint ett_tcp_option_wscale = -1; static gint ett_tcp_option_sack = -1; static gint ett_tcp_option_snack = -1; static gint ett_tcp_option_scps = -1; +static gint ett_tcp_scpsoption_flags = -1; static gint ett_tcp_option_scps_extended = -1; static gint ett_tcp_option_user_to = -1; static gint ett_tcp_option_exp = -1; @@ -3646,14 +3647,12 @@ tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val) } static gboolean -tcp_option_len_check(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, int proto, guint len, guint optlen) +tcp_option_len_check(proto_item* length_item, packet_info *pinfo, guint len, guint optlen) { if (len != optlen) { /* Bogus - option length isn't what it's supposed to be for this option. */ - proto_tree_add_expert_format(tree, pinfo, &ei_tcp_opt_len_invalid, tvb, 0, len, - "%s (with option length = %u byte%s; should be %u)", - proto_get_protocol_short_name(find_protocol_by_id(proto)), - len, plurality(len, "", "s"), optlen); + expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, + "option length should be %u", optlen); return FALSE; } @@ -3665,16 +3664,17 @@ dissect_tcpopt_default_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tre { proto_item *item; proto_tree *exp_tree; + proto_item *length_item; int offset = 0; - if (!tcp_option_len_check(tree, pinfo, tvb, proto, tvb_reported_length(tvb), 2)) - return tvb_captured_length(tvb); - - item = proto_tree_add_item(tree, proto, tvb, offset, 2, ENC_NA); + item = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA); exp_tree = proto_item_add_subtree(item, ett); 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); + length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), 2)) + return tvb_captured_length(tvb); return tvb_captured_length(tvb); } @@ -3721,14 +3721,14 @@ dissect_tcpopt_tfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* da { proto_item *item; proto_tree *exp_tree; - int offset = 0, optlen = tvb_reported_length(tvb); + int offset = 0; - item = proto_tree_add_item(tree, proto_tcp_option_tfo, tvb, offset, optlen, ENC_NA); + item = proto_tree_add_item(tree, proto_tcp_option_tfo, 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); - dissect_tcpopt_tfo_payload(tvb, offset, optlen, pinfo, exp_tree, data); + dissect_tcpopt_tfo_payload(tvb, offset, tvb_reported_length(tvb), pinfo, exp_tree, data); return tvb_captured_length(tvb); } @@ -3740,7 +3740,7 @@ dissect_tcpopt_exp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* da guint16 magic; int offset = 0, optlen = tvb_reported_length(tvb); - item = proto_tree_add_item(tree, proto_tcp_option_exp, tvb, offset, optlen, ENC_NA); + 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); @@ -3770,18 +3770,20 @@ dissect_tcpopt_sack_perm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo { proto_item *item; proto_tree *exp_tree; + proto_item *length_item; int offset = 0; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_sack_perm, tvb_reported_length(tvb), TCPOLEN_SACK_PERM)) - return tvb_captured_length(tvb); - - item = proto_tree_add_item(tree, proto_tcp_option_sack_perm, tvb, offset, TCPOLEN_SACK_PERM, ENC_NA); + item = proto_tree_add_item(tree, proto_tcp_option_sack_perm, tvb, offset, -1, ENC_NA); exp_tree = proto_item_add_subtree(item, ett_tcp_option_sack_perm); 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); + length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); tcp_info_append_uint(pinfo, "SACK_PERM", TRUE); + + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SACK_PERM)) + return tvb_captured_length(tvb); + return tvb_captured_length(tvb); } @@ -3789,18 +3791,20 @@ static int dissect_tcpopt_mss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { proto_item *item; - int offset = 0; proto_tree *exp_tree; + proto_item *length_item; + int offset = 0; guint32 mss; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_mss, tvb_reported_length(tvb), TCPOLEN_MSS)) - return tvb_captured_length(tvb); - - item = proto_tree_add_item(tree, proto_tcp_option_mss, tvb, offset, TCPOLEN_MSS, ENC_NA); + item = proto_tree_add_item(tree, proto_tcp_option_mss, tvb, offset, -1, ENC_NA); exp_tree = proto_item_add_subtree(item, ett_tcp_option_mss); 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); + length_item = proto_tree_add_item(exp_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_MSS)) + return tvb_captured_length(tvb); + proto_tree_add_item_ret_uint(exp_tree, hf_tcp_option_mss_val, tvb, offset + 2, 2, ENC_BIG_ENDIAN, &mss); proto_item_append_text(item, ": %u bytes", mss); tcp_info_append_uint(pinfo, "MSS", mss); @@ -3816,23 +3820,24 @@ dissect_tcpopt_wscale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* guint32 shift; proto_item *wscale_pi, *shift_pi, *gen_pi; proto_tree *wscale_tree; + proto_item *length_item; int offset = 0; struct tcp_analysis *tcpd; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_wscale, tvb_reported_length(tvb), TCPOLEN_WINDOW)) - return tvb_captured_length(tvb); - tcpd=get_tcp_conversation_data(NULL,pinfo); - wscale_pi = proto_tree_add_item(tree, proto_tcp_option_wscale, tvb, offset, TCPOLEN_WINDOW, ENC_NA); + wscale_pi = proto_tree_add_item(tree, proto_tcp_option_wscale, tvb, offset, -1, ENC_NA); wscale_tree = proto_item_add_subtree(wscale_pi, ett_tcp_option_wscale); proto_tree_add_item(wscale_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; - proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN); + length_item = proto_tree_add_item(wscale_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_WINDOW)) + return tvb_captured_length(tvb); + shift_pi = proto_tree_add_item_ret_uint(wscale_tree, hf_tcp_option_wscale_shift, tvb, offset, 1, ENC_BIG_ENDIAN, &shift); if (shift > 14) { /* RFC 1323: "If a Window Scale option is received with a shift.cnt @@ -3880,7 +3885,7 @@ dissect_tcpopt_sack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d } } - ti = proto_tree_add_item(tree, proto_tcp_option_sack, tvb, offset, optlen, ENC_NA); + ti = proto_tree_add_item(tree, proto_tcp_option_sack, tvb, offset, -1, ENC_NA); field_tree = proto_item_add_subtree(ti, ett_tcp_option_sack); proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, @@ -3942,19 +3947,21 @@ dissect_tcpopt_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d { proto_tree *field_tree; proto_item *item; + proto_item *length_item; guint32 echo; int offset = 0; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_echo, tvb_reported_length(tvb), TCPOLEN_ECHO)) - return tvb_captured_length(tvb); - - item = proto_tree_add_item(tree, proto_tcp_option_echo, tvb, offset, TCPOLEN_ECHO, ENC_NA); + item = proto_tree_add_item(tree, proto_tcp_option_echo, tvb, offset, -1, ENC_NA); field_tree = proto_item_add_subtree(item, ett_tcp_opt_echo); proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_ECHO)) + return tvb_captured_length(tvb); + proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_echo, tvb, offset + 2, 4, ENC_BIG_ENDIAN, &echo); @@ -3972,22 +3979,23 @@ dissect_tcpopt_timestamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo { proto_item *ti; proto_tree *ts_tree; + proto_item *length_item; int offset = 0; guint32 ts_val, ts_ecr; int len = tvb_reported_length(tvb); - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_timestamp, len, TCPOLEN_TIMESTAMP)) - return tvb_captured_length(tvb); - - ti = proto_tree_add_item(tree, proto_tcp_option_timestamp, tvb, offset, TCPOLEN_TIMESTAMP, ENC_NA); + ti = proto_tree_add_item(tree, proto_tcp_option_timestamp, tvb, offset, -1, ENC_NA); ts_tree = proto_item_add_subtree(ti, ett_tcp_option_timestamp); proto_tree_add_item(ts_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; - proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN); + length_item = proto_tree_add_item(ts_tree, hf_tcp_option_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; + if (!tcp_option_len_check(length_item, pinfo, len, TCPOLEN_TIMESTAMP)) + return tvb_captured_length(tvb); + proto_tree_add_item_ret_uint(ts_tree, hf_tcp_option_timestamp_tsval, tvb, offset, 4, ENC_BIG_ENDIAN, &ts_val); offset += 4; @@ -4171,7 +4179,7 @@ dissect_tcpopt_mptcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* } col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPTCP"); - main_item = proto_tree_add_item(tree, proto_mptcp, tvb, offset, optlen, ENC_NA); + main_item = proto_tree_add_item(tree, proto_mptcp, tvb, offset, -1, ENC_NA); mptcp_tree = proto_item_add_subtree(main_item, ett_tcp_option_mptcp); proto_tree_add_item(mptcp_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); @@ -4560,19 +4568,21 @@ dissect_tcpopt_cc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat { proto_tree *field_tree; proto_item *item; + proto_item *length_item; int offset = 0; guint32 cc; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_cc, tvb_reported_length(tvb), TCPOLEN_CC)) - return tvb_captured_length(tvb); - - item = proto_tree_add_item(tree, proto_tcp_option_cc, tvb, offset, TCPOLEN_CC, ENC_NA); + item = proto_tree_add_item(tree, proto_tcp_option_cc, tvb, offset, -1, ENC_NA); field_tree = proto_item_add_subtree(item, ett_tcp_opt_cc); proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_CC)) + return tvb_captured_length(tvb); + proto_tree_add_item_ret_uint(field_tree, hf_tcp_option_cc, tvb, offset + 2, 4, ENC_BIG_ENDIAN, &cc); @@ -4585,19 +4595,21 @@ dissect_tcpopt_md5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* da { proto_tree *field_tree; proto_item *item; + proto_item *length_item; int offset = 0, optlen = tvb_reported_length(tvb); - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_md5, optlen, TCPOLEN_MD5)) - return tvb_captured_length(tvb); - - item = proto_tree_add_item(tree, proto_tcp_option_md5, tvb, offset, TCPOLEN_MD5, ENC_NA); + item = proto_tree_add_item(tree, proto_tcp_option_md5, tvb, offset, -1, ENC_NA); field_tree = proto_item_add_subtree(item, ett_tcp_opt_md5); col_append_lstr(pinfo->cinfo, COL_INFO, " MD5", COL_ADD_LSTR_TERMINATOR); proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + 1, 1, ENC_BIG_ENDIAN); + length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_MD5)) + return tvb_captured_length(tvb); + proto_tree_add_item(field_tree, hf_tcp_option_md5_digest, tvb, offset + 2, optlen - 2, ENC_NA); @@ -4609,19 +4621,20 @@ dissect_tcpopt_qs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat { proto_tree *field_tree; proto_item *item; + proto_item *length_item; guint8 rate; int offset = 0; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_qs, tvb_reported_length(tvb), TCPOLEN_QS)) - return tvb_captured_length(tvb); - - item = proto_tree_add_item(tree, proto_tcp_option_qs, tvb, offset, TCPOLEN_QS, ENC_NA); + item = proto_tree_add_item(tree, proto_tcp_option_qs, tvb, offset, -1, ENC_NA); field_tree = proto_item_add_subtree(item, ett_tcp_opt_qs); proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + 1, 1, ENC_BIG_ENDIAN); + length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_QS)) + return tvb_captured_length(tvb); rate = tvb_get_guint8(tvb, offset + 2) & 0x0f; col_append_lstr(pinfo->cinfo, COL_INFO, @@ -4643,6 +4656,7 @@ dissect_tcpopt_scps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d tcp_flow_t *flow; int direction; proto_item *tf = NULL, *item; + proto_tree *flags_tree = NULL; guint8 capvector; guint8 connid; int offset = 0, optlen = tvb_reported_length(tvb); @@ -4662,37 +4676,36 @@ dissect_tcpopt_scps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d else flow =&(tcpd->flow2); + item = proto_tree_add_item(tree, proto_tcp_option_scps, + tvb, offset, -1, ENC_NA); + field_tree = proto_item_add_subtree(item, ett_tcp_option_scps); + + proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, + offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + offset + 1, 1, ENC_BIG_ENDIAN); + /* If the option length == 4, this is a real SCPS capability option * See "CCSDS 714.0-B-2 (CCSDS Recommended Standard for SCPS Transport Protocol * (SCPS-TP)" Section 3.2.3 for definition. */ if (optlen == 4) { - item = proto_tree_add_item(tree, proto_tcp_option_scps, - tvb, offset, optlen, ENC_NA); - PROTO_ITEM_SET_HIDDEN(item); - - capvector = tvb_get_guint8(tvb, offset + 2); - connid = tvb_get_guint8(tvb, offset + 3); - - tf = proto_tree_add_item(tree, hf_tcp_option_scps_vector, tvb, + tf = proto_tree_add_item(field_tree, hf_tcp_option_scps_vector, tvb, offset + 2, 1, ENC_BIG_ENDIAN); - field_tree = proto_item_add_subtree(tf, ett_tcp_option_scps); - proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, - offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + 1, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_bets, tvb, + flags_tree = proto_item_add_subtree(tf, ett_tcp_scpsoption_flags); + proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_bets, tvb, offset + 2, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_snack1, tvb, + proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack1, tvb, offset + 2, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_snack2, tvb, + proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_snack2, tvb, offset + 2, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_compress, tvb, + proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_compress, tvb, offset + 2, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_nlts, tvb, + proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_nlts, tvb, offset + 2, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_scpsoption_flags_reserved, tvb, + proto_tree_add_item(flags_tree, hf_tcp_scpsoption_flags_reserved, tvb, offset + 2, 1, ENC_BIG_ENDIAN); + capvector = tvb_get_guint8(tvb, offset + 2); if (capvector) { struct capvec @@ -4728,6 +4741,7 @@ dissect_tcpopt_scps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d proto_tree_add_item(field_tree, hf_tcp_scpsoption_connection_id, tvb, offset + 3, 1, ENC_BIG_ENDIAN); + connid = tvb_get_guint8(tvb, offset + 3); flow->scps_capable = 1; if (connid) @@ -4747,25 +4761,13 @@ dissect_tcpopt_scps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* d if (flow->scps_capable != 1) { /* There was no SCPS capabilities option preceding this */ - tf = proto_tree_add_uint_format(tree, hf_tcp_option_scps_vector, - tvb, offset, optlen, 0, - "Illegal SCPS Extended Capabilities (%d bytes)", - optlen); - field_tree=proto_item_add_subtree(tf, ett_tcp_option_scps_extended); - proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, - offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + 1, 1, ENC_BIG_ENDIAN); + proto_item_set_text(item, + "Illegal SCPS Extended Capabilities (%u bytes)", + optlen); } else { - tf = proto_tree_add_uint_format(tree, hf_tcp_option_scps_vector, - tvb, offset, optlen, 0, - "SCPS Extended Capabilities (%d bytes)", - optlen); - field_tree=proto_item_add_subtree(tf, ett_tcp_option_scps_extended); - proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, - offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + 1, 1, ENC_BIG_ENDIAN); + proto_item_set_text(item, + "SCPS Extended Capabilities (%u bytes)", + optlen); /* There may be multiple binding spaces included in a single option, * so we will semi-parse each of the stacked binding spaces - skipping @@ -4815,19 +4817,20 @@ dissect_tcpopt_user_to(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void { proto_item *tf; proto_tree *field_tree; + proto_item *length_item; guint16 to; int offset = 0; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_user_to, tvb_reported_length(tvb), TCPOLEN_USER_TO)) - return tvb_captured_length(tvb); - - tf = proto_tree_add_item(tree, proto_tcp_option_user_to, tvb, offset, TCPOLEN_USER_TO, ENC_NA); + tf = proto_tree_add_item(tree, proto_tcp_option_user_to, tvb, offset, -1, ENC_NA); field_tree = proto_item_add_subtree(tf, ett_tcp_option_user_to); proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + 1, 1, ENC_BIG_ENDIAN); + length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_USER_TO)) + return tvb_captured_length(tvb); proto_tree_add_item(field_tree, hf_tcp_option_user_to_granularity, tvb, offset + 2, 2, ENC_BIG_ENDIAN); to = tvb_get_ntohs(tvb, offset + 2) & 0x7FFF; @@ -4874,17 +4877,18 @@ dissect_tcpopt_snack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* int offset = 0; proto_item *hidden_item, *tf; proto_tree *field_tree; + proto_item *length_item; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_snack, tvb_reported_length(tvb), TCPOLEN_SNACK)) - return tvb_captured_length(tvb); - - tf = proto_tree_add_item(tree, proto_tcp_option_snack, tvb, offset, TCPOLEN_SNACK, ENC_NA); + tf = proto_tree_add_item(tree, proto_tcp_option_snack, tvb, offset, -1, ENC_NA); field_tree = proto_item_add_subtree(tf, ett_tcp_option_snack); proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + 1, 1, ENC_BIG_ENDIAN); + length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, tvb_reported_length(tvb), TCPOLEN_SNACK)) + return tvb_captured_length(tvb); tcpd = get_tcp_conversation_data(NULL,pinfo); @@ -5035,23 +5039,28 @@ dissect_tcpopt_rvbd_probe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v guint8 ver, type; proto_tree *field_tree; proto_item *pitem; + proto_item *length_item; int offset = 0, optlen = tvb_reported_length(tvb); struct tcpheader *tcph = (struct tcpheader*)data; + pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_probe, tvb, offset, -1, ENC_NA); + field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe); + + proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, + offset, 1, ENC_BIG_ENDIAN); + length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + offset + 1, 1, ENC_BIG_ENDIAN); + if (optlen < TCPOLEN_RVBD_PROBE_MIN) { /* Bogus - option length is less than what it's supposed to be for this option. */ - proto_tree_add_expert_format(tree, pinfo, &ei_tcp_opt_len_invalid, tvb, offset, optlen, - "%s (with option length = %u bytes; should be >= %u)", - proto_get_protocol_short_name(find_protocol_by_id(proto_tcp_option_rvbd_probe)), - optlen, TCPOLEN_RVBD_PROBE_MIN); + expert_add_info_format(pinfo, length_item, &ei_tcp_opt_len_invalid, + "option length should be >= %u)", + TCPOLEN_RVBD_PROBE_MIN); return tvb_captured_length(tvb); } - pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_probe, tvb, offset, optlen, ENC_NA); - field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_probe); - rvbd_probe_decode_version_type( tvb_get_guint8(tvb, offset + PROBE_VERSION_TYPE_OFFSET), &ver, &type); @@ -5061,12 +5070,6 @@ dissect_tcpopt_rvbd_probe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v if (type >= PROBE_TYPE_MAX) return tvb_captured_length(tvb); - /* optlen, type, ver are common for all probes */ - proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, - offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN); - if (ver == PROBE_VERSION_1) { guint16 port; @@ -5268,6 +5271,7 @@ dissect_tcpopt_rvbd_trpy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo { proto_tree *field_tree; proto_item *pitem; + proto_item *length_item; guint16 sport, dport, flags; int offset = 0, optlen = tvb_reported_length(tvb); @@ -5281,18 +5285,18 @@ dissect_tcpopt_rvbd_trpy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo NULL }; - if (!tcp_option_len_check(tree, pinfo, tvb, proto_tcp_option_rvbd_trpy, optlen, TCPOLEN_RVBD_TRPY_MIN)) - return tvb_captured_length(tvb); - col_prepend_fstr(pinfo->cinfo, COL_INFO, "TRPY, "); - pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_trpy, tvb, offset, TCPOLEN_RVBD_TRPY_MIN, ENC_NA); + pitem = proto_tree_add_item(tree, proto_tcp_option_rvbd_trpy, tvb, offset, -1, ENC_NA); field_tree = proto_item_add_subtree(pitem, ett_tcp_opt_rvbd_trpy); proto_tree_add_item(field_tree, hf_tcp_option_kind, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, - offset + PROBE_OPTLEN_OFFSET, 1, ENC_BIG_ENDIAN); + length_item = proto_tree_add_item(field_tree, hf_tcp_option_len, tvb, + offset + 1, 1, ENC_BIG_ENDIAN); + + if (!tcp_option_len_check(length_item, pinfo, optlen, TCPOLEN_RVBD_TRPY_MIN)) + return tvb_captured_length(tvb); flags = tvb_get_ntohs(tvb, offset + TRPY_OPTIONS_OFFSET); proto_tree_add_bitmask_with_flags(field_tree, tvb, offset + TRPY_OPTIONS_OFFSET, hf_tcp_option_rvbd_trpy_flags, @@ -7256,6 +7260,7 @@ proto_register_tcp(void) &ett_tcp_option_sack, &ett_tcp_option_snack, &ett_tcp_option_scps, + &ett_tcp_scpsoption_flags, &ett_tcp_option_scps_extended, &ett_tcp_option_user_to, &ett_tcp_option_exp,