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