diff options
-rw-r--r-- | wiretap/peektagged.c | 24 | ||||
-rw-r--r-- | wsutil/nstime.c | 92 | ||||
-rw-r--r-- | wsutil/nstime.h | 5 |
3 files changed, 78 insertions, 43 deletions
diff --git a/wiretap/peektagged.c b/wiretap/peektagged.c index 8d9806899e..51bd43af62 100644 --- a/wiretap/peektagged.c +++ b/wiretap/peektagged.c @@ -462,16 +462,6 @@ wtap_open_return_val peektagged_open(wtap *wth, int *err, gchar **err_info) } /* - * 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. * * XXX - we should supply the additional radio information; @@ -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) { diff --git a/wsutil/nstime.c b/wsutil/nstime.c index 28693273f0..f2450489f2 100644 --- a/wsutil/nstime.c +++ b/wsutil/nstime.c @@ -183,10 +183,19 @@ 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 * calendar, 00:00:00 "GMT") @@ -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 */ @@ -263,6 +260,50 @@ filetime_to_nstime(nstime_t *nstime, guint64 filetime) } /* + * 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 * * Local Variables: @@ -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: */ - diff --git a/wsutil/nstime.h b/wsutil/nstime.h index c72daa19c6..4145ac583c 100644 --- a/wsutil/nstime.h +++ b/wsutil/nstime.h @@ -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 */ |