src/openvpn/otime.h
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 */