diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | doc/editcap.pod | 42 | ||||
-rw-r--r-- | docbook/release-notes.xml | 3 | ||||
-rw-r--r-- | editcap.c | 156 |
4 files changed, 199 insertions, 3 deletions
@@ -2483,6 +2483,7 @@ Jim Young <sysjhy [AT] langate.gsu.edu> { Improvements LLDP dissection (803.3 "PMD Auto-Negotiation Advertised Capability" and "Operational MAU Type") Capinfos time order checking + Editcap time order forcing } diff --git a/doc/editcap.pod b/doc/editcap.pod index 5499154731..f2cb2f7e34 100644 --- a/doc/editcap.pod +++ b/doc/editcap.pod @@ -17,6 +17,7 @@ S<[ B<-i> E<lt>seconds per fileE<gt> ]> S<[ B<-r> ]> S<[ B<-s> E<lt>snaplenE<gt> ]> S<[ B<-t> E<lt>time adjustmentE<gt> ]> +S<[ B<-S> E<lt>strict time adjustmentE<gt> ]> S<[ B<-T> E<lt>encapsulation typeE<gt> ]> S<[ B<-v> ]> I<infile> @@ -204,6 +205,39 @@ 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. +=item -S E<lt>strict time adjustmentE<gt> + +Time adjust selected packets to insure strict chronological order. + +The <strict time adjustment> value represents relative seconds +specified as [-]I<seconds>[I<.fractional seconds>]. + +As the capture file is processed each packet's absolute time is +I<possibly> adjusted to be equal to or greater than the previous +packet's absolute timestamp depending on the <strict time +adjustment> value. + +If <strict time adjustment> value is 0 or greater (e.g. 0.000001) +then B<only> packets with a timestamp less than the previous packet +will adjusted. The adjusted timestamp value will be set to be +equal to the timestamp value of the previous packet plus the value +of the <strict time adjustment> value. A <strict time adjustment> +value of 0 will adjust the minimum number of timestamp values +necessary to insure that the resulting capture file is in +strict chronological order. + +If <strict time adjustment> value is specified as a +negative value, then the timestamp values of B<all> +packets will be adjusted to be equal to the timestamp value +of the previous packet plus the absolute value of the +<lt>strict time adjustment<gt> value. A <strict time +adjustment> value of -0 will result in all packets +having the timestamp value of the first packet. + +This feature is useful when the trace file has an occasional +packet with a negative delta time relative to the previous +packet. + =item -T E<lt>encapsulation typeE<gt> Sets the packet encapsulation type of the output capture file. @@ -288,6 +322,14 @@ or on Windows systems editcap -v -D 0 capture.pcap NUL +To advance the timestamps of each packet forward by 3.0827 seconds: + + editcap -t 3.0827 capture.pcap adjusted.pcap + +To insure all timestamps are in strict chronological order: + + editcap -S 0 capture.pcap adjusted.pcap + To introduce 5% random errors in a capture file use: =over 4 diff --git a/docbook/release-notes.xml b/docbook/release-notes.xml index 62cc6af4b2..ccba280ecd 100644 --- a/docbook/release-notes.xml +++ b/docbook/release-notes.xml @@ -137,7 +137,8 @@ Wireshark Info <listitem> <para> - Capinfos now checks the time order of capture files. + Capinfos and editcap now respectively support time order checking + and forcing. </para> </listitem> @@ -134,6 +134,10 @@ static gboolean check_startstop = FALSE; static gboolean dup_detect = FALSE; static gboolean dup_detect_by_time = FALSE; +static int do_strict_time_adjustment = FALSE; +static struct time_adjustment strict_time_adj = {{0, 0}, 0}; /* strict time adjustment */ +static nstime_t previous_time = {0, 0}; /* previous time */ + static int find_dct2000_real_data(guint8 *buf); static gchar * @@ -365,6 +369,81 @@ set_time_adjustment(char *optarg_str_p) } static void +set_strict_time_adj(char *optarg) +{ + char *frac, *end; + long val; + size_t frac_digits; + + if (!optarg) + return; + + /* skip leading whitespace */ + while (*optarg == ' ' || *optarg == '\t') { + optarg++; + } + + /* + * check for a negative adjustment + * A negative strict adjustment value is a flag + * to adjust all frames by the specifed delta time. + */ + if (*optarg == '-') { + strict_time_adj.is_negative = 1; + optarg++; + } + + /* collect whole number of seconds, if any */ + if (*optarg == '.') { /* only fractional (i.e., .5 is ok) */ + val = 0; + frac = optarg; + } else { + val = strtol(optarg, &frac, 10); + if (frac == NULL || frac == optarg || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg); + exit(1); + } + if (val < 0) { /* implies '--' since we caught '-' above */ + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg); + exit(1); + } + } + strict_time_adj.tv.tv_sec = val; + + /* now collect the partial seconds, if any */ + if (*frac != '\0') { /* chars left, so get fractional part */ + val = strtol(&(frac[1]), &end, 10); + /* if more than 6 fractional digits truncate to 6 */ + if((end - &(frac[1])) > 6) { + frac[7] = 't'; /* 't' for truncate */ + 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\" isn't 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++; + } + } + strict_time_adj.tv.tv_usec = val; +} + +static void set_rel_time(char *optarg_str_p) { char *frac, *end; @@ -613,7 +692,7 @@ usage(gboolean is_error) fprintf(output, "\n"); fprintf(output, " NOTE: The use of the 'Duplicate packet removal' options with\n"); fprintf(output, " other editcap options except -v may not always work as expected.\n"); - fprintf(output, " Specifically the -r and -t options will very likely NOT have the\n"); + fprintf(stderr, " Specifically the -r, -t or -S options will very likely NOT have the\n"); fprintf(output, " desired effect if combined with the -d, -D or -w.\n"); fprintf(output, "\n"); fprintf(output, "Packet manipulation:\n"); @@ -621,6 +700,14 @@ usage(gboolean is_error) fprintf(output, " -C <choplen> chop each packet at the end by <choplen> bytes.\n"); fprintf(output, " -t <time adjustment> adjust the timestamp of each packet;\n"); fprintf(output, " <time adjustment> is in relative seconds (e.g. -0.5).\n"); + fprintf(stderr, " -S <strict adjustment> adjust timestamp of packets if necessary to insure\n"); + fprintf(stderr, " strict chronological increasing order. The <strict\n"); + fprintf(stderr, " adjustment> is specified in relative seconds with\n"); + fprintf(stderr, " values of 0 or 0.000001 being the most reasonable.\n"); + fprintf(stderr, " A negative adjustment value will modify timestamps so\n"); + fprintf(stderr, " that each packet's delta time is the absolute value\n"); + fprintf(stderr, " of the adjustment specified. A value of -0 will set\n"); + fprintf(stderr, " all packets to the timestamp of the first packet.\n"); fprintf(output, " -E <error probability> set the probability (between 0.0 and 1.0 incl.)\n"); fprintf(output, " that a particular packet byte will be randomly changed.\n"); fprintf(output, "\n"); @@ -734,7 +821,7 @@ main(int argc, char *argv[]) #endif /* Process the options */ - while ((opt = getopt(argc, argv, "A:B:c:C:dD:E:F:hrs:i:t:T:vw:")) !=-1) { + while ((opt = getopt(argc, argv, "A:B:c:C:dD:E:F:hrs:i:t:S:T:vw:")) !=-1) { switch (opt) { @@ -846,6 +933,11 @@ main(int argc, char *argv[]) set_time_adjustment(optarg); break; + case 'S': + set_strict_time_adj(optarg); + do_strict_time_adjustment = TRUE; + break; + case 'T': out_frame_type = wtap_short_string_to_encap(optarg); if (out_frame_type < 0) { @@ -1096,6 +1188,66 @@ main(int argc, char *argv[]) phdr = &snap_phdr; } + /* + * Do we adjust timestamps to insure strict chronologically order? + */ + + if (do_strict_time_adjustment) { + if (previous_time.secs || previous_time.nsecs) { + if (!strict_time_adj.is_negative) { + nstime_t current; + nstime_t delta; + + current.secs = phdr->ts.secs; + current.nsecs = phdr->ts.nsecs; + + nstime_delta(&delta, ¤t, &previous_time); + + if (delta.secs < 0 || delta.nsecs < 0) + { + /* + * A negative delta indicates that the current packet + * has an absolute timestamp less than the previous packet + * that it is being compared to. This is NOT a normal + * situation since trace files usually have packets in + * chronological order (oldest to newest). + */ + /* printf("++out of order, need to adjust this packet!\n"); */ + snap_phdr = *phdr; + snap_phdr.ts.secs = previous_time.secs + strict_time_adj.tv.tv_sec; + snap_phdr.ts.nsecs = previous_time.nsecs; + if (snap_phdr.ts.nsecs + strict_time_adj.tv.tv_usec * 1000 > ONE_MILLION * 1000) { + /* carry */ + snap_phdr.ts.secs++; + snap_phdr.ts.nsecs += (strict_time_adj.tv.tv_usec - ONE_MILLION) * 1000; + } else { + snap_phdr.ts.nsecs += strict_time_adj.tv.tv_usec * 1000; + } + phdr = &snap_phdr; + } + } else { + /* + * A negative strict time adjustment is requested. + * Unconditionally set each timestamp to previous + * packet's timestamp plus delta. + */ + snap_phdr = *phdr; + snap_phdr.ts.secs = previous_time.secs + strict_time_adj.tv.tv_sec; + snap_phdr.ts.nsecs = previous_time.nsecs; + if (snap_phdr.ts.nsecs + strict_time_adj.tv.tv_usec * 1000 > ONE_MILLION * 1000) { + /* carry */ + snap_phdr.ts.secs++; + snap_phdr.ts.nsecs += (strict_time_adj.tv.tv_usec - ONE_MILLION) * 1000; + } else { + snap_phdr.ts.nsecs += strict_time_adj.tv.tv_usec * 1000; + } + phdr = &snap_phdr; + } + } + previous_time.secs = phdr->ts.secs; + previous_time.nsecs = phdr->ts.nsecs; + } + /* assume that if the frame's tv_sec is 0, then * the timestamp isn't supported */ if (phdr->ts.secs > 0 && time_adj.tv.tv_sec != 0) { |