Calculate *Peek tagged timestamps in fixed-point.
authorGuy Harris <guy@alum.mit.edu>
Tue, 21 Apr 2015 01:27:41 +0000 (18:27 -0700)
committerGuy Harris <guy@alum.mit.edu>
Tue, 21 Apr 2015 01:28:15 +0000 (01:28 +0000)
Add a variant of filetime_to_nstime() that takes a value that's like a
FILETIME but in units of nanoseconds rather than tenths of a
microsecond, and use that.  (It looks as if they might just get FILETIME
values from the OS and multiply them by 100, as the nanosecond-FILETIME
values appear to be multiples of 100 in the captures I've seen, but they
might have chosen nanosecond resolution in case they need to support a
higher-resolution time stamp source, so we don't assume that the values
will always be a multiple of 100.)

Change-Id: If6a1cb2cb673688b042eb113b79cfd267f5454a5
Reviewed-on: https://code.wireshark.org/review/8150
Reviewed-by: Guy Harris <guy@alum.mit.edu>
wiretap/peektagged.c
wsutil/nstime.c
wsutil/nstime.h

index 8d9806899e6e83ae91b91feb9eadb273abb858fc..51bd43af62d6817cb3ad2bdc84d0efdd8578dc73 100644 (file)
@@ -461,16 +461,6 @@ wtap_open_return_val peektagged_open(wtap *wth, int *err, gchar **err_info)
     return WTAP_OPEN_MINE;
 }
 
-/*
- * Time stamps appear to be in nanoseconds since the Windows epoch
- * as used in FILETIMEs, i.e. midnight, January 1, 1601.
- *
- * This magic number came from "nt_time_to_nstime()" in "packet-smb.c".
- * 1970-1601 is 369; I'm not sure what the extra 3 days and 6 hours are
- * that are being subtracted.
- */
-#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
-
 /*
  * Read the packet.
  *
@@ -499,7 +489,7 @@ peektagged_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
     guint32 data_rate_or_mcs_index = 0;
     struct ieee_802_11_phdr ieee_802_11;
     int skip_len = 0;
-    double  t;
+    guint64 t;
 
     timestamp.upper = 0;
     timestamp.lower = 0;
@@ -678,12 +668,12 @@ peektagged_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
     phdr->caplen = sliceLength;
 
     /* calculate and fill in packet time stamp */
