aboutsummaryrefslogtreecommitdiffstats
path: root/packet-tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet-tcp.c')
-rw-r--r--packet-tcp.c208
1 files changed, 116 insertions, 92 deletions
diff --git a/packet-tcp.c b/packet-tcp.c
index a7e82a8d1f..d37600cad6 100644
--- a/packet-tcp.c
+++ b/packet-tcp.c
@@ -1,7 +1,7 @@
/* packet-tcp.c
* Routines for TCP packet disassembly
*
- * $Id: packet-tcp.c,v 1.87 2000/11/05 09:26:47 oabad Exp $
+ * $Id: packet-tcp.c,v 1.88 2000/11/18 10:38:25 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -163,32 +163,38 @@ tcp_info_append_uint(const char *abbrev, guint32 val) {
}
static void
-dissect_tcpopt_maxseg(const ip_tcp_opt *optp, const u_char *opd,
+dissect_tcpopt_maxseg(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint optlen, proto_tree *opt_tree)
{
- proto_tree_add_text(opt_tree, NullTVB, offset, optlen,
- "%s: %u bytes", optp->name, pntohs(opd));
- tcp_info_append_uint("MSS", pntohs(opd));
+ guint16 mss;
+
+ mss = tvb_get_ntohs(tvb, offset + 2);
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %u bytes", optp->name, mss);
+ tcp_info_append_uint("MSS", mss);
}
static void
-dissect_tcpopt_wscale(const ip_tcp_opt *optp, const u_char *opd,
+dissect_tcpopt_wscale(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint optlen, proto_tree *opt_tree)
{
- proto_tree_add_text(opt_tree, NullTVB, offset, optlen,
- "%s: %u bytes", optp->name, *opd);
- tcp_info_append_uint("WS", *opd);
+ guint8 ws;
+
+ ws = tvb_get_guint8(tvb, offset + 2);
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %u bytes", optp->name, ws);
+ tcp_info_append_uint("WS", ws);
}
static void
-dissect_tcpopt_sack(const ip_tcp_opt *optp, const u_char *opd,
+dissect_tcpopt_sack(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint optlen, proto_tree *opt_tree)
{
proto_tree *field_tree = NULL;
proto_item *tf;
guint leftedge, rightedge;
- tf = proto_tree_add_text(opt_tree, NullTVB, offset, optlen, "%s:", optp->name);
+ tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
offset += 2; /* skip past type and length */
optlen -= 2; /* subtract size of type and length */
while (optlen > 0) {
@@ -197,24 +203,21 @@ dissect_tcpopt_sack(const ip_tcp_opt *optp, const u_char *opd,
field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
}
if (optlen < 4) {
- proto_tree_add_text(field_tree, NullTVB, offset, optlen,
+ proto_tree_add_text(field_tree, tvb, offset, optlen,
"(suboption would go past end of option)");
break;
}
- /* XXX - check whether it goes past end of packet */
- leftedge = pntohl(opd);
- opd += 4;
+ leftedge = tvb_get_ntohl(tvb, offset);
optlen -= 4;
if (optlen < 4) {
- proto_tree_add_text(field_tree, NullTVB, offset, optlen,
+ proto_tree_add_text(field_tree, tvb, offset, optlen,
"(suboption would go past end of option)");
break;
}
/* XXX - check whether it goes past end of packet */
- rightedge = pntohl(opd);
- opd += 4;
+ rightedge = tvb_get_ntohl(tvb, offset + 4);
optlen -= 4;
- proto_tree_add_text(field_tree, NullTVB, offset, 8,
+ proto_tree_add_text(field_tree, tvb, offset, 8,
"left edge = %u, right edge = %u", leftedge, rightedge);
tcp_info_append_uint("SLE", leftedge);
tcp_info_append_uint("SRE", rightedge);
@@ -223,31 +226,41 @@ dissect_tcpopt_sack(const ip_tcp_opt *optp, const u_char *opd,
}
static void
-dissect_tcpopt_echo(const ip_tcp_opt *optp, const u_char *opd,
+dissect_tcpopt_echo(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint optlen, proto_tree *opt_tree)
{
- proto_tree_add_text(opt_tree, NullTVB, offset, optlen,
- "%s: %u", optp->name, pntohl(opd));
- tcp_info_append_uint("ECHO", pntohl(opd));
+ guint32 echo;
+
+ echo = tvb_get_ntohl(tvb, offset + 2);
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %u", optp->name, echo);
+ tcp_info_append_uint("ECHO", echo);
}
static void
-dissect_tcpopt_timestamp(const ip_tcp_opt *optp, const u_char *opd,
+dissect_tcpopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint optlen, proto_tree *opt_tree)
{
- proto_tree_add_text(opt_tree, NullTVB, offset, optlen,
- "%s: tsval %u, tsecr %u", optp->name, pntohl(opd), pntohl(opd + 4));
- tcp_info_append_uint("TSV", pntohl(opd));
- tcp_info_append_uint("TSER", pntohl(opd + 4));
+ guint32 tsv, tser;
+
+ tsv = tvb_get_ntohl(tvb, offset + 2);
+ tser = tvb_get_ntohl(tvb, offset + 6);
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: tsval %u, tsecr %u", optp->name, tsv, tser);
+ tcp_info_append_uint("TSV", tsv);
+ tcp_info_append_uint("TSER", tser);
}
static void
-dissect_tcpopt_cc(const ip_tcp_opt *optp, const u_char *opd,
+dissect_tcpopt_cc(const ip_tcp_opt *optp, tvbuff_t *tvb,
int offset, guint optlen, proto_tree *opt_tree)
{
- proto_tree_add_text(opt_tree, NullTVB, offset, optlen,
- "%s: %u", optp->name, pntohl(opd));
- tcp_info_append_uint("CC", pntohl(opd));
+ guint32 cc;
+
+ cc = tvb_get_ntohl(tvb, offset + 2);
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %u", optp->name, cc);
+ tcp_info_append_uint("CC", cc);
}
static const ip_tcp_opt tcpopts[] = {
@@ -363,14 +376,20 @@ static const true_false_string flags_set_truth = {
/* can call to it, ie. socks */
void
-decode_tcp_ports(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
- int src_port, int dst_port)
+decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, int src_port, int dst_port)
{
+ tvbuff_t *next_tvb;
+ const u_char *next_pd;
+ int next_offset;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
/* determine if this packet is part of a conversation and call dissector */
/* for the conversation if available */
- if (old_try_conversation_dissector(&pi.src, &pi.dst, PT_TCP,
- src_port, dst_port, pd, offset, fd, tree))
+ if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP,
+ src_port, dst_port, next_tvb, pinfo, tree))
return;
/* try to apply the plugins */
@@ -379,10 +398,11 @@ decode_tcp_ports(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
plugin *pt_plug = plugin_list;
if (enabled_plugins_number > 0) {
+ tvb_compat(next_tvb, &next_pd, &next_offset);
while (pt_plug) {
if (pt_plug->enabled && strstr(pt_plug->protocol, "tcp") &&
- tree && dfilter_apply(pt_plug->filter, tree, pd, fd->cap_len)) {
- pt_plug->dissector(pd, offset, fd, tree);
+ tree && dfilter_apply(pt_plug->filter, tree, next_pd, pinfo->fd->cap_len)) {
+ pt_plug->dissector(next_pd, next_offset, pinfo->fd, tree);
return;
}
pt_plug = pt_plug->next;
@@ -392,39 +412,42 @@ decode_tcp_ports(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
#endif
/* do lookup with the subdissector table */
- if (old_dissector_try_port(subdissector_table, src_port, pd, offset, fd, tree) ||
- old_dissector_try_port(subdissector_table, dst_port, pd, offset, fd, tree))
+ if (dissector_try_port(subdissector_table, src_port, next_tvb, pinfo, tree) ||
+ dissector_try_port(subdissector_table, dst_port, next_tvb, pinfo, tree))
return;
/* do lookup with the heuristic subdissector table */
- if (old_dissector_try_heuristic(heur_subdissector_list, pd, offset, fd, tree))
+ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
return;
/* Oh, well, we don't know this; dissect it as data. */
- old_dissect_data(pd, offset, fd, tree);
+ dissect_data(next_tvb, 0, pinfo, tree);
}
static void
-dissect_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
+dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
e_tcphdr th;
proto_tree *tcp_tree = NULL, *field_tree = NULL;
proto_item *ti, *tf;
+ int offset = 0;
gchar flags[64] = "<None>";
gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR" };
gint fpos = 0, i;
guint bpos;
guint hlen;
guint optlen;
- guint packet_max = pi.len;
guint32 seglen;
guint32 nxtseq;
+ guint length_remaining;
+
+ CHECK_DISPLAY_AS_DATA(proto_tcp, tvb, pinfo, tree);
- OLD_CHECK_DISPLAY_AS_DATA(proto_tcp, pd, offset, fd, tree);
+ pinfo->current_proto = "TCP";
- /* To do: Check for {cap len,pkt len} < struct len */
/* Avoids alignment problems on many architectures. */
- memcpy(&th, &pd[offset], sizeof(e_tcphdr));
+ tvb_memcpy(tvb, (guint8 *)&th, offset, sizeof(e_tcphdr));
th.th_sport = ntohs(th.th_sport);
th.th_dport = ntohs(th.th_dport);
th.th_win = ntohs(th.th_win);
@@ -439,7 +462,7 @@ dissect_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
info_len = 0;
- if (check_col(fd, COL_INFO) || tree) {
+ if (check_col(pinfo->fd, COL_INFO) || tree) {
for (i = 0; i < 8; i++) {
bpos = 1 << i;
if (th.th_flags & bpos) {
@@ -457,14 +480,14 @@ dissect_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
hlen = hi_nibble(th.th_off_x2) * 4; /* TCP header length, in bytes */
/* Compute the length of data in this segment. */
- seglen = pi.len - (offset + hlen);
+ seglen = tvb_reported_length(tvb) - hlen;
/* Compute the sequence number of next octet after this segment. */
nxtseq = th.th_seq + seglen;
- if (check_col(fd, COL_PROTOCOL))
- col_add_str(fd, COL_PROTOCOL, "TCP");
- if (check_col(fd, COL_INFO)) {
+ if (check_col(pinfo->fd, COL_PROTOCOL))
+ col_add_str(pinfo->fd, COL_PROTOCOL, "TCP");
+ if (check_col(pinfo->fd, COL_INFO)) {
/* Copy the data into info_str in case one of the option handling
routines needs to append to it. */
if (th.th_flags & TH_URG)
@@ -480,40 +503,40 @@ dissect_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
if (tree) {
if (g_tcp_summary_in_tree) {
- ti = proto_tree_add_protocol_format(tree, proto_tcp, NullTVB, offset, hlen, "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u), Seq: %u, Ack: %u", get_tcp_port(th.th_sport), th.th_sport, get_tcp_port(th.th_dport), th.th_dport, th.th_seq, th.th_ack);
+ ti = proto_tree_add_protocol_format(tree, proto_tcp, tvb, offset, hlen, "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u), Seq: %u, Ack: %u", get_tcp_port(th.th_sport), th.th_sport, get_tcp_port(th.th_dport), th.th_dport, th.th_seq, th.th_ack);
}
else {
- ti = proto_tree_add_item(tree, proto_tcp, NullTVB, offset, hlen, FALSE);
+ ti = proto_tree_add_item(tree, proto_tcp, tvb, offset, hlen, FALSE);
}
tcp_tree = proto_item_add_subtree(ti, ett_tcp);
- proto_tree_add_uint_format(tcp_tree, hf_tcp_srcport, NullTVB, offset, 2, th.th_sport,
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_srcport, tvb, offset, 2, th.th_sport,
"Source port: %s (%u)", get_tcp_port(th.th_sport), th.th_sport);
- proto_tree_add_uint_format(tcp_tree, hf_tcp_dstport, NullTVB, offset + 2, 2, th.th_dport,
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, th.th_dport,
"Destination port: %s (%u)", get_tcp_port(th.th_dport), th.th_dport);
- proto_tree_add_uint_hidden(tcp_tree, hf_tcp_port, NullTVB, offset, 2, th.th_sport);
- proto_tree_add_uint_hidden(tcp_tree, hf_tcp_port, NullTVB, offset + 2, 2, th.th_dport);
- proto_tree_add_uint(tcp_tree, hf_tcp_seq, NullTVB, offset + 4, 4, th.th_seq);
+ proto_tree_add_uint_hidden(tcp_tree, hf_tcp_port, tvb, offset, 2, th.th_sport);
+ proto_tree_add_uint_hidden(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, th.th_dport);
+ proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, th.th_seq);
if (nxtseq != th.th_seq)
- proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, NullTVB, offset, 0, nxtseq);
+ proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
if (th.th_flags & TH_ACK)
- proto_tree_add_uint(tcp_tree, hf_tcp_ack, NullTVB, offset + 8, 4, th.th_ack);
- proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, NullTVB, offset + 12, 1, hlen,
+ proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, th.th_ack);
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, hlen,
"Header length: %u bytes", hlen);
- tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, NullTVB, offset + 13, 1,
+ tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 13, 1,
th.th_flags, "Flags: 0x%04x (%s)", th.th_flags, flags);
field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
- proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, NullTVB, offset + 13, 1, th.th_flags);
- proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, NullTVB, offset + 13, 1, th.th_flags);
- proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, NullTVB, offset + 13, 1, th.th_flags);
- proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, NullTVB, offset + 13, 1, th.th_flags);
- proto_tree_add_boolean(field_tree, hf_tcp_flags_push, NullTVB, offset + 13, 1, th.th_flags);
- proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, NullTVB, offset + 13, 1, th.th_flags);
- proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, NullTVB, offset + 13, 1, th.th_flags);
- proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, NullTVB, offset + 13, 1, th.th_flags);
- proto_tree_add_uint(tcp_tree, hf_tcp_window_size, NullTVB, offset + 14, 2, th.th_win);
- proto_tree_add_uint(tcp_tree, hf_tcp_checksum, NullTVB, offset + 16, 2, th.th_sum);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, th.th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, tvb, offset + 13, 1, th.th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, th.th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, th.th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, th.th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, th.th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, th.th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, th.th_flags);
+ proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, th.th_win);
+ proto_tree_add_uint(tcp_tree, hf_tcp_checksum, tvb, offset + 16, 2, th.th_sum);
if (th.th_flags & TH_URG)
- proto_tree_add_uint(tcp_tree, hf_tcp_urgent_pointer, NullTVB, offset + 18, 2, th.th_urp);
+ proto_tree_add_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, th.th_urp);
}
/* Decode TCP options, if any. */
@@ -521,26 +544,27 @@ dissect_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
/* There's more than just the fixed-length header. Decode the
options. */
optlen = hlen - sizeof (e_tcphdr); /* length of options, in bytes */
- tf = proto_tree_add_text(tcp_tree, NullTVB, offset + 20, optlen,
+ tf = proto_tree_add_text(tcp_tree, tvb, offset + 20, optlen,
"Options: (%d bytes)", optlen);
field_tree = proto_item_add_subtree(tf, ett_tcp_options);
- dissect_ip_tcp_options(&pd[offset + 20], offset + 20, optlen,
+ dissect_ip_tcp_options(tvb, offset + 20, optlen,
tcpopts, N_TCP_OPTS, TCPOPT_EOL, field_tree);
}
- if (check_col(fd, COL_INFO))
- col_add_str(fd, COL_INFO, info_str);
+ if (check_col(pinfo->fd, COL_INFO))
+ col_add_str(pinfo->fd, COL_INFO, info_str);
/* Skip over header + options */
offset += hlen;
- pi.ptype = PT_TCP;
- pi.srcport = th.th_sport;
- pi.destport = th.th_dport;
+ pinfo->ptype = PT_TCP;
+ pinfo->srcport = th.th_sport;
+ pinfo->destport = th.th_dport;
/* Check the packet length to see if there's more data
(it could be an ACK-only packet) */
- if (packet_max > offset) {
+ length_remaining = tvb_length_remaining(tvb, offset);
+ if (length_remaining != 0) {
if (th.th_flags & TH_RST) {
/*
* RFC1122 says:
@@ -557,23 +581,23 @@ dissect_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
*
* so for segments with RST we just display the data as text.
*/
- proto_tree_add_text(tcp_tree, NullTVB, offset, END_OF_FRAME,
+ proto_tree_add_text(tcp_tree, tvb, offset, length_remaining,
"Reset cause: %s",
- format_text(&pd[offset], END_OF_FRAME));
+ tvb_format_text(tvb, offset, length_remaining));
} else
- decode_tcp_ports( pd, offset, fd, tree, th.th_sport, th.th_dport);
+ decode_tcp_ports( tvb, offset, pinfo, tree, th.th_sport, th.th_dport);
}
if( data_out_file ) {
reassemble_tcp( th.th_seq, /* sequence number */
seglen, /* data length */
- ( pd+offset ), /* data */
- ( pi.captured_len - offset ), /* captured data length */
+ tvb_get_ptr(tvb, offset, length_remaining), /* data */
+ length_remaining, /* captured data length */
( th.th_flags & TH_SYN ), /* is syn set? */
- &pi.net_src,
- &pi.net_dst,
- pi.srcport,
- pi.destport);
+ &pinfo->net_src,
+ &pinfo->net_dst,
+ pinfo->srcport,
+ pinfo->destport);
}
}
@@ -685,5 +709,5 @@ proto_register_tcp(void)
void
proto_reg_handoff_tcp(void)
{
- old_dissector_add("ip.proto", IP_PROTO_TCP, dissect_tcp);
+ dissector_add("ip.proto", IP_PROTO_TCP, dissect_tcp);
}