Ethereal-dev: [Ethereal-dev] editcap time adjustment patch

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

From: Scott Renfro <scott@xxxxxxxxxx>
Date: Wed, 11 Jul 2001 22:11:58 -0700
Here's a patch for editcap.c and editcap.pod that adds a -t option.

This option allows you to specify a time adjustment value that is
applied to the timestamps of selected frames (all frames by default in
editcap).

This is useful when comparing two dump files from different machines
where the clocks were not synchronized, but the difference is known or
can be estimated.  This will also be useful if/when someone writes a
utility to merge dump files.

cheers,
--Scott

-- 
Scott Renfro <scott@xxxxxxxxxx>                          +1 650 862 4206
Index: editcap.c
===================================================================
RCS file: /cvsroot/ethereal/editcap.c,v
retrieving revision 1.15
diff -u -r1.15 editcap.c
--- editcap.c	2001/06/19 23:08:55	1.15
+++ editcap.c	2001/07/12 04:57:28
@@ -1,5 +1,5 @@
-/* Edit capture files.  We can delete records, or simply convert from one 
- * format to another format.
+/* Edit capture files.  We can delete records, adjust timestamps, or
+ * simply convert from one format to another format.
  *
  * $Id: editcap.c,v 1.15 2001/06/19 23:08:55 guy Exp $
  *
@@ -46,6 +46,13 @@
 
 } select_item;
 
+#define ONE_MILLION 1000000
+
+struct time_adjustment {
+  struct timeval tv;
+  int is_negative;
+};
+
 struct select_item selectfrm[100];
 int max_selected = -1;
 static int count = 1;
@@ -54,6 +61,7 @@
 static int out_frame_type = -2;              /* Leave frame type alone */
 static int verbose = 0;                      /* Not so verbose         */
 static unsigned int snaplen = 0;             /* No limit               */
+static struct time_adjustment time_adj = {{0, 0}, 0}; /* no adjustment */
 
 /* Add a selection item, a simple parser for now */
 
@@ -151,6 +159,39 @@
       phdr = &snap_phdr;
     }
 
