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