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.
  *
564a2109
  *  Copyright (C) 2002-2010 OpenVPN Technologies, 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.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program (see the file COPYING included with this
  *  distribution); if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #ifndef OTIME_H
 #define OTIME_H
 
 #include "common.h"
 #include "integer.h"
 #include "buffer.h"
 #include "thread.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);
 
 #ifdef WIN32
 int gettimeofday(struct timeval *tv, void *tz);
 #endif
 
 /* 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);
 
0475d17e
 extern time_t now; /* updated frequently to time(NULL) */
 
428b8279
 void time_test (void);
0475d17e
 
e5239fc2
 #if TIME_BACKTRACK_PROTECTION && defined(HAVE_GETTIMEOFDAY)
 
 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 && defined(HAVE_GETTIMEOFDAY)) */
 
0475d17e
 static inline void
 update_time (void)
 {
428b8279
 #if defined(WIN32) && defined(HAVE_GETTIMEOFDAY)
   struct timeval tv;
   if (!gettimeofday (&tv, NULL))
0475d17e
     {
428b8279
       if (tv.tv_sec != now)
 	now = tv.tv_sec;
0475d17e
     }
 #else
9423103d
   const time_t real_time = time (NULL);
   if (real_time != now)
6fbf66fa
     now = real_time;
428b8279
 #endif
6fbf66fa
 }
 
0475d17e
 #ifdef HAVE_GETTIMEOFDAY
 
 static inline int
 openvpn_gettimeofday (struct timeval *tv, void *tz)
 {
   return gettimeofday (tv, tz);
 }
 
 #endif
 
e5239fc2
 #endif /* TIME_BACKTRACK_PROTECTION && defined(HAVE_GETTIMEOFDAY) */
 
0475d17e
 static inline time_t
 openvpn_time (time_t *t)
 {
   update_time ();
   if (t)
     *t = now;
   return now;
 }
 
6fbf66fa
 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