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