-    t =  (double) timestamp.lower +
-         (double) timestamp.upper * 4294967296.0;
-    t *= 1.0e-9;
-    t -= TIME_FIXUP_CONSTANT;
-    phdr->ts.secs  = (time_t) t;
-    phdr->ts.nsecs = (guint32) ((t - phdr->ts.secs)*1000000000);
+    t = (((guint64) timestamp.upper) << 32) + timestamp.lower;
+    if (!nsfiletime_to_nstime(&phdr->ts, t)) {
+        *err = WTAP_ERR_BAD_FILE;
+        *err_info = g_strdup_printf("peektagged: time stamp outside supported range");
+        return -1;
+    }
 
     switch (wth->file_encap) {
 
index 28693273f0e5ed85db4ee4e44f55aa9efbab153d..f2450489f2f055c101d772630221cd206580ea0e 100644 (file)
@@ -183,9 +183,18 @@ double nstime_to_msec(const nstime_t *nstime)
 
 double nstime_to_sec(const nstime_t *nstime)
 {
-    return ((double)nstime->secs + (double)nstime->nsecs/1000000000);
+    return ((double)nstime->secs + (double)nstime->nsecs/NS_PER_S);
 }
 
+/*
+ * This code is based on the Samba code:
+ *
+ *  Unix SMB/Netbios implementation.
+ *  Version 1.9.
+ *  time handling functions
+ *  Copyright (C) Andrew Tridgell 1992-1998
+ */
+
 /*
  * Number of seconds between the UN*X epoch (January 1, 1970, 00:00:00 GMT)
  * and the Windows NT epoch (January 1, 1601 in the proleptic Gregorian
@@ -217,37 +226,25 @@ double nstime_to_sec(const nstime_t *nstime)
 #define TIME_T_MAX ((time_t) (~ (time_t) 0 - TIME_T_MIN))
 #endif
 
-/*
- * function: filetime_to_nstime
- * converts a Windows FILETIME value to an nstime_t
- * returns TRUE if the conversion succeeds, FALSE if it doesn't
- * (for example, with a 32-bit time_t, the time overflows or
- * underflows time_t)
- */
-gboolean
-filetime_to_nstime(nstime_t *nstime, guint64 filetime)
+static gboolean
+common_filetime_to_nstime(nstime_t *nstime, guint64 ftsecs, int nsecs)
 {
-    /*
-     * This code is based on the Samba code:
-     *
-     *  Unix SMB/Netbios implementation.
-     *  Version 1.9.
-     *  time handling functions
-     *  Copyright (C) Andrew Tridgell 1992-1998
-     */
     gint64 secs;
-    int nsecs;
     /* The next two lines are a fix needed for the
        broken SCO compiler. JRA. */
     time_t l_time_min = TIME_T_MIN;
     time_t l_time_max = TIME_T_MAX;
 
-    /* Split into seconds and nanoseconds. */
-    secs = filetime / 10000000;
-    nsecs = (int)((filetime % 10000000)*100);
-
-    /* Now adjust the seconds. */
-    secs -= TIME_FIXUP_CONSTANT;
+    /*
+     * Shift the seconds from the Windows epoch to the UN*X epoch.
+     * ftsecs's value should fit in a 64-bit signed variable, as
+     * ftsecs is derived from a 64-bit fractions-of-a-second value,
+     * and is far from the maximum 64-bit signed value, and
+     * TIME_FIXUP_CONSTANT is also far from the maximum 64-bit
+     * signed value, so the difference between them should also
+     * fit in a 64-bit signed value.
+     */
+    secs = (gint64)ftsecs - TIME_FIXUP_CONSTANT;
 
     if (!(l_time_min <= secs && secs <= l_time_max)) {
         /* The result won't fit in a time_t */
@@ -262,6 +259,50 @@ filetime_to_nstime(nstime_t *nstime, guint64 filetime)
     return TRUE;
 }
 
+/*
+ * function: filetime_to_nstime
+ * converts a Windows FILETIME value to an nstime_t
+ * returns TRUE if the conversion succeeds, FALSE if it doesn't
+ * (for example, with a 32-bit time_t, the time overflows or
+ * underflows time_t)
+ */
+gboolean
+filetime_to_nstime(nstime_t *nstime, guint64 filetime)
+{
+    guint64 ftsecs;
+    int nsecs;
+
+    /*
+     * Split into seconds and tenths of microseconds, and
+     * then convert tenths of microseconds to nanoseconds.
+     */
+    ftsecs = filetime / 10000000;
+    nsecs = (int)((filetime % 10000000)*100);
+
+    return common_filetime_to_nstime(nstime, ftsecs, nsecs);
+}
+
+/*
+ * function: nsfiletime_to_nstime
+ * converts a Windows FILETIME-like value, but given in nanoseconds
+ * rather than 10ths of microseconds, to an nstime_t
+ * returns TRUE if the conversion succeeds, FALSE if it doesn't
+ * (for example, with a 32-bit time_t, the time overflows or
+ * underflows time_t)
+ */
+gboolean
+nsfiletime_to_nstime(nstime_t *nstime, guint64 nsfiletime)
+{
+    guint64 ftsecs;
+    int nsecs;
+
+    /* Split into seconds and nanoseconds. */
+    ftsecs = nsfiletime / NS_PER_S;
+    nsecs = (int)(nsfiletime % NS_PER_S);
+
+    return common_filetime_to_nstime(nstime, ftsecs, nsecs);
+}
+
 /*
  * Editor modelines
  *
@@ -274,4 +315,3 @@ filetime_to_nstime(nstime_t *nstime, guint64 filetime)
  * ex: set shiftwidth=4 tabstop=8 expandtab:
  * :indentSize=4:tabSize=8:noTabs=true:
  */
-
index c72daa19c600a5c526e5900009722099dbd4a0cf..4145ac583c842395f764da36debce2e54a355f17 100644 (file)
@@ -106,6 +106,11 @@ WS_DLL_PUBLIC double nstime_to_sec(const nstime_t *nstime);
     FALSE on failure */
 WS_DLL_PUBLIC gboolean filetime_to_nstime(nstime_t *nstime, guint64 filetime);
 
+/** converts time like Windows FILETIME, but expressed in nanoseconds
+    rather than tenths of microseconds, to nstime, returns TRUE on success,
+    FALSE on failure */
+WS_DLL_PUBLIC gboolean nsfiletime_to_nstime(nstime_t *nstime, guint64 nsfiletime);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */