From: Michal Sekletar Date: Wed, 19 Mar 2014 13:14:25 +0000 (+0100) Subject: Introduce --time-stamp-precision X-Git-Tag: tcpdump-4.6.0~8^2 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/52b27d11fc50ebc4f1fc54b53fd9437d62dd7f4a Introduce --time-stamp-precision A while ago we introduced new API in libpcap which made possible to request time stamps with higher precision (nanoseconds). This commit aims to move things forward and implement missing bits. It introduces new long option --time-stamp-precision. Note that there is no equivalent short option. When used for a live capture tcpdump will ask the kernel for time stamp with desired precision and tcpdump will print fraction part of the time stamp using respective format. We currently support only microsecond and nanosecond precision. In the future we might support even more granular time stamp precision, but we should be fine to support only microseconds and nanoseconds for now. libpcap doesn't provide anything else at the moment anyway. When used in combination with -r/-w options then we obtain time stamps appropriately scaled up or down from libpcap. Also note that distinct magic number is used for savefiles containing nanosecond time stamps. --- diff --git a/netdissect.h b/netdissect.h index e94ca976..1b11bf8e 100644 --- a/netdissect.h +++ b/netdissect.h @@ -126,6 +126,7 @@ struct netdissect_options { int ndo_Hflag; /* dissect 802.11s draft mesh standard */ int ndo_packet_number; /* print a packet number in the beginning of line */ int ndo_suppress_default_print; /* don't use default_print() for unknown packet types */ + int ndo_tstamp_precision; /* requested time stamp precision */ const char *ndo_dltname; char *ndo_espsecret; diff --git a/tcpdump.1.in b/tcpdump.1.in index b1867419..3cceb468 100644 --- a/tcpdump.1.in +++ b/tcpdump.1.in @@ -432,6 +432,15 @@ List the supported time stamp types for the interface and exit. If the time stamp type cannot be set for the interface, no time stamp types are listed. .TP +.BI \-\-time\-stamp\-precision= tstamp_precision +.PD +Set the time stamp precision for the capture to +\fItstamp_precision\fP. Currently supported are microseconds and +nanoseconds. Note that availability of high precision time stamps (nanoseconds) +and their actual accuracy is platform and HW dependent. Also note that when +writing captures to the savefile, distinct magic number is used to distinguish +savefiles which contains time stamps in nanoseconds. +.TP .B \-K .PD 0 .TP diff --git a/tcpdump.c b/tcpdump.c index 39811867..95b5ac0a 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -650,6 +650,7 @@ show_devices_and_exit (void) */ #define OPTION_NUMBER 128 #define OPTION_VERSION 129 +#define OPTION_TSTAMP_PRECISION 130 static struct option longopts[] = { #if defined(HAVE_PCAP_CREATE) || defined(WIN32) @@ -665,6 +666,7 @@ static struct option longopts[] = { { "time-stamp-type", required_argument, NULL, 'j' }, { "list-time-stamp-types", no_argument, NULL, 'J' }, #endif + { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, { "dont-verify-checksums", no_argument, NULL, 'K' }, { "list-data-link-types", no_argument, NULL, 'L' }, { "no-optimize", no_argument, NULL, 'O' }, @@ -840,6 +842,18 @@ get_next_file(FILE *VFile, char *ptr) return ret; } +static int +tstamp_precision_from_string(const char *precision) +{ + if (strncmp(precision, "nano", strlen("nano")) == 0) + return PCAP_TSTAMP_PRECISION_NANO; + + if (strncmp(precision, "micro", strlen("micro")) == 0) + return PCAP_TSTAMP_PRECISION_MICRO; + + return -EINVAL; +} + int main(int argc, char **argv) { @@ -1275,6 +1289,12 @@ main(int argc, char **argv) exit(0); break; + case OPTION_TSTAMP_PRECISION: + gndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg); + if (gndo->ndo_tstamp_precision < 0) + error("unsupported time stamp precision"); + break; + default: print_usage(); exit(1); @@ -1366,7 +1386,11 @@ main(int argc, char **argv) RFileName = VFileLine; } - pd = pcap_open_offline(RFileName, ebuf); + if (gndo->ndo_tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) + pd = pcap_open_offline_with_tstamp_precision(RFileName, PCAP_TSTAMP_PRECISION_NANO, ebuf); + else + pd = pcap_open_offline_with_tstamp_precision(RFileName, PCAP_TSTAMP_PRECISION_MICRO, ebuf); + if (pd == NULL) error("%s", ebuf); dlt = pcap_datalink(pd); @@ -1413,6 +1437,13 @@ main(int argc, char **argv) if (Jflag) show_tstamp_types_and_exit(device, pd); #endif + if (gndo->ndo_tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) { + status = pcap_set_tstamp_precision(pd, PCAP_TSTAMP_PRECISION_NANO); + if (status != 0) + error("%s: Can't set nanosecond time stamp precision: %s", + device, pcap_statustostr(status)); + } + /* * Is this an interface that supports monitor mode? */ diff --git a/util.c b/util.c index 12a15023..2fd26ef1 100644 --- a/util.c +++ b/util.c @@ -135,11 +135,14 @@ fn_printzp(netdissect_options *ndo, * Format the timestamp */ static char * -ts_format(register int sec, register int usec) +ts_format(netdissect_options *ndo, int sec, int usec) { - static char buf[sizeof("00:00:00.000000")]; - (void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06u", - sec / 3600, (sec % 3600) / 60, sec % 60, usec); + static char buf[sizeof("00:00:00.000000000")]; + const char *format = ndo->ndo_tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? + "%02d:%02d:%02d.%09u" : "%02d:%02d:%02d.%06u"; + + snprintf(buf, sizeof(buf), format, + sec / 3600, (sec % 3600) / 60, sec % 60, usec); return buf; } @@ -163,7 +166,7 @@ ts_print(netdissect_options *ndo, case 0: /* Default */ s = (tvp->tv_sec + thiszone) % 86400; - ND_PRINT((ndo, "%s ", ts_format(s, tvp->tv_usec))); + ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec))); break; case 1: /* No time stamp */ @@ -191,7 +194,7 @@ ts_print(netdissect_options *ndo, d_sec--; } - ND_PRINT((ndo, "%s ", ts_format(d_sec, d_usec))); + ND_PRINT((ndo, "%s ", ts_format(ndo, d_sec, d_usec))); if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */ b_sec = tvp->tv_sec; @@ -208,7 +211,7 @@ ts_print(netdissect_options *ndo, else ND_PRINT((ndo, "%04d-%02d-%02d %s ", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, - ts_format(s, tvp->tv_usec))); + ts_format(ndo, s, tvp->tv_usec))); break; } }