editcap: add support for epoch timestamps in `-A` and `-B` options

Inspired in https://gitlab.com/wireshark/wireshark/-/merge_requests/1618.

Tested:

Timestamps on file used for comparison:
```
$ tshark -r test/captures/snakeoil-dtls.pcap -T fields -e frame.time_epoch
1150121069.248818000
1150121069.249193000
1150121069.251152000
1150121069.251384000
1150121069.293686000
1150121069.319315000
1150121075.230753000
1150121105.510885000
1150121105.510934000
```

Before:
```
$ ./build/run/editcap -B 1150121069.3 test/captures/snakeoil-dtls.pcap -
editcap: "1150121069.3" isn't a valid date and time
$ ./build/run/editcap -A 1150121069.3 test/captures/snakeoil-dtls.pcap -
editcap: "1150121069.3" isn't a valid date and time
$ ./build/run/editcap -A 1150121069 test/captures/snakeoil-dtls.pcap -
editcap: "1150121069" isn't a valid date and time
$ ./build/run/editcap -B 1150121069 test/captures/snakeoil-dtls.pcap -
editcap: "1150121069" isn't a valid date and time
```

After:
```
$ ./build/run/editcap -A 1150121069.3 test/captures/snakeoil-dtls.pcap - | tshark -r - -T fields -e frame.time_epoch
1150121069.319315000
1150121075.230753000
1150121105.510885000
1150121105.510934000
$ ./build/run/editcap -A 1150121069 test/captures/snakeoil-dtls.pcap - | tshark -r - -T fields -e frame.time_epoch
1150121069.248818000
1150121069.249193000
1150121069.251152000
1150121069.251384000
1150121069.293686000
1150121069.319315000
1150121075.230753000
1150121105.510885000
1150121105.510934000
$ ./build/run/editcap -B 1150121069.3 test/captures/snakeoil-dtls.pcap - | tshark -r - -T fields -e frame.time_epoch
1150121069.248818000
1150121069.249193000
1150121069.251152000
1150121069.251384000
1150121069.293686000
$ ./build/run/editcap -B 1150121069 test/captures/snakeoil-dtls.pcap - | tshark -r - -T fields -e frame.time_epoch
```
This commit is contained in:
Chema Gonzalez 2020-11-02 13:51:36 -08:00 committed by Wireshark GitLab Utility
parent 0e84610676
commit 03baf65ae7
5 changed files with 90 additions and 3 deletions

View File

@ -186,6 +186,7 @@ libwsutil.so.0 libwsutil0 #MINVER#
type_util_gdouble_to_guint64@Base 1.10.0
type_util_guint64_to_gdouble@Base 1.10.0
ulaw2linear@Base 1.12.0~rc1
unix_epoch_to_nstime@Base 3.5.0
update_adler32@Base 1.12.0~rc1
update_crc10_by_bytes@Base 1.10.0
ws_add_crash_info@Base 1.10.0

View File

@ -105,7 +105,8 @@ The time is given in ISO 8601 format, either
YYYY-MM-DD HH:MM:SS[.nnnnnnnnn][Z|±hh:mm] or
YYYY-MM-DDTHH:MM:SS[.nnnnnnnnn][Z|±hh:mm] .
The fractional seconds are optional, as is the time zone offset from UTC
(in which case local time is assumed).
(in which case local time is assumed). Unix epoch timestamps
(floating point format) are also accepted.
=item -B E<lt>stop timeE<gt>
@ -114,7 +115,8 @@ The time is given in ISO 8601 format, either
YYYY-MM-DD HH:MM:SS[.nnnnnnnnn][Z|±hh:mm] or
YYYY-MM-DDTHH:MM:SS[.nnnnnnnnn][Z|±hh:mm] .
The fractional seconds are optional, as is the time zone offset from UTC
(in which case local time is assumed).
(in which case local time is assumed). Unix epoch timestamps
(floating point format) are also accepted.
=item -c E<lt>packets per fileE<gt>

View File

