| /* |
| * 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. |
| * |
| * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> |
| * |
| * 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. |
| * |
| * 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. |
| */ |
| |
| #ifndef OTIME_H |
| #define OTIME_H |
| |
| #include "common.h" |
| #include "integer.h" |
| #include "buffer.h" |
| |
| struct frequency_limit |
| { |
| int max; |
| int per; |
| int n; |
| time_t reset; |
| }; |
| |
| 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); |
| |
| /* format a time_t as ascii, or use current time if 0 */ |
| const char *time_string(time_t t, int usec, bool show_usec, struct gc_arena *gc); |
| |
| /* struct timeval functions */ |
| |
| 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); |
| |
| extern time_t now; /* updated frequently to time(NULL) */ |
| |
| void time_test(void); |
| |
| #if TIME_BACKTRACK_PROTECTION |
| |
| void update_now(const time_t system_time); |
| |
| extern time_t now_usec; |
| void update_now_usec(struct timeval *tv); |
| |
| static inline int |
| openvpn_gettimeofday(struct timeval *tv, void *tz) |
| { |
| const int status = gettimeofday(tv, tz); |
| if (!status) |
| { |
| update_now_usec(tv); |
| tv->tv_sec = now; |
| tv->tv_usec = now_usec; |
| } |
| return status; |
| } |
| |
| static inline void |
| update_time(void) |
| { |
| #ifdef _WIN32 |
| /* on _WIN32, gettimeofday is faster than time(NULL) */ |
| struct timeval tv; |
| openvpn_gettimeofday(&tv, NULL); |
| #else |
| update_now(time(NULL)); |
| #endif |
| } |
| |
| #else /* !TIME_BACKTRACK_PROTECTION */ |
| |
| static inline void |
| update_time(void) |
| { |
| #if defined(_WIN32) |
| /* on _WIN32, gettimeofday is faster than time(NULL) */ |
| struct timeval tv; |
| if (!gettimeofday(&tv, NULL)) |
| { |
| 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; |
| } |
| #endif |
| } |
| |
| static inline int |
| openvpn_gettimeofday(struct timeval *tv, void *tz) |
| { |
| return gettimeofday(tv, tz); |
| } |
| |
| #endif /* TIME_BACKTRACK_PROTECTION */ |
| |
| static inline time_t |
| openvpn_time(time_t *t) |
| { |
| update_time(); |
| if (t) |
| { |
| *t = now; |
| } |
| return now; |
| } |
| |
| static inline void |
| tv_clear(struct timeval *tv) |
| { |
| tv->tv_sec = 0; |
| tv->tv_usec = 0; |
| } |
| |
| static inline bool |
| tv_defined(const struct timeval *tv) |
| { |
| return tv->tv_sec > 0 && tv->tv_usec > 0; |
| } |
| |
| /* return tv1 - tv2 in usec, constrained by max_seconds */ |
| static inline int |
| tv_subtract(const struct timeval *tv1, const struct timeval *tv2, const unsigned int max_seconds) |
| { |
| 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); |
| } |
| |
| static inline void |
| tv_add(struct timeval *dest, const struct timeval *src) |
| { |
| 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) |
| { |
| dest->tv_usec -= 1000000; |
| dest->tv_sec += 1; |
| } |
| } |
| |
| static inline bool |
| tv_lt(const struct timeval *t1, const struct timeval *t2) |
| { |
| 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; |
| } |
| } |
| |
| static inline bool |
| tv_le(const struct timeval *t1, const struct timeval *t2) |
| { |
| 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; |
| } |
| } |
| |
| static inline bool |
| tv_ge(const struct timeval *t1, const struct timeval *t2) |
| { |
| 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; |
| } |
| } |
| |
| static inline bool |
| tv_gt(const struct timeval *t1, const struct timeval *t2) |
| { |
| 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; |
| } |
| } |
| |
| static inline bool |
| tv_eq(const struct timeval *t1, const struct timeval *t2) |
| { |
| return t1->tv_sec == t2->tv_sec && t1->tv_usec == t2->tv_usec; |
| } |
| |
| static inline void |
| tv_delta(struct timeval *dest, const struct timeval *t1, const struct timeval *t2) |
| { |
| int sec = t2->tv_sec - t1->tv_sec; |
| int usec = t2->tv_usec - t1->tv_usec; |
| |
| while (usec < 0) |
| { |
| usec += 1000000; |
| sec -= 1; |
| } |
| |
| if (sec < 0) |
| { |
| usec = sec = 0; |
| } |
| |
| dest->tv_sec = sec; |
| dest->tv_usec = usec; |
| } |
| |
| #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 |
| tv_within_sigma(const struct timeval *t1, const struct timeval *t2, unsigned int sigma) |
| { |
| 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; |
| } |
| |
| /* |
| * Used to determine in how many seconds we should be |
| * called again. |
| */ |
| static inline void |
| interval_earliest_wakeup(interval_t *wakeup, time_t at, time_t current) |
| { |
| if (at > current) |
| { |
| const interval_t delta = (interval_t) (at - current); |
| if (delta < *wakeup) |
| { |
| *wakeup = delta; |
| } |
| if (*wakeup < 0) |
| { |
| *wakeup = 0; |
| } |
| } |
| } |
| |
| #endif /* ifndef OTIME_H */ |