]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Introduce --time-stamp-precision 377/head
authorMichal Sekletar <[email protected]>
Wed, 19 Mar 2014 13:14:25 +0000 (14:14 +0100)
committerMichal Sekletar <[email protected]>
Wed, 14 May 2014 12:18:40 +0000 (14:18 +0200)
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.

netdissect.h
tcpdump.1.in
tcpdump.c
util.c

index e94ca976740f16cfe68f36293a7d73e5888f27f7..1b11bf8e9f3ba19f0e6cd51448035757fce6dbb7 100644 (file)
@@ -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;
index b1867419f5b95ebfd15aaa701c2d02a1c5df4d52..3cceb4683fba647570e997f6d6fa701db9f2fb6f 100644 (file)
@@ -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
index 39811867f72ee0f17bbe7127211c44c7e351d284..95b5ac0a10849da2ff898dabc46026ad374a76cd 100644 (file)
--- 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 12a15023e6d2a6145aa22f508585e11eb624da26..2fd26ef17fa69f73ce79230db4d71121a391afc3 100644 (file)
--- 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;
        }
 }