@ -764,6 +764,7 @@ print_usage(FILE *output)
fprintf(output, " given time.\n");
fprintf(output, " Time format for -A/-B options is\n");
fprintf(output, " YYYY-MM-DDThh:mm:ss[.nnnnnnnnn][Z|+-hh:mm]\n");
fprintf(output, " Unix epoch timestamps are also supported.\n");
fprintf(output, "\n");
fprintf(output, "Duplicate packet removal:\n");
fprintf(output, " --novlan remove vlan info from packets before checking for duplicates.\n");
@ -1284,7 +1285,7 @@ main(int argc, char *argv[])
nstime_t in_time;
check_startstop = TRUE;
if (0 < iso8601_to_nstime(&in_time, optarg)) {
if ((0 < iso8601_to_nstime(&in_time, optarg)) || (0 < unix_epoch_to_nstime(&in_time, optarg))) {
if (opt == 'A') {
nstime_copy(&starttime, &in_time);
have_starttime = TRUE;

View File

@ -17,6 +17,10 @@
#include "epochs.h"
#include "time_util.h"
#ifndef HAVE_STRPTIME
# include "wsutil/strptime.h"
#endif
/* this is #defined so that we can clearly see that we have the right number of
zeros, rather than as a guard against the number of nanoseconds in a second
changing ;) */
@ -453,6 +457,80 @@ iso8601_to_nstime(nstime_t *nstime, const char *ptr)
return ret_val;
}
/*
* function: unix_epoch_to_nstime
* parses a character string for a date and time given in
* a floating point number containing a Unix epoch date-time
* format (e.g. 1600000000.000 for Sun Sep 13 05:26:40 AM PDT 2020)
* and converts to an nstime_t
* returns number of chars parsed on success, or 0 on failure
*
* Reference: https://en.wikipedia.org/wiki/Unix_time
*/
guint8
unix_epoch_to_nstime(nstime_t *nstime, const char *ptr)
{
struct tm tm;
char *ptr_new;
gint n_chars = 0;
guint frac = 0;
guint8 ret_val = 0;
const char *start = ptr;
memset(&tm, 0, sizeof(tm));
tm.tm_isdst = -1;
nstime_set_unset(nstime);
if (!(ptr_new=strptime(ptr, "%s", &tm))) {
return 0;
}
/* Validate what we got so far. mktime() doesn't care about strange
values (and we use this to our advantage when calculating the
time zone offset) but we should at least start with something valid */
if (!tm_is_valid(&tm)) {
return 0;
}
/* No UTC offset given; ISO 8601 says this means localtime */
nstime->secs = mktime(&tm);
/* Now let's test for fractional seconds */
if (*ptr_new == '.' || *ptr_new == ',') {
/* Get fractional seconds */
ptr_new++;
if (1 <= sscanf(ptr_new, "%u%n", &frac, &n_chars)) {
/* normalize frac to nanoseconds */
if ((frac >= 1000000000) || (frac == 0)) {
frac = 0;
} else {
switch (n_chars) { /* including leading zeros */
case 1: frac *= 100000000; break;
case 2: frac *= 10000000; break;
case 3: frac *= 1000000; break;
case 4: frac *= 100000; break;
case 5: frac *= 10000; break;
case 6: frac *= 1000; break;
case 7: frac *= 100; break;
case 8: frac *= 10; break;
default: break;
}
}
ptr_new += n_chars;
}
/* If we didn't get frac, it's still its default of 0 */
}
else {
tm.tm_sec = 0;
}
nstime->nsecs = frac;
/* return pointer shift */
ret_val = (guint)(ptr_new-start);
return ret_val;
}
/*
* Editor modelines
*

View File

@ -128,6 +128,11 @@ WS_DLL_PUBLIC gboolean nsfiletime_to_nstime(nstime_t *nstime, guint64 nsfiletime
Note that nstime is set to unset in the case of failure */
WS_DLL_PUBLIC guint8 iso8601_to_nstime(nstime_t *nstime, const char *ptr);
/** parse an Unix epoch timestamp format datetime string to nstime, returns
number of chars parsed on success, 0 on failure.
Note that nstime is set to unset in the case of failure */
WS_DLL_PUBLIC guint8 unix_epoch_to_nstime(nstime_t *nstime, const char *ptr);
#ifdef __cplusplus
}
#endif /* __cplusplus */