From 8e8ce31dc422c0116ae2866d5874ef70fbb21f57 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sat, 16 Jun 2007 00:34:44 +0000 Subject: removed openvpn source files tundevice can now be compiled added main added some helper classes --- Makefile | 43 +- anytun.cpp | 58 + buffer.cpp | 111 ++ buffer.h | 55 + datatypes.h | 48 + openvpn/basic.h | 41 - openvpn/buffer.h | 712 ----------- openvpn/common.h | 76 -- openvpn/event.h | 157 --- openvpn/integer.h | 114 -- openvpn/interval.h | 239 ---- openvpn/misc.h | 257 ---- openvpn/mtu.h | 304 ----- openvpn/otime.h | 206 ---- openvpn/perf.h | 82 -- openvpn/proto.h | 163 --- openvpn/sig.h | 100 -- openvpn/status.h | 95 -- openvpn/thread.h | 235 ---- openvpn/tun.c | 3446 ---------------------------------------------------- openvpn/tun.h | 413 ------- openvpn/win32.h | 251 ---- threadutils.hpp | 174 +++ tunDevice.cpp | 59 +- tunDevice.h | 9 +- 25 files changed, 541 insertions(+), 6907 deletions(-) create mode 100644 anytun.cpp create mode 100644 buffer.cpp create mode 100644 buffer.h create mode 100644 datatypes.h delete mode 100644 openvpn/basic.h delete mode 100644 openvpn/buffer.h delete mode 100644 openvpn/common.h delete mode 100644 openvpn/event.h delete mode 100644 openvpn/integer.h delete mode 100644 openvpn/interval.h delete mode 100644 openvpn/misc.h delete mode 100644 openvpn/mtu.h delete mode 100644 openvpn/otime.h delete mode 100644 openvpn/perf.h delete mode 100644 openvpn/proto.h delete mode 100644 openvpn/sig.h delete mode 100644 openvpn/status.h delete mode 100644 openvpn/thread.h delete mode 100644 openvpn/tun.c delete mode 100644 openvpn/tun.h delete mode 100755 openvpn/win32.h create mode 100644 threadutils.hpp diff --git a/Makefile b/Makefile index 35e62b2..31ed266 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,50 @@ C = gcc +CFLAGS = -g -Wall C++ = g++ -CCFLAGS = -Wall -LDFLAGS = #-lpthread #-static +CCFLAGS = -g -Wall +LD = g++ +LDFLAGS = -g -O2 -ldl -OBJS = tunDevice.o tun.c +OPENVPNDEPS = openvpn/tun.o \ + openvpn/error.o \ + openvpn/socket.o \ + openvpn/buffer.o \ + openvpn/misc.o \ + openvpn/manage.o \ + openvpn/fdmisc.o \ + openvpn/otime.o \ + openvpn/options.o \ + openvpn/mtu.o \ + openvpn/plugin.o \ + openvpn/sig.o \ + openvpn/proxy.o \ + openvpn/socks.o \ + openvpn/status.o \ + openvpn/event.o \ + openvpn/route.o \ + openvpn/helper.o \ + openvpn/init.o \ + openvpn/interval.o \ + openvpn/base64.o \ + openvpn/shaper.o \ + openvpn/fragment.o + +OBJS = anytun.o tunDevice.o buffer.o $(OPENVPNDEPS) EXECUTABLE = anytun all: $(EXECUTABLE) anytun: $(OBJS) - $(C++) $(OBJS) -o $@ $(LDFLAGS) + $(LD) $(OBJS) -o $@ $(LDFLAGS) + +tunDevice.o: tunDevice.cpp tunDevice.h + $(C++) $(CCFLAGS) $< -c -tunDevice.o: tunDevice.cpp tunDevice.h openvpn/tun.h +Buffer.o: buffer.cpp buffer.h $(C++) $(CCFLAGS) $< -c -tun.o: openvpn/tun.c openvpn/tun.h - $(C) $(CCFLAGS) $< -c +anytun.o: anytun.cpp + $(C++) $(CCFLAGS) $< -c clean: rm -f *.o diff --git a/anytun.cpp b/anytun.cpp new file mode 100644 index 0000000..02f0192 --- /dev/null +++ b/anytun.cpp @@ -0,0 +1,58 @@ +/* + * anytun + * + * The secure anycast tunneling protocol (satp) defines a protocol used + * for communication between any combination of unicast and anycast + * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel + * mode and allows tunneling of every ETHER TYPE protocol (e.g. + * ethernet, ip, arp ...). satp directly includes cryptography and + * message authentication based on the methodes used by SRTP. It is + * intended to deliver a generic, scaleable and secure solution for + * tunneling and relaying of packets of any protocol. + * + * + * Copyright (C) 2007 anytun.org + * + * 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 + */ + +#include + +#include "datatypes.h" + +#include "buffer.h" + +int main(int argc, char* argv[]) +{ + std::cout << "anytun - secure anycast tunneling protocol" << std::endl; + + u_int8_t test[100]; + for(int i=0;i<100;++i) + test[i] = i; + + + Buffer a(test, 100); + Buffer b(a); + Buffer c; + + c = b; + + c.resize(500); + + for(unsigned int i=0;i + * + * 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 + */ + +#include + +#include "datatypes.h" + +#include "buffer.h" + +Buffer::Buffer() : buf_(0), length_(0) +{ +} + +Buffer::Buffer(u_int8_t* data, u_int32_t length) : length_(length) +{ + buf_ = new u_int8_t[length_]; + if(buf_) + std::memcpy(buf_, data, length_); + else + length_ = 0; +} + +Buffer::~Buffer() +{ + if(buf_) + delete[] buf_; +} + +Buffer::Buffer(const Buffer &src) : length_(src.length_) +{ + buf_ = new u_int8_t[length_]; + if(buf_) + std::memcpy(buf_, src.buf_, length_); + else + length_ = 0; +} + +void Buffer::operator=(const Buffer &src) +{ + if(buf_) + delete[] buf_; + + length_ = src.length_; + + buf_ = new u_int8_t[length_]; + if(buf_) + std::memcpy(buf_, src.buf_, length_); + else + length_ = 0; +} + +u_int32_t Buffer::resize(u_int32_t new_length) +{ + if(length_ == new_length) + return length_; + + u_int8_t *tmp = new u_int8_t[new_length]; + if(!tmp) + return length_; + + if(buf_) + { + std::memcpy(tmp, buf_, length_); + delete[] buf_; + } + + length_ = new_length; + buf_ = tmp; +} + +u_int32_t Buffer::getLength() const +{ + return length_; +} + +u_int8_t* Buffer::getBuf() +{ + return buf_; +} + +Buffer::operator u_int8_t*( ) +{ + return buf_; +} diff --git a/buffer.h b/buffer.h new file mode 100644 index 0000000..a68258b --- /dev/null +++ b/buffer.h @@ -0,0 +1,55 @@ +/* + * anytun + * + * The secure anycast tunneling protocol (satp) defines a protocol used + * for communication between any combination of unicast and anycast + * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel + * mode and allows tunneling of every ETHER TYPE protocol (e.g. + * ethernet, ip, arp ...). satp directly includes cryptography and + * message authentication based on the methodes used by SRTP. It is + * intended to deliver a generic, scaleable and secure solution for + * tunneling and relaying of packets of any protocol. + * + * + * Copyright (C) 2007 anytun.org + * + * 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_ + +class Buffer +{ +public: + Buffer(); + Buffer(u_int8_t* data, u_int32_t length); + ~Buffer(); + Buffer(const Buffer &src); + void operator=(const Buffer &src); + + u_int32_t resize(u_int32_t new_length); + u_int32_t getLength() const; + u_int8_t* getBuf(); + operator u_int8_t*( ); + +protected: + + u_int32_t length_; + u_int8_t *buf_; +}; + + +#endif diff --git a/datatypes.h b/datatypes.h new file mode 100644 index 0000000..62fda83 --- /dev/null +++ b/datatypes.h @@ -0,0 +1,48 @@ +/* + * anytun + * + * The secure anycast tunneling protocol (satp) defines a protocol used + * for communication between any combination of unicast and anycast + * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel + * mode and allows tunneling of every ETHER TYPE protocol (e.g. + * ethernet, ip, arp ...). satp directly includes cryptography and + * message authentication based on the methodes used by SRTP. It is + * intended to deliver a generic, scaleable and secure solution for + * tunneling and relaying of packets of any protocol. + * + * + * Copyright (C) 2007 anytun.org + * + * 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 _DATATYPES_H_ +#define _DATATYPES_H_ + +typedef signed char int8_t; +typedef unsigned char u_int8_t; + +typedef signed short int16; +typedef unsigned short u_int16_t; + +typedef signed int int32; +typedef unsigned int u_int32_t; + +typedef signed long long int64_t; +typedef unsigned long long u_int64_t; + +typedef u_int32_t auth_tag_t; + +#endif diff --git a/openvpn/basic.h b/openvpn/basic.h deleted file mode 100644 index cde638e..0000000 --- a/openvpn/basic.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 1e5266b..0000000 --- a/openvpn/buffer.h +++ /dev/null @@ -1,712 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 70efdbf..0000000 --- a/openvpn/common.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 314ef4c..0000000 --- a/openvpn/event.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 68cf40f..0000000 --- a/openvpn/integer.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 9845066..0000000 --- a/openvpn/interval.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 00ddae8..0000000 --- a/openvpn/misc.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 3c53a26..0000000 --- a/openvpn/mtu.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 974d0af..0000000 --- a/openvpn/otime.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 6080886..0000000 --- a/openvpn/perf.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index 440d3d1..0000000 --- a/openvpn/proto.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index dd17c40..0000000 --- a/openvpn/sig.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index be3c3f3..0000000 --- a/openvpn/status.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 - * - * 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 deleted file mode 100644 index ecc3616..0000000 --- a/openvpn/thread.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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 - * - * 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/tun.c b/openvpn/tun.c deleted file mode 100644 index e904a0c..0000000 --- a/openvpn/tun.c +++ /dev/null @@ -1,3446 +0,0 @@ -/* - * 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 - * - * 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 - */ - -/* - * Support routines for configuring and accessing TUN/TAP - * virtual network adapters. - * - * This file is based on the TUN/TAP driver interface routines - * from VTun by Maxim Krasnyansky . - */ - -#ifdef WIN32 -#include "config-win32.h" -#else -#include "config.h" -#endif - -#include "syshead.h" - -#include "tun.h" -#include "fdmisc.h" -#include "common.h" -#include "misc.h" -#include "socket.h" -#include "manage.h" - -#include "memdbg.h" - -#ifdef TARGET_SOLARIS -static void solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual); -#endif - -bool -is_dev_type (const char *dev, const char *dev_type, const char *match_type) -{ - ASSERT (match_type); - if (!dev) - return false; - if (dev_type) - return !strcmp (dev_type, match_type); - else - return !strncmp (dev, match_type, strlen (match_type)); -} - -int -dev_type_enum (const char *dev, const char *dev_type) -{ - if (is_dev_type (dev, dev_type, "tun")) - return DEV_TYPE_TUN; - else if (is_dev_type (dev, dev_type, "tap")) - return DEV_TYPE_TAP; - else if (is_dev_type (dev, dev_type, "null")) - return DEV_TYPE_NULL; - else - return DEV_TYPE_UNDEF; -} - -const char * -dev_type_string (const char *dev, const char *dev_type) -{ - switch (dev_type_enum (dev, dev_type)) - { - case DEV_TYPE_TUN: - return "tun"; - case DEV_TYPE_TAP: - return "tap"; - case DEV_TYPE_NULL: - return "null"; - default: - return "[unknown-dev-type]"; - } -} - -const char * -dev_component_in_dev_node (const char *dev_node) -{ - const char *ret; - const int dirsep = OS_SPECIFIC_DIRSEP; - - if (dev_node) - { - ret = strrchr (dev_node, dirsep); - if (ret && *ret) - ++ret; - else - ret = dev_node; - if (*ret) - return ret; - } - return NULL; -} - -/* - * Try to predict the actual TUN/TAP device instance name, - * before the device is actually opened. - */ -const char * -guess_tuntap_dev (const char *dev, - const char *dev_type, - const char *dev_node, - struct gc_arena *gc) -{ -#ifdef WIN32 - const int dt = dev_type_enum (dev, dev_type); - if (dt == DEV_TYPE_TUN || dt == DEV_TYPE_TAP) - { - return get_netsh_id (dev_node, gc); - } -#endif - - /* default case */ - return dev; -} - -/* - * Called by the open_tun function of OSes to check if we - * explicitly support IPv6. - * - * In this context, explicit means that the OS expects us to - * do something special to the tun socket in order to support - * IPv6, i.e. it is not transparent. - * - * ipv6_explicitly_supported should be set to false if we don't - * have any explicit IPv6 code in the tun device handler. - * - * If ipv6_explicitly_supported is true, then we have explicit - * OS-specific tun dev code for handling IPv6. If so, tt->ipv6 - * is set according to the --tun-ipv6 command line option. - */ -static void -ipv6_support (bool ipv6, bool ipv6_explicitly_supported, struct tuntap* tt) -{ - tt->ipv6 = false; - if (ipv6_explicitly_supported) - tt->ipv6 = ipv6; - else if (ipv6) - msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS"); -} - -/* --ifconfig-nowarn disables some options sanity checking */ -static const char ifconfig_warn_how_to_silence[] = "(silence this warning with --ifconfig-nowarn)"; - -/* - * If !tun, make sure ifconfig_remote_netmask looks - * like a netmask. - * - * If tun, make sure ifconfig_remote_netmask looks - * like an IPv4 address. - */ -static void -ifconfig_sanity_check (bool tun, in_addr_t addr) -{ - struct gc_arena gc = gc_new (); - const bool looks_like_netmask = ((addr & 0xFF000000) == 0xFF000000); - if (tun) - { - if (looks_like_netmask) - msg (M_WARN, "WARNING: Since you are using --dev tun, the second argument to --ifconfig must be an IP address. You are using something (%s) that looks more like a netmask. %s", - print_in_addr_t (addr, 0, &gc), - ifconfig_warn_how_to_silence); - } - else /* tap */ - { - if (!looks_like_netmask) - msg (M_WARN, "WARNING: Since you are using --dev tap, the second argument to --ifconfig must be a netmask, for example something like 255.255.255.0. %s", - ifconfig_warn_how_to_silence); - } - gc_free (&gc); -} - -/* - * For TAP-style devices, generate a broadcast address. - */ -static in_addr_t -generate_ifconfig_broadcast_addr (in_addr_t local, - in_addr_t netmask) -{ - return local | ~netmask; -} - -/* - * Check that --local and --remote addresses do not - * clash with ifconfig addresses or subnet. - */ -static void -check_addr_clash (const char *name, - int type, - in_addr_t public, - in_addr_t local, - in_addr_t remote_netmask) -{ - struct gc_arena gc = gc_new (); -#if 0 - msg (M_INFO, "CHECK_ADDR_CLASH type=%d public=%s local=%s, remote_netmask=%s", - type, - print_in_addr_t (public, 0, &gc), - print_in_addr_t (local, 0, &gc), - print_in_addr_t (remote_netmask, 0, &gc)); -#endif - - if (public) - { - if (type == DEV_TYPE_TUN) - { - const in_addr_t test_netmask = 0xFFFFFF00; - const in_addr_t public_net = public & test_netmask; - const in_addr_t local_net = local & test_netmask; - const in_addr_t remote_net = remote_netmask & test_netmask; - - if (public == local || public == remote_netmask) - msg (M_WARN, - "WARNING: --%s address [%s] conflicts with --ifconfig address pair [%s, %s]. %s", - name, - print_in_addr_t (public, 0, &gc), - print_in_addr_t (local, 0, &gc), - print_in_addr_t (remote_netmask, 0, &gc), - ifconfig_warn_how_to_silence); - - if (public_net == local_net || public_net == remote_net) - msg (M_WARN, - "WARNING: potential conflict between --%s address [%s] and --ifconfig address pair [%s, %s] -- this is a warning only that is triggered when local/remote addresses exist within the same /24 subnet as --ifconfig endpoints. %s", - name, - print_in_addr_t (public, 0, &gc), - print_in_addr_t (local, 0, &gc), - print_in_addr_t (remote_netmask, 0, &gc), - ifconfig_warn_how_to_silence); - } - else if (type == DEV_TYPE_TAP) - { - const in_addr_t public_network = public & remote_netmask; - const in_addr_t virtual_network = local & remote_netmask; - if (public_network == virtual_network) - msg (M_WARN, - "WARNING: --%s address [%s] conflicts with --ifconfig subnet [%s, %s] -- local and remote addresses cannot be inside of the --ifconfig subnet. %s", - name, - print_in_addr_t (public, 0, &gc), - print_in_addr_t (local, 0, &gc), - print_in_addr_t (remote_netmask, 0, &gc), - ifconfig_warn_how_to_silence); - } - } - gc_free (&gc); -} - -/* - * Complain if --dev tap and --ifconfig is used on an OS for which - * we don't have a custom tap ifconfig template below. - */ -static void -no_tap_ifconfig () -{ - msg (M_FATAL, "Sorry but you cannot use --dev tap and --ifconfig together on this OS because I have not yet been programmed to understand the appropriate ifconfig syntax to use for TAP-style devices on this OS. Your best alternative is to use an --up script and do the ifconfig command manually."); -} - -/* - * Return a string to be used for options compatibility check - * between peers. - */ -const char * -ifconfig_options_string (const struct tuntap* tt, bool remote, bool disable, struct gc_arena *gc) -{ - struct buffer out = alloc_buf_gc (256, gc); - if (tt->did_ifconfig_setup && !disable) - { - if (tt->type == DEV_TYPE_TUN) - { - const char *l, *r; - if (remote) - { - r = print_in_addr_t (tt->local, 0, gc); - l = print_in_addr_t (tt->remote_netmask, 0, gc); - } - else - { - l = print_in_addr_t (tt->local, 0, gc); - r = print_in_addr_t (tt->remote_netmask, 0, gc); - } - buf_printf (&out, "%s %s", r, l); - } - else if (tt->type == DEV_TYPE_TAP) - { - buf_printf (&out, "%s %s", - print_in_addr_t (tt->local & tt->remote_netmask, 0, gc), - print_in_addr_t (tt->remote_netmask, 0, gc)); - } - else - buf_printf (&out, "[undef]"); - } - return BSTR (&out); -} - -/* - * Return a status string describing wait state. - */ -const char * -tun_stat (const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc) -{ - struct buffer out = alloc_buf_gc (64, gc); - if (tt) - { - if (rwflags & EVENT_READ) - { - buf_printf (&out, "T%s", - (tt->rwflags_debug & EVENT_READ) ? "R" : "r"); -#ifdef WIN32 - buf_printf (&out, "%s", - overlapped_io_state_ascii (&tt->reads)); -#endif - } - if (rwflags & EVENT_WRITE) - { - buf_printf (&out, "T%s", - (tt->rwflags_debug & EVENT_WRITE) ? "W" : "w"); -#ifdef WIN32 - buf_printf (&out, "%s", - overlapped_io_state_ascii (&tt->writes)); -#endif - } - } - else - { - buf_printf (&out, "T?"); - } - return BSTR (&out); -} - -/* - * Init tun/tap object. - * - * Set up tuntap structure for ifconfig, - * but don't execute yet. - */ -struct tuntap * -init_tun (const char *dev, /* --dev option */ - const char *dev_type, /* --dev-type option */ - const char *ifconfig_local_parm, /* --ifconfig parm 1 */ - const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */ - in_addr_t local_public, - in_addr_t remote_public, - const bool strict_warn, - struct env_set *es) -{ - struct gc_arena gc = gc_new (); - struct tuntap *tt; - - ALLOC_OBJ (tt, struct tuntap); - clear_tuntap (tt); - - tt->type = dev_type_enum (dev, dev_type); - - if (ifconfig_local_parm && ifconfig_remote_netmask_parm) - { - bool tun = false; - const char *ifconfig_local = NULL; - const char *ifconfig_remote_netmask = NULL; - const char *ifconfig_broadcast = NULL; - - /* - * We only handle TUN/TAP devices here, not --dev null devices. - */ - if (tt->type == DEV_TYPE_TUN) - tun = true; - else if (tt->type == DEV_TYPE_TAP) - tun = false; - else - msg (M_FATAL, "'%s' is not a TUN/TAP device. The --ifconfig option works only for TUN/TAP devices.", dev); - - /* - * Convert arguments to binary IPv4 addresses. - */ - - tt->local = getaddr ( - GETADDR_RESOLVE - | GETADDR_HOST_ORDER - | GETADDR_FATAL_ON_SIGNAL - | GETADDR_FATAL, - ifconfig_local_parm, - 0, - NULL, - NULL); - - tt->remote_netmask = getaddr ( - (tun ? GETADDR_RESOLVE : 0) - | GETADDR_HOST_ORDER - | GETADDR_FATAL_ON_SIGNAL - | GETADDR_FATAL, - ifconfig_remote_netmask_parm, - 0, - NULL, - NULL); - - /* - * Look for common errors in --ifconfig parms - */ - if (strict_warn) - { - ifconfig_sanity_check (tun, tt->remote_netmask); - - /* - * If local_public or remote_public addresses are defined, - * make sure they do not clash with our virtual subnet. - */ - - check_addr_clash ("local", - tt->type, - local_public, - tt->local, - tt->remote_netmask); - - check_addr_clash ("remote", - tt->type, - remote_public, - tt->local, - tt->remote_netmask); - } - - /* - * Set ifconfig parameters - */ - ifconfig_local = print_in_addr_t (tt->local, 0, &gc); - ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc); - - /* - * If TAP-style interface, generate broadcast address. - */ - if (!tun) - { - tt->broadcast = generate_ifconfig_broadcast_addr (tt->local, tt->remote_netmask); - ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc); - } - - /* - * Set environmental variables with ifconfig parameters. - */ - if (es) - { - setenv_str (es, "ifconfig_local", ifconfig_local); - if (tun) - { - setenv_str (es, "ifconfig_remote", ifconfig_remote_netmask); - } - else - { - setenv_str (es, "ifconfig_netmask", ifconfig_remote_netmask); - setenv_str (es, "ifconfig_broadcast", ifconfig_broadcast); - } - } - - tt->did_ifconfig_setup = true; - } - gc_free (&gc); - return tt; -} - -/* - * Platform specific tun initializations - */ -void -init_tun_post (struct tuntap *tt, - const struct frame *frame, - const struct tuntap_options *options) -{ - tt->options = *options; -#ifdef WIN32 - overlapped_io_init (&tt->reads, frame, FALSE, true); - overlapped_io_init (&tt->writes, frame, TRUE, true); - tt->rw_handle.read = tt->reads.overlapped.hEvent; - tt->rw_handle.write = tt->writes.overlapped.hEvent; - tt->adapter_index = ~0; -#endif -} - -/* execute the ifconfig command through the shell */ -void -do_ifconfig (struct tuntap *tt, - const char *actual, /* actual device name */ - int tun_mtu, - const struct env_set *es) -{ - struct gc_arena gc = gc_new (); - - if (tt->did_ifconfig_setup) - { - bool tun = false; - const char *ifconfig_local = NULL; - const char *ifconfig_remote_netmask = NULL; - const char *ifconfig_broadcast = NULL; - char command_line[256]; - - /* - * We only handle TUN/TAP devices here, not --dev null devices. - */ - if (tt->type == DEV_TYPE_TUN) - tun = true; - else if (tt->type == DEV_TYPE_TAP) - tun = false; - else - ASSERT (0); /* should have been caught in init_tun */ - - /* - * Set ifconfig parameters - */ - ifconfig_local = print_in_addr_t (tt->local, 0, &gc); - ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc); - - /* - * If TAP-style device, generate broadcast address. - */ - if (!tun) - ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc); - -#ifdef ENABLE_MANAGEMENT - if (management) - { - management_set_state (management, - OPENVPN_STATE_ASSIGN_IP, - NULL, - tt->local); - } -#endif - - -#if defined(TARGET_LINUX) -#ifdef CONFIG_FEATURE_IPROUTE - /* - * Set the MTU for the device - */ - openvpn_snprintf (command_line, sizeof (command_line), - IPROUTE_PATH " link set dev %s up mtu %d", - actual, - tun_mtu - ); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "Linux ip link set failed"); - - if (tun) { - - /* - * Set the address for the device - */ - openvpn_snprintf (command_line, sizeof (command_line), - IPROUTE_PATH " addr add dev %s local %s peer %s", - actual, - ifconfig_local, - ifconfig_remote_netmask - ); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "Linux ip addr add failed"); - } else { - openvpn_snprintf (command_line, sizeof (command_line), - IPROUTE_PATH " addr add dev %s %s/%d broadcast %s", - actual, - ifconfig_local, - count_netmask_bits(ifconfig_remote_netmask), - ifconfig_broadcast - ); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "Linux ip addr add failed"); - } - tt->did_ifconfig = true; -#else - if (tun) - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s pointopoint %s mtu %d", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - else - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu, - ifconfig_broadcast - ); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "Linux ifconfig failed"); - tt->did_ifconfig = true; - -#endif /*CONFIG_FEATURE_IPROUTE*/ -#elif defined(TARGET_SOLARIS) - - /* Solaris 2.6 (and 7?) cannot set all parameters in one go... - * example: - * ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 up - * ifconfig tun2 netmask 255.255.255.255 - */ - if (tun) - { - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s %s mtu %d up", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - - msg (M_INFO, "%s", command_line); - if (!system_check (command_line, es, 0, "Solaris ifconfig phase-1 failed")) - solaris_error_close (tt, es, actual); - - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s netmask 255.255.255.255", - actual - ); - } - else - no_tap_ifconfig (); - - msg (M_INFO, "%s", command_line); - if (!system_check (command_line, es, 0, "Solaris ifconfig phase-2 failed")) - solaris_error_close (tt, es, actual); - - tt->did_ifconfig = true; - -#elif defined(TARGET_OPENBSD) - - /* - * OpenBSD tun devices appear to be persistent by default. It seems in order - * to make this work correctly, we need to delete the previous instance - * (if it exists), and re-ifconfig. Let me know if you know a better way. - */ - - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s destroy", - actual); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, 0, NULL); - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s create", - actual); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, 0, NULL); - msg (M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure"); - - /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ - if (tun) - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - else - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s link0", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu, - ifconfig_broadcast - ); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "OpenBSD ifconfig failed"); - tt->did_ifconfig = true; - -#elif defined(TARGET_NETBSD) - - if (tun) - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - else - /* - * NetBSD has distinct tun and tap devices - * so we don't need the "link0" extra parameter to specify we want to do - * tunneling at the ethernet level - */ - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu, - ifconfig_broadcast - ); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "NetBSD ifconfig failed"); - tt->did_ifconfig = true; - -#elif defined(TARGET_DARWIN) - - /* - * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD... - */ - - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s delete", - actual); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, 0, NULL); - msg (M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure"); - - - /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ - if (tun) - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - else - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s netmask %s mtu %d up", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "Mac OS X ifconfig failed"); - tt->did_ifconfig = true; - -#elif defined(TARGET_FREEBSD) - - /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ - if (tun) - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - else - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s %s netmask %s mtu %d up", - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "FreeBSD ifconfig failed"); - tt->did_ifconfig = true; - -#elif defined (WIN32) - { - const char *netmask; - - /* - * Make sure that both ifconfig addresses are part of the - * same .252 subnet. - */ - if (tun) - { - verify_255_255_255_252 (tt->local, tt->remote_netmask); - tt->adapter_netmask = ~3; - netmask = print_in_addr_t (tt->adapter_netmask, 0, &gc); - } - else - { - netmask = ifconfig_remote_netmask; - tt->adapter_netmask = tt->remote_netmask; - } - - /* example: netsh interface ip set address my-tap static 10.3.0.1 255.255.255.0 */ - openvpn_snprintf (command_line, sizeof (command_line), - "netsh interface ip set address \"%s\" static %s %s", - actual, - ifconfig_local, - netmask); - - switch (tt->options.ip_win32_type) - { - case IPW32_SET_MANUAL: - msg (M_INFO, "******** NOTE: Please manually set the IP/netmask of '%s' to %s/%s (if it is not already set)", - actual, - ifconfig_local, - netmask); - break; - case IPW32_SET_NETSH: - if (!strcmp (actual, "NULL")) - msg (M_FATAL, "Error: When using --ip-win32 netsh, if you have more than one TAP-Win32 adapter, you must also specify --dev-node"); - netcmd_semaphore_lock (); - msg (M_INFO, "%s", command_line); - system_check (command_line, es, S_FATAL, "ERROR: netsh command failed"); - netcmd_semaphore_release (); - break; - } - tt->did_ifconfig = true; - } - -#else - msg (M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script."); -#endif - } - gc_free (&gc); -} - -void -clear_tuntap (struct tuntap *tuntap) -{ - CLEAR (*tuntap); -#ifdef WIN32 - tuntap->hand = NULL; -#else - tuntap->fd = -1; -#endif -#ifdef TARGET_SOLARIS - tuntap->ip_fd = -1; -#endif - tuntap->ipv6 = false; -} - -static void -open_null (struct tuntap *tt) -{ - tt->actual_name = string_alloc ("null", NULL); -} - -#ifndef WIN32 -static void -open_tun_generic (const char *dev, const char *dev_type, const char *dev_node, - bool ipv6, bool ipv6_explicitly_supported, bool dynamic, - struct tuntap *tt) -{ - char tunname[256]; - char dynamic_name[256]; - bool dynamic_opened = false; - - ipv6_support (ipv6, ipv6_explicitly_supported, tt); - - if (tt->type == DEV_TYPE_NULL) - { - open_null (tt); - } - else - { - /* - * --dev-node specified, so open an explicit device node - */ - if (dev_node) - { - openvpn_snprintf (tunname, sizeof (tunname), "%s", dev_node); - } - else - { - /* - * dynamic open is indicated by --dev specified without - * explicit unit number. Try opening /dev/[dev]n - * where n = [0, 255]. - */ - if (dynamic && !has_digit(dev)) - { - int i; - for (i = 0; i < 256; ++i) - { - openvpn_snprintf (tunname, sizeof (tunname), - "/dev/%s%d", dev, i); - openvpn_snprintf (dynamic_name, sizeof (dynamic_name), - "%s%d", dev, i); - if ((tt->fd = open (tunname, O_RDWR)) > 0) - { - dynamic_opened = true; - break; - } - msg (D_READ_WRITE | M_ERRNO, "Tried opening %s (failed)", tunname); - } - if (!dynamic_opened) - msg (M_FATAL, "Cannot allocate TUN/TAP dev dynamically"); - } - /* - * explicit unit number specified - */ - else - { - openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s", dev); - } - } - - if (!dynamic_opened) - { - if ((tt->fd = open (tunname, O_RDWR)) < 0) - msg (M_ERR, "Cannot open TUN/TAP dev %s", tunname); - } - - set_nonblock (tt->fd); - set_cloexec (tt->fd); /* don't pass fd to scripts */ - msg (M_INFO, "TUN/TAP device %s opened", tunname); - - /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */ - tt->actual_name = string_alloc (dynamic_opened ? dynamic_name : dev, NULL); - } -} - -static void -close_tun_generic (struct tuntap *tt) -{ - if (tt->fd >= 0) - close (tt->fd); - if (tt->actual_name) - free (tt->actual_name); - clear_tuntap (tt); -} - -#endif - -#if defined(TARGET_LINUX) - -#ifdef HAVE_LINUX_IF_TUN_H /* New driver support */ - -#ifndef HAVE_LINUX_SOCKIOS_H -#error header file linux/sockios.h required -#endif - -#if defined(HAVE_TUN_PI) && defined(HAVE_IPHDR) && defined(HAVE_IOVEC) && defined(ETH_P_IPV6) && defined(ETH_P_IP) && defined(HAVE_READV) && defined(HAVE_WRITEV) -#define LINUX_IPV6 1 -/* #warning IPv6 ON */ -#else -#define LINUX_IPV6 0 -/* #warning IPv6 OFF */ -#endif - -#if !PEDANTIC - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - struct ifreq ifr; - - /* - * Set tt->ipv6 to true if - * (a) we have the capability of supporting --tun-ipv6, and - * (b) --tun-ipv6 was specified. - */ - ipv6_support (ipv6, LINUX_IPV6, tt); - - /* - * We handle --dev null specially, we do not open /dev/null for this. - */ - if (tt->type == DEV_TYPE_NULL) - { - open_null (tt); - } - else - { - /* - * Process --dev-node - */ - const char *node = dev_node; - if (!node) - node = "/dev/net/tun"; - - /* - * Open the interface - */ - if ((tt->fd = open (node, O_RDWR)) < 0) - { - msg (M_WARN | M_ERRNO, "Note: Cannot open TUN/TAP dev %s", node); - goto linux_2_2_fallback; - } - - /* - * Process --tun-ipv6 - */ - CLEAR (ifr); - if (!tt->ipv6) - ifr.ifr_flags = IFF_NO_PI; - -#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) - ifr.ifr_flags |= IFF_ONE_QUEUE; -#endif - - /* - * Figure out if tun or tap device - */ - if (tt->type == DEV_TYPE_TUN) - { - ifr.ifr_flags |= IFF_TUN; - } - else if (tt->type == DEV_TYPE_TAP) - { - ifr.ifr_flags |= IFF_TAP; - } - else - { - msg (M_FATAL, "I don't recognize device %s as a tun or tap device", - dev); - } - - /* - * Set an explicit name, if --dev is not tun or tap - */ - if (strcmp(dev, "tun") && strcmp(dev, "tap")) - strncpynt (ifr.ifr_name, dev, IFNAMSIZ); - - /* - * Use special ioctl that configures tun/tap device with the parms - * we set in ifr - */ - if (ioctl (tt->fd, TUNSETIFF, (void *) &ifr) < 0) - { - msg (M_WARN | M_ERRNO, "Note: Cannot ioctl TUNSETIFF %s", dev); - goto linux_2_2_fallback; - } - - msg (M_INFO, "TUN/TAP device %s opened", ifr.ifr_name); - - /* - * Try making the TX send queue bigger - */ -#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) - { - struct ifreq netifr; - int ctl_fd; - - if ((ctl_fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0) - { - CLEAR (netifr); - strncpynt (netifr.ifr_name, ifr.ifr_name, IFNAMSIZ); - netifr.ifr_qlen = tt->options.txqueuelen; - if (ioctl (ctl_fd, SIOCSIFTXQLEN, (void *) &netifr) >= 0) - msg (D_OSBUF, "TUN/TAP TX queue length set to %d", tt->options.txqueuelen); - else - msg (M_WARN | M_ERRNO, "Note: Cannot set tx queue length on %s", ifr.ifr_name); - close (ctl_fd); - } - else - { - msg (M_WARN | M_ERRNO, "Note: Cannot open control socket on %s", ifr.ifr_name); - } - } -#endif - - set_nonblock (tt->fd); - set_cloexec (tt->fd); - tt->actual_name = string_alloc (ifr.ifr_name, NULL); - } - return; - - linux_2_2_fallback: - msg (M_INFO, "Note: Attempting fallback to kernel 2.2 TUN/TAP interface"); - if (tt->fd >= 0) - { - close (tt->fd); - tt->fd = -1; - } - open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt); -} - -#else - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - ASSERT (0); -} - -#endif - -#else - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt); -} - -#endif /* HAVE_LINUX_IF_TUN_H */ - -#ifdef TUNSETPERSIST - -void -tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode) -{ - struct tuntap *tt; - - ALLOC_OBJ (tt, struct tuntap); - clear_tuntap (tt); - tt->type = dev_type_enum (dev, dev_type); - open_tun (dev, dev_type, dev_node, ipv6, tt); - if (ioctl (tt->fd, TUNSETPERSIST, persist_mode) < 0) - msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev); - close_tun (tt); - msg (M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF")); -} - -#endif /* TUNSETPERSIST */ - -void -close_tun (struct tuntap *tt) -{ - if (tt) - { - close_tun_generic (tt); - free (tt); - } -} - -int -write_tun (struct tuntap* tt, uint8_t *buf, int len) -{ -#if LINUX_IPV6 - if (tt->ipv6) - { - struct tun_pi pi; - struct iphdr *iph; - struct iovec vect[2]; - int ret; - - iph = (struct iphdr *)buf; - - pi.flags = 0; - - if(iph->version == 6) - pi.proto = htons(ETH_P_IPV6); - else - pi.proto = htons(ETH_P_IP); - - vect[0].iov_len = sizeof(pi); - vect[0].iov_base = π - vect[1].iov_len = len; - vect[1].iov_base = buf; - - ret = writev(tt->fd, vect, 2); - return(ret - sizeof(pi)); - } - else -#endif - return write (tt->fd, buf, len); -} - -int -read_tun (struct tuntap* tt, uint8_t *buf, int len) -{ -#if LINUX_IPV6 - if (tt->ipv6) - { - struct iovec vect[2]; - struct tun_pi pi; - int ret; - - vect[0].iov_len = sizeof(pi); - vect[0].iov_base = π - vect[1].iov_len = len; - vect[1].iov_base = buf; - - ret = readv(tt->fd, vect, 2); - return(ret - sizeof(pi)); - } - else -#endif - return read (tt->fd, buf, len); -} - -#elif defined(TARGET_SOLARIS) - -#ifndef TUNNEWPPA -#error I need the symbol TUNNEWPPA from net/if_tun.h -#endif - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - int if_fd, muxid, ppa = -1; - struct ifreq ifr; - const char *ptr; - const char *ip_node; - const char *dev_tuntap_type; - int link_type; - bool is_tun; - - ipv6_support (ipv6, false, tt); - - if (tt->type == DEV_TYPE_NULL) - { - open_null (tt); - return; - } - - if (tt->type == DEV_TYPE_TUN) - { - ip_node = "/dev/udp"; - if (!dev_node) - dev_node = "/dev/tun"; - dev_tuntap_type = "tun"; - link_type = I_PLINK; - is_tun = true; - } - else if (tt->type == DEV_TYPE_TAP) - { - ip_node = "/dev/ip"; - if (!dev_node) - dev_node = "/dev/tap"; - dev_tuntap_type = "tap"; - link_type = I_PLINK; /* was: I_LINK */ - is_tun = false; - } - else - { - msg (M_FATAL, "I don't recognize device %s as a tun or tap device", - dev); - } - - /* get unit number */ - if (*dev) - { - ptr = dev; - while (*ptr && !isdigit ((int) *ptr)) - ptr++; - ppa = atoi (ptr); - } - - if ((tt->ip_fd = open (ip_node, O_RDWR, 0)) < 0) - msg (M_ERR, "Can't open %s", ip_node); - - if ((tt->fd = open (dev_node, O_RDWR, 0)) < 0) - msg (M_ERR, "Can't open %s", dev_node); - - /* Assign a new PPA and get its unit number. */ - if ((ppa = ioctl (tt->fd, TUNNEWPPA, ppa)) < 0) - msg (M_ERR, "Can't assign new interface"); - - if ((if_fd = open (dev_node, O_RDWR, 0)) < 0) - msg (M_ERR, "Can't open %s (2)", dev_node); - - if (ioctl (if_fd, I_PUSH, "ip") < 0) - msg (M_ERR, "Can't push IP module"); - - /* Assign ppa according to the unit number returned by tun device */ - if (ioctl (if_fd, IF_UNITSEL, (char *) &ppa) < 0) - msg (M_ERR, "Can't set PPA %d", ppa); - - if ((muxid = ioctl (tt->ip_fd, link_type, if_fd)) < 0) - msg (M_ERR, "Can't link %s device to IP", dev_tuntap_type); - - close (if_fd); - - tt->actual_name = (char *) malloc (32); - check_malloc_return (tt->actual_name); - - openvpn_snprintf (tt->actual_name, 32, "%s%d", dev_tuntap_type, ppa); - - CLEAR (ifr); - strncpynt (ifr.ifr_name, tt->actual_name, sizeof (ifr.ifr_name)); - ifr.ifr_ip_muxid = muxid; - - if (ioctl (tt->ip_fd, SIOCSIFMUXID, &ifr) < 0) - { - ioctl (tt->ip_fd, I_PUNLINK, muxid); - msg (M_ERR, "Can't set multiplexor id"); - } - - set_nonblock (tt->fd); - set_cloexec (tt->fd); - set_cloexec (tt->ip_fd); - - msg (M_INFO, "TUN/TAP device %s opened", tt->actual_name); -} - -static void -solaris_close_tun (struct tuntap *tt) -{ - if (tt) - { - if (tt->ip_fd >= 0) - { - struct ifreq ifr; - CLEAR (ifr); - strncpynt (ifr.ifr_name, tt->actual_name, sizeof (ifr.ifr_name)); - - if (ioctl (tt->ip_fd, SIOCGIFFLAGS, &ifr) < 0) - msg (M_WARN | M_ERRNO, "Can't get iface flags"); - - if (ioctl (tt->ip_fd, SIOCGIFMUXID, &ifr) < 0) - msg (M_WARN | M_ERRNO, "Can't get multiplexor id"); - - if (ioctl (tt->ip_fd, I_PUNLINK, ifr.ifr_ip_muxid) < 0) - msg (M_WARN | M_ERRNO, "Can't unlink interface"); - - close (tt->ip_fd); - tt->ip_fd = -1; - } - - if (tt->fd >= 0) - { - close (tt->fd); - tt->fd = -1; - } - } -} - -/* - * Close TUN device. - */ -void -close_tun (struct tuntap *tt) -{ - if (tt) - { - solaris_close_tun (tt); - - if (tt->actual_name) - free (tt->actual_name); - - clear_tuntap (tt); - free (tt); - } -} - -static void -solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual) -{ - char command_line[256]; - - openvpn_snprintf (command_line, sizeof (command_line), - IFCONFIG_PATH " %s unplumb", - actual); - - msg (M_INFO, "%s", command_line); - system_check (command_line, es, 0, "Solaris ifconfig unplumb failed"); - close_tun (tt); - msg (M_FATAL, "Solaris ifconfig failed"); -} - -int -write_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - struct strbuf sbuf; - sbuf.len = len; - sbuf.buf = (char *)buf; - return putmsg (tt->fd, NULL, &sbuf, 0) >= 0 ? sbuf.len : -1; -} - -int -read_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - struct strbuf sbuf; - int f = 0; - - sbuf.maxlen = len; - sbuf.buf = (char *)buf; - return getmsg (tt->fd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1; -} - -#elif defined(TARGET_OPENBSD) - -#if !defined(HAVE_READV) || !defined(HAVE_WRITEV) -#error openbsd build requires readv & writev library functions -#endif - -/* - * OpenBSD has a slightly incompatible TUN device from - * the rest of the world, in that it prepends a - * uint32 to the beginning of the IP header - * to designate the protocol (why not just - * look at the version field in the IP header to - * determine v4 or v6?). - * - * We strip off this field on reads and - * put it back on writes. - * - * I have not tested TAP devices on OpenBSD, - * but I have conditionalized the special - * TUN handling code described above to - * go away for TAP devices. - */ - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt); - - /* Enable multicast on the interface */ - if (tt->fd >= 0) - { - struct tuninfo info; - - if (ioctl (tt->fd, TUNGIFINFO, &info) < 0) { - msg (M_WARN | M_ERRNO, "Can't get interface info: %s", - strerror(errno)); - } - - info.flags |= IFF_MULTICAST; - - if (ioctl (tt->fd, TUNSIFINFO, &info) < 0) { - msg (M_WARN | M_ERRNO, "Can't set interface info: %s", - strerror(errno)); - } - } -} - -void -close_tun (struct tuntap* tt) -{ - if (tt) - { - close_tun_generic (tt); - free (tt); - } -} - -static inline int -openbsd_modify_read_write_return (int len) -{ - if (len > 0) - return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; - else - return len; -} - -int -write_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - if (tt->type == DEV_TYPE_TUN) - { - u_int32_t type; - struct iovec iv[2]; - struct ip *iph; - - iph = (struct ip *) buf; - - if (tt->ipv6 && iph->ip_v == 6) - type = htonl (AF_INET6); - else - type = htonl (AF_INET); - - iv[0].iov_base = &type; - iv[0].iov_len = sizeof (type); - iv[1].iov_base = buf; - iv[1].iov_len = len; - - return openbsd_modify_read_write_return (writev (tt->fd, iv, 2)); - } - else - return write (tt->fd, buf, len); -} - -int -read_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - if (tt->type == DEV_TYPE_TUN) - { - u_int32_t type; - struct iovec iv[2]; - - iv[0].iov_base = &type; - iv[0].iov_len = sizeof (type); - iv[1].iov_base = buf; - iv[1].iov_len = len; - - return openbsd_modify_read_write_return (readv (tt->fd, iv, 2)); - } - else - return read (tt->fd, buf, len); -} - -#elif defined(TARGET_NETBSD) - -/* - * NetBSD does not support IPv6 on tun out of the box, - * but there exists a patch. When this patch is applied, - * only two things are left to openvpn: - * 1. Activate multicasting (this has already been done - * before by the kernel, but we make sure that nobody - * has deactivated multicasting inbetween. - * 2. Deactivate "link layer mode" (otherwise NetBSD - * prepends the address family to the packet, and we - * would run into the same trouble as with OpenBSD. - */ - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt); - if (tt->fd >= 0) - { - int i = IFF_POINTOPOINT|IFF_MULTICAST; - ioctl (tt->fd, TUNSIFMODE, &i); /* multicast on */ - i = 0; - ioctl (tt->fd, TUNSLMODE, &i); /* link layer mode off */ - } -} - -void -close_tun (struct tuntap *tt) -{ - if (tt) - { - close_tun_generic (tt); - free (tt); - } -} - -int -write_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - return write (tt->fd, buf, len); -} - -int -read_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - return read (tt->fd, buf, len); -} - -#elif defined(TARGET_FREEBSD) - -static inline int -freebsd_modify_read_write_return (int len) -{ - if (len > 0) - return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; - else - return len; -} - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt); - - if (tt->fd >= 0) - { - int i = 0; - - /* Disable extended modes */ - ioctl (tt->fd, TUNSLMODE, &i); - i = 1; - ioctl (tt->fd, TUNSIFHEAD, &i); - } -} - -void -close_tun (struct tuntap *tt) -{ - if (tt) - { - close_tun_generic (tt); - free (tt); - } -} - -int -write_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - if (tt->type == DEV_TYPE_TUN) - { - u_int32_t type; - struct iovec iv[2]; - struct ip *iph; - - iph = (struct ip *) buf; - - if (tt->ipv6 && iph->ip_v == 6) - type = htonl (AF_INET6); - else - type = htonl (AF_INET); - - iv[0].iov_base = (char *)&type; - iv[0].iov_len = sizeof (type); - iv[1].iov_base = buf; - iv[1].iov_len = len; - - return freebsd_modify_read_write_return (writev (tt->fd, iv, 2)); - } - else - return write (tt->fd, buf, len); -} - -int -read_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - if (tt->type == DEV_TYPE_TUN) - { - u_int32_t type; - struct iovec iv[2]; - - iv[0].iov_base = (char *)&type; - iv[0].iov_len = sizeof (type); - iv[1].iov_base = buf; - iv[1].iov_len = len; - - return freebsd_modify_read_write_return (readv (tt->fd, iv, 2)); - } - else - return read (tt->fd, buf, len); -} - -#elif defined(WIN32) - -int -tun_read_queue (struct tuntap *tt, int maxsize) -{ - if (tt->reads.iostate == IOSTATE_INITIAL) - { - DWORD len; - BOOL status; - int err; - - /* reset buf to its initial state */ - tt->reads.buf = tt->reads.buf_init; - - len = maxsize ? maxsize : BLEN (&tt->reads.buf); - ASSERT (len <= BLEN (&tt->reads.buf)); - - /* the overlapped read will signal this event on I/O completion */ - ASSERT (ResetEvent (tt->reads.overlapped.hEvent)); - - status = ReadFile( - tt->hand, - BPTR (&tt->reads.buf), - len, - &tt->reads.size, - &tt->reads.overlapped - ); - - if (status) /* operation completed immediately? */ - { - /* since we got an immediate return, we must signal the event object ourselves */ - ASSERT (SetEvent (tt->reads.overlapped.hEvent)); - - tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN; - tt->reads.status = 0; - - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read immediate return [%d,%d]", - (int) len, - (int) tt->reads.size); - } - else - { - err = GetLastError (); - if (err == ERROR_IO_PENDING) /* operation queued? */ - { - tt->reads.iostate = IOSTATE_QUEUED; - tt->reads.status = err; - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read queued [%d]", - (int) len); - } - else /* error occurred */ - { - struct gc_arena gc = gc_new (); - ASSERT (SetEvent (tt->reads.overlapped.hEvent)); - tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN; - tt->reads.status = err; - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read error [%d] : %s", - (int) len, - strerror_win32 (status, &gc)); - gc_free (&gc); - } - } - } - return tt->reads.iostate; -} - -int -tun_write_queue (struct tuntap *tt, struct buffer *buf) -{ - if (tt->writes.iostate == IOSTATE_INITIAL) - { - BOOL status; - int err; - - /* make a private copy of buf */ - tt->writes.buf = tt->writes.buf_init; - tt->writes.buf.len = 0; - ASSERT (buf_copy (&tt->writes.buf, buf)); - - /* the overlapped write will signal this event on I/O completion */ - ASSERT (ResetEvent (tt->writes.overlapped.hEvent)); - - status = WriteFile( - tt->hand, - BPTR (&tt->writes.buf), - BLEN (&tt->writes.buf), - &tt->writes.size, - &tt->writes.overlapped - ); - - if (status) /* operation completed immediately? */ - { - tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN; - - /* since we got an immediate return, we must signal the event object ourselves */ - ASSERT (SetEvent (tt->writes.overlapped.hEvent)); - - tt->writes.status = 0; - - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write immediate return [%d,%d]", - BLEN (&tt->writes.buf), - (int) tt->writes.size); - } - else - { - err = GetLastError (); - if (err == ERROR_IO_PENDING) /* operation queued? */ - { - tt->writes.iostate = IOSTATE_QUEUED; - tt->writes.status = err; - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write queued [%d]", - BLEN (&tt->writes.buf)); - } - else /* error occurred */ - { - struct gc_arena gc = gc_new (); - ASSERT (SetEvent (tt->writes.overlapped.hEvent)); - tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN; - tt->writes.status = err; - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write error [%d] : %s", - BLEN (&tt->writes.buf), - strerror_win32 (err, &gc)); - gc_free (&gc); - } - } - } - return tt->writes.iostate; -} - -int -tun_finalize ( - HANDLE h, - struct overlapped_io *io, - struct buffer *buf) -{ - int ret = -1; - BOOL status; - - switch (io->iostate) - { - case IOSTATE_QUEUED: - status = GetOverlappedResult( - h, - &io->overlapped, - &io->size, - FALSE - ); - if (status) - { - /* successful return for a queued operation */ - if (buf) - *buf = io->buf; - ret = io->size; - io->iostate = IOSTATE_INITIAL; - ASSERT (ResetEvent (io->overlapped.hEvent)); - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion success [%d]", ret); - } - else - { - /* error during a queued operation */ - ret = -1; - if (GetLastError() != ERROR_IO_INCOMPLETE) - { - /* if no error (i.e. just not finished yet), - then DON'T execute this code */ - io->iostate = IOSTATE_INITIAL; - ASSERT (ResetEvent (io->overlapped.hEvent)); - msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion error"); - } - } - break; - - case IOSTATE_IMMEDIATE_RETURN: - io->iostate = IOSTATE_INITIAL; - ASSERT (ResetEvent (io->overlapped.hEvent)); - if (io->status) - { - /* error return for a non-queued operation */ - SetLastError (io->status); - ret = -1; - msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion non-queued error"); - } - else - { - /* successful return for a non-queued operation */ - if (buf) - *buf = io->buf; - ret = io->size; - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion non-queued success [%d]", ret); - } - break; - - case IOSTATE_INITIAL: /* were we called without proper queueing? */ - SetLastError (ERROR_INVALID_FUNCTION); - ret = -1; - dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion BAD STATE"); - break; - - default: - ASSERT (0); - } - - if (buf) - buf->len = ret; - return ret; -} - -const struct tap_reg * -get_tap_reg (struct gc_arena *gc) -{ - HKEY adapter_key; - LONG status; - DWORD len; - struct tap_reg *first = NULL; - struct tap_reg *last = NULL; - int i = 0; - - status = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - ADAPTER_KEY, - 0, - KEY_READ, - &adapter_key); - - if (status != ERROR_SUCCESS) - msg (M_FATAL, "Error opening registry key: %s", ADAPTER_KEY); - - while (true) - { - char enum_name[256]; - char unit_string[256]; - HKEY unit_key; - char component_id_string[] = "ComponentId"; - char component_id[256]; - char net_cfg_instance_id_string[] = "NetCfgInstanceId"; - char net_cfg_instance_id[256]; - DWORD data_type; - - len = sizeof (enum_name); - status = RegEnumKeyEx( - adapter_key, - i, - enum_name, - &len, - NULL, - NULL, - NULL, - NULL); - if (status == ERROR_NO_MORE_ITEMS) - break; - else if (status != ERROR_SUCCESS) - msg (M_FATAL, "Error enumerating registry subkeys of key: %s", - ADAPTER_KEY); - - openvpn_snprintf (unit_string, sizeof(unit_string), "%s\\%s", - ADAPTER_KEY, enum_name); - - status = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - unit_string, - 0, - KEY_READ, - &unit_key); - - if (status != ERROR_SUCCESS) - dmsg (D_REGISTRY, "Error opening registry key: %s", unit_string); - else - { - len = sizeof (component_id); - status = RegQueryValueEx( - unit_key, - component_id_string, - NULL, - &data_type, - component_id, - &len); - - if (status != ERROR_SUCCESS || data_type != REG_SZ) - dmsg (D_REGISTRY, "Error opening registry key: %s\\%s", - unit_string, component_id_string); - else - { - len = sizeof (net_cfg_instance_id); - status = RegQueryValueEx( - unit_key, - net_cfg_instance_id_string, - NULL, - &data_type, - net_cfg_instance_id, - &len); - - if (status == ERROR_SUCCESS && data_type == REG_SZ) - { - if (!strcmp (component_id, TAP_COMPONENT_ID)) - { - struct tap_reg *reg; - ALLOC_OBJ_CLEAR_GC (reg, struct tap_reg, gc); - reg->guid = string_alloc (net_cfg_instance_id, gc); - - /* link into return list */ - if (!first) - first = reg; - if (last) - last->next = reg; - last = reg; - } - } - } - RegCloseKey (unit_key); - } - ++i; - } - - RegCloseKey (adapter_key); - return first; -} - -const struct panel_reg * -get_panel_reg (struct gc_arena *gc) -{ - LONG status; - HKEY network_connections_key; - DWORD len; - struct panel_reg *first = NULL; - struct panel_reg *last = NULL; - int i = 0; - - status = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - NETWORK_CONNECTIONS_KEY, - 0, - KEY_READ, - &network_connections_key); - - if (status != ERROR_SUCCESS) - msg (M_FATAL, "Error opening registry key: %s", NETWORK_CONNECTIONS_KEY); - - while (true) - { - char enum_name[256]; - char connection_string[256]; - HKEY connection_key; - char name_data[256]; - DWORD name_type; - const char name_string[] = "Name"; - - len = sizeof (enum_name); - status = RegEnumKeyEx( - network_connections_key, - i, - enum_name, - &len, - NULL, - NULL, - NULL, - NULL); - if (status == ERROR_NO_MORE_ITEMS) - break; - else if (status != ERROR_SUCCESS) - msg (M_FATAL, "Error enumerating registry subkeys of key: %s", - NETWORK_CONNECTIONS_KEY); - - openvpn_snprintf (connection_string, sizeof(connection_string), - "%s\\%s\\Connection", - NETWORK_CONNECTIONS_KEY, enum_name); - - status = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - connection_string, - 0, - KEY_READ, - &connection_key); - - if (status != ERROR_SUCCESS) - dmsg (D_REGISTRY, "Error opening registry key: %s", connection_string); - else - { - len = sizeof (name_data); - status = RegQueryValueEx( - connection_key, - name_string, - NULL, - &name_type, - name_data, - &len); - - if (status != ERROR_SUCCESS || name_type != REG_SZ) - dmsg (D_REGISTRY, "Error opening registry key: %s\\%s\\%s", - NETWORK_CONNECTIONS_KEY, connection_string, name_string); - else - { - struct panel_reg *reg; - - ALLOC_OBJ_CLEAR_GC (reg, struct panel_reg, gc); - reg->name = string_alloc (name_data, gc); - reg->guid = string_alloc (enum_name, gc); - - /* link into return list */ - if (!first) - first = reg; - if (last) - last->next = reg; - last = reg; - } - RegCloseKey (connection_key); - } - ++i; - } - - RegCloseKey (network_connections_key); - - return first; -} - -/* - * Check that two addresses are part of the same 255.255.255.252 subnet. - */ -void -verify_255_255_255_252 (in_addr_t local, in_addr_t remote) -{ - struct gc_arena gc = gc_new (); - const unsigned int mask = 3; - const char *err = NULL; - - if (local == remote) - { - err = "must be different"; - goto error; - } - if ((local & (~mask)) != (remote & (~mask))) - { - err = "must exist within the same 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver"; - goto error; - } - if ((local & mask) == 0 - || (local & mask) == 3 - || (remote & mask) == 0 - || (remote & mask) == 3) - { - err = "cannot use the first or last address within a given 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver"; - goto error; - } - - gc_free (&gc); - return; - - error: - msg (M_FATAL, "There is a problem in your selection of --ifconfig endpoints [local=%s, remote=%s]. The local and remote VPN endpoints %s. Try '" PACKAGE " --show-valid-subnets' option for more info.", - print_in_addr_t (local, 0, &gc), - print_in_addr_t (remote, 0, &gc), - err); - gc_free (&gc); -} - -void show_valid_win32_tun_subnets (void) -{ - int i; - int col = 0; - - printf ("On Windows, point-to-point IP support (i.e. --dev tun)\n"); - printf ("is emulated by the TAP-Win32 driver. The major limitation\n"); - printf ("imposed by this approach is that the --ifconfig local and\n"); - printf ("remote endpoints must be part of the same 255.255.255.252\n"); - printf ("subnet. The following list shows examples of endpoint\n"); - printf ("pairs which satisfy this requirement. Only the final\n"); - printf ("component of the IP address pairs is at issue.\n\n"); - printf ("As an example, the following option would be correct:\n"); - printf (" --ifconfig 10.7.0.5 10.7.0.6 (on host A)\n"); - printf (" --ifconfig 10.7.0.6 10.7.0.5 (on host B)\n"); - printf ("because [5,6] is part of the below list.\n\n"); - - for (i = 0; i < 256; i += 4) - { - printf("[%3d,%3d] ", i+1, i+2); - if (++col > 4) - { - col = 0; - printf ("\n"); - } - } - if (col) - printf ("\n"); -} - -void -show_tap_win32_adapters (int msglev, int warnlev) -{ - struct gc_arena gc = gc_new (); - - bool warn_panel_null = false; - bool warn_panel_dup = false; - bool warn_tap_dup = false; - - int links; - - const struct tap_reg *tr; - const struct tap_reg *tr1; - const struct panel_reg *pr; - - const struct tap_reg *tap_reg = get_tap_reg (&gc); - const struct panel_reg *panel_reg = get_panel_reg (&gc); - - msg (msglev, "Available TAP-WIN32 adapters [name, GUID]:"); - - /* loop through each TAP-Win32 adapter registry entry */ - for (tr = tap_reg; tr != NULL; tr = tr->next) - { - links = 0; - - /* loop through each network connections entry in the control panel */ - for (pr = panel_reg; pr != NULL; pr = pr->next) - { - if (!strcmp (tr->guid, pr->guid)) - { - msg (msglev, "'%s' %s", pr->name, tr->guid); - ++links; - } - } - - if (links > 1) - { - warn_panel_dup = true; - } - else if (links == 0) - { - /* a TAP adapter exists without a link from the network - connections control panel */ - warn_panel_null = true; - msg (msglev, "[NULL] %s", tr->guid); - } - } - - /* check for TAP-Win32 adapter duplicated GUIDs */ - for (tr = tap_reg; tr != NULL; tr = tr->next) - { - for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next) - { - if (tr != tr1 && !strcmp (tr->guid, tr1->guid)) - warn_tap_dup = true; - } - } - - /* warn on registry inconsistencies */ - if (warn_tap_dup) - msg (warnlev, "WARNING: Some TAP-Win32 adapters have duplicate GUIDs"); - - if (warn_panel_dup) - msg (warnlev, "WARNING: Some TAP-Win32 adapters have duplicate links from the Network Connections control panel"); - - if (warn_panel_null) - msg (warnlev, "WARNING: Some TAP-Win32 adapters have no link from the Network Connections control panel"); - - gc_free (&gc); -} - -/* - * Confirm that GUID is a TAP-Win32 adapter. - */ -static bool -is_tap_win32 (const char *guid, const struct tap_reg *tap_reg) -{ - const struct tap_reg *tr; - - for (tr = tap_reg; tr != NULL; tr = tr->next) - { - if (guid && !strcmp (tr->guid, guid)) - return true; - } - - return false; -} - -static const char * -guid_to_name (const char *guid, const struct panel_reg *panel_reg) -{ - const struct panel_reg *pr; - - for (pr = panel_reg; pr != NULL; pr = pr->next) - { - if (guid && !strcmp (pr->guid, guid)) - return pr->name; - } - - return NULL; -} - -static const char * -name_to_guid (const char *name, const struct tap_reg *tap_reg, const struct panel_reg *panel_reg) -{ - const struct panel_reg *pr; - - for (pr = panel_reg; pr != NULL; pr = pr->next) - { - if (name && !strcmp (pr->name, name) && is_tap_win32 (pr->guid, tap_reg)) - return pr->guid; - } - - return NULL; -} - -static void -at_least_one_tap_win32 (const struct tap_reg *tap_reg) -{ - if (!tap_reg) - msg (M_FATAL, "There are no TAP-Win32 adapters on this system. You should be able to create a TAP-Win32 adapter by going to Start -> All Programs -> " PACKAGE_NAME " -> Add a new TAP-Win32 virtual ethernet adapter."); -} - -/* - * Get an adapter GUID and optional actual_name from the - * registry for the TAP device # = device_number. - */ -static const char * -get_unspecified_device_guid (const int device_number, - char *actual_name, - int actual_name_size, - const struct tap_reg *tap_reg_src, - const struct panel_reg *panel_reg_src, - struct gc_arena *gc) -{ - const struct tap_reg *tap_reg = tap_reg_src; - struct buffer ret = clear_buf (); - struct buffer actual = clear_buf (); - int i; - - ASSERT (device_number >= 0); - - /* Make sure we have at least one TAP adapter */ - if (!tap_reg) - return NULL; - - /* The actual_name output buffer may be NULL */ - if (actual_name) - { - ASSERT (actual_name_size > 0); - buf_set_write (&actual, actual_name, actual_name_size); - } - - /* Move on to specified device number */ - for (i = 0; i < device_number; i++) - { - tap_reg = tap_reg->next; - if (!tap_reg) - return NULL; - } - - /* Save Network Panel name (if exists) in actual_name */ - if (actual_name) - { - const char *act = guid_to_name (tap_reg->guid, panel_reg_src); - if (act) - buf_printf (&actual, "%s", act); - else - buf_printf (&actual, "NULL"); - } - - /* Save GUID for return value */ - ret = alloc_buf_gc (256, gc); - buf_printf (&ret, "%s", tap_reg->guid); - return BSTR (&ret); -} - -/* - * Lookup a --dev-node adapter name in the registry - * returning the GUID and optional actual_name. - */ -static const char * -get_device_guid (const char *name, - char *actual_name, - int actual_name_size, - const struct tap_reg *tap_reg, - const struct panel_reg *panel_reg, - struct gc_arena *gc) -{ - struct buffer ret = alloc_buf_gc (256, gc); - struct buffer actual = clear_buf (); - - /* Make sure we have at least one TAP adapter */ - if (!tap_reg) - return NULL; - - /* The actual_name output buffer may be NULL */ - if (actual_name) - { - ASSERT (actual_name_size > 0); - buf_set_write (&actual, actual_name, actual_name_size); - } - - /* Check if GUID was explicitly specified as --dev-node parameter */ - if (is_tap_win32 (name, tap_reg)) - { - const char *act = guid_to_name (name, panel_reg); - buf_printf (&ret, "%s", name); - if (act) - buf_printf (&actual, "%s", act); - else - buf_printf (&actual, "NULL"); - return BSTR (&ret); - } - - /* Lookup TAP adapter in network connections list */ - { - const char *guid = name_to_guid (name, tap_reg, panel_reg); - if (guid) - { - buf_printf (&actual, "%s", name); - buf_printf (&ret, "%s", guid); - return BSTR (&ret); - } - } - - return NULL; -} - -/* - * Return a TAP name for netsh commands. - */ -const char * -get_netsh_id (const char *dev_node, struct gc_arena *gc) -{ - const struct tap_reg *tap_reg = get_tap_reg (gc); - const struct panel_reg *panel_reg = get_panel_reg (gc); - struct buffer actual = alloc_buf_gc (256, gc); - const char *guid; - - at_least_one_tap_win32 (tap_reg); - - if (dev_node) - { - guid = get_device_guid (dev_node, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc); - } - else - { - guid = get_unspecified_device_guid (0, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc); - - if (get_unspecified_device_guid (1, NULL, 0, tap_reg, panel_reg, gc)) /* ambiguous if more than one TAP-Win32 adapter */ - guid = NULL; - } - - if (!guid) - return "NULL"; /* not found */ - else if (strcmp (BPTR (&actual), "NULL")) - return BPTR (&actual); /* control panel name */ - else - return guid; /* no control panel name, return GUID instead */ -} - -/* - * Get adapter info list - */ -const IP_ADAPTER_INFO * -get_adapter_info_list (struct gc_arena *gc) -{ - ULONG size = 0; - IP_ADAPTER_INFO *pi = NULL; - DWORD status; - - if ((status = GetAdaptersInfo (NULL, &size)) != ERROR_BUFFER_OVERFLOW) - { - msg (M_INFO, "GetAdaptersInfo #1 failed (status=%u) : %s", - (unsigned int)status, - strerror_win32 (status, gc)); - } - else - { - pi = (PIP_ADAPTER_INFO) gc_malloc (size, false, gc); - if ((status = GetAdaptersInfo (pi, &size)) == NO_ERROR) - return pi; - else - { - msg (M_INFO, "GetAdaptersInfo #2 failed (status=%u) : %s", - (unsigned int)status, - strerror_win32 (status, gc)); - } - } - return pi; -} - -static const IP_INTERFACE_INFO * -get_interface_info_list (struct gc_arena *gc) -{ - ULONG size = 0; - IP_INTERFACE_INFO *ii = NULL; - DWORD status; - - if ((status = GetInterfaceInfo (NULL, &size)) != ERROR_INSUFFICIENT_BUFFER) - { - msg (M_INFO, "GetInterfaceInfo #1 failed (status=%u) : %s", - (unsigned int)status, - strerror_win32 (status, gc)); - } - else - { - ii = (PIP_INTERFACE_INFO) gc_malloc (size, false, gc); - if ((status = GetInterfaceInfo (ii, &size)) == NO_ERROR) - return ii; - else - { - msg (M_INFO, "GetInterfaceInfo #2 failed (status=%u) : %s", - (unsigned int)status, - strerror_win32 (status, gc)); - } - } - return ii; -} - -static const IP_ADAPTER_INDEX_MAP * -get_interface_info (DWORD index, struct gc_arena *gc) -{ - const IP_INTERFACE_INFO *list = get_interface_info_list (gc); - if (list) - { - int i; - for (i = 0; i < list->NumAdapters; ++i) - { - const IP_ADAPTER_INDEX_MAP *inter = &list->Adapter[i]; - if (index == inter->Index) - return inter; - } - } - return NULL; -} - -/* - * Given an adapter index, return a pointer to the - * IP_ADAPTER_INFO structure for that adapter. - */ - -static const IP_ADAPTER_INFO * -get_adapter (const IP_ADAPTER_INFO *ai, DWORD index) -{ - if (ai && index != (DWORD)~0) - { - const IP_ADAPTER_INFO *a; - - /* find index in the linked list */ - for (a = ai; a != NULL; a = a->Next) - { - if (a->Index == index) - return a; - } - } - return NULL; -} - -static const IP_ADAPTER_INFO * -get_adapter_info (DWORD index, struct gc_arena *gc) -{ - return get_adapter (get_adapter_info_list (gc), index); -} - -static int -get_adapter_n_ip_netmask (const IP_ADAPTER_INFO *ai) -{ - if (ai) - { - int n = 0; - const IP_ADDR_STRING *ip = &ai->IpAddressList; - - while (ip) - { - ++n; - ip = ip->Next; - } - return n; - } - else - return 0; -} - -static bool -get_adapter_ip_netmask (const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, in_addr_t *netmask) -{ - bool ret = false; - *ip = 0; - *netmask = 0; - - if (ai) - { - const IP_ADDR_STRING *iplist = &ai->IpAddressList; - int i = 0; - - while (iplist) - { - if (i == n) - break; - ++i; - iplist = iplist->Next; - } - - if (iplist) - { - const unsigned int getaddr_flags = GETADDR_HOST_ORDER; - const char *ip_str = iplist->IpAddress.String; - const char *netmask_str = iplist->IpMask.String; - bool succeed1 = false; - bool succeed2 = false; - - if (ip_str && netmask_str && strlen (ip_str) && strlen (netmask_str)) - { - *ip = getaddr (getaddr_flags, ip_str, 0, &succeed1, NULL); - *netmask = getaddr (getaddr_flags, netmask_str, 0, &succeed2, NULL); - ret = (succeed1 == true && succeed2 == true); - } - } - } - - return ret; -} - -const IP_ADAPTER_INFO * -get_tun_adapter (const struct tuntap *tt, const IP_ADAPTER_INFO *list) -{ - if (list && tt) - return get_adapter (list, tt->adapter_index); - else - return NULL; -} - -bool -is_adapter_up (const struct tuntap *tt, const IP_ADAPTER_INFO *list) -{ - int i; - bool ret = false; - - const IP_ADAPTER_INFO *ai = get_tun_adapter (tt, list); - - if (ai) - { - const int n = get_adapter_n_ip_netmask (ai); - - /* loop once for every IP/netmask assigned to adapter */ - for (i = 0; i < n; ++i) - { - in_addr_t ip, netmask; - if (get_adapter_ip_netmask (ai, i, &ip, &netmask)) - { - if (tt->local && tt->adapter_netmask) - { - /* wait for our --ifconfig parms to match the actual adapter parms */ - if (tt->local == ip && tt->adapter_netmask == netmask) - ret = true; - } - else - { - /* --ifconfig was not defined, maybe using a real DHCP server */ - if (ip && netmask) - ret = true; - } - } - } - } - else - ret = true; /* this can occur when TAP adapter is bridged */ - - return ret; -} - -bool -is_ip_in_adapter_subnet (const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask) -{ - int i; - bool ret = false; - - if (highest_netmask) - *highest_netmask = 0; - - if (ai) - { - const int n = get_adapter_n_ip_netmask (ai); - for (i = 0; i < n; ++i) - { - in_addr_t adapter_ip, adapter_netmask; - if (get_adapter_ip_netmask (ai, i, &adapter_ip, &adapter_netmask)) - { - if (adapter_ip && adapter_netmask && (ip & adapter_netmask) == (adapter_ip & adapter_netmask)) - { - if (highest_netmask && adapter_netmask > *highest_netmask) - *highest_netmask = adapter_netmask; - ret = true; - } - } - } - } - return ret; -} - -DWORD -adapter_index_of_ip (const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count) -{ - struct gc_arena gc = gc_new (); - DWORD ret = ~0; - in_addr_t highest_netmask = 0; - bool first = true; - - if (count) - *count = 0; - - while (list) - { - in_addr_t hn; - - if (is_ip_in_adapter_subnet (list, ip, &hn)) - { - if (first || hn > highest_netmask) - { - highest_netmask = hn; - if (count) - *count = 1; - ret = list->Index; - first = false; - } - else if (hn == highest_netmask) - { - if (count) - ++*count; - } - } - list = list->Next; - } - - dmsg (D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d", - print_in_addr_t (ip, 0, &gc), - print_in_addr_t (highest_netmask, 0, &gc), - (int)ret, - count ? *count : -1); - - if (ret == ~0 && count) - *count = 0; - - gc_free (&gc); - return ret; -} - -/* - * Given an adapter index, return true if the adapter - * is DHCP disabled. - */ -static bool -dhcp_disabled (DWORD index) -{ - struct gc_arena gc = gc_new (); - const IP_ADAPTER_INFO *ai = get_adapter_info (index, &gc); - bool ret = false; - - if (ai && !ai->DhcpEnabled) - ret = true; - - gc_free (&gc); - return ret; -} - -/* - * Delete all temporary address/netmask pairs which were added - * to adapter (given by index) by previous calls to AddIPAddress. - */ -static void -delete_temp_addresses (DWORD index) -{ - struct gc_arena gc = gc_new (); - const IP_ADAPTER_INFO *a = get_adapter_info (index, &gc); - - if (a) - { - const IP_ADDR_STRING *ip = &a->IpAddressList; - while (ip) - { - DWORD status; - const DWORD context = ip->Context; - - if ((status = DeleteIPAddress ((ULONG) context)) == NO_ERROR) - { - msg (M_INFO, "Successfully deleted previously set dynamic IP/netmask: %s/%s", - ip->IpAddress.String, - ip->IpMask.String); - } - else - { - const char *empty = "0.0.0.0"; - if (strcmp (ip->IpAddress.String, empty) - || strcmp (ip->IpMask.String, empty)) - msg (M_INFO, "NOTE: could not delete previously set dynamic IP/netmask: %s/%s (status=%u)", - ip->IpAddress.String, - ip->IpMask.String, - (unsigned int)status); - } - ip = ip->Next; - } - } - gc_free (&gc); -} - -/* - * Get interface index for use with IP Helper API functions. - */ -static DWORD -get_interface_index (const char *guid) -{ - struct gc_arena gc = gc_new (); - ULONG index; - DWORD status; - wchar_t wbuf[256]; - snwprintf (wbuf, SIZE (wbuf), L"\\DEVICE\\TCPIP_%S", guid); - wbuf [SIZE(wbuf) - 1] = 0; - if ((status = GetAdapterIndex (wbuf, &index)) != NO_ERROR) - { - msg (M_INFO, "NOTE: could not get adapter index for %S, status=%u : %s", - wbuf, - (unsigned int)status, - strerror_win32 (status, &gc)); - gc_free (&gc); - return (DWORD)~0; - } - else - { - gc_free (&gc); - return index; - } -} - -/* - * Return a string representing a PIP_ADDR_STRING - */ -static const char * -format_ip_addr_string (const IP_ADDR_STRING *ip, struct gc_arena *gc) -{ - struct buffer out = alloc_buf_gc (256, gc); - while (ip) - { - buf_printf (&out, "%s", ip->IpAddress.String); - if (strlen (ip->IpMask.String)) - { - buf_printf (&out, "/"); - buf_printf (&out, "%s", ip->IpMask.String); - } - buf_printf (&out, " "); - ip = ip->Next; - } - return BSTR (&out); -} - -/* - * Show info for a single adapter - */ -static void -show_adapter (int msglev, const IP_ADAPTER_INFO *a, struct gc_arena *gc) -{ - msg (msglev, "%s", a->Description); - msg (msglev, " Index = %d", (int)a->Index); - msg (msglev, " GUID = %s", a->AdapterName); - msg (msglev, " IP = %s", format_ip_addr_string (&a->IpAddressList, gc)); - msg (msglev, " MAC = %s", format_hex_ex (a->Address, a->AddressLength, 0, 1, ":", gc)); - msg (msglev, " GATEWAY = %s", format_ip_addr_string (&a->GatewayList, gc)); - if (a->DhcpEnabled) - { - msg (msglev, " DHCP SERV = %s", format_ip_addr_string (&a->DhcpServer, gc)); - msg (msglev, " DHCP LEASE OBTAINED = %s", time_string (a->LeaseObtained, 0, false, gc)); - msg (msglev, " DHCP LEASE EXPIRES = %s", time_string (a->LeaseExpires, 0, false, gc)); - } - if (a->HaveWins) - { - msg (msglev, " PRI WINS = %s", format_ip_addr_string (&a->PrimaryWinsServer, gc)); - msg (msglev, " SEC WINS = %s", format_ip_addr_string (&a->SecondaryWinsServer, gc)); - } -} - -/* - * Show current adapter list - */ -void -show_adapters (int msglev) -{ - struct gc_arena gc = gc_new (); - const IP_ADAPTER_INFO *ai = get_adapter_info_list (&gc); - - msg (msglev, "SYSTEM ADAPTER LIST"); - if (ai) - { - const IP_ADAPTER_INFO *a; - - /* find index in the linked list */ - for (a = ai; a != NULL; a = a->Next) - { - show_adapter (msglev, a, &gc); - } - } - gc_free (&gc); -} - -/* - * DHCP release/renewal - */ - -bool -dhcp_release (const struct tuntap *tt) -{ - struct gc_arena gc = gc_new (); - bool ret = false; - if (tt && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ && tt->adapter_index != ~0) - { - const IP_ADAPTER_INDEX_MAP *inter = get_interface_info (tt->adapter_index, &gc); - if (inter) - { - DWORD status = IpReleaseAddress ((IP_ADAPTER_INDEX_MAP *)inter); - if (status == NO_ERROR) - { - msg (D_TUNTAP_INFO, "TAP: DHCP address released"); - ret = true; - } - else - msg (M_WARN, "NOTE: Release of DHCP-assigned IP address lease on TAP-Win32 adapter failed: %s (code=%u)", - strerror_win32 (status, &gc), - (unsigned int)status); - } - } - gc_free (&gc); - return ret; -} - -bool -dhcp_renew (const struct tuntap *tt) -{ - struct gc_arena gc = gc_new (); - bool ret = false; - if (tt && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ && tt->adapter_index != ~0) - { - const IP_ADAPTER_INDEX_MAP *inter = get_interface_info (tt->adapter_index, &gc); - if (inter) - { - DWORD status = IpRenewAddress ((IP_ADAPTER_INDEX_MAP *)inter); - if (status == NO_ERROR) - { - msg (D_TUNTAP_INFO, "TAP: DHCP address renewal succeeded"); - ret = true; - } - else - msg (M_WARN, "WARNING: Failed to renew DHCP IP address lease on TAP-Win32 adapter: %s (code=%u)", - strerror_win32 (status, &gc), - (unsigned int)status); - } - } - gc_free (&gc); - return ret; -} - -/* - * Convert DHCP options from the command line / config file - * into a raw DHCP-format options string. - */ - -static void -write_dhcp_u8 (struct buffer *buf, const int type, const int data) -{ - if (!buf_safe (buf, 3)) - msg (M_FATAL, "write_dhcp_u8: buffer overflow building DHCP options"); - buf_write_u8 (buf, type); - buf_write_u8 (buf, 1); - buf_write_u8 (buf, data); -} - -static void -write_dhcp_u32_array (struct buffer *buf, const int type, const uint32_t *data, const unsigned int len) -{ - if (len > 0) - { - int i; - const int size = len * sizeof (uint32_t); - - if (!buf_safe (buf, 2 + size)) - msg (M_FATAL, "write_dhcp_u32_array: buffer overflow building DHCP options"); - if (size < 1 || size > 255) - msg (M_FATAL, "write_dhcp_u32_array: size (%d) must be > 0 and <= 255", size); - buf_write_u8 (buf, type); - buf_write_u8 (buf, size); - for (i = 0; i < len; ++i) - buf_write_u32 (buf, data[i]); - } -} - -static void -write_dhcp_str (struct buffer *buf, const int type, const char *str) -{ - const int len = strlen (str); - if (!buf_safe (buf, 2 + len)) - msg (M_FATAL, "write_dhcp_str: buffer overflow building DHCP options"); - if (len < 1 || len > 255) - msg (M_FATAL, "write_dhcp_str: string '%s' must be > 0 bytes and <= 255 bytes", str); - buf_write_u8 (buf, type); - buf_write_u8 (buf, len); - buf_write (buf, str, len); -} - -static void -build_dhcp_options_string (struct buffer *buf, const struct tuntap_options *o) -{ - if (o->domain) - write_dhcp_str (buf, 15, o->domain); - - if (o->netbios_scope) - write_dhcp_str (buf, 47, o->netbios_scope); - - if (o->netbios_node_type) - write_dhcp_u8 (buf, 46, o->netbios_node_type); - - write_dhcp_u32_array (buf, 6, (uint32_t*)o->dns, o->dns_len); - write_dhcp_u32_array (buf, 44, (uint32_t*)o->wins, o->wins_len); - write_dhcp_u32_array (buf, 42, (uint32_t*)o->ntp, o->ntp_len); - write_dhcp_u32_array (buf, 45, (uint32_t*)o->nbdd, o->nbdd_len); - - /* the MS DHCP server option 'Disable Netbios-over-TCP/IP - is implemented as vendor option 001, value 002. - A value of 001 means 'leave NBT alone' which is the default */ - if (o->disable_nbt) - { - buf_write_u8 (buf, 43); - buf_write_u8 (buf, 6); /* total length field */ - buf_write_u8 (buf, 0x001); - buf_write_u8 (buf, 4); /* length of the vendor specified field */ - buf_write_u32 (buf, 0x002); - } -} - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - struct gc_arena gc = gc_new (); - char device_path[256]; - const char *device_guid = NULL; - DWORD len; - - /*netcmd_semaphore_lock ();*/ - - ipv6_support (ipv6, false, tt); - - if (tt->type == DEV_TYPE_NULL) - { - open_null (tt); - gc_free (&gc); - return; - } - else if (tt->type == DEV_TYPE_TAP || tt->type == DEV_TYPE_TUN) - { - ; - } - else - { - msg (M_FATAL|M_NOPREFIX, "Unknown virtual device type: '%s'", dev); - } - - /* - * Lookup the device name in the registry, using the --dev-node high level name. - */ - { - const struct tap_reg *tap_reg = get_tap_reg (&gc); - const struct panel_reg *panel_reg = get_panel_reg (&gc); - char guid_buffer[256]; - - at_least_one_tap_win32 (tap_reg); - - if (dev_node) - { - /* Get the device GUID for the device specified with --dev-node. */ - device_guid = get_device_guid (dev_node, guid_buffer, sizeof (guid_buffer), tap_reg, panel_reg, &gc); - - if (!device_guid) - msg (M_FATAL, "TAP-Win32 adapter '%s' not found", dev_node); - - /* Open Windows TAP-Win32 adapter */ - openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s", - USERMODEDEVICEDIR, - device_guid, - TAPSUFFIX); - - tt->hand = CreateFile ( - device_path, - GENERIC_READ | GENERIC_WRITE, - 0, /* was: FILE_SHARE_READ */ - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, - 0 - ); - - if (tt->hand == INVALID_HANDLE_VALUE) - msg (M_ERR, "CreateFile failed on TAP device: %s", device_path); - } - else - { - int device_number = 0; - - /* Try opening all TAP devices until we find one available */ - while (true) - { - device_guid = get_unspecified_device_guid (device_number, - guid_buffer, - sizeof (guid_buffer), - tap_reg, - panel_reg, - &gc); - - if (!device_guid) - msg (M_FATAL, "All TAP-Win32 adapters on this system are currently in use."); - - /* Open Windows TAP-Win32 adapter */ - openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s", - USERMODEDEVICEDIR, - device_guid, - TAPSUFFIX); - - tt->hand = CreateFile ( - device_path, - GENERIC_READ | GENERIC_WRITE, - 0, /* was: FILE_SHARE_READ */ - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, - 0 - ); - - if (tt->hand == INVALID_HANDLE_VALUE) - msg (D_TUNTAP_INFO, "CreateFile failed on TAP device: %s", device_path); - else - break; - - device_number++; - } - } - - /* translate high-level device name into a device instance - GUID using the registry */ - tt->actual_name = string_alloc (guid_buffer, NULL); - } - - msg (M_INFO, "TAP-WIN32 device [%s] opened: %s", tt->actual_name, device_path); - - /* get driver version info */ - { - ULONG info[3]; - CLEAR (info); - if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_VERSION, - &info, sizeof (info), - &info, sizeof (info), &len, NULL)) - { - msg (D_TUNTAP_INFO, "TAP-Win32 Driver Version %d.%d %s", - (int) info[0], - (int) info[1], - (info[2] ? "(DEBUG)" : "")); - - } - if ( !(info[0] > TAP_WIN32_MIN_MAJOR - || (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) ) - msg (M_FATAL, "ERROR: This version of " PACKAGE_NAME " requires a TAP-Win32 driver that is at least version %d.%d -- If you recently upgraded your " PACKAGE_NAME " distribution, a reboot is probably required at this point to get Windows to see the new driver.", - TAP_WIN32_MIN_MAJOR, - TAP_WIN32_MIN_MINOR); - } - - /* get driver MTU */ - { - ULONG mtu; - if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_MTU, - &mtu, sizeof (mtu), - &mtu, sizeof (mtu), &len, NULL)) - { - tt->post_open_mtu = (int) mtu; - msg (D_MTU_INFO, "TAP-Win32 MTU=%d", (int) mtu); - } - } - - /* set point-to-point mode if TUN device */ - - if (tt->type == DEV_TYPE_TUN) - { - in_addr_t ep[2]; - ep[0] = htonl (tt->local); - ep[1] = htonl (tt->remote_netmask); - if (!tt->did_ifconfig_setup) - { - msg (M_FATAL, "ERROR: --dev tun also requires --ifconfig"); - } - if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_POINT_TO_POINT, - ep, sizeof (ep), - ep, sizeof (ep), &len, NULL)) - msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set Point-to-Point mode, which is required for --dev tun"); - } - - /* should we tell the TAP-Win32 driver to masquerade as a DHCP server as a means - of setting the adapter address? */ - if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ) - { - uint32_t ep[4]; - - /* We will answer DHCP requests with a reply to set IP/subnet to these values */ - ep[0] = htonl (tt->local); - ep[1] = htonl (tt->adapter_netmask); - - /* At what IP address should the DHCP server masquerade at? */ - if (tt->type == DEV_TYPE_TUN) - { - ep[2] = htonl (tt->remote_netmask); - if (tt->options.dhcp_masq_custom_offset) - msg (M_WARN, "WARNING: because you are using '--dev tun' mode, the '--ip-win32 dynamic [offset]' option is ignoring the offset parameter"); - } - else - { - in_addr_t dsa; /* DHCP server addr */ - - ASSERT (tt->type == DEV_TYPE_TAP); - - if (tt->options.dhcp_masq_offset < 0) - dsa = (tt->local | (~tt->adapter_netmask)) + tt->options.dhcp_masq_offset; - else - dsa = (tt->local & tt->adapter_netmask) + tt->options.dhcp_masq_offset; - - if (dsa == tt->local) - msg (M_FATAL, "ERROR: There is a clash between the --ifconfig local address and the internal DHCP server address -- both are set to %s -- please use the --ip-win32 dynamic option to choose a different free address from the --ifconfig subnet for the internal DHCP server", print_in_addr_t (dsa, 0, &gc)); - - if ((tt->local & tt->adapter_netmask) != (dsa & tt->adapter_netmask)) - msg (M_FATAL, "ERROR: --tap-win32 dynamic [offset] : offset is outside of --ifconfig subnet"); - - ep[2] = htonl (dsa); - } - - /* lease time in seconds */ - ep[3] = (uint32_t) tt->options.dhcp_lease_time; - - ASSERT (ep[3] > 0); - - if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_MASQ, - ep, sizeof (ep), - ep, sizeof (ep), &len, NULL)) - msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set TAP_IOCTL_CONFIG_DHCP_MASQ mode"); - - msg (M_INFO, "Notified TAP-Win32 driver to set a DHCP IP/netmask of %s/%s on interface %s [DHCP-serv: %s, lease-time: %d]", - print_in_addr_t (tt->local, 0, &gc), - print_in_addr_t (tt->adapter_netmask, 0, &gc), - device_guid, - print_in_addr_t (ep[2], IA_NET_ORDER, &gc), - ep[3] - ); - - /* user-supplied DHCP options capability */ - if (tt->options.dhcp_options) - { - struct buffer buf = alloc_buf (256); - build_dhcp_options_string (&buf, &tt->options); - msg (D_DHCP_OPT, "DHCP option string: %s", format_hex (BPTR (&buf), BLEN (&buf), 0, &gc)); - if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_SET_OPT, - BPTR (&buf), BLEN (&buf), - BPTR (&buf), BLEN (&buf), &len, NULL)) - msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a TAP_IOCTL_CONFIG_DHCP_SET_OPT DeviceIoControl call"); - free_buf (&buf); - } - } - - /* set driver media status to 'connected' */ - { - ULONG status = TRUE; - if (!DeviceIoControl (tt->hand, TAP_IOCTL_SET_MEDIA_STATUS, - &status, sizeof (status), - &status, sizeof (status), &len, NULL)) - msg (M_WARN, "WARNING: The TAP-Win32 driver rejected a TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call."); - } - - /* possible wait for adapter to come up */ - { - int s = tt->options.tap_sleep; - if (s > 0) - { - msg (M_INFO, "Sleeping for %d seconds...", s); - openvpn_sleep (s); - } - } - - /* possibly use IP Helper API to set IP address on adapter */ - { - DWORD index = get_interface_index (device_guid); - tt->adapter_index = index; - - /* flush arp cache */ - if (index != (DWORD)~0) - { - DWORD status; - - if ((status = FlushIpNetTable (index)) == NO_ERROR) - msg (M_INFO, "Successful ARP Flush on interface [%u] %s", - (unsigned int)index, - device_guid); - else - msg (M_WARN, "NOTE: FlushIpNetTable failed on interface [%u] %s (status=%u) : %s", - (unsigned int)index, - device_guid, - (unsigned int)status, - strerror_win32 (status, &gc)); - } - - /* - * If the TAP-Win32 driver is masquerading as a DHCP server - * make sure the TCP/IP properties for the adapter are - * set correctly. - */ - if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ) - { - /* check dhcp enable status */ - if (dhcp_disabled (index)) - msg (M_WARN, "WARNING: You have selected '--ip-win32 dynamic', which will not work unless the TAP-Win32 TCP/IP properties are set to 'Obtain an IP address automatically'"); - - /* force an explicit DHCP lease renewal on TAP adapter? */ - if (tt->options.dhcp_pre_release) - dhcp_release (tt); - if (tt->options.dhcp_renew) - dhcp_renew (tt); - } - - if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_IPAPI) - { - DWORD status; - const char *error_suffix = "I am having trouble using the Windows 'IP helper API' to automatically set the IP address -- consider using other --ip-win32 methods (not 'ipapi')"; - - /* couldn't get adapter index */ - if (index == (DWORD)~0) - { - msg (M_FATAL, "ERROR: unable to get adapter index for interface %s -- %s", - device_guid, - error_suffix); - } - - /* check dhcp enable status */ - if (dhcp_disabled (index)) - msg (M_WARN, "NOTE: You have selected (explicitly or by default) '--ip-win32 ipapi', which has a better chance of working correctly if the TAP-Win32 TCP/IP properties are set to 'Obtain an IP address automatically'"); - - /* delete previously added IP addresses which were not - correctly deleted */ - delete_temp_addresses (index); - - /* add a new IP address */ - if ((status = AddIPAddress (htonl(tt->local), - htonl(tt->adapter_netmask), - index, - &tt->ipapi_context, - &tt->ipapi_instance)) == NO_ERROR) - msg (M_INFO, "Succeeded in adding a temporary IP/netmask of %s/%s to interface %s using the Win32 IP Helper API", - print_in_addr_t (tt->local, 0, &gc), - print_in_addr_t (tt->adapter_netmask, 0, &gc), - device_guid - ); - else - msg (M_FATAL, "ERROR: AddIPAddress %s/%s failed on interface %s, index=%d, status=%u (windows error: '%s') -- %s", - print_in_addr_t (tt->local, 0, &gc), - print_in_addr_t (tt->adapter_netmask, 0, &gc), - device_guid, - (int)index, - (unsigned int)status, - strerror_win32 (status, &gc), - error_suffix); - tt->ipapi_context_defined = true; - } - } - /*netcmd_semaphore_release ();*/ - gc_free (&gc); -} - -const char * -tap_win32_getinfo (const struct tuntap *tt, struct gc_arena *gc) -{ - if (tt && tt->hand != NULL) - { - struct buffer out = alloc_buf_gc (256, gc); - DWORD len; - if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_INFO, - BSTR (&out), BCAP (&out), - BSTR (&out), BCAP (&out), - &len, NULL)) - { - return BSTR (&out); - } - } - return NULL; -} - -void -tun_show_debug (struct tuntap *tt) -{ - if (tt && tt->hand != NULL) - { - struct buffer out = alloc_buf (1024); - DWORD len; - while (DeviceIoControl (tt->hand, TAP_IOCTL_GET_LOG_LINE, - BSTR (&out), BCAP (&out), - BSTR (&out), BCAP (&out), - &len, NULL)) - { - msg (D_TAP_WIN32_DEBUG, "TAP-Win32: %s", BSTR (&out)); - } - free_buf (&out); - } -} - -void -close_tun (struct tuntap *tt) -{ - struct gc_arena gc = gc_new (); - - if (tt) - { -#if 1 - if (tt->ipapi_context_defined) - { - DWORD status; - if ((status = DeleteIPAddress (tt->ipapi_context)) != NO_ERROR) - { - msg (M_WARN, "Warning: DeleteIPAddress[%u] failed on TAP-Win32 adapter, status=%u : %s", - (unsigned int)tt->ipapi_context, - (unsigned int)status, - strerror_win32 (status, &gc)); - } - } -#endif - - if (tt->options.dhcp_release) - dhcp_release (tt); - - if (tt->hand != NULL) - { - dmsg (D_WIN32_IO_LOW, "Attempting CancelIO on TAP-Win32 adapter"); - if (!CancelIo (tt->hand)) - msg (M_WARN | M_ERRNO, "Warning: CancelIO failed on TAP-Win32 adapter"); - } - - dmsg (D_WIN32_IO_LOW, "Attempting close of overlapped read event on TAP-Win32 adapter"); - overlapped_io_close (&tt->reads); - - dmsg (D_WIN32_IO_LOW, "Attempting close of overlapped write event on TAP-Win32 adapter"); - overlapped_io_close (&tt->writes); - - if (tt->hand != NULL) - { - dmsg (D_WIN32_IO_LOW, "Attempting CloseHandle on TAP-Win32 adapter"); - if (!CloseHandle (tt->hand)) - msg (M_WARN | M_ERRNO, "Warning: CloseHandle failed on TAP-Win32 adapter"); - } - - if (tt->actual_name) - free (tt->actual_name); - - clear_tuntap (tt); - free (tt); - } - gc_free (&gc); -} - -/* - * Convert --ip-win32 constants between index and ascii form. - */ - -struct ipset_names { - const char *short_form; -}; - -/* Indexed by IPW32_SET_x */ -static const struct ipset_names ipset_names[] = { - {"manual"}, - {"netsh"}, - {"ipapi"}, - {"dynamic"} -}; - -int -ascii2ipset (const char* name) -{ - int i; - ASSERT (IPW32_SET_N == SIZE (ipset_names)); - for (i = 0; i < IPW32_SET_N; ++i) - if (!strcmp (name, ipset_names[i].short_form)) - return i; - return -1; -} - -const char * -ipset2ascii (int index) -{ - ASSERT (IPW32_SET_N == SIZE (ipset_names)); - if (index < 0 || index >= IPW32_SET_N) - return "[unknown --ip-win32 type]"; - else - return ipset_names[index].short_form; -} - -const char * -ipset2ascii_all (struct gc_arena *gc) -{ - struct buffer out = alloc_buf_gc (256, gc); - int i; - - ASSERT (IPW32_SET_N == SIZE (ipset_names)); - for (i = 0; i < IPW32_SET_N; ++i) - { - if (i) - buf_printf(&out, " "); - buf_printf(&out, "[%s]", ipset2ascii(i)); - } - return BSTR (&out); -} - -#else /* generic */ - -void -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) -{ - open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt); -} - -void -close_tun (struct tuntap* tt) -{ - if (tt) - { - close_tun_generic (tt); - free (tt); - } -} - -int -write_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - return write (tt->fd, buf, len); -} - -int -read_tun (struct tuntap* tt, uint8_t *buf, int len) -{ - return read (tt->fd, buf, len); -} - -#endif diff --git a/openvpn/tun.h b/openvpn/tun.h deleted file mode 100644 index 76c4867..0000000 --- a/openvpn/tun.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * 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 - * - * 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 TUN_H -#define TUN_H - -#ifdef WIN32 -#include -#include "tap-win32/common.h" -#endif - -#include "buffer.h" -#include "error.h" -#include "mtu.h" -#include "win32.h" -#include "event.h" -#include "proto.h" -#include "misc.h" - -#ifdef WIN32 - -struct tuntap_options { - /* --ip-win32 options */ - bool ip_win32_defined; - -# define IPW32_SET_MANUAL 0 /* "--ip-win32 manual" */ -# define IPW32_SET_NETSH 1 /* "--ip-win32 netsh" */ -# define IPW32_SET_IPAPI 2 /* "--ip-win32 ipapi" */ -# define IPW32_SET_DHCP_MASQ 3 /* "--ip-win32 dynamic" */ -# define IPW32_SET_N 4 - int ip_win32_type; - - /* --ip-win32 dynamic options */ - bool dhcp_masq_custom_offset; - int dhcp_masq_offset; - int dhcp_lease_time; - - /* --tap-sleep option */ - int tap_sleep; - - /* --dhcp-option options */ - - bool dhcp_options; - - const char *domain; /* DOMAIN (15) */ - - const char *netbios_scope; /* NBS (47) */ - - int netbios_node_type; /* NBT 1,2,4,8 (46) */ - -#define N_DHCP_ADDR 4 /* Max # of addresses allowed for - DNS, WINS, etc. */ - - /* DNS (6) */ - in_addr_t dns[N_DHCP_ADDR]; - int dns_len; - - /* WINS (44) */ - in_addr_t wins[N_DHCP_ADDR]; - int wins_len; - - /* NTP (42) */ - in_addr_t ntp[N_DHCP_ADDR]; - int ntp_len; - - /* NBDD (45) */ - in_addr_t nbdd[N_DHCP_ADDR]; - int nbdd_len; - - /* DISABLE_NBT (43, Vendor option 001) */ - bool disable_nbt; - - bool dhcp_renew; - bool dhcp_pre_release; - bool dhcp_release; -}; - -#elif TARGET_LINUX - -struct tuntap_options { - int txqueuelen; -}; - -#else - -struct tuntap_options { - int dummy; /* not used */ -}; - -#endif - -/* - * Define a TUN/TAP dev. - */ - -struct tuntap -{ -# define TUNNEL_TYPE(tt) ((tt) ? ((tt)->type) : DEV_TYPE_UNDEF) - int type; /* DEV_TYPE_x as defined in proto.h */ - - bool did_ifconfig_setup; - bool did_ifconfig; - - bool ipv6; - - struct tuntap_options options; /* options set on command line */ - - char *actual_name; /* actual name of TUN/TAP dev, usually including unit number */ - - /* number of TX buffers */ - int txqueuelen; - - /* ifconfig parameters */ - in_addr_t local; - in_addr_t remote_netmask; - in_addr_t broadcast; - -#ifdef WIN32 - HANDLE hand; - struct overlapped_io reads; - struct overlapped_io writes; - struct rw_handle rw_handle; - - /* used for setting interface address via IP Helper API - or DHCP masquerade */ - bool ipapi_context_defined; - ULONG ipapi_context; - ULONG ipapi_instance; - in_addr_t adapter_netmask; - - /* Windows adapter index for TAP-Win32 adapter, - ~0 if undefined */ - DWORD adapter_index; -#else - int fd; /* file descriptor for TUN/TAP dev */ -#endif - -#ifdef TARGET_SOLARIS - int ip_fd; -#endif - - /* used for printing status info only */ - unsigned int rwflags_debug; - - /* Some TUN/TAP drivers like to be ioctled for mtu - after open */ - int post_open_mtu; -}; - -static inline bool -tuntap_defined (const struct tuntap *tt) -{ -#ifdef WIN32 - return tt && tt->hand != NULL; -#else - return tt && tt->fd >= 0; -#endif -} - -/* - * Function prototypes - */ - -void clear_tuntap (struct tuntap *tuntap); - -void open_tun (const char *dev, const char *dev_type, const char *dev_node, - bool ipv6, struct tuntap *tt); - -void close_tun (struct tuntap *tt); - -int write_tun (struct tuntap* tt, uint8_t *buf, int len); - -int read_tun (struct tuntap* tt, uint8_t *buf, int len); - -void tuncfg (const char *dev, const char *dev_type, const char *dev_node, - bool ipv6, int persist_mode); - -const char *guess_tuntap_dev (const char *dev, - const char *dev_type, - const char *dev_node, - struct gc_arena *gc); - -struct tuntap *init_tun (const char *dev, /* --dev option */ - const char *dev_type, /* --dev-type option */ - const char *ifconfig_local_parm, /* --ifconfig parm 1 */ - const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */ - in_addr_t local_public, - in_addr_t remote_public, - const bool strict_warn, - struct env_set *es); - -void init_tun_post (struct tuntap *tt, - const struct frame *frame, - const struct tuntap_options *options); - -void do_ifconfig (struct tuntap *tt, - const char *actual, /* actual device name */ - int tun_mtu, - const struct env_set *es); - -const char *dev_component_in_dev_node (const char *dev_node); - -bool is_dev_type (const char *dev, const char *dev_type, const char *match_type); -int dev_type_enum (const char *dev, const char *dev_type); -const char *dev_type_string (const char *dev, const char *dev_type); - -const char *ifconfig_options_string (const struct tuntap* tt, bool remote, bool disable, struct gc_arena *gc); - -/* - * Inline functions - */ - -static inline void -tun_adjust_frame_parameters (struct frame* frame, int size) -{ - frame_add_to_extra_tun (frame, size); -} - -/* - * Should ifconfig be called before or after - * tun dev open? - */ - -#define IFCONFIG_BEFORE_TUN_OPEN 0 -#define IFCONFIG_AFTER_TUN_OPEN 1 - -#define IFCONFIG_DEFAULT IFCONFIG_AFTER_TUN_OPEN - -static inline int -ifconfig_order(void) -{ -#if defined(TARGET_LINUX) - return IFCONFIG_AFTER_TUN_OPEN; -#elif defined(TARGET_SOLARIS) - return IFCONFIG_AFTER_TUN_OPEN; -#elif defined(TARGET_OPENBSD) - return IFCONFIG_BEFORE_TUN_OPEN; -#elif defined(TARGET_DARWIN) - return IFCONFIG_AFTER_TUN_OPEN; -#elif defined(TARGET_NETBSD) - return IFCONFIG_AFTER_TUN_OPEN; -#elif defined(WIN32) - return IFCONFIG_BEFORE_TUN_OPEN; -#else - return IFCONFIG_DEFAULT; -#endif -} - -#ifdef WIN32 - -#define TUN_PASS_BUFFER - -struct tap_reg -{ - const char *guid; - struct tap_reg *next; -}; - -struct panel_reg -{ - const char *name; - const char *guid; - struct panel_reg *next; -}; - -int ascii2ipset (const char* name); -const char *ipset2ascii (int index); -const char *ipset2ascii_all (struct gc_arena *gc); - -void verify_255_255_255_252 (in_addr_t local, in_addr_t remote); - -const IP_ADAPTER_INFO *get_adapter_info_list (struct gc_arena *gc); -const IP_ADAPTER_INFO *get_tun_adapter (const struct tuntap *tt, const IP_ADAPTER_INFO *list); -bool is_adapter_up (const struct tuntap *tt, const IP_ADAPTER_INFO *list); -bool is_ip_in_adapter_subnet (const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask); -DWORD adapter_index_of_ip (const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count); - -void show_tap_win32_adapters (int msglev, int warnlev); -void show_adapters (int msglev); - -void show_valid_win32_tun_subnets (void); -const char *tap_win32_getinfo (const struct tuntap *tt, struct gc_arena *gc); -void tun_show_debug (struct tuntap *tt); - -bool dhcp_release (const struct tuntap *tt); -bool dhcp_renew (const struct tuntap *tt); - -int tun_read_queue (struct tuntap *tt, int maxsize); -int tun_write_queue (struct tuntap *tt, struct buffer *buf); -int tun_finalize (HANDLE h, struct overlapped_io *io, struct buffer *buf); - -const char *get_netsh_id (const char *dev_node, struct gc_arena *gc); - -static inline bool -tuntap_stop (int status) -{ - /* - * This corresponds to the STATUS_NO_SUCH_DEVICE - * error in tapdrvr.c. - */ - if (status < 0) - { - return openvpn_errno () == ERROR_FILE_NOT_FOUND; - } - return false; -} - -static inline int -tun_write_win32 (struct tuntap *tt, struct buffer *buf) -{ - int err = 0; - int status = 0; - if (overlapped_io_active (&tt->writes)) - { - status = tun_finalize (tt->hand, &tt->writes, NULL); - if (status < 0) - err = GetLastError (); - } - tun_write_queue (tt, buf); - if (status < 0) - { - SetLastError (err); - return status; - } - else - return BLEN (buf); -} - -static inline int -read_tun_buffered (struct tuntap *tt, struct buffer *buf, int maxsize) -{ - return tun_finalize (tt->hand, &tt->reads, buf); -} - -static inline int -write_tun_buffered (struct tuntap *tt, struct buffer *buf) -{ - return tun_write_win32 (tt, buf); -} - -#else - -static inline bool -tuntap_stop (int status) -{ - return false; -} - -#endif - -/* - * TUN/TAP I/O wait functions - */ - -static inline event_t -tun_event_handle (const struct tuntap *tt) -{ -#ifdef WIN32 - return &tt->rw_handle; -#else - return tt->fd; -#endif -} - -static inline unsigned int -tun_set (struct tuntap *tt, - struct event_set *es, - unsigned int rwflags, - void *arg, - unsigned int *persistent) -{ - if (tuntap_defined (tt)) - { - /* if persistent is defined, call event_ctl only if rwflags has changed since last call */ - if (!persistent || *persistent != rwflags) - { - event_ctl (es, tun_event_handle (tt), rwflags, arg); - if (persistent) - *persistent = rwflags; - } -#ifdef WIN32 - if (rwflags & EVENT_READ) - tun_read_queue (tt, 0); -#endif - tt->rwflags_debug = rwflags; - } - return rwflags; -} - -const char *tun_stat (const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc); - -#endif /* TUN_H */ diff --git a/openvpn/win32.h b/openvpn/win32.h deleted file mode 100755 index 12af854..0000000 --- a/openvpn/win32.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * 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 - * - * 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 diff --git a/threadutils.hpp b/threadutils.hpp new file mode 100644 index 0000000..ad45f68 --- /dev/null +++ b/threadutils.hpp @@ -0,0 +1,174 @@ +/* + * anytun + * + * The secure anycast tunneling protocol (satp) defines a protocol used + * for communication between any combination of unicast and anycast + * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel + * mode and allows tunneling of every ETHER TYPE protocol (e.g. + * ethernet, ip, arp ...). satp directly includes cryptography and + * message authentication based on the methodes used by SRTP. It is + * intended to deliver a generic, scaleable and secure solution for + * tunneling and relaying of packets of any protocol. + * + * + * Copyright (C) 2007 anytun.org + * + * 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 _THREADUTILS_HPP_ +#define _THREADUTILS_HPP_ + +#include +#include + +class Mutex +{ +public: + Mutex() + { + if(pthread_mutex_init(&mutex,NULL)) + throw std::runtime_error("can't create mutex"); + } + + ~Mutex() + { + pthread_mutex_destroy(&mutex); + } + +private: + Mutex(const Mutex& src); + void operator=(const Mutex& src); + + void lock() + { + if(pthread_mutex_lock(&mutex)) + throw std::runtime_error("can't lock mutex"); + } + + void unlock() + { + if(pthread_mutex_unlock(&mutex)) + throw std::runtime_error("can't unlock mutex"); + } + friend class Lock; + friend class Condition; + pthread_mutex_t mutex; +}; + + +class Lock +{ +public: + Lock(Mutex &m) : mutex(m) + { + mutex.lock(); + } + + ~Lock() + { + mutex.unlock(); + } + +private: + Lock(const Lock& src); + void operator=(const Lock& src); + + Mutex &mutex; +}; + +class Condition +{ +public: + Condition() + { + if(pthread_cond_init(&cond, NULL)) + throw std::runtime_error("can't create condition"); + } + + ~Condition() + { + pthread_cond_destroy(&cond); + } + + void wait() + { + mutex.lock(); + if(pthread_cond_wait(&cond, &mutex.mutex)) + { + mutex.unlock(); + throw std::runtime_error("error on waiting for condition"); + } + mutex.unlock(); + } + + void signal() + { + mutex.lock(); + if(pthread_cond_signal(&cond)) + { + mutex.unlock(); + throw std::runtime_error("can't signal condition"); + } + mutex.unlock(); + } + + void broadcast() + { + mutex.lock(); + if(pthread_cond_broadcast(&cond)) + { + mutex.unlock(); + throw std::runtime_error("can't broadcast condition"); + } + mutex.unlock(); + } + +private: + pthread_cond_t cond; + Mutex mutex; +}; + +class Semaphore +{ +public: + Semaphore(unsigned int initVal=0) + { + if(sem_init(&sem, 0, initVal)) + throw std::runtime_error("can't create semaphore"); + } + + ~Semaphore() + { + sem_destroy(&sem); + } + + void down() + { + if(sem_wait(&sem)) + throw std::runtime_error("error on semaphore down"); + } + + void up() + { + if(sem_post(&sem)) + throw std::runtime_error("error on semaphore up"); + } + +private: + sem_t sem; +}; + +#endif diff --git a/tunDevice.cpp b/tunDevice.cpp index e0fc270..b42e6ce 100644 --- a/tunDevice.cpp +++ b/tunDevice.cpp @@ -27,28 +27,75 @@ * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - +extern "C" { +#include "openvpn/config.h" +#include "openvpn/syshead.h" #include "openvpn/tun.h" +} + #include "tunDevice.h" -TunDevice::TunDevice(string dev_name) +TunDevice::TunDevice(const char* dev) { -// dev = init_tun(dev_name.c_str(), ... ); + dev_ = NULL; + + +// init_tun (const char *dev, /* --dev option */ +// const char *dev_type, /* --dev-type option */ +// const char *ifconfig_local_parm, /* --ifconfig parm 1 */ +// const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */ +// in_addr_t local_public, +// in_addr_t remote_public, +// const bool strict_warn, +// struct env_set *es) + +// init_tun_post (struct tuntap *tt, +// const struct frame *frame, +// const struct tuntap_options *options) + + +// open_tun (const char *dev, const char *dev_type, const char *dev_node, false, dev_) + +//------------------------ +// c->c1.tuntap = init_tun (c->options.dev, +// c->options.dev_type, +// c->options.ifconfig_local, +// c->options.ifconfig_remote_netmask, +// addr_host (&c->c1.link_socket_addr.local), +// addr_host (&c->c1.link_socket_addr.remote), +// !c->options.ifconfig_nowarn, +// c->c2.es); + +// init_tun_post (c->c1.tuntap, +// &c->c2.frame, +// &c->options.tuntap_options); + +// dev_ = init_tun(dev, + + } TunDevice::~TunDevice() { - close_tun(dev); + if(dev_) + close_tun(dev_); + } int TunDevice::read(uint8_t *buf, int len) { - return read_tun(dev, buf, len); + if(!dev_) + return -1; + + return read_tun(dev_, buf, len); } int TunDevice::write(uint8_t *buf, int len) { - return write_tun(dev, buf, len); + if(!dev_) + return -1; + + return write_tun(dev_, buf, len); } diff --git a/tunDevice.h b/tunDevice.h index 5602f90..487167a 100644 --- a/tunDevice.h +++ b/tunDevice.h @@ -28,12 +28,13 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "openvpn/tun.h" +#ifndef _TUNDEVICE_H_ +#define _TUNDEVICE_H_ class TunDevice { public: - TunDevice(string dev_name); + TunDevice(const char* dev); ~TunDevice(); int read(uint8_t *buf, int len); @@ -44,4 +45,6 @@ private: TunDevice(const TunDevice &src); struct tuntap *dev_; -} +}; + +#endif -- cgit v1.2.3