OpenVPN
otime.c
Go to the documentation of this file.
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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #include "otime.h"
33 
34 #include "memdbg.h"
35 
36 time_t now = 0; /* GLOBAL */
37 
38 #if TIME_BACKTRACK_PROTECTION
39 
40 static time_t now_adj = 0; /* GLOBAL */
41 time_t now_usec = 0; /* GLOBAL */
42 
43 /*
44  * Try to filter out time instability caused by the system
45  * clock backtracking or jumping forward.
46  */
47 
48 void
49 update_now(const time_t system_time)
50 {
51  const int forward_threshold = 86400; /* threshold at which to dampen forward jumps */
52  const int backward_trigger = 10; /* backward jump must be >= this many seconds before we adjust */
53  time_t real_time = system_time + now_adj;
54 
55  if (real_time > now)
56  {
57  const time_t overshoot = real_time - now - 1;
58  if (overshoot > forward_threshold && now_adj >= overshoot)
59  {
60  now_adj -= overshoot;
61  real_time -= overshoot;
62  }
63  now = real_time;
64  }
65  else if (real_time < now - backward_trigger)
66  {
67  now_adj += (now - real_time);
68  }
69 }
70 
71 void
72 update_now_usec(struct timeval *tv)
73 {
74  const time_t last = now;
75  update_now(tv->tv_sec);
76  if (now > last || (now == last && tv->tv_usec > now_usec))
77  {
78  now_usec = tv->tv_usec;
79  }
80 }
81 
82 #endif /* TIME_BACKTRACK_PROTECTION */
83 
84 /*
85  * Return a numerical string describing a struct timeval.
86  */
87 const char *
88 tv_string(const struct timeval *tv, struct gc_arena *gc)
89 {
90  struct buffer out = alloc_buf_gc(64, gc);
91  buf_printf(&out, "[%" PRIi64 "/%ld]",
92  (int64_t)tv->tv_sec,
93  (long)tv->tv_usec);
94  return BSTR(&out);
95 }
96 
97 /*
98  * Return an ascii string describing an absolute
99  * date/time in a struct timeval.
100  *
101  */
102 const char *
103 tv_string_abs(const struct timeval *tv, struct gc_arena *gc)
104 {
105  return time_string((time_t) tv->tv_sec,
106  (long) tv->tv_usec,
107  true,
108  gc);
109 }
110 
111 /* format a time_t as ascii, or use current time if 0 */
112 
113 const char *
114 time_string(time_t t, int usec, bool show_usec, struct gc_arena *gc)
115 {
116  struct buffer out = alloc_buf_gc(64, gc);
117  struct timeval tv;
118 
119  if (t)
120  {
121  tv.tv_sec = t;
122  tv.tv_usec = usec;
123  }
124  else
125  {
126  gettimeofday(&tv, NULL);
127  }
128 
129  t = tv.tv_sec;
130  buf_printf(&out, "%s", ctime(&t));
131  buf_rmtail(&out, '\n');
132 
133  if (show_usec && tv.tv_usec)
134  {
135  buf_printf(&out, " us=%ld", (long)tv.tv_usec);
136  }
137 
138  return BSTR(&out);
139 }
140 
141 /*
142  * Limit the frequency of an event stream.
143  *
144  * Used to control maximum rate of new
145  * incoming connections.
146  */
147 
148 struct frequency_limit *
150 {
151  struct frequency_limit *f;
152 
153  ASSERT(max >= 0 && per >= 0);
154 
155  ALLOC_OBJ(f, struct frequency_limit);
156  f->max = max;
157  f->per = per;
158  f->n = 0;
159  f->reset = 0;
160  return f;
161 }
162 
163 void
165 {
166  free(f);
167 }
168 
169 bool
171 {
172  if (f->per)
173  {
174  bool ret;
175  if (now >= f->reset + f->per)
176  {
177  f->reset = now;
178  f->n = 0;
179  }
180  ret = (++f->n <= f->max);
181  return ret;
182  }
183  else
184  {
185  return true;
186  }
187 }
188 
189 #ifdef TIME_TEST
190 void
191 time_test(void)
192 {
193  struct timeval tv;
194  time_t t;
195  int i;
196  for (i = 0; i < 10000; ++i)
197  {
198  t = time(NULL);
199  gettimeofday(&tv, NULL);
200 #if 1
201  msg(M_INFO, "t=%" PRIi64 " s=%" PRIi64 " us=%ld",
202  (int64_t)t,
203  (int64_t)tv.tv_sec,
204  (long)tv.tv_usec);
205 #endif
206  }
207 }
208 #endif
#define ALLOC_OBJ(dptr, type)
Definition: buffer.h:1045
#define M_INFO
Definition: errlevel.h:55
bool frequency_limit_event_allowed(struct frequency_limit *f)
Definition: otime.c:170
#define ASSERT(x)
Definition: error.h:221
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:245
static time_t now_adj
Definition: otime.c:40
time_t reset
Definition: otime.h:36
const char * tv_string(const struct timeval *tv, struct gc_arena *gc)
Definition: otime.c:88
string f
Definition: http-client.py:6
time_t now
Definition: otime.c:36
time_t now_usec
Definition: otime.c:41
const char * time_string(time_t t, int usec, bool show_usec, struct gc_arena *gc)
Definition: otime.c:114
struct frequency_limit * frequency_limit_init(int max, int per)
Definition: otime.c:149
void update_now_usec(struct timeval *tv)
Definition: otime.c:72
const char * tv_string_abs(const struct timeval *tv, struct gc_arena *gc)
Definition: otime.c:103
void time_test(void)
__int64 int64_t
Definition: config-msvc.h:124
#define msg
Definition: error.h:173
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
void update_now(const time_t system_time)
Definition: otime.c:49
void buf_rmtail(struct buffer *buf, uint8_t remove)
Definition: buffer.c:557
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:90
#define free
Definition: cmocka.c:1850
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
#define BSTR(buf)
Definition: buffer.h:129
void frequency_limit_free(struct frequency_limit *f)
Definition: otime.c:164