Ethereal-dev: [Ethereal-dev] patch to packet-tcp.c to display up times if timestamps

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Charles Levert <chuck@xxxxxxxxxxxxxxxx>
Date: Sat, 23 Oct 2004 03:47:07 -0400
Hi.

The following patch displays TCP timestamps as up times, somewhat
as p0f <http://lcamtuf.coredump.cx/p0f/p0f.shtml>
and Netcraft <http://uptime.netcraft.com/up/graph> do.

Of course, these up times are meaningless for hosts running operating
systems that apply countermeasures (like OpenBSD).  They are valid for
most OSes (including Linux), though.



[ Generated with ude,
    the unified-format diff-output ("unidiff") editor,
    version 0.1 of 2004-10-13.  ]
--- epan/dissectors/packet-tcp.c.orig-0.10.7	2004-10-20 18:34:51 -0400
+++ epan/dissectors/packet-tcp.c	2004-10-23 02:54:44 -0400
@@ -4 +4 @@
  * $Id: packet-tcp.c 12259 2004-10-11 08:12:34Z sahlberg $
@@ -132,6 +132,7 @@
 static gint ett_tcp_flags = -1;
 static gint ett_tcp_options = -1;
 static gint ett_tcp_option_sack = -1;
+static gint ett_tcp_option_timestamp = -1;
 static gint ett_tcp_analysis = -1;
 static gint ett_tcp_analysis_faults = -1;
 static gint ett_tcp_segments = -1;
@@ -2205,18 +2206,71 @@ dissect_tcpopt_echo(const ip_tcp_opt *op
   tcp_info_append_uint(pinfo, "ECHO", echo);
 }
 
+static void
+dissect_tcpopt_timestamp_field(const proto_tree *ts_tree,
+    tvbuff_t *tvb, int offset,
+    const char *name, guint32 value)
+{
+  /* Always use correct unit symbols.  We assume a 10 ms tick.  */
+  /* " (up time: 497 d + 02 h + 27 min + 52.95 s)" */
+  char up[44];
+  char *s = "";
+  const char sp[] = " + ";
+  guint32 r, q;
+
+  if (value) {
+    strcpy(up, " (up time: ");
+    r = value;
+    q = r / 8640000;
+    if (q) {
+      r -= q * 8640000;
+      sprintf(up + strlen(up), "%u d", q);
+      s = sp;
+    }
+    q = r / 360000;
+    if (q) {
+      r -= q * 360000;
+      sprintf(up + strlen(up), "%s%u h", s, q);
+      s = sp;
+    }
+    q = r / 6000;
+    if (q) {
+      r -= q * 6000;
+      sprintf(up + strlen(up), "%s%u min", s, q);
+      s = sp;
+    }
+    q = r / 100;
+    r -= q * 100;
+    if (q || r)
+      sprintf(up + strlen(up), "%s%u.%02u s", s, q, r);
+    strcpy(up + strlen(up), ")");
+  } else
+    up[0] = '\0';
+
+  proto_tree_add_text(ts_tree, tvb, offset, 4,
+    "%s: %u%s", name, value, up);
+}
+
 static void
 dissect_tcpopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
     int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
 {
   guint32 tsv, tser;
+  proto_item *tf;
+  proto_tree *ts_tree;
 
   tsv = tvb_get_ntohl(tvb, offset + 2);
   tser = tvb_get_ntohl(tvb, offset + 6);
   proto_tree_add_boolean_hidden(opt_tree, hf_tcp_option_time_stamp, tvb, 
 				offset, optlen, TRUE);
-  proto_tree_add_text(opt_tree, tvb, offset,      optlen,
+  tf = proto_tree_add_text(opt_tree, tvb, offset, optlen,
     "%s: tsval %u, tsecr %u", optp->name, tsv, tser);
+  ts_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+  dissect_tcpopt_timestamp_field(ts_tree, tvb, offset + 2,
+    "Timestamp Value", tsv);
+  /* XXX:  TSecr invalid unless ACK; we should warn.  */
+  dissect_tcpopt_timestamp_field(ts_tree, tvb, offset + 6,
+    "Timestamp Echo Reply", tser);
   tcp_info_append_uint(pinfo, "TSV", tsv);
   tcp_info_append_uint(pinfo, "TSER", tser);
 }
@@ -2303,7 +2357,7 @@ static const ip_tcp_opt tcpopts[] = {
   {
     TCPOPT_TIMESTAMP,
     "Time stamp",
-    NULL,
+    &ett_tcp_option_timestamp,
     FIXED_LENGTH,
     TCPOLEN_TIMESTAMP,
     dissect_tcpopt_timestamp
@@ -3223,6 +3277,7 @@ proto_register_tcp(void)
 		&ett_tcp_flags,
 		&ett_tcp_options,
 		&ett_tcp_option_sack,
+		&ett_tcp_option_timestamp,
 		&ett_tcp_analysis_faults,
 		&ett_tcp_analysis,
 		&ett_tcp_segments,