6fbf66fa |
/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single TCP/UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
* |
49979459 |
* Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> |
6fbf66fa |
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* |
caa54ac3 |
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
6fbf66fa |
*/
|
c110b289 |
#ifdef HAVE_CONFIG_H
#include "config.h"
#elif defined(_MSC_VER)
#include "config-msvc.h"
#endif
|
6fbf66fa |
#include "syshead.h"
#include "otime.h"
#include "memdbg.h"
|
0475d17e |
time_t now = 0; /* GLOBAL */
|
3d163bc5 |
#if TIME_BACKTRACK_PROTECTION |
0475d17e |
|
e5239fc2 |
static time_t now_adj = 0; /* GLOBAL */ |
0475d17e |
time_t now_usec = 0; /* GLOBAL */
|
e5239fc2 |
/*
* Try to filter out time instability caused by the system
* clock backtracking or jumping forward.
*/
void |
81d882d5 |
update_now(const time_t system_time) |
e5239fc2 |
{ |
81d882d5 |
const int forward_threshold = 86400; /* threshold at which to dampen forward jumps */
const int backward_trigger = 10; /* backward jump must be >= this many seconds before we adjust */
time_t real_time = system_time + now_adj; |
e5239fc2 |
|
81d882d5 |
if (real_time > now) |
e5239fc2 |
{ |
81d882d5 |
const time_t overshoot = real_time - now - 1;
if (overshoot > forward_threshold && now_adj >= overshoot) |
e5239fc2 |
{ |
81d882d5 |
now_adj -= overshoot;
real_time -= overshoot; |
e5239fc2 |
} |
81d882d5 |
now = real_time;
}
else if (real_time < now - backward_trigger)
{
now_adj += (now - real_time); |
e5239fc2 |
}
}
void |
81d882d5 |
update_now_usec(struct timeval *tv) |
e5239fc2 |
{ |
81d882d5 |
const time_t last = now;
update_now(tv->tv_sec);
if (now > last || (now == last && tv->tv_usec > now_usec))
{
now_usec = tv->tv_usec;
} |
e5239fc2 |
}
|
3d163bc5 |
#endif /* TIME_BACKTRACK_PROTECTION */ |
6fbf66fa |
|
81d882d5 |
/* |
6fbf66fa |
* Return a numerical string describing a struct timeval.
*/
const char * |
81d882d5 |
tv_string(const struct timeval *tv, struct gc_arena *gc) |
6fbf66fa |
{ |
81d882d5 |
struct buffer out = alloc_buf_gc(64, gc); |
06ad53e0 |
buf_printf(&out, "[%"PRIi64"/%ld]",
(int64_t)tv->tv_sec, |
31b5c0e9 |
(long)tv->tv_usec); |
81d882d5 |
return BSTR(&out); |
6fbf66fa |
}
|
81d882d5 |
/* |
6fbf66fa |
* Return an ascii string describing an absolute
* date/time in a struct timeval. |
81d882d5 |
* |
6fbf66fa |
*/
const char * |
81d882d5 |
tv_string_abs(const struct timeval *tv, struct gc_arena *gc) |
6fbf66fa |
{ |
81d882d5 |
return time_string((time_t) tv->tv_sec, |
31b5c0e9 |
(long) tv->tv_usec, |
81d882d5 |
true,
gc); |
6fbf66fa |
}
/* format a time_t as ascii, or use current time if 0 */
const char * |
81d882d5 |
time_string(time_t t, int usec, bool show_usec, struct gc_arena *gc) |
6fbf66fa |
{ |
81d882d5 |
struct buffer out = alloc_buf_gc(64, gc);
struct timeval tv; |
6fbf66fa |
|
81d882d5 |
if (t) |
6fbf66fa |
{ |
81d882d5 |
tv.tv_sec = t;
tv.tv_usec = usec; |
6fbf66fa |
} |
81d882d5 |
else |
6fbf66fa |
{ |
81d882d5 |
gettimeofday(&tv, NULL); |
6fbf66fa |
}
|
81d882d5 |
t = tv.tv_sec;
buf_printf(&out, "%s", ctime(&t));
buf_rmtail(&out, '\n'); |
6fbf66fa |
|
81d882d5 |
if (show_usec && tv.tv_usec)
{ |
31b5c0e9 |
buf_printf(&out, " us=%ld", (long)tv.tv_usec); |
81d882d5 |
} |
6fbf66fa |
|
81d882d5 |
return BSTR(&out); |
6fbf66fa |
}
/*
* Limit the frequency of an event stream.
*
* Used to control maximum rate of new
* incoming connections.
*/
struct frequency_limit * |
81d882d5 |
frequency_limit_init(int max, int per) |
6fbf66fa |
{ |
81d882d5 |
struct frequency_limit *f; |
6fbf66fa |
|
81d882d5 |
ASSERT(max >= 0 && per >= 0); |
6fbf66fa |
|
81d882d5 |
ALLOC_OBJ(f, struct frequency_limit);
f->max = max;
f->per = per;
f->n = 0;
f->reset = 0;
return f; |
6fbf66fa |
}
void |
81d882d5 |
frequency_limit_free(struct frequency_limit *f) |
6fbf66fa |
{ |
81d882d5 |
free(f); |
6fbf66fa |
}
bool |
81d882d5 |
frequency_limit_event_allowed(struct frequency_limit *f) |
6fbf66fa |
{ |
81d882d5 |
if (f->per)
{
bool ret;
if (now >= f->reset + f->per)
{
f->reset = now;
f->n = 0;
}
ret = (++f->n <= f->max);
return ret;
}
else |
6fbf66fa |
{ |
81d882d5 |
return true; |
6fbf66fa |
}
}
|
428b8279 |
#ifdef TIME_TEST
void |
81d882d5 |
time_test(void) |
428b8279 |
{ |
81d882d5 |
struct timeval tv;
time_t t;
int i;
for (i = 0; i < 10000; ++i) |
428b8279 |
{ |
81d882d5 |
t = time(NULL);
gettimeofday(&tv, NULL); |
428b8279 |
#if 1 |
06ad53e0 |
msg(M_INFO, "t=%"PRIi64" s=%"PRIi64" us=%ld",
(int64_t)t,
(int64_t)tv.tv_sec, |
31b5c0e9 |
(long)tv.tv_usec); |
428b8279 |
#endif
}
}
#endif |