diff --git a/AUTHORS b/AUTHORS index 72389b6c18..17c26dfd06 100644 --- a/AUTHORS +++ b/AUTHORS @@ -642,6 +642,7 @@ Christian Lacunza { Scott Renfro { LDAP checks for invalid packets + "-t" flag for editcap, to adjust timestamps in frames } Juan Toledo { diff --git a/doc/editcap.pod b/doc/editcap.pod index b19fde905e..fbb681b80d 100644 --- a/doc/editcap.pod +++ b/doc/editcap.pod @@ -11,6 +11,7 @@ S<[ B<-T> encapsulation type ]> S<[ B<-r> ]> S<[ B<-v> ]> S<[ B<-s> snaplen ]> +S<[ B<-t> time adjustment ]> S<[ B<-h> ]> I I @@ -61,6 +62,15 @@ appear to reject Ethernet frames larger than the standard Ethernet MTU, 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[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 @@ -98,6 +108,10 @@ Causes B to print a number of messages while it's working. Sets the snapshot length to use when writing the data. +=item -t + +Sets the time adjustment to use on selected frames. + =item -h Prints the version and options and exits. diff --git a/editcap.c b/editcap.c index 0c26c46e27..d003633868 100644 --- a/editcap.c +++ b/editcap.c @@ -1,7 +1,7 @@ -/* 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 $ + * $Id: editcap.c,v 1.16 2001/07/12 08:16:44 guy Exp $ * * Originally written by Richard Sharpe. * Improved by Guy Harris. @@ -46,6 +46,13 @@ struct select_item { } 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_file_type = WTAP_FILE_PCAP; /* default to "libpcap" */ 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 @@ edit_callback(u_char *user, const struct wtap_pkthdr *phdr, int offset, 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 @@ edit_callback(u_char *user, const struct wtap_pkthdr *phdr, int offset, } +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 @@ void usage() fprintf(stderr, " \t default is libpcap\n"); fprintf(stderr, " \t-s specifies that packets should be truncated to\n"); fprintf(stderr, " \t bytes of data\n"); + fprintf(stderr, " \t-t