diff options
Diffstat (limited to 'openvpn')
-rw-r--r-- | openvpn/basic.h | 41 | ||||
-rw-r--r-- | openvpn/buffer.h | 712 | ||||
-rw-r--r-- | openvpn/common.h | 76 | ||||
-rw-r--r-- | openvpn/event.h | 157 | ||||
-rw-r--r-- | openvpn/integer.h | 114 | ||||
-rw-r--r-- | openvpn/interval.h | 239 | ||||
-rw-r--r-- | openvpn/misc.h | 257 | ||||
-rw-r--r-- | openvpn/mtu.h | 304 | ||||
-rw-r--r-- | openvpn/otime.h | 206 | ||||
-rw-r--r-- | openvpn/perf.h | 82 | ||||
-rw-r--r-- | openvpn/proto.h | 163 | ||||
-rw-r--r-- | openvpn/sig.h | 100 | ||||
-rw-r--r-- | openvpn/status.h | 95 | ||||
-rw-r--r-- | openvpn/thread.h | 235 | ||||
-rwxr-xr-x | openvpn/win32.h | 251 |
15 files changed, 3032 insertions, 0 deletions
diff --git a/openvpn/basic.h b/openvpn/basic.h new file mode 100644 index 0000000..cde638e --- /dev/null +++ b/openvpn/basic.h @@ -0,0 +1,41 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@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 (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 BASIC_H +#define BASIC_H + +/* bool definitions */ +#define bool int +#define true 1 +#define false 0 + +#define BOOL_CAST(x) ((x) ? (true) : (false)) + +/* size of an array */ +#define SIZE(x) (sizeof(x)/sizeof(x[0])) + +/* clear an object */ +#define CLEAR(x) memset(&(x), 0, sizeof(x)) + +#endif diff --git a/openvpn/buffer.h b/openvpn/buffer.h new file mode 100644 index 0000000..1e5266b --- /dev/null +++ b/openvpn/buffer.h @@ -0,0 +1,712 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@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 (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 BUFFER_H +#define BUFFER_H + +#include "basic.h" +#include "thread.h" + +/* + * Define verify_align function, otherwise + * it will be a noop. + */ +/* #define VERIFY_ALIGNMENT */ + +/* + * Keep track of source file/line of buf_init calls + */ +#ifdef VERIFY_ALIGNMENT +#define BUF_INIT_TRACKING +#endif + +/* basic buffer class for OpenVPN */ + +struct buffer +{ + int capacity; /* size of buffer allocated by malloc */ + int offset; /* data starts at data + offset, offset > 0 to allow for efficient prepending */ + int len; /* length of data that starts at data + offset */ + uint8_t *data; + +#ifdef BUF_INIT_TRACKING + const char *debug_file; + int debug_line; +#endif +}; + +/* for garbage collection */ + +struct gc_entry +{ + struct gc_entry *next; +}; + +struct gc_arena +{ + struct gc_entry *list; +}; + +#define BPTR(buf) ((buf)->data + (buf)->offset) +#define BEND(buf) (BPTR(buf) + (buf)->len) +#define BLAST(buf) (((buf)->data && (buf)->len) ? (BPTR(buf) + (buf)->len - 1) : NULL) +#define BLEN(buf) ((buf)->len) +#define BDEF(buf) ((buf)->data != NULL) +#define BSTR(buf) ((char *)BPTR(buf)) +#define BCAP(buf) (buf_forward_capacity (buf)) + +void buf_clear (struct buffer *buf); + +struct buffer clear_buf (void); +void free_buf (struct buffer *buf); + +bool buf_assign (struct buffer *dest, const struct buffer *src); + + + +/* for dmalloc debugging */ + +#ifdef DMALLOC + +#define alloc_buf(size) alloc_buf_debug (size, __FILE__, __LINE__) +#define alloc_buf_gc(size, gc) alloc_buf_gc_debug (size, gc, __FILE__, __LINE__); +#define clone_buf(buf) clone_buf_debug (buf, __FILE__, __LINE__); +#define gc_malloc(size, clear, arena) gc_malloc_debug (size, clear, arena, __FILE__, __LINE__) +#define string_alloc(str, gc) string_alloc_debug (str, gc, __FILE__, __LINE__) +#define string_alloc_buf(str, gc) string_alloc_buf_debug (str, gc, __FILE__, __LINE__) + +struct buffer alloc_buf_debug (size_t size, const char *file, int line); +struct buffer alloc_buf_gc_debug (size_t size, struct gc_arena *gc, const char *file, int line); +struct buffer clone_buf_debug (const struct buffer* buf, const char *file, int line); +void *gc_malloc_debug (size_t size, bool clear, struct gc_arena *a, const char *file, int line); +char *string_alloc_debug (const char *str, struct gc_arena *gc, const char *file, int line); +struct buffer string_alloc_buf_debug (const char *str, struct gc_arena *gc, const char *file, int line); + +#else + +struct buffer alloc_buf (size_t size); +struct buffer alloc_buf_gc (size_t size, struct gc_arena *gc); /* allocate buffer with garbage collection */ +struct buffer clone_buf (const struct buffer* buf); +void *gc_malloc (size_t size, bool clear, struct gc_arena *a); +char *string_alloc (const char *str, struct gc_arena *gc); +struct buffer string_alloc_buf (const char *str, struct gc_arena *gc); + +#endif + +#ifdef BUF_INIT_TRACKING +#define buf_init(buf, offset) buf_init_debug (buf, offset, __FILE__, __LINE__) +bool buf_init_debug (struct buffer *buf, int offset, const char *file, int line); +#else +#define buf_init(buf, offset) buf_init_dowork (buf, offset) +#endif + + +/* inline functions */ + +static inline void +buf_reset (struct buffer *buf) +{ + buf->capacity = 0; + buf->offset = 0; + buf->len = 0; + buf->data = NULL; +} + +static inline bool +buf_init_dowork (struct buffer *buf, int offset) +{ + if (offset < 0 || offset > buf->capacity || buf->data == NULL) + return false; + buf->len = 0; + buf->offset = offset; + return true; +} + +static inline bool +buf_defined (struct buffer *buf) +{ + return buf->data != NULL; +} + +static inline void +buf_set_write (struct buffer *buf, uint8_t *data, int size) +{ + buf->len = 0; + buf->offset = 0; + buf->capacity = size; + buf->data = data; + if (size > 0 && data) + *data = 0; +} + +static inline void +buf_set_read (struct buffer *buf, const uint8_t *data, int size) +{ + buf->len = buf->capacity = size; + buf->offset = 0; + buf->data = (uint8_t *)data; +} + +/* Like strncpy but makes sure dest is always null terminated */ +static inline void +strncpynt (char *dest, const char *src, size_t maxlen) +{ + strncpy (dest, src, maxlen); + if (maxlen > 0) + dest[maxlen - 1] = 0; +} + +/* return true if string contains at least one numerical digit */ +static inline bool +has_digit (const char* src) +{ + char c; + while ((c = *src++)) + { + if (isdigit(c)) + return true; + } + return false; +} + +/* + * printf append to a buffer with overflow check + */ +void buf_printf (struct buffer *buf, const char *format, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 2, 3))) +#endif + ; + +/* + * Like snprintf but guarantees null termination for size > 0 + */ +int openvpn_snprintf(char *str, size_t size, const char *format, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 3, 4))) +#endif + ; + +/* + * remove/add trailing characters + */ + +void buf_null_terminate (struct buffer *buf); +void buf_chomp (struct buffer *buf); +void buf_rmtail (struct buffer *buf, uint8_t remove); + +/* + * non-buffer string functions + */ +void chomp (char *str); +void string_null_terminate (char *str, int len, int capacity); + +/* + * Write string in buf to file descriptor fd. + * NOTE: requires that string be null terminated. + */ +void buf_write_string_file (const struct buffer *buf, const char *filename, int fd); + +/* + * write a string to the end of a buffer that was + * truncated by buf_printf + */ +void buf_catrunc (struct buffer *buf, const char *str); + +/* + * convert a multi-line output to one line + */ +void convert_to_one_line (struct buffer *buf); + +/* + * Parse a string based on a given delimiter char + */ +bool buf_parse (struct buffer *buf, const int delim, char *line, const int size); + +/* + * Hex dump -- Output a binary buffer to a hex string and return it. + */ +char * +format_hex_ex (const uint8_t *data, int size, int maxoutput, + int space_break, const char* separator, + struct gc_arena *gc); + +static inline char * +format_hex (const uint8_t *data, int size, int maxoutput, struct gc_arena *gc) +{ + return format_hex_ex (data, size, maxoutput, 4, " ", gc); +} + +/* + * Return a buffer that is a subset of another buffer. + */ +struct buffer buf_sub (struct buffer *buf, int size, bool prepend); + +/* + * Check if sufficient space to append to buffer. + */ + +static inline bool +buf_safe (const struct buffer *buf, int len) +{ + return len >= 0 && buf->offset + buf->len + len <= buf->capacity; +} + +static inline bool +buf_safe_bidir (const struct buffer *buf, int len) +{ + const int newlen = buf->len + len; + return newlen >= 0 && buf->offset + newlen <= buf->capacity; +} + +static inline int +buf_forward_capacity (const struct buffer *buf) +{ + int ret = buf->capacity - (buf->offset + buf->len); + if (ret < 0) + ret = 0; + return ret; +} + +static inline int +buf_forward_capacity_total (const struct buffer *buf) +{ + int ret = buf->capacity - buf->offset; + if (ret < 0) + ret = 0; + return ret; +} + +static inline int +buf_reverse_capacity (const struct buffer *buf) +{ + return buf->offset; +} + +static inline bool +buf_inc_len (struct buffer *buf, int inc) +{ + if (!buf_safe_bidir (buf, inc)) + return false; + buf->len += inc; + return true; +} + +/* + * Make space to prepend to a buffer. + * Return NULL if no space. + */ + +static inline uint8_t * +buf_prepend (struct buffer *buf, int size) +{ + if (size < 0 || size > buf->offset) + return NULL; + buf->offset -= size; + buf->len += size; + return BPTR (buf); +} + +static inline bool +buf_advance (struct buffer *buf, int size) +{ + if (size < 0 || buf->len < size) + return false; + buf->offset += size; + buf->len -= size; + return true; +} + +/* + * Return a pointer to allocated space inside a buffer. + * Return NULL if no space. + */ + +static inline uint8_t * +buf_write_alloc (struct buffer *buf, int size) +{ + uint8_t *ret; + if (!buf_safe (buf, size)) + return NULL; + ret = BPTR (buf) + buf->len; + buf->len += size; + return ret; +} + +static inline uint8_t * +buf_write_alloc_prepend (struct buffer *buf, int size, bool prepend) +{ + return prepend ? buf_prepend (buf, size) : buf_write_alloc (buf, size); +} + +static inline uint8_t * +buf_read_alloc (struct buffer *buf, int size) +{ + uint8_t *ret; + if (size < 0 || buf->len < size) + return NULL; + ret = BPTR (buf); + buf->offset += size; + buf->len -= size; + return ret; +} + +static inline bool +buf_write (struct buffer *dest, const void *src, int size) +{ + uint8_t *cp = buf_write_alloc (dest, size); + if (!cp) + return false; + memcpy (cp, src, size); + return true; +} + +static inline bool +buf_write_prepend (struct buffer *dest, const void *src, int size) +{ + uint8_t *cp = buf_prepend (dest, size); + if (!cp) + return false; + memcpy (cp, src, size); + return true; +} + +static inline bool +buf_write_u8 (struct buffer *dest, int data) +{ + uint8_t u8 = (uint8_t) data; + return buf_write (dest, &u8, sizeof (uint8_t)); +} + +static inline bool +buf_write_u16 (struct buffer *dest, int data) +{ + uint16_t u16 = htons ((uint16_t) data); + return buf_write (dest, &u16, sizeof (uint16_t)); +} + +static inline bool +buf_write_u32 (struct buffer *dest, int data) +{ + uint32_t u32 = htonl ((uint32_t) data); + return buf_write (dest, &u32, sizeof (uint32_t)); +} + +static inline bool +buf_copy (struct buffer *dest, const struct buffer *src) +{ + return buf_write (dest, BPTR (src), BLEN (src)); +} + +static inline bool +buf_copy_n (struct buffer *dest, struct buffer *src, int n) +{ + uint8_t *cp = buf_read_alloc (src, n); + if (!cp) + return false; + return buf_write (dest, cp, n); +} + +static inline bool +buf_copy_range (struct buffer *dest, + int dest_index, + const struct buffer *src, + int src_index, + int src_len) +{ + if (src_index < 0 + || src_len < 0 + || src_index + src_len > src->len + || dest_index < 0 + || dest->offset + dest_index + src_len > dest->capacity) + return false; + memcpy (dest->data + dest->offset + dest_index, src->data + src->offset + src_index, src_len); + if (dest_index + src_len > dest->len) + dest->len = dest_index + src_len; + return true; +} + +/* truncate src to len, copy excess data beyond len to dest */ +static inline bool +buf_copy_excess (struct buffer *dest, + struct buffer *src, + int len) +{ + if (len < 0) + return false; + if (src->len > len) + { + struct buffer b = *src; + src->len = len; + if (!buf_advance (&b, len)) + return false; + return buf_copy (dest, &b); + } + else + { + return true; + } +} + +static inline bool +buf_read (struct buffer *src, void *dest, int size) +{ + uint8_t *cp = buf_read_alloc (src, size); + if (!cp) + return false; + memcpy (dest, cp, size); + return true; +} + +static inline int +buf_read_u8 (struct buffer *buf) +{ + int ret; + if (BLEN (buf) < 1) + return -1; + ret = *BPTR(buf); + buf_advance (buf, 1); + return ret; +} + +static inline int +buf_read_u16 (struct buffer *buf) +{ + uint16_t ret; + if (!buf_read (buf, &ret, sizeof (uint16_t))) + return -1; + return ntohs (ret); +} + +static inline uint32_t +buf_read_u32 (struct buffer *buf, bool *good) +{ + uint32_t ret; + if (!buf_read (buf, &ret, sizeof (uint32_t))) + { + if (good) + *good = false; + return 0; + } + else + { + if (good) + *good = true; + return ntohl (ret); + } +} + +static inline bool +buf_string_match (const struct buffer *src, const void *match, int size) +{ + if (size != src->len) + return false; + return memcmp (BPTR (src), match, size) == 0; +} + +static inline bool +buf_string_match_head (const struct buffer *src, const void *match, int size) +{ + if (size < 0 || size > src->len) + return false; + return memcmp (BPTR (src), match, size) == 0; +} + +bool buf_string_match_head_str (const struct buffer *src, const char *match); +bool buf_string_compare_advance (struct buffer *src, const char *match); +int buf_substring_len (const struct buffer *buf, int delim); + +/* + * Bitwise operations + */ +static inline void +xor (uint8_t *dest, const uint8_t *src, int len) +{ + while (len-- > 0) + *dest++ ^= *src++; +} + +/* + * Classify and mutate strings based on character types. + */ + +/*#define CHARACTER_CLASS_DEBUG*/ + +/* character classes */ + +#define CC_ANY (1<<0) +#define CC_NULL (1<<1) + +#define CC_ALNUM (1<<2) +#define CC_ALPHA (1<<3) +#define CC_ASCII (1<<4) +#define CC_CNTRL (1<<5) +#define CC_DIGIT (1<<6) +#define CC_PRINT (1<<7) +#define CC_PUNCT (1<<8) +#define CC_SPACE (1<<9) +#define CC_XDIGIT (1<<10) + +#define CC_BLANK (1<<11) +#define CC_NEWLINE (1<<12) +#define CC_CR (1<<13) + +#define CC_BACKSLASH (1<<14) +#define CC_UNDERBAR (1<<15) +#define CC_DASH (1<<16) +#define CC_DOT (1<<17) +#define CC_COMMA (1<<18) +#define CC_COLON (1<<19) +#define CC_SLASH (1<<20) +#define CC_SINGLE_QUOTE (1<<21) +#define CC_DOUBLE_QUOTE (1<<22) +#define CC_REVERSE_QUOTE (1<<23) +#define CC_AT (1<<24) +#define CC_EQUAL (1<<25) + +/* macro classes */ +#define CC_NAME (CC_ALNUM|CC_UNDERBAR) +#define CC_CRLF (CC_CR|CC_NEWLINE) + +bool char_class (const char c, const unsigned int flags); +bool string_class (const char *str, const unsigned int inclusive, const unsigned int exclusive); +bool string_mod (char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace); + +const char *string_mod_const (const char *str, + const unsigned int inclusive, + const unsigned int exclusive, + const char replace, + struct gc_arena *gc); + +#ifdef CHARACTER_CLASS_DEBUG +void character_class_debug (void); +#endif + +/* + * Verify that a pointer is correctly aligned + */ +#ifdef VERIFY_ALIGNMENT + void valign4 (const struct buffer *buf, const char *file, const int line); +# define verify_align_4(ptr) valign4(buf, __FILE__, __LINE__) +#else +# define verify_align_4(ptr) +#endif + +/* + * Very basic garbage collection, mostly for routines that return + * char ptrs to malloced strings. + */ + +void x_gc_free (struct gc_arena *a); + +static inline void +gc_init (struct gc_arena *a) +{ + a->list = NULL; +} + +static inline void +gc_detach (struct gc_arena *a) +{ + gc_init (a); +} + +static inline struct gc_arena +gc_new (void) +{ + struct gc_arena ret; + ret.list = NULL; + return ret; +} + +static inline void +gc_free (struct gc_arena *a) +{ + if (a->list) + x_gc_free (a); +} + +static inline void +gc_reset (struct gc_arena *a) +{ + gc_free (a); +} + +/* + * Allocate memory to hold a structure + */ + +void out_of_memory (void); + +#define ALLOC_OBJ(dptr, type) \ +{ \ + check_malloc_return ((dptr) = (type *) malloc (sizeof (type))); \ +} + +#define ALLOC_OBJ_CLEAR(dptr, type) \ +{ \ + ALLOC_OBJ (dptr, type); \ + memset ((dptr), 0, sizeof(type)); \ +} + +#define ALLOC_ARRAY(dptr, type, n) \ +{ \ + check_malloc_return ((dptr) = (type *) malloc (sizeof (type) * (n))); \ +} + +#define ALLOC_ARRAY_GC(dptr, type, n, gc) \ +{ \ + (dptr) = (type *) gc_malloc (sizeof (type) * (n), false, (gc)); \ +} + +#define ALLOC_ARRAY_CLEAR(dptr, type, n) \ +{ \ + ALLOC_ARRAY (dptr, type, n); \ + memset ((dptr), 0, (sizeof(type) * (n))); \ +} + +#define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc) \ +{ \ + (dptr) = (type *) gc_malloc (sizeof (type) * (n), true, (gc)); \ +} + +#define ALLOC_OBJ_GC(dptr, type, gc) \ +{ \ + (dptr) = (type *) gc_malloc (sizeof (type), false, (gc)); \ +} + +#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc) \ +{ \ + (dptr) = (type *) gc_malloc (sizeof (type), true, (gc)); \ +} + +static inline void +check_malloc_return (void *p) +{ + void out_of_memory (void); + if (!p) + out_of_memory (); +} + +#endif /* BUFFER_H */ diff --git a/openvpn/common.h b/openvpn/common.h new file mode 100644 index 0000000..70efdbf --- /dev/null +++ b/openvpn/common.h @@ -0,0 +1,76 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@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 (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 COMMON_H +#define COMMON_H + +/* + * Statistics counters and associated printf formats. + */ +#ifdef USE_64_BIT_COUNTERS + typedef unsigned long long int counter_type; +# ifdef WIN32 +# define counter_format "%I64u" +# else +# define counter_format "%llu" +# endif +#else + typedef unsigned int counter_type; +# define counter_format "%u" +#endif + +/* + * Time intervals + */ +typedef int interval_t; + +/* + * Used as an upper bound for timeouts. + */ +#define BIG_TIMEOUT (60*60*24*7) /* one week (in seconds) */ + +/* + * Printf formats for special types + */ +#define ptr_format "0x%08lx" +#define time_format "%lu" +#define fragment_header_format "0x%08x" + +/* these are used to cast the arguments + * and MUST match the formats above */ +typedef unsigned long time_type; +typedef unsigned long ptr_type; + +/* the --client-config-dir default file */ +#define CCD_DEFAULT "DEFAULT" + +/* + * This parameter controls the TLS channel buffer size. Among + * other things, this buffer must be large enough to contain + * the full --push/--pull list. If you increase it, do so + * on both server and client. + */ +#define TLS_CHANNEL_BUF_SIZE 1024 + +#endif diff --git a/openvpn/event.h b/openvpn/event.h new file mode 100644 index 0000000..314ef4c --- /dev/null +++ b/openvpn/event.h @@ -0,0 +1,157 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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 EVENT_H +#define EVENT_H + +#include "win32.h" +#include "sig.h" +#include "perf.h" + +/* + * rwflags passed to event_ctl and returned by + * struct event_set_return. + */ +#define EVENT_READ (1<<0) +#define EVENT_WRITE (1<<1) + +/* + * Initialization flags passed to event_set_init + */ +#define EVENT_METHOD_US_TIMEOUT (1<<0) +#define EVENT_METHOD_FAST (1<<1) + +#ifdef WIN32 + +typedef const struct rw_handle *event_t; + +#define UNDEFINED_EVENT (NULL) + +#else + +typedef int event_t; + +#define UNDEFINED_EVENT (-1) + +#endif + +struct event_set; +struct event_set_return; + +struct event_set_functions +{ + void (*free)(struct event_set *es); + void (*reset)(struct event_set *es); + void (*del)(struct event_set *es, event_t event); + void (*ctl)(struct event_set *es, event_t event, unsigned int rwflags, void *arg); + + /* + * Return status for wait: + * -1 on signal or error + * 0 on timeout + * length of event_set_return if at least 1 event is returned + */ + int (*wait)(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen); +}; + +struct event_set_return +{ + unsigned int rwflags; + void *arg; +}; + +struct event_set +{ + struct event_set_functions func; +}; + +/* + * maxevents on input: desired max number of event_t descriptors + * simultaneously set with event_ctl + * maxevents on output: may be modified down, depending on limitations + * of underlying API + * flags: EVENT_METHOD_x flags + */ +struct event_set *event_set_init (int *maxevents, unsigned int flags); + +static inline void +event_free (struct event_set *es) +{ + (*es->func.free)(es); +} + +static inline void +event_reset (struct event_set *es) +{ + (*es->func.reset)(es); +} + +static inline void +event_del (struct event_set *es, event_t event) +{ + (*es->func.del)(es, event); +} + +static inline void +event_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg) +{ + (*es->func.ctl)(es, event, rwflags, arg); +} + +static inline int +event_wait (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen) +{ + int ret; + perf_push (PERF_IO_WAIT); + ret = (*es->func.wait)(es, tv, out, outlen); + perf_pop (); + return ret; +} + +static inline void +event_set_return_init (struct event_set_return *esr) +{ + esr->rwflags = 0; + esr->arg = NULL; +} + +#ifdef WIN32 + +static inline void +wait_signal (struct event_set *es, void *arg) +{ + if (HANDLE_DEFINED (win32_signal.in.read)) + event_ctl (es, &win32_signal.in, EVENT_READ, arg); +} + +#else + +static inline void +wait_signal (struct event_set *es, void *arg) +{ +} + +#endif + +#endif diff --git a/openvpn/integer.h b/openvpn/integer.h new file mode 100644 index 0000000..68cf40f --- /dev/null +++ b/openvpn/integer.h @@ -0,0 +1,114 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@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 (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 INTEGER_H +#define INTEGER_H + +#include "error.h" + +/* + * min/max functions + */ + +static inline int +max_int (int x, int y) +{ + if (x > y) + return x; + else + return y; +} + +static inline int +min_int (int x, int y) +{ + if (x < y) + return x; + else + return y; +} + +static inline int +constrain_int (int x, int min, int max) +{ + if (min > max) + return min; + if (x < min) + return min; + else if (x > max) + return max; + else + return x; +} + +/* + * Functions used for circular buffer index arithmetic. + */ + +/* + * Return x - y on a circle of circumference mod by shortest path. + * + * 0 <= x < mod + * 0 <= y < mod + */ +static inline int +modulo_subtract(int x, int y, int mod) +{ + const int d1 = x - y; + const int d2 = (x > y ? -mod : mod) + d1; + ASSERT (0 <= x && x < mod && 0 <= y && y < mod); + return abs(d1) > abs(d2) ? d2 : d1; +} + +/* + * Return x + y on a circle of circumference mod. + * + * 0 <= x < mod + * -mod <= y <= mod + */ +static inline int +modulo_add(int x, int y, int mod) +{ + int sum = x + y; + ASSERT (0 <= x && x < mod && -mod <= y && y <= mod); + if (sum >= mod) + sum -= mod; + if (sum < 0) + sum += mod; + return sum; +} + +static inline int +index_verify (int index, int size, const char *file, int line) +{ + if (index < 0 || index >= size) + msg (M_FATAL, "Assertion Failed: Array index=%d out of bounds for array size=%d in %s:%d", + index, + size, + file, + line); + return index; +} + +#endif diff --git a/openvpn/interval.h b/openvpn/interval.h new file mode 100644 index 0000000..9845066 --- /dev/null +++ b/openvpn/interval.h @@ -0,0 +1,239 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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 + */ + +/* + * The interval_ routines are designed to optimize the calling of a routine + * (normally tls_multi_process()) which can be called less frequently + * between triggers. + */ + +#ifndef INTERVAL_H +#define INTERVAL_H + +#include "otime.h" + +#define INTERVAL_DEBUG 0 + +/* + * Designed to limit calls to expensive functions that need to be called + * regularly. + */ + +struct interval +{ + interval_t refresh; + interval_t horizon; + time_t future_trigger; + time_t last_action; + time_t last_test_true; +}; + +void interval_init (struct interval *top, int horizon, int refresh); + +/* + * IF + * last_action less than horizon seconds ago + * OR last_test_true more than refresh seconds ago + * OR hit future_trigger + * THEN + * return true + * ELSE + * set wakeup to the number of seconds until a true return + * return false + */ + +static inline bool +interval_test (struct interval* top) +{ + bool trigger = false; + const time_t local_now = now; + + if (top->future_trigger && local_now >= top->future_trigger) + { + trigger = true; + top->future_trigger = 0; + } + + if (top->last_action + top->horizon > local_now || + top->last_test_true + top->refresh <= local_now || + trigger) + { + top->last_test_true = local_now; +#if INTERVAL_DEBUG + dmsg (D_INTERVAL, "INTERVAL interval_test true"); +#endif + return true; + } + else + { + return false; + } +} + +static inline void +interval_schedule_wakeup (struct interval* top, interval_t *wakeup) +{ + const time_t local_now = now; + interval_earliest_wakeup (wakeup, top->last_test_true + top->refresh, local_now); + interval_earliest_wakeup (wakeup, top->future_trigger, local_now); +#if INTERVAL_DEBUG + dmsg (D_INTERVAL, "INTERVAL interval_schedule wakeup=%d", (int)*wakeup); +#endif +} + +/* + * In wakeup seconds, interval_test will return true once. + */ +static inline void +interval_future_trigger (struct interval* top, interval_t wakeup) { + if (wakeup) + { +#if INTERVAL_DEBUG + dmsg (D_INTERVAL, "INTERVAL interval_future_trigger %d", (int)wakeup); +#endif + top->future_trigger = now + wakeup; + } +} + +/* + * Once an action is triggered, interval_test will remain true for + * horizon seconds. + */ +static inline void +interval_action (struct interval* top) +{ +#if INTERVAL_DEBUG + dmsg (D_INTERVAL, "INTERVAL action"); +#endif + top->last_action = now; +} + +/* + * Measure when n seconds beyond an event have elapsed + */ + +struct event_timeout +{ + bool defined; + interval_t n; + time_t last; /* time of last event */ +}; + +static inline bool +event_timeout_defined (const struct event_timeout* et) +{ + return et->defined; +} + +static inline void +event_timeout_clear (struct event_timeout* et) +{ + et->defined = false; + et->n = 0; + et->last = 0; +} + +static inline struct event_timeout +event_timeout_clear_ret () +{ + struct event_timeout ret; + event_timeout_clear (&ret); + return ret; +} + +static inline void +event_timeout_init (struct event_timeout* et, interval_t n, const time_t local_now) +{ + et->defined = true; + et->n = (n >= 0) ? n : 0; + et->last = local_now; +} + +static inline void +event_timeout_reset (struct event_timeout* et) +{ + if (et->defined) + et->last = now; +} + +/* + * This is the principal function for testing and triggering recurring + * timers and will return true on a timer signal event. + * If et_const_retry == ETT_DEFAULT and a signal occurs, + * the function will return true and *et will be armed for the + * next event. If et_const_retry >= 0 and a signal occurs, + * *et will not be touched, but *tv will be set to + * minimum (*tv, et_const_retry) for a future re-test, + * and the function will return true. + */ + +#define ETT_DEFAULT (-1) + +bool event_timeout_trigger (struct event_timeout *et, + struct timeval *tv, + const int et_const_retry); + +/* + * Measure time intervals in microseconds + */ + +#define USEC_TIMER_MAX 60 /* maximum interval size in seconds */ + +#define USEC_TIMER_MAX_USEC (USEC_TIMER_MAX * 1000000) + +struct usec_timer { + struct timeval start; + struct timeval end; +}; + +#ifdef HAVE_GETTIMEOFDAY + +static inline void +usec_timer_start (struct usec_timer *obj) +{ + CLEAR (*obj); + gettimeofday (&obj->start, NULL); +} + +static inline void +usec_timer_end (struct usec_timer *obj) +{ + gettimeofday (&obj->end, NULL); +} + +#endif /* HAVE_GETTIMEOFDAY */ + +static inline bool +usec_timer_interval_defined (struct usec_timer *obj) +{ + return obj->start.tv_sec && obj->end.tv_sec; +} + +static inline int +usec_timer_interval (struct usec_timer *obj) +{ + return tv_subtract (&obj->end, &obj->start, USEC_TIMER_MAX); +} + +#endif /* INTERVAL_H */ diff --git a/openvpn/misc.h b/openvpn/misc.h new file mode 100644 index 0000000..00ddae8 --- /dev/null +++ b/openvpn/misc.h @@ -0,0 +1,257 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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 MISC_H +#define MISC_H + +#include "basic.h" +#include "common.h" +#include "integer.h" +#include "buffer.h" + +/* socket descriptor passed by inetd/xinetd server to us */ +#define INETD_SOCKET_DESCRIPTOR 0 + +/* forward declarations */ +struct plugin_list; + +/* + * Handle environmental variable lists + */ + +struct env_item { + char *string; + struct env_item *next; +}; + +struct env_set { + struct gc_arena *gc; + struct env_item *list; +}; + +/* Get/Set UID of process */ + +struct user_state { +#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID) + const char *username; + struct passwd *pw; +#else + int dummy; +#endif +}; + +bool get_user (const char *username, struct user_state *state); +void set_user (const struct user_state *state); + +/* Get/Set GID of process */ + +struct group_state { +#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID) + const char *groupname; + struct group *gr; +#else + int dummy; +#endif +}; + +bool get_group (const char *groupname, struct group_state *state); +void set_group (const struct group_state *state); + +void set_nice (int niceval); +void do_chroot (const char *path); + +void run_up_down (const char *command, + const struct plugin_list *plugins, + int plugin_type, + const char *arg, + int tun_mtu, + int link_mtu, + const char *ifconfig_local, + const char* ifconfig_remote, + const char *context, + const char *signal_text, + const char *script_type, + struct env_set *es); + +/* workspace for get_pid_file/write_pid */ +struct pid_state { + FILE *fp; + const char *filename; +}; + +void get_pid_file (const char* filename, struct pid_state *state); +void write_pid (const struct pid_state *state); +unsigned int openvpn_getpid (void); + +void do_mlockall (bool print_msg); /* Disable paging */ + +#ifndef HAVE_DAEMON +int daemon (int nochdir, int noclose); +#endif + +/* check file protections */ +void warn_if_group_others_accessible(const char* filename); + +/* system flags */ +#define S_SCRIPT (1<<0) +#define S_FATAL (1<<1) + +/* wrapper around the system() call. */ +int openvpn_system (const char *command, const struct env_set *es, unsigned int flags); + +/* interpret the status code returned by system() */ +bool system_ok(int); +int system_executed (int stat); +const char *system_error_message (int, struct gc_arena *gc); + +/* run system() with error check, return true if success, + false if error, exit if error and fatal==true */ +bool system_check (const char *command, const struct env_set *es, unsigned int flags, const char *error_message); + +#ifdef HAVE_STRERROR +/* a thread-safe version of strerror */ +const char* strerror_ts (int errnum, struct gc_arena *gc); +#endif + +/* Set standard file descriptors to /dev/null */ +void set_std_files_to_null (bool stdin_only); + +/* Wrapper for chdir library function */ +int openvpn_chdir (const char* dir); + +/* dup inetd/xinetd socket descriptor and save */ +extern int inetd_socket_descriptor; +void save_inetd_socket_descriptor (void); + +/* init random() function, only used as source for weak random numbers, when !USE_CRYPTO */ +void init_random_seed(void); + +/* set/delete environmental variable */ +void setenv_str_ex (struct env_set *es, + const char *name, + const char *value, + const unsigned int name_include, + const unsigned int name_exclude, + const char name_replace, + const unsigned int value_include, + const unsigned int value_exclude, + const char value_replace); + +void setenv_counter (struct env_set *es, const char *name, counter_type value); +void setenv_int (struct env_set *es, const char *name, int value); +void setenv_str (struct env_set *es, const char *name, const char *value); +void setenv_del (struct env_set *es, const char *name); + +/* struct env_set functions */ + +struct env_set *env_set_create (struct gc_arena *gc); +bool env_set_del (struct env_set *es, const char *str); +void env_set_add (struct env_set *es, const char *str); + +void env_set_print (int msglevel, const struct env_set *es); + +void env_set_inherit (struct env_set *es, const struct env_set *src); + +void env_set_add_to_environment (const struct env_set *es); +void env_set_remove_from_environment (const struct env_set *es); + +/* Make arrays of strings */ + +const char **make_env_array (const struct env_set *es, struct gc_arena *gc); +const char **make_arg_array (const char *first, const char *parms, struct gc_arena *gc); + +/* convert netmasks for iproute2 */ +int count_netmask_bits(const char *); +unsigned int count_bits(unsigned int ); + +/* go to sleep for n milliseconds */ +void sleep_milliseconds (unsigned int n); + +/* go to sleep indefinitely */ +void sleep_until_signal (void); + +/* an analogue to the random() function, but use OpenSSL functions if available */ +#ifdef USE_CRYPTO +long int get_random(void); +#else +#define get_random random +#endif + +/* return true if filename can be opened for read */ +bool test_file (const char *filename); + +/* create a temporary filename in directory */ +const char *create_temp_filename (const char *directory, struct gc_arena *gc); + +/* put a directory and filename together */ +const char *gen_path (const char *directory, const char *filename, struct gc_arena *gc); + +/* delete a file, return true if succeeded */ +bool delete_file (const char *filename); + +/* return the next largest power of 2 */ +unsigned int adjust_power_of_2 (unsigned int u); + +/* + * Get and store a username/password + */ + +struct user_pass +{ + bool defined; + bool nocache; + +/* max length of username/password */ +# define USER_PASS_LEN 128 + char username[USER_PASS_LEN]; + char password[USER_PASS_LEN]; +}; + +bool get_console_input (const char *prompt, const bool echo, char *input, const int capacity); + +#define GET_USER_PASS_MANAGEMENT (1<<0) +#define GET_USER_PASS_SENSITIVE (1<<1) + +void get_user_pass (struct user_pass *up, + const char *auth_file, + const bool password_only, + const char *prefix, + const unsigned int flags); + +void purge_user_pass (struct user_pass *up, const bool force); + +/* + * Process string received by untrusted peer before + * printing to console or log file. + * Assumes that string has been null terminated. + */ +const char *safe_print (const char *str, struct gc_arena *gc); + +/* + * A sleep function that services the management layer for n + * seconds rather than doing nothing. + */ +void openvpn_sleep (const int n); + +#endif diff --git a/openvpn/mtu.h b/openvpn/mtu.h new file mode 100644 index 0000000..3c53a26 --- /dev/null +++ b/openvpn/mtu.h @@ -0,0 +1,304 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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 MTU_H +#define MTU_H + +#include "buffer.h" + +/* + * + * Packet maninipulation routes such as encrypt, decrypt, compress, decompress + * are passed a frame buffer that looks like this: + * + * [extra_frame bytes] [mtu bytes] [extra_frame_bytes] [compression overflow bytes] + * ^ + * Pointer passed to function points here so that routine + * can make use of extra_frame bytes before pointer + * to prepend headers, etc. + * + * extra_frame bytes is large enough for all encryption related overhead. + * + * mtu bytes will be the MTU size set in the ifconfig statement that configures + * the TUN or TAP device such as: + * + * ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450 + * + * Compression overflow bytes is the worst-case size expansion that would be + * expected if we tried to compress mtu + extra_frame bytes of uncompressible data. + */ + +/* + * Standard ethernet MTU + */ +#define ETHERNET_MTU 1500 + +/* + * It is a fatal error if mtu is less than + * this value for tun device. + */ +#define TUN_MTU_MIN 100 + +/* + * Default MTU of network over which tunnel data will pass by TCP/UDP. + */ +#define LINK_MTU_DEFAULT 1500 + +/* + * Default MTU of tunnel device. + */ +#define TUN_MTU_DEFAULT 1500 + +/* + * MTU Defaults for TAP devices + */ +#define TAP_MTU_EXTRA_DEFAULT 32 + +/* + * Default MSSFIX value, used for reducing TCP MTU size + */ +#define MSSFIX_DEFAULT 1450 + +/* + * Alignment of payload data such as IP packet or + * ethernet frame. + */ +#define PAYLOAD_ALIGN 4 + +struct frame { + /* + * Maximum datagram size to be sent over the tunnel TCP/UDP channel. + */ + int link_mtu; + int link_mtu_dynamic; + + /* + * How many extra bytes might each subsystem (crypto, TLS, or, compression) + * add to frame in worst case? + * + * mtu + extra_frame = MTU of TCP/UDP transport + */ + int extra_frame; + + /* + * Worst case size added to internal buffer due to functions + * such as compression which can potentially expand the size of uncompressible + * data. + */ + int extra_buffer; + + /* + * Max number of bytes in excess of tun mtu size that we might read + * or write from TUN/TAP device. + */ + int extra_tun; + + /* + * Max number of bytes in excess of link mtu size that we might read + * or write from UDP/TCP link. + */ + int extra_link; + + /* + * Alignment control + */ +# define FRAME_HEADROOM_MARKER_DECRYPT (1<<0) +# define FRAME_HEADROOM_MARKER_FRAGMENT (1<<1) +# define FRAME_HEADROOM_MARKER_READ_LINK (1<<2) +# define FRAME_HEADROOM_MARKER_READ_STREAM (1<<3) + unsigned int align_flags; + int align_adjust; +}; + +/* Routines which read struct frame should use the macros below */ + +/* + * Overhead added to packet payload due to encapsulation + */ +#define EXTRA_FRAME(f) ((f)->extra_frame) + +/* + * Delta between tun payload size and final TCP/UDP datagram size + * (not including extra_link additions) + */ +#define TUN_LINK_DELTA(f) ((f)->extra_frame + (f)->extra_tun) + +/* + * This is the size to "ifconfig" the tun or tap device. + */ +#define TUN_MTU_SIZE(f) ((f)->link_mtu - TUN_LINK_DELTA(f)) +#define TUN_MTU_SIZE_DYNAMIC(f) ((f)->link_mtu_dynamic - TUN_LINK_DELTA(f)) + +/* + * This is the maximum packet size that we need to be able to + * read from or write to a tun or tap device. For example, + * a tap device ifconfiged to an MTU of 1200 might actually want + * to return a packet size of 1214 on a read(). + */ +#define PAYLOAD_SIZE(f) ((f)->link_mtu - (f)->extra_frame) +#define PAYLOAD_SIZE_DYNAMIC(f) ((f)->link_mtu_dynamic - (f)->extra_frame) + +/* + * Max size of a payload packet after encryption, compression, etc. + * overhead is added. + */ +#define EXPANDED_SIZE(f) ((f)->link_mtu) +#define EXPANDED_SIZE_DYNAMIC(f) ((f)->link_mtu_dynamic) +#define EXPANDED_SIZE_MIN(f) (TUN_MTU_MIN + TUN_LINK_DELTA(f)) + +/* + * These values are used as maximum size constraints + * on read() or write() from TUN/TAP device or TCP/UDP port. + */ +#define MAX_RW_SIZE_TUN(f) (PAYLOAD_SIZE(f)) +#define MAX_RW_SIZE_LINK(f) (EXPANDED_SIZE(f) + (f)->extra_link) + +/* + * Control buffer headroom allocations to allow for efficient prepending. + */ +#define FRAME_HEADROOM_BASE(f) (TUN_LINK_DELTA(f) + (f)->extra_buffer + (f)->extra_link) +#define FRAME_HEADROOM(f) frame_headroom(f, 0) +#define FRAME_HEADROOM_ADJ(f, fm) frame_headroom(f, fm) + +/* + * Max size of a buffer used to build a packet for output to + * the TCP/UDP port. + */ +#define BUF_SIZE(f) (TUN_MTU_SIZE(f) + FRAME_HEADROOM_BASE(f) * 2) + +/* + * Function prototypes. + */ + +void frame_finalize (struct frame *frame, + bool link_mtu_defined, + int link_mtu, + bool tun_mtu_defined, + int tun_mtu); + +void frame_subtract_extra (struct frame *frame, const struct frame *src); + +void frame_print (const struct frame *frame, + int level, + const char *prefix); + +void set_mtu_discover_type (int sd, int mtu_type); +int translate_mtu_discover_type_name (const char *name); + +/* + * frame_set_mtu_dynamic and flags + */ + +#define SET_MTU_TUN (1<<0) /* use tun/tap rather than link sizing */ +#define SET_MTU_UPPER_BOUND (1<<1) /* only decrease dynamic MTU */ + +void frame_set_mtu_dynamic (struct frame *frame, int mtu, unsigned int flags); + +/* + * allocate a buffer for socket or tun layer + */ +void alloc_buf_sock_tun (struct buffer *buf, + const struct frame *frame, + const bool tuntap_buffer, + const unsigned int align_mask); + +/* + * EXTENDED_SOCKET_ERROR_CAPABILITY functions -- print extra error info + * on socket errors, such as PMTU size. As of 2003.05.11, only works + * on Linux 2.4+. + */ + +#if EXTENDED_SOCKET_ERROR_CAPABILITY + +void set_sock_extended_error_passing (int sd); +const char *format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc); + +#endif + +/* + * Calculate a starting offset into a buffer object, dealing with + * headroom and alignment issues. + */ +static inline int +frame_headroom (const struct frame *f, const unsigned int flag_mask) +{ + const int offset = FRAME_HEADROOM_BASE (f); + const int adjust = (flag_mask & f->align_flags) ? f->align_adjust : 0; + const int delta = ((PAYLOAD_ALIGN << 24) - (offset + adjust)) & (PAYLOAD_ALIGN - 1); + return offset + delta; +} + +/* + * frame member adjustment functions + */ + +static inline void +frame_add_to_extra_frame (struct frame *frame, const int increment) +{ + frame->extra_frame += increment; +} + +static inline void +frame_add_to_extra_tun (struct frame *frame, const int increment) +{ + frame->extra_tun += increment; +} + +static inline void +frame_add_to_extra_link (struct frame *frame, const int increment) +{ + frame->extra_link += increment; +} + +static inline void +frame_add_to_extra_buffer (struct frame *frame, const int increment) +{ + frame->extra_buffer += increment; +} + +static inline void +frame_add_to_align_adjust (struct frame *frame, const int increment) +{ + frame->align_adjust += increment; +} + +static inline void +frame_align_to_extra_frame (struct frame *frame) +{ + frame->align_adjust = frame->extra_frame + frame->extra_link; +} + +static inline void +frame_or_align_flags (struct frame *frame, const unsigned int flag_mask) +{ + frame->align_flags |= flag_mask; +} + +static inline bool +frame_defined (const struct frame *frame) +{ + return frame->link_mtu > 0; +} + +#endif diff --git a/openvpn/otime.h b/openvpn/otime.h new file mode 100644 index 0000000..974d0af --- /dev/null +++ b/openvpn/otime.h @@ -0,0 +1,206 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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); + +extern volatile time_t now; /* updated frequently to time(NULL) */ + +static inline void +update_time (void) +{ + const time_t real_time = time (NULL); + if (real_time != now) + now = real_time; +} + +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 diff --git a/openvpn/perf.h b/openvpn/perf.h new file mode 100644 index 0000000..6080886 --- /dev/null +++ b/openvpn/perf.h @@ -0,0 +1,82 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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 + */ + +/* + * The interval_ routines are designed to optimize the calling of a routine + * (normally tls_multi_process()) which can be called less frequently + * between triggers. + */ + +#ifndef PERF_H +#define PERF_H + +/*#define ENABLE_PERFORMANCE_METRICS*/ + +/* + * Metrics + */ +#define PERF_BIO_READ_PLAINTEXT 0 +#define PERF_BIO_WRITE_PLAINTEXT 1 +#define PERF_BIO_READ_CIPHERTEXT 2 +#define PERF_BIO_WRITE_CIPHERTEXT 3 +#define PERF_TLS_MULTI_PROCESS 4 +#define PERF_IO_WAIT 5 +#define PERF_EVENT_LOOP 6 +#define PERF_MULTI_CREATE_INSTANCE 7 +#define PERF_MULTI_CLOSE_INSTANCE 8 +#define PERF_MULTI_SHOW_STATS 9 +#define PERF_MULTI_BCAST 10 +#define PERF_MULTI_MCAST 11 +#define PERF_SCRIPT 12 +#define PERF_READ_IN_LINK 13 +#define PERF_PROC_IN_LINK 14 +#define PERF_READ_IN_TUN 15 +#define PERF_PROC_IN_TUN 16 +#define PERF_PROC_OUT_LINK 17 +#define PERF_PROC_OUT_TUN 18 +#define PERF_PROC_OUT_TUN_MTCP 19 +#define PERF_N 20 + +#ifdef ENABLE_PERFORMANCE_METRICS + +#include "basic.h" + +/* + * Stack size + */ +#define STACK_N 64 + +void perf_push (int type); +void perf_pop (void); +void perf_output_results (void); + +#else + +static inline void perf_push (int type) {} +static inline void perf_pop (void) {} +static inline void perf_output_results (void) {} + +#endif + +#endif diff --git a/openvpn/proto.h b/openvpn/proto.h new file mode 100644 index 0000000..440d3d1 --- /dev/null +++ b/openvpn/proto.h @@ -0,0 +1,163 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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 PROTO_H +#define PROTO_H + +#include "buffer.h" + +/* + * Tunnel types + */ +#define DEV_TYPE_UNDEF 0 +#define DEV_TYPE_NULL 1 +#define DEV_TYPE_TUN 2 /* point-to-point IP tunnel */ +#define DEV_TYPE_TAP 3 /* ethernet (802.3) tunnel */ + +/* + * IP and Ethernet protocol structs. For portability, + * OpenVPN needs its own definitions of these structs, and + * names have been adjusted to avoid collisions with + * native structs. + */ + +#define OPENVPN_ETH_ALEN 6 /* ethernet address length */ +struct openvpn_ethhdr +{ + uint8_t dest[OPENVPN_ETH_ALEN]; /* destination ethernet addr */ + uint8_t source[OPENVPN_ETH_ALEN]; /* source ethernet addr */ + +# define OPENVPN_ETH_P_IPV4 0x0800 /* IPv4 protocol */ +# define OPENVPN_ETH_P_IPV6 0x86DD /* IPv6 protocol */ +# define OPENVPN_ETH_P_ARP 0x0806 /* ARP protocol */ + uint16_t proto; /* packet type ID field */ +}; + +struct openvpn_iphdr { +# define OPENVPN_IPH_GET_VER(v) (((v) >> 4) & 0x0F) +# define OPENVPN_IPH_GET_LEN(v) (((v) & 0x0F) << 2) + uint8_t version_len; + + uint8_t tos; + uint16_t tot_len; + uint16_t id; + +# define OPENVPN_IP_OFFMASK 0x1fff + uint16_t frag_off; + + uint8_t ttl; + +# define OPENVPN_IPPROTO_IGMP 2 /* IGMP protocol */ +# define OPENVPN_IPPROTO_TCP 6 /* TCP protocol */ +# define OPENVPN_IPPROTO_UDP 17 /* UDP protocol */ + uint8_t protocol; + + uint16_t check; + uint32_t saddr; + uint32_t daddr; + /*The options start here. */ +}; + +/* + * UDP header + */ +struct openvpn_udphdr { + uint16_t source; + uint16_t dest; + uint16_t len; + uint16_t check; +}; + +/* + * TCP header, per RFC 793. + */ +struct openvpn_tcphdr { + uint16_t source; /* source port */ + uint16_t dest; /* destination port */ + uint32_t seq; /* sequence number */ + uint32_t ack_seq; /* acknowledgement number */ + +# define OPENVPN_TCPH_GET_DOFF(d) (((d) & 0xF0) >> 2) + uint8_t doff_res; + +# define OPENVPN_TCPH_FIN_MASK (1<<0) +# define OPENVPN_TCPH_SYN_MASK (1<<1) +# define OPENVPN_TCPH_RST_MASK (1<<2) +# define OPENVPN_TCPH_PSH_MASK (1<<3) +# define OPENVPN_TCPH_ACK_MASK (1<<4) +# define OPENVPN_TCPH_URG_MASK (1<<5) +# define OPENVPN_TCPH_ECE_MASK (1<<6) +# define OPENVPN_TCPH_CWR_MASK (1<<7) + uint8_t flags; + + uint16_t window; + uint16_t check; + uint16_t urg_ptr; +}; + +#define OPENVPN_TCPOPT_EOL 0 +#define OPENVPN_TCPOPT_NOP 1 +#define OPENVPN_TCPOPT_MAXSEG 2 +#define OPENVPN_TCPOLEN_MAXSEG 4 + +/* + * The following macro is used to update an + * internet checksum. "acc" is a 32-bit + * accumulation of all the changes to the + * checksum (adding in old 16-bit words and + * subtracting out new words), and "cksum" + * is the checksum value to be updated. + */ +#define ADJUST_CHECKSUM(acc, cksum) { \ + (acc) += (cksum); \ + if ((acc) < 0) { \ + (acc) = -(acc); \ + (acc) = ((acc) >> 16) + ((acc) & 0xffff); \ + (acc) += (acc) >> 16; \ + (cksum) = (uint16_t) ~(acc); \ + } else { \ + (acc) = ((acc) >> 16) + ((acc) & 0xffff); \ + (acc) += (acc) >> 16; \ + (cksum) = (uint16_t) (acc); \ + } \ +} + +/* + * We are in a "liberal" position with respect to MSS, + * i.e. we assume that MSS can be calculated from MTU + * by subtracting out only the IP and TCP header sizes + * without options. + * + * (RFC 879, section 7). + */ +#define MTU_TO_MSS(mtu) (mtu - sizeof(struct openvpn_iphdr) \ + - sizeof(struct openvpn_tcphdr)) + +/* + * If raw tunnel packet is IPv4, return true and increment + * buffer offset to start of IP header. + */ +bool is_ipv4 (int tunnel_type, struct buffer *buf); + +#endif diff --git a/openvpn/sig.h b/openvpn/sig.h new file mode 100644 index 0000000..dd17c40 --- /dev/null +++ b/openvpn/sig.h @@ -0,0 +1,100 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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 SIG_H +#define SIG_H + +#include "status.h" +#include "win32.h" + +/* + * Signal information, including signal code + * and descriptive text. + */ +struct signal_info +{ + volatile int signal_received; + volatile bool hard; + const char *signal_text; +}; + +#define IS_SIG(c) ((c)->sig->signal_received) + +struct context; + +extern struct signal_info siginfo_static; + +int parse_signal (const char *signame); +const char *signal_name (const int sig, const bool upper); +const char *signal_description (const int signum, const char *sigtext); +void throw_signal (const int signum); + +void pre_init_signal_catch (void); +void post_init_signal_catch (void); + +void print_signal (const struct signal_info *si, const char *title, int msglevel); +void print_status (const struct context *c, struct status_output *so); + +void remap_signal (struct context *c); + +void signal_restart_status (const struct signal_info *si); + +bool process_signal (struct context *c); + +#ifdef ENABLE_OCC +void process_explicit_exit_notification_timer_wakeup (struct context *c); +#endif + +#ifdef WIN32 + +static inline void +get_signal (volatile int *sig) +{ + *sig = win32_signal_get (&win32_signal); +} + +static inline void +halt_non_edge_triggered_signals (void) +{ + win32_signal_close (&win32_signal); +} + +#else + +static inline void +get_signal (volatile int *sig) +{ + const int i = siginfo_static.signal_received; + if (i) + *sig = i; +} + +static inline void +halt_non_edge_triggered_signals (void) +{ +} + +#endif + +#endif diff --git a/openvpn/status.h b/openvpn/status.h new file mode 100644 index 0000000..be3c3f3 --- /dev/null +++ b/openvpn/status.h @@ -0,0 +1,95 @@ +/* + * 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-2005 OpenVPN Solutions LLC <info@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 (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 STATUS_H +#define STATUS_H + +#include "interval.h" + +/* + * virtual function interface for status output + */ +struct virtual_output { + void *arg; + unsigned int flags_default; + void (*func) (void *arg, const unsigned int flags, const char *str); +}; + +static inline void +virtual_output_print (const struct virtual_output *vo, const unsigned int flags, const char *str) +{ + (*vo->func) (vo->arg, flags, str); +} + +/* + * printf-style interface for inputting/outputting status info + */ + +struct status_output +{ +# define STATUS_OUTPUT_READ (1<<0) +# define STATUS_OUTPUT_WRITE (1<<1) + unsigned int flags; + + char *filename; + int fd; + int msglevel; + const struct virtual_output *vout; + + struct buffer read_buf; + + struct event_timeout et; + + bool errors; +}; + +struct status_output *status_open (const char *filename, + const int refresh_freq, + const int msglevel, + const struct virtual_output *vout, + const unsigned int flags); + +bool status_trigger_tv (struct status_output *so, struct timeval *tv); +bool status_trigger (struct status_output *so); +void status_reset (struct status_output *so); +void status_flush (struct status_output *so); +bool status_close (struct status_output *so); +void status_printf (struct status_output *so, const char *format, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 2, 3))) +#endif + ; + +bool status_read (struct status_output *so, struct buffer *buf); + +static inline unsigned int +status_rw_flags (const struct status_output *so) +{ + if (so) + return so->flags; + else + return 0; +} + +#endif diff --git a/openvpn/thread.h b/openvpn/thread.h new file mode 100644 index 0000000..ecc3616 --- /dev/null +++ b/openvpn/thread.h @@ -0,0 +1,235 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@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 (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 THREAD_H +#define THREAD_H + +#include "basic.h" +#include "common.h" + +/* + * OpenVPN static mutex locks, by mutex type + */ +#define L_UNUSED 0 +#define L_CTIME 1 +#define L_INET_NTOA 2 +#define L_MSG 3 +#define L_STRERR 4 +#define L_PUTENV 5 +#define L_PRNG 6 +#define L_GETTIMEOFDAY 7 +#define L_ENV_SET 8 +#define L_SYSTEM 9 +#define L_CREATE_TEMP 10 +#define L_PLUGIN 11 +#define N_MUTEXES 12 + +#ifdef USE_PTHREAD + +#define MAX_THREADS 50 + +#define CACHE_LINE_SIZE 128 + +/* + * Improve SMP performance by making sure that each + * mutex resides in its own cache line. + */ +struct sparse_mutex +{ + pthread_mutex_t mutex; + uint8_t dummy [CACHE_LINE_SIZE - sizeof (pthread_mutex_t)]; +}; + +typedef pthread_t openvpn_thread_t; + +extern bool pthread_initialized; + +extern struct sparse_mutex mutex_array[N_MUTEXES]; + +#define MUTEX_DEFINE(lock) pthread_mutex_t lock +#define MUTEX_PTR_DEFINE(lock) pthread_mutex_t *lock + +static inline bool +openvpn_thread_enabled (void) +{ + return pthread_initialized; +} + +static inline openvpn_thread_t +openvpn_thread_self (void) +{ + return pthread_initialized ? pthread_self() : 0; +} + +static inline void +mutex_init (pthread_mutex_t *mutex) +{ + if (mutex) + pthread_mutex_init (mutex, NULL); +} + +static inline void +mutex_destroy (pthread_mutex_t *mutex) +{ + if (mutex) + pthread_mutex_destroy (mutex); +} + +static inline void +mutex_lock (pthread_mutex_t *mutex) +{ + if (pthread_initialized && mutex) + pthread_mutex_lock (mutex); +} + +static inline bool +mutex_trylock (pthread_mutex_t *mutex) +{ + if (pthread_initialized && mutex) + return pthread_mutex_trylock (mutex) == 0; + else + return true; +} + +static inline void +mutex_unlock (pthread_mutex_t *mutex) +{ + if (pthread_initialized && mutex) + { + pthread_mutex_unlock (mutex); +#if 1 /* JYFIXME: if race conditions exist, make them more likely to occur */ + sleep (0); +#endif + } +} + +static inline void +mutex_cycle (pthread_mutex_t *mutex) +{ + if (pthread_initialized && mutex) + { + pthread_mutex_unlock (mutex); + sleep (0); + pthread_mutex_lock (mutex); + } +} + +static inline void +mutex_lock_static (int type) +{ + mutex_lock (&mutex_array[type].mutex); +} + +static inline void +mutex_unlock_static (int type) +{ + mutex_unlock (&mutex_array[type].mutex); +} + +static inline void +mutex_cycle_static (int type) +{ + mutex_cycle (&mutex_array[type].mutex); +} + +void openvpn_thread_init (void); +void openvpn_thread_cleanup (void); + +openvpn_thread_t openvpn_thread_create (void *(*start_routine) (void *), void* arg); +void openvpn_thread_join (openvpn_thread_t id); + +#else /* USE_PTHREAD */ + +typedef int openvpn_thread_t; + +#if defined(_MSC_VER) || PEDANTIC + +#define MUTEX_DEFINE(lock) int eat_semicolon +#define MUTEX_PTR_DEFINE(lock) int eat_semicolon + +#else + +#define MUTEX_DEFINE(lock) +#define MUTEX_PTR_DEFINE(lock) + +#endif + +#define mutex_init(m) +#define mutex_destroy(m) +#define mutex_lock(m) +#define mutex_trylock(m) (true) +#define mutex_unlock(m) +#define mutex_cycle(m) + +static inline bool +openvpn_thread_enabled (void) +{ + return false; +} + +static inline openvpn_thread_t +openvpn_thread_self (void) +{ + return 0; +} + +static inline void +openvpn_thread_init (void) +{ +} + +static inline void +openvpn_thread_cleanup (void) +{ +} + +static inline openvpn_thread_t +openvpn_thread_create (void *(*start_routine) (void *), void* arg) +{ + return 0; +} + +static inline void +work_thread_join (openvpn_thread_t id) +{ +} + +static inline void +mutex_lock_static (int type) +{ +} + +static inline void +mutex_unlock_static (int type) +{ +} + +static inline void +mutex_cycle_static (int type) +{ +} + +#endif /* USE_PTHREAD */ + +#endif /* THREAD_H */ diff --git a/openvpn/win32.h b/openvpn/win32.h new file mode 100755 index 0000000..12af854 --- /dev/null +++ b/openvpn/win32.h @@ -0,0 +1,251 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@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 (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 + */ + +#ifdef WIN32 +#ifndef OPENVPN_WIN32_H +#define OPENVPN_WIN32_H + +#include "mtu.h" + +/* + * Win32-specific OpenVPN code, targetted at the mingw + * development environment. + */ + +void init_win32 (void); +void uninit_win32 (void); + +void set_pause_exit_win32 (void); + +/* + * Use keyboard input or events + * to simulate incoming signals + */ + +#define SIGUSR1 1 +#define SIGUSR2 2 +#define SIGHUP 3 +#define SIGTERM 4 +#define SIGINT 5 + +struct security_attributes +{ + SECURITY_ATTRIBUTES sa; + SECURITY_DESCRIPTOR sd; +}; + +#define HANDLE_DEFINED(h) ((h) != NULL && (h) != INVALID_HANDLE_VALUE) + +/* + * Save old window title. + */ +struct window_title +{ + bool saved; + char old_window_title [256]; +}; + +struct rw_handle { + HANDLE read; + HANDLE write; +}; + +/* + * Event-based notification of incoming TCP connections + */ + +#define NE32_PERSIST_EVENT (1<<0) +#define NE32_WRITE_EVENT (1<<1) + +static inline bool +defined_net_event_win32 (const struct rw_handle *event) +{ + return event->read != NULL; +} + +void init_net_event_win32 (struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags); +long reset_net_event_win32 (struct rw_handle *event, socket_descriptor_t sd); +void close_net_event_win32 (struct rw_handle *event, socket_descriptor_t sd, unsigned int flags); + +/* + * A stateful variant of the net_event_win32 functions above + */ + +struct net_event_win32 +{ + struct rw_handle handle; + socket_descriptor_t sd; + long event_mask; +}; + +void net_event_win32_init (struct net_event_win32 *ne); +void net_event_win32_start (struct net_event_win32 *ne, long network_events, socket_descriptor_t sd); +void net_event_win32_reset (struct net_event_win32 *ne); +void net_event_win32_reset_write (struct net_event_win32 *ne); +void net_event_win32_stop (struct net_event_win32 *ne); +void net_event_win32_close (struct net_event_win32 *ne); + +static bool +net_event_win32_defined (const struct net_event_win32 *ne) +{ + return defined_net_event_win32 (&ne->handle); +} + +static inline struct rw_handle * +net_event_win32_get_event (struct net_event_win32 *ne) +{ + return &ne->handle; +} + +static inline long +net_event_win32_get_event_mask (const struct net_event_win32 *ne) +{ + return ne->event_mask; +} + +static inline void +net_event_win32_clear_selected_events (struct net_event_win32 *ne, long selected_events) +{ + ne->event_mask &= ~selected_events; +} + +/* + * Signal handling + */ +struct win32_signal { +# define WSO_MODE_UNDEF 0 +# define WSO_MODE_SERVICE 1 +# define WSO_MODE_CONSOLE 2 + int mode; + struct rw_handle in; + DWORD console_mode_save; + bool console_mode_save_defined; +}; + +extern struct win32_signal win32_signal; /* static/global */ +extern struct window_title window_title; /* static/global */ + +void win32_signal_clear (struct win32_signal *ws); + +/* win32_signal_open startup type */ +#define WSO_NOFORCE 0 +#define WSO_FORCE_SERVICE 1 +#define WSO_FORCE_CONSOLE 2 + +void win32_signal_open (struct win32_signal *ws, + int force, /* set to WSO force parm */ + const char *exit_event_name, + bool exit_event_initial_state); + +void win32_signal_close (struct win32_signal *ws); + +int win32_signal_get (struct win32_signal *ws); + +void win32_pause (struct win32_signal *ws); + +/* + * Set the text on the window title bar + */ + +void window_title_clear (struct window_title *wt); +void window_title_save (struct window_title *wt); +void window_title_restore (const struct window_title *wt); +void window_title_generate (const char *title); + +/* + * We try to do all Win32 I/O using overlapped + * (i.e. asynchronous) I/O for a performance win. + */ +struct overlapped_io { +# define IOSTATE_INITIAL 0 +# define IOSTATE_QUEUED 1 /* overlapped I/O has been queued */ +# define IOSTATE_IMMEDIATE_RETURN 2 /* I/O function returned immediately without queueing */ + int iostate; + OVERLAPPED overlapped; + DWORD size; + DWORD flags; + int status; + bool addr_defined; + struct sockaddr_in addr; + int addrlen; + struct buffer buf_init; + struct buffer buf; +}; + +void overlapped_io_init (struct overlapped_io *o, + const struct frame *frame, + BOOL event_state, + bool tuntap_buffer); + +void overlapped_io_close (struct overlapped_io *o); + +static inline bool +overlapped_io_active (struct overlapped_io *o) +{ + return o->iostate == IOSTATE_QUEUED || o->iostate == IOSTATE_IMMEDIATE_RETURN; +} + +char *overlapped_io_state_ascii (const struct overlapped_io *o); + +/* + * Use to control access to resources that only one + * OpenVPN process on a given machine can access at + * a given time. + */ + +struct semaphore +{ + const char *name; + bool locked; + HANDLE hand; +}; + +void semaphore_clear (struct semaphore *s); +void semaphore_open (struct semaphore *s, const char *name); +bool semaphore_lock (struct semaphore *s, int timeout_milliseconds); +void semaphore_release (struct semaphore *s); +void semaphore_close (struct semaphore *s); + +/* + * Special global semaphore used to protect network + * shell commands from simultaneous instantiation. + * + * It seems you can't run more than one instance + * of netsh on the same machine at the same time. + */ + +extern struct semaphore netcmd_semaphore; +void netcmd_semaphore_init (void); +void netcmd_semaphore_close (void); +void netcmd_semaphore_lock (void); +void netcmd_semaphore_release (void); + +bool get_console_input_win32 (const char *prompt, const bool echo, char *input, const int capacity); +char *getpass (const char *prompt); + +/* Set Win32 security attributes structure to allow all access */ +bool init_security_attributes_allow_all (struct security_attributes *obj); + +#endif +#endif |