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 |
*/
#ifndef OTIME_H
#define OTIME_H
#include "common.h"
#include "integer.h"
#include "buffer.h"
struct frequency_limit
{ |
81d882d5 |
int max;
int per;
int n;
time_t reset; |
6fbf66fa |
};
|
81d882d5 |
struct frequency_limit *frequency_limit_init(int max, int per);
void frequency_limit_free(struct frequency_limit *f);
bool frequency_limit_event_allowed(struct frequency_limit *f); |
6fbf66fa |
/* format a time_t as ascii, or use current time if 0 */ |
81d882d5 |
const char *time_string(time_t t, int usec, bool show_usec, struct gc_arena *gc); |
6fbf66fa |
/* struct timeval functions */
|
81d882d5 |
const char *tv_string(const struct timeval *tv, struct gc_arena *gc);
const char *tv_string_abs(const struct timeval *tv, struct gc_arena *gc); |
6fbf66fa |
|
0475d17e |
extern time_t now; /* updated frequently to time(NULL) */
|
81d882d5 |
void time_test(void); |
0475d17e |
|
3d163bc5 |
#if TIME_BACKTRACK_PROTECTION |
e5239fc2 |
|
81d882d5 |
void update_now(const time_t system_time); |
e5239fc2 |
extern time_t now_usec; |
81d882d5 |
void update_now_usec(struct timeval *tv); |
e5239fc2 |
static inline int |
81d882d5 |
openvpn_gettimeofday(struct timeval *tv, void *tz) |
e5239fc2 |
{ |
81d882d5 |
const int status = gettimeofday(tv, tz);
if (!status) |
e5239fc2 |
{ |
81d882d5 |
update_now_usec(tv);
tv->tv_sec = now;
tv->tv_usec = now_usec; |
e5239fc2 |
} |
81d882d5 |
return status; |
e5239fc2 |
}
static inline void |
81d882d5 |
update_time(void) |
e5239fc2 |
{ |
445b192a |
#ifdef _WIN32 |
81d882d5 |
/* on _WIN32, gettimeofday is faster than time(NULL) */
struct timeval tv;
openvpn_gettimeofday(&tv, NULL); |
e5239fc2 |
#else |
81d882d5 |
update_now(time(NULL)); |
e5239fc2 |
#endif
}
|
3d163bc5 |
#else /* !TIME_BACKTRACK_PROTECTION */ |
e5239fc2 |
|
0475d17e |
static inline void |
81d882d5 |
update_time(void) |
0475d17e |
{ |
445b192a |
#if defined(_WIN32) |
81d882d5 |
/* on _WIN32, gettimeofday is faster than time(NULL) */
struct timeval tv;
if (!gettimeofday(&tv, NULL)) |
0475d17e |
{ |
81d882d5 |
if (tv.tv_sec != now)
{
now = tv.tv_sec;
}
}
#else /* if defined(_WIN32) */
const time_t real_time = time(NULL);
if (real_time != now)
{
now = real_time; |
0475d17e |
} |
428b8279 |
#endif |
6fbf66fa |
}
|
0475d17e |
static inline int |
81d882d5 |
openvpn_gettimeofday(struct timeval *tv, void *tz) |
0475d17e |
{ |
81d882d5 |
return gettimeofday(tv, tz); |
0475d17e |
}
|
3d163bc5 |
#endif /* TIME_BACKTRACK_PROTECTION */ |
e5239fc2 |
|
0475d17e |
static inline time_t |
81d882d5 |
openvpn_time(time_t *t) |
0475d17e |
{ |
81d882d5 |
update_time();
if (t)
{
*t = now;
}
return now; |
0475d17e |
}
|
6fbf66fa |
static inline void |
81d882d5 |
tv_clear(struct timeval *tv) |
6fbf66fa |
{ |
81d882d5 |
tv->tv_sec = 0;
tv->tv_usec = 0; |
6fbf66fa |
}
static inline bool |
81d882d5 |
tv_defined(const struct timeval *tv) |
6fbf66fa |
{ |
81d882d5 |
return tv->tv_sec > 0 && tv->tv_usec > 0; |
6fbf66fa |
}
/* return tv1 - tv2 in usec, constrained by max_seconds */
static inline int |
81d882d5 |
tv_subtract(const struct timeval *tv1, const struct timeval *tv2, const unsigned int max_seconds) |
6fbf66fa |
{ |
81d882d5 |
const int max_usec = max_seconds * 1000000;
const int sec_diff = tv1->tv_sec - tv2->tv_sec;
if (sec_diff > ((int)max_seconds + 10))
{
return max_usec;
}
else if (sec_diff < -((int)max_seconds + 10))
{
return -max_usec;
}
return constrain_int(sec_diff * 1000000 + (tv1->tv_usec - tv2->tv_usec), -max_usec, max_usec); |
6fbf66fa |
}
static inline void |
81d882d5 |
tv_add(struct timeval *dest, const struct timeval *src) |
6fbf66fa |
{ |
81d882d5 |
dest->tv_sec += src->tv_sec;
dest->tv_usec += src->tv_usec;
dest->tv_sec += (dest->tv_usec >> 20);
dest->tv_usec &= 0x000FFFFF;
if (dest->tv_usec >= 1000000) |
6fbf66fa |
{ |
81d882d5 |
dest->tv_usec -= 1000000;
dest->tv_sec += 1;
} |
6fbf66fa |
}
static inline bool |
81d882d5 |
tv_lt(const struct timeval *t1, const struct timeval *t2) |
6fbf66fa |
{ |
81d882d5 |
if (t1->tv_sec < t2->tv_sec)
{
return true;
}
else if (t1->tv_sec > t2->tv_sec)
{
return false;
}
else
{
return t1->tv_usec < t2->tv_usec;
} |
6fbf66fa |
}
static inline bool |
81d882d5 |
tv_le(const struct timeval *t1, const struct timeval *t2) |
6fbf66fa |
{ |
81d882d5 |
if (t1->tv_sec < t2->tv_sec)
{
return true;
}
else if (t1->tv_sec > t2->tv_sec)
{
return false;
}
else
{
return t1->tv_usec <= t2->tv_usec;
} |
6fbf66fa |
}
static inline bool |
81d882d5 |
tv_ge(const struct timeval *t1, const struct timeval *t2) |
6fbf66fa |
{ |
81d882d5 |
if (t1->tv_sec > t2->tv_sec)
{
return true;
}
else if (t1->tv_sec < t2->tv_sec)
{
return false;
}
else
{
return t1->tv_usec >= t2->tv_usec;
} |
6fbf66fa |
}
static inline bool |
81d882d5 |
tv_gt(const struct timeval *t1, const struct timeval *t2) |
6fbf66fa |
{ |
81d882d5 |
if (t1->tv_sec > t2->tv_sec)
{
return true;
}
else if (t1->tv_sec < t2->tv_sec)
{
return false;
}
else
{
return t1->tv_usec > t2->tv_usec;
} |
6fbf66fa |
}
static inline bool |
81d882d5 |
tv_eq(const struct timeval *t1, const struct timeval *t2) |
6fbf66fa |
{ |
81d882d5 |
return t1->tv_sec == t2->tv_sec && t1->tv_usec == t2->tv_usec; |
6fbf66fa |
}
static inline void |
81d882d5 |
tv_delta(struct timeval *dest, const struct timeval *t1, const struct timeval *t2) |
6fbf66fa |
{ |
81d882d5 |
int sec = t2->tv_sec - t1->tv_sec;
int usec = t2->tv_usec - t1->tv_usec; |
6fbf66fa |
|
81d882d5 |
while (usec < 0) |
6fbf66fa |
{ |
81d882d5 |
usec += 1000000;
sec -= 1; |
6fbf66fa |
}
|
81d882d5 |
if (sec < 0)
{
usec = sec = 0;
} |
6fbf66fa |
|
81d882d5 |
dest->tv_sec = sec;
dest->tv_usec = usec; |
6fbf66fa |
}
#define TV_WITHIN_SIGMA_MAX_SEC 600
#define TV_WITHIN_SIGMA_MAX_USEC (TV_WITHIN_SIGMA_MAX_SEC * 1000000)
/*
* Is t1 and t2 within sigma microseconds of each other?
*/
static inline bool |
81d882d5 |
tv_within_sigma(const struct timeval *t1, const struct timeval *t2, unsigned int sigma) |
6fbf66fa |
{ |
81d882d5 |
const int delta = tv_subtract(t1, t2, TV_WITHIN_SIGMA_MAX_SEC); /* sigma should be less than 10 minutes */
return -(int)sigma <= delta && delta <= (int)sigma; |
6fbf66fa |
}
/*
* Used to determine in how many seconds we should be
* called again.
*/
static inline void |
4cd4899e |
interval_earliest_wakeup(interval_t *wakeup, time_t at, time_t current)
{ |
81d882d5 |
if (at > current) |
6fbf66fa |
{ |
81d882d5 |
const interval_t delta = (interval_t) (at - current);
if (delta < *wakeup)
{
*wakeup = delta;
}
if (*wakeup < 0)
{
*wakeup = 0;
} |
6fbf66fa |
}
}
|
81d882d5 |
#endif /* ifndef OTIME_H */ |