forked from osmocom/wireshark
Don't truncate the options field.
Create a placeholder protocol tree item under which to put the options, do the analysis of fields from the fixed-length portion of the TCP header (such as sequence numbers), and then do a straightforward dissection of the options, throwing an exception if we run past the end of the options field. This is a bit simpler, and doesn't add confusing notes about truncation of the options. XXX - we're currently not including selective acknowledgments in any of the SEQ/ACK analysis; should we? That means, of course, that we have to dissect the options before doing that analysis, and if the options were cut short by slicing, you lose.... Change-Id: I425a6c83f26512b802267f76739cbf40121b3040 Reviewed-on: https://code.wireshark.org/review/511 Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
parent
b2689ab4e0
commit
8881f3f61a
|
@ -4065,6 +4065,8 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
guint16 th_urp;
|
||||
proto_tree *tcp_tree = NULL, *field_tree = NULL;
|
||||
proto_item *ti = NULL, *tf, *hidden_item;
|
||||
proto_item *options_item;
|
||||
proto_tree *options_tree;
|
||||
int offset = 0;
|
||||
wmem_strbuf_t *flags_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
|
||||
static const gchar *flags[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR", "NS"};
|
||||
|
@ -4609,42 +4611,29 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", tcph->th_seglen);
|
||||
}
|
||||
|
||||
/* If there's more than just the fixed-length header (20 bytes), decode the options. */
|
||||
tcph->num_sack_ranges = 0;
|
||||
if (tcph->th_hlen > TCPH_MIN_LEN) {
|
||||
/* If there's more than just the fixed-length header (20 bytes), create
|
||||
a protocol tree item for the options. (We already know there's
|
||||
not less than the fixed-length header - we checked that above.)
|
||||
|
||||
We ensure that we don't throw an exception here, so that we can
|
||||
do some analysis before we dissect the options and possibly
|
||||
throw an exception. (Trying to avoid throwing an exception when
|
||||
dissecting options is not something we should do.) */
|
||||
optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
|
||||
options_item = NULL;
|
||||
options_tree = NULL;
|
||||
if (optlen != 0) {
|
||||
guint bc = (guint)MAX(0, tvb_length_remaining(tvb, offset + 20));
|
||||
|
||||
optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
|
||||
|
||||
if (tcp_tree != NULL) {
|
||||
/* If the frame has been sliced but the options field is at least 4 bytes, decode as much
|
||||
* of it as possible; otherwise, set optlen to zero. */
|
||||
if (bc < optlen) {
|
||||
if (bc >= 4) {
|
||||
guint8 *p_options = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset + 20, bc);
|
||||
|
||||
tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
|
||||
bc, p_options, "Options: (%u bytes but truncated to %u bytes)", optlen, bc);
|
||||
optlen = bc;
|
||||
} else {
|
||||
optlen = 0;
|
||||
}
|
||||
} else {
|
||||
guint8 *p_options = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset + 20, optlen);
|
||||
|
||||
tf = proto_tree_add_bytes_format(tcp_tree, hf_tcp_options, tvb, offset + 20,
|
||||
optlen, p_options, "Options: (%u bytes)", optlen);
|
||||
}
|
||||
field_tree = proto_item_add_subtree(tf, ett_tcp_options);
|
||||
} else {
|
||||
tf = NULL;
|
||||
field_tree = NULL;
|
||||
}
|
||||
if (optlen)
|
||||
dissect_ip_tcp_options(tvb, offset + 20, optlen, tcpopts, N_TCP_OPTS, TCPOPT_EOL,
|
||||
&TCP_OPT_TYPES, &ei_tcp_opt_len_invalid, pinfo, field_tree, tf, tcph);
|
||||
options_item = proto_tree_add_item(tcp_tree, hf_tcp_options, tvb, offset + 20,
|
||||
bc < optlen ? bc : optlen, ENC_NA);
|
||||
proto_item_set_text(options_item, "Options: (%u bytes)", optlen);
|
||||
options_tree = proto_item_add_subtree(options_item, ett_tcp_options);
|
||||
}
|
||||
}
|
||||
|
||||
tcph->num_sack_ranges = 0;
|
||||
if(!pinfo->fd->flags.visited) {
|
||||
if((tcph->th_flags & TH_SYN)==TH_SYN) {
|
||||
/* Check the validity of the window scale value
|
||||
|
@ -4664,6 +4653,33 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
}
|
||||
}
|
||||
|
||||
/* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
|
||||
if(tcp_analyze_seq) {
|
||||
guint32 use_seq = tcph->th_seq;
|
||||
guint32 use_ack = tcph->th_ack;
|
||||
/* May need to recover absolute values here... */
|
||||
if (tcp_relative_seq) {
|
||||
use_seq += tcpd->fwd->base_seq;
|
||||
if (tcph->th_flags & TH_ACK) {
|
||||
use_ack += tcpd->rev->base_seq;
|
||||
}
|
||||
}
|
||||
tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd, use_seq, use_ack);
|
||||
}
|
||||
|
||||
/* handle conversation timestamps */
|
||||
if(tcp_calculate_ts) {
|
||||
tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
|
||||
}
|
||||
|
||||
/* Now dissect the options. */
|
||||
if (options_tree != NULL) {
|
||||
dissect_ip_tcp_options(tvb, offset + 20, optlen, tcpopts, N_TCP_OPTS,
|
||||
TCPOPT_EOL, &TCP_OPT_TYPES,
|
||||
&ei_tcp_opt_len_invalid, pinfo, options_tree,
|
||||
options_item, tcph);
|
||||
}
|
||||
|
||||
/* Skip over header + options */
|
||||
offset += tcph->th_hlen;
|
||||
|
||||
|
@ -4688,28 +4704,8 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
}
|
||||
}
|
||||
|
||||
/* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
|
||||
if(tcp_analyze_seq) {
|
||||
guint32 use_seq = tcph->th_seq;
|
||||
guint32 use_ack = tcph->th_ack;
|
||||
/* May need to recover absolute values here... */
|
||||
if (tcp_relative_seq) {
|
||||
use_seq += tcpd->fwd->base_seq;
|
||||
if (tcph->th_flags & TH_ACK) {
|
||||
use_ack += tcpd->rev->base_seq;
|
||||
}
|
||||
}
|
||||
tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree, tcpd, use_seq, use_ack);
|
||||
}
|
||||
|
||||
/* handle conversation timestamps */
|
||||
if(tcp_calculate_ts) {
|
||||
tcp_print_timestamps(pinfo, tvb, tcp_tree, tcpd, tcppd);
|
||||
}
|
||||
|
||||
tap_queue_packet(tcp_tap, pinfo, tcph);
|
||||
|
||||
|
||||
/* If we're reassembling something whose length isn't known
|
||||
* beforehand, and that runs all the way to the end of
|
||||
* the data stream, a FIN indicates the end of the data
|
||||
|
|
Loading…
Reference in New Issue