1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/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 #ifndef OTIME_H
25 #define OTIME_H
26
27 #include "common.h"
28 #include "integer.h"
29 #include "buffer.h"
30
31 struct frequency_limit
32 {
33 int max;
34 int per;
35 int n;
36 time_t reset;
37 };
38
39 struct frequency_limit *frequency_limit_init(int max, int per);
40
41 void frequency_limit_free(struct frequency_limit *f);
42
43 bool frequency_limit_event_allowed(struct frequency_limit *f);
44
45 /* format a time_t as ascii, or use current time if 0 */
46 const char *time_string(time_t t, int usec, bool show_usec, struct gc_arena *gc);
47
48 /* struct timeval functions */
49
50 const char *tv_string(const struct timeval *tv, struct gc_arena *gc);
51
52 const char *tv_string_abs(const struct timeval *tv, struct gc_arena *gc);
53
54 extern time_t now; /* updated frequently to time(NULL) */
55
56 void time_test(void);
57
58 void update_now(const time_t system_time);
59
60 extern time_t now_usec;
61 void update_now_usec(struct timeval *tv);
62
63 static inline int
openvpn_gettimeofday(struct timeval * tv,void * tz)64 openvpn_gettimeofday(struct timeval *tv, void *tz)
65 {
66 const int status = gettimeofday(tv, tz);
67 if (!status)
68 {
69 update_now_usec(tv);
70 tv->tv_sec = now;
71 tv->tv_usec = now_usec;
72 }
73 return status;
74 }
75
76 static inline void
update_time(void)77 update_time(void)
78 {
79 #ifdef _WIN32
80 /* on _WIN32, gettimeofday is faster than time(NULL) */
81 struct timeval tv;
82 openvpn_gettimeofday(&tv, NULL);
83 #else
84 update_now(time(NULL));
85 now_usec = 0;
86 #endif
87 }
88
89 static inline time_t
openvpn_time(time_t * t)90 openvpn_time(time_t *t)
91 {
92 update_time();
93 if (t)
94 {
95 *t = now;
96 }
97 return now;
98 }
99
100 static inline void
tv_clear(struct timeval * tv)101 tv_clear(struct timeval *tv)
102 {
103 tv->tv_sec = 0;
104 tv->tv_usec = 0;
105 }
106
107 static inline bool
tv_defined(const struct timeval * tv)108 tv_defined(const struct timeval *tv)
109 {
110 return tv->tv_sec > 0 && tv->tv_usec > 0;
111 }
112
113 /* return tv1 - tv2 in usec, constrained by max_seconds */
114 static inline int
tv_subtract(const struct timeval * tv1,const struct timeval * tv2,const unsigned int max_seconds)115 tv_subtract(const struct timeval *tv1, const struct timeval *tv2, const unsigned int max_seconds)
116 {
117 const int max_usec = max_seconds * 1000000;
118 const int sec_diff = tv1->tv_sec - tv2->tv_sec;
119
120 if (sec_diff > ((int)max_seconds + 10))
121 {
122 return max_usec;
123 }
124 else if (sec_diff < -((int)max_seconds + 10))
125 {
126 return -max_usec;
127 }
128 return constrain_int(sec_diff * 1000000 + (tv1->tv_usec - tv2->tv_usec), -max_usec, max_usec);
129 }
130
131 static inline void
tv_add(struct timeval * dest,const struct timeval * src)132 tv_add(struct timeval *dest, const struct timeval *src)
133 {
134 dest->tv_sec += src->tv_sec;
135 dest->tv_usec += src->tv_usec;
136 dest->tv_sec += (dest->tv_usec >> 20);
137 dest->tv_usec &= 0x000FFFFF;
138 if (dest->tv_usec >= 1000000)
139 {
140 dest->tv_usec -= 1000000;
141 dest->tv_sec += 1;
142 }
143 }
144
145 static inline bool
tv_lt(const struct timeval * t1,const struct timeval * t2)146 tv_lt(const struct timeval *t1, const struct timeval *t2)
147 {
148 if (t1->tv_sec < t2->tv_sec)
149 {
150 return true;
151 }
152 else if (t1->tv_sec > t2->tv_sec)
153 {
154 return false;
155 }
156 else
157 {
158 return t1->tv_usec < t2->tv_usec;
159 }
160 }
161
162 static inline bool
tv_le(const struct timeval * t1,const struct timeval * t2)163 tv_le(const struct timeval *t1, const struct timeval *t2)
164 {
165 if (t1->tv_sec < t2->tv_sec)
166 {
167 return true;
168 }
169 else if (t1->tv_sec > t2->tv_sec)
170 {
171 return false;
172 }
173 else
174 {
175 return t1->tv_usec <= t2->tv_usec;
176 }
177 }
178
179 static inline bool
tv_ge(const struct timeval * t1,const struct timeval * t2)180 tv_ge(const struct timeval *t1, const struct timeval *t2)
181 {
182 if (t1->tv_sec > t2->tv_sec)
183 {
184 return true;
185 }
186 else if (t1->tv_sec < t2->tv_sec)
187 {
188 return false;
189 }
190 else
191 {
192 return t1->tv_usec >= t2->tv_usec;
193 }
194 }
195
196 static inline bool
tv_gt(const struct timeval * t1,const struct timeval * t2)197 tv_gt(const struct timeval *t1, const struct timeval *t2)
198 {
199 if (t1->tv_sec > t2->tv_sec)
200 {
201 return true;
202 }
203 else if (t1->tv_sec < t2->tv_sec)
204 {
205 return false;
206 }
207 else
208 {
209 return t1->tv_usec > t2->tv_usec;
210 }
211 }
212
213 static inline bool
tv_eq(const struct timeval * t1,const struct timeval * t2)214 tv_eq(const struct timeval *t1, const struct timeval *t2)
215 {
216 return t1->tv_sec == t2->tv_sec && t1->tv_usec == t2->tv_usec;
217 }
218
219 static inline void
tv_delta(struct timeval * dest,const struct timeval * t1,const struct timeval * t2)220 tv_delta(struct timeval *dest, const struct timeval *t1, const struct timeval *t2)
221 {
222 int sec = t2->tv_sec - t1->tv_sec;
223 int usec = t2->tv_usec - t1->tv_usec;
224
225 while (usec < 0)
226 {
227 usec += 1000000;
228 sec -= 1;
229 }
230
231 if (sec < 0)
232 {
233 usec = sec = 0;
234 }
235
236 dest->tv_sec = sec;
237 dest->tv_usec = usec;
238 }
239
240 #define TV_WITHIN_SIGMA_MAX_SEC 600
241 #define TV_WITHIN_SIGMA_MAX_USEC (TV_WITHIN_SIGMA_MAX_SEC * 1000000)
242
243 /*
244 * Is t1 and t2 within sigma microseconds of each other?
245 */
246 static inline bool
tv_within_sigma(const struct timeval * t1,const struct timeval * t2,unsigned int sigma)247 tv_within_sigma(const struct timeval *t1, const struct timeval *t2, unsigned int sigma)
248 {
249 const int delta = tv_subtract(t1, t2, TV_WITHIN_SIGMA_MAX_SEC); /* sigma should be less than 10 minutes */
250 return -(int)sigma <= delta && delta <= (int)sigma;
251 }
252
253 /*
254 * Used to determine in how many seconds we should be
255 * called again.
256 */
257 static inline void
interval_earliest_wakeup(interval_t * wakeup,time_t at,time_t current)258 interval_earliest_wakeup(interval_t *wakeup, time_t at, time_t current)
259 {
260 if (at > current)
261 {
262 const interval_t delta = (interval_t) (at - current);
263 if (delta < *wakeup)
264 {
265 *wakeup = delta;
266 }
267 if (*wakeup < 0)
268 {
269 *wakeup = 0;
270 }
271 }
272 }
273
274 #endif /* ifndef OTIME_H */
275