+    /* assume that if the frame's tv_sec is 0, then
+     * the timestamp isn't supported */
+    if (phdr->ts.tv_sec > 0 && time_adj.tv.tv_sec != 0) {
+      snap_phdr = *phdr;
+      if (time_adj.is_negative)
+        snap_phdr.ts.tv_sec -= time_adj.tv.tv_sec;
+      else
+        snap_phdr.ts.tv_sec += time_adj.tv.tv_sec;
+      phdr = &snap_phdr;
+    }
+
+    /* assume that if the frame's tv_sec is 0, then
+     * the timestamp isn't supported */
+    if (phdr->ts.tv_sec > 0 && time_adj.tv.tv_usec != 0) {
+      snap_phdr = *phdr;
+      if (time_adj.is_negative) { /* subtract */
+        if (snap_phdr.ts.tv_usec < time_adj.tv.tv_usec) { /* borrow */
+          snap_phdr.ts.tv_sec--;
+          snap_phdr.ts.tv_usec += ONE_MILLION;
+        }
+        snap_phdr.ts.tv_usec -= time_adj.tv.tv_usec;
+      } else {                  /* add */
+        if (snap_phdr.ts.tv_usec + time_adj.tv.tv_usec > ONE_MILLION) {
+          /* carry */
+          snap_phdr.ts.tv_sec++;
+          snap_phdr.ts.tv_usec += time_adj.tv.tv_usec - ONE_MILLION;
+        } else {
+          snap_phdr.ts.tv_usec += time_adj.tv.tv_usec;
+        }
+      }
+      phdr = &snap_phdr;
+    }
+      
     if (!wtap_dump(argp->pdh, phdr, pseudo_header, buf, &err)) {
 
       fprintf(stderr, "editcap: Error writing to %s: %s\n", argp->filename,
@@ -165,6 +206,55 @@
 
 }
 
+static void
+set_time_adjustment(char *optarg)
+{
+  char *frac, *end;
+  long val;
+  int frac_digits;
+
+  if (!optarg)
+    return;
+
+  /* first collect the whole seconds */
+  val = strtol(optarg, &frac, 10);
+  if (frac == NULL || frac == optarg || val == LONG_MIN || val == LONG_MAX) {
+    fprintf(stderr, "editcap: \"%s\" is not a valid time adjustment\n",
+            optarg);
+    exit(1);
+  }
+  if (val < 0) {
+    time_adj.is_negative = 1;
+    val = -val;
+  }
+  time_adj.tv.tv_sec = val;
+
+  /* now collect the partial seconds, if any */
+  if (*frac != '\0') {             /* have more to string, so more to */
+    val = strtol(&(frac[1]), &end, 10);
+    if (*frac != '.' || end == NULL || end == frac
+        || val < 0 || val > ONE_MILLION || val == LONG_MIN || val == LONG_MAX) {
+      fprintf(stderr, "editcap: \"%s\" is not a valid time adjustment\n",
+              optarg);
+      exit(1);
+    }
+  }
+  else {
+    return;                     /* no fractional digits */
+  }
+
+  /* adjust fractional portion from fractional to numerator
+   * e.g., in "1.5" from 5 to 500000 since .5*10^6 = 500000 */
+  if (frac && end) {            /* both are valid */
+    frac_digits = end - frac - 1;   /* fractional digit count (remember '.') */
+    while(frac_digits < 6) {    /* this is frac of 10^6 */
+      val *= 10;
+      frac_digits++;
+    }
+  }
+  time_adj.tv.tv_usec = val;
+}
+
 void usage()
 {
   int i;
@@ -193,6 +283,8 @@
   fprintf(stderr, "       \t    default is libpcap\n");
   fprintf(stderr, "       \t-s <snaplen> specifies that packets should be truncated to\n");
   fprintf(stderr, "       \t   <snaplen> bytes of data\n");
+  fprintf(stderr, "       \t-t <time adjustment> specifies the time adjustment\n");
+  fprintf(stderr, "       \t   to be applied to selected packets\n");
   fprintf(stderr, "\n      \t    A range of records can be specified as well\n");
 }
 
@@ -209,7 +301,7 @@
 
   /* Process the options first */
 
-  while ((opt = getopt(argc, argv, "T:F:rvs:h")) != EOF) {
+  while ((opt = getopt(argc, argv, "T:F:rvs:t:h")) != EOF) {
 
     switch (opt) {
 
@@ -246,6 +338,10 @@
       	    optarg);
       	exit(1);
       }
+      break;
+
+    case 't':
+      set_time_adjustment(optarg);
       break;
 
     case 'h':
Index: doc/editcap.pod
===================================================================
RCS file: /cvsroot/ethereal/doc/editcap.pod,v
retrieving revision 1.8
diff -u -r1.8 editcap.pod
--- editcap.pod	2001/07/05 21:27:11	1.8
+++ editcap.pod	2001/07/12 04:57:31
@@ -11,6 +11,7 @@
 S<[ B<-r> ]>
 S<[ B<-v> ]>
 S<[ B<-s> snaplen ]>
+S<[ B<-t> time adjustment ]>
 S<[ B<-h> ]>
 I<infile>
 I<outfile>
@@ -61,6 +62,15 @@
 making them incapable of handling gigabit Ethernet captures if jumbo
 frames were used).
 
+If the B<-t> flag is used to specify a time adjustment, the specified
+adjustment will be applied to all selected frames in the capture file.
+The adjustment is specified as [-]I<seconds>[I<.fractional seconds>].
+For example, B<-t> 3600 advances the timestamp on selected frames by one
+hour while B<-t> -0.5 reduces the timestamp on selected frames by
+one-half second.  This feature is useful when synchronizing dumps
+collected on different machines where the time difference between the
+two machines is known or can be estimated.
+
 If the B<-T> flag is used to specify an encapsulation type, the
 encapsulation type of the output capture file will be forced to the
 specified type, rather than being the type appropriate to the
@@ -97,6 +107,10 @@
 =item -s
 
 Sets the snapshot length to use when writing the data.
+
+=item -t
+
+Sets the time adjustment to use on selected frames.
 
 =item -h