aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--doc/editcap.pod42
-rw-r--r--docbook/release-notes.xml3
-rw-r--r--editcap.c156
4 files changed, 199 insertions, 3 deletions
diff --git a/AUTHORS b/AUTHORS
index 8106652a88..c5e74135d7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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>
diff --git a/editcap.c b/editcap.c
index 3492fb75cc..3cdfe59ce0 100644
--- a/editcap.c
+++ b/editcap.c
@@ -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, &current, &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) {