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