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  struct tm *tm = localtime(&t);
131 
132  buf_printf(&out, "%04d-%02d-%02d %02d:%02d:%02d",
133  tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
134  tm->tm_hour, tm->tm_min, tm->tm_sec);
135 
136  if (show_usec && tv.tv_usec)
137  {
138  buf_printf(&out, " us=%ld", (long)tv.tv_usec);
139  }
140 
141  return BSTR(&out);
142 }
143 
144 /*
145  * Limit the frequency of an event stream.
146  *
147  * Used to control maximum rate of new
148  * incoming connections.
149  */
150 
151 struct frequency_limit *
153 {
154  struct frequency_limit *f;
155 
156  ASSERT(max >= 0 && per >= 0);
157 
158  ALLOC_OBJ(f, struct frequency_limit);
159  f->max = max;
160  f->per = per;
161  f->n = 0;
162  f->reset = 0;
163  return f;
164 }
165 
166 void
168 {
169  free(f);
170 }
171 
172 bool
174 {
175  if (f->per)
176  {
177  bool ret;
178  if (now >= f->reset + f->per)
179  {
180  f->reset = now;
181  f->n = 0;
182  }
183  ret = (++f->n <= f->max);
184  return ret;
185  }
186  else
187  {
188  return true;
189  }
190 }
191 
192 #ifdef TIME_TEST
193 void
194 time_test(void)
195 {
196  struct timeval tv;
197  time_t t;
198  int i;
199  for (i = 0; i < 10000; ++i)
200  {
201  t = time(NULL);
202  gettimeofday(&tv, NULL);
203 #if 1
204  msg(M_INFO, "t=%" PRIi64 " s=%" PRIi64 " us=%ld",
205  (int64_t)t,
206  (int64_t)tv.tv_sec,
207  (long)tv.tv_usec);
208 #endif
209  }
210 }
211 #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:173
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:242
#define ASSERT(x)
Definition: error.h:221
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:152
void update_now_usec(struct timeval *tv)
Definition: otime.c:72
#define msg
Definition: error.h:173
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:160
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
void update_now(const time_t system_time)
Definition: otime.c:49
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:167