diff options
Diffstat (limited to '')
-rw-r--r-- | tun.h | 413 |
1 files changed, 413 insertions, 0 deletions
@@ -0,0 +1,413 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TUN_H +#define TUN_H + +#ifdef WIN32 +#include <winioctl.h> +#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 */ |