1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29
30 #ifndef HAVE_GETTIMEOFDAY
31
32 #include "compat.h"
33
34 #ifdef _WIN32
35 /*
36 * NOTICE: mingw has much faster gettimeofday!
37 * autoconf will set HAVE_GETTIMEOFDAY
38 */
39
40 #include <windows.h>
41 #include <time.h>
42
43 static time_t gtc_base = 0;
44 static DWORD gtc_last = 0;
45 static time_t last_sec = 0;
46 static unsigned int last_msec = 0;
47 static int bt_last = 0;
48
49 static void
gettimeofday_calibrate(void)50 gettimeofday_calibrate(void)
51 {
52 const time_t t = time(NULL);
53 const DWORD gtc = GetTickCount();
54 gtc_base = t - gtc/1000;
55 gtc_last = gtc;
56 }
57
58 /*
59 * Rewritten by JY for OpenVPN 2.1, after I realized that
60 * QueryPerformanceCounter takes nearly 2 orders of magnitude
61 * more processor cycles than GetTickCount.
62 */
63 int
gettimeofday(struct timeval * tv,void * tz)64 gettimeofday(struct timeval *tv, void *tz)
65 {
66 const DWORD gtc = GetTickCount();
67 int bt = 0;
68 time_t sec;
69 unsigned int msec;
70 const int backtrack_hold_seconds = 10;
71
72 (void)tz;
73
74 /* recalibrate at the dreaded 49.7 day mark */
75 if (!gtc_base || gtc < gtc_last)
76 {
77 gettimeofday_calibrate();
78 }
79 gtc_last = gtc;
80
81 sec = gtc_base + gtc / 1000;
82 msec = gtc % 1000;
83
84 if (sec == last_sec)
85 {
86 if (msec < last_msec)
87 {
88 msec = last_msec;
89 bt = 1;
90 }
91 }
92 else if (sec < last_sec)
93 {
94 /* We try to dampen out backtracks of less than backtrack_hold_seconds.
95 * Larger backtracks will be passed through and dealt with by the
96 * TIME_BACKTRACK_PROTECTION code */
97 if (sec > last_sec - backtrack_hold_seconds)
98 {
99 sec = last_sec;
100 msec = last_msec;
101 }
102 bt = 1;
103 }
104
105 last_sec = sec;
106 tv->tv_sec = (long)sec;
107 tv->tv_usec = (last_msec = msec) * 1000;
108
109 if (bt && !bt_last)
110 {
111 gettimeofday_calibrate();
112 }
113 bt_last = bt;
114
115 return 0;
116 }
117
118 #else /* ifdef _WIN32 */
119
120 #include <time.h>
121
122 int
gettimeofday(struct timeval * tv,void * tz)123 gettimeofday(struct timeval *tv, void *tz)
124 {
125 (void)tz;
126 tv->tv_sec = time(NULL);
127 tv->tv_usec = 0;
128 return 0;
129 }
130
131 #endif /* _WIN32 */
132
133 #endif /* HAVE_GETTIMEOFDAY */
134