tun.h
6fbf66fa
 /*
  *  OpenVPN -- An application to securely tunnel IP networks
  *             over a single TCP/UDP port, with support for SSL/TLS-based
  *             session authentication and key exchange,
  *             packet encryption, packet authentication, and
  *             packet compression.
  *
d7fa38f2
  *  Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
6fbf66fa
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2
  *  as published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program (see the file COPYING included with this
  *  distribution); if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #ifndef 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
 
c67d59cd
 /* time constants for --ip-win32 adaptive */
 #define IPW32_SET_ADAPTIVE_DELAY_WINDOW 300
 #define IPW32_SET_ADAPTIVE_TRY_NETSH    20
 
6fbf66fa
 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" */
c67d59cd
 # define IPW32_SET_ADAPTIVE     4  /* "--ip-win32 adaptive" */
 # define IPW32_SET_N            5
6fbf66fa
   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 */
 
3c7f2f55
 # define TUNNEL_TOPOLOGY(tt) ((tt) ? ((tt)->topology) : TOP_UNDEF)
   int topology; /* one of the TOP_x values */
 
6fbf66fa
   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;
c67d59cd
 
   int standby_iter;
6fbf66fa
 #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,
0aee9ca7
 	     bool ipv6, int persist_mode, const char *username,
 	     const char *groupname, const struct tuntap_options *options);
6fbf66fa
 
 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 */
3c7f2f55
 			 int topology,          /* one of the TOP_x values */
6fbf66fa
 			 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);
 
 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);
 
3c7f2f55
 bool is_tun_p2p (const struct tuntap *tt);
 
f77c60d3
 void check_subnet_conflict (const in_addr_t ip,
 			    const in_addr_t netmask,
 			    const char *prefix);
 
 void warn_on_use_of_common_subnets (void);
 
6fbf66fa
 /*
  * 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);
3c7f2f55
 
 const IP_ADAPTER_INFO *get_adapter_info (DWORD index, struct gc_arena *gc);
 const IP_PER_ADAPTER_INFO *get_per_adapter_info (const DWORD index, struct gc_arena *gc);
5f31881e
 const IP_ADAPTER_INFO *get_adapter (const IP_ADAPTER_INFO *ai, DWORD index);
3c7f2f55
 
6fbf66fa
 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);
f77c60d3
 
 DWORD adapter_index_of_ip (const IP_ADAPTER_INFO *list,
 			   const in_addr_t ip,
 			   int *count,
 			   in_addr_t *netmask);
6fbf66fa
 
 void show_tap_win32_adapters (int msglev, int warnlev);
 void show_adapters (int msglev);
 
3c7f2f55
 void tap_allow_nonadmin_access (const char *dev_node);
 
6fbf66fa
 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);
 
c67d59cd
 void tun_standby_init (struct tuntap *tt);
a9c802b2
 bool tun_standby (struct tuntap *tt);
c67d59cd
 
6fbf66fa
 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);
 
 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;
 }
 
c67d59cd
 static inline void
 tun_standby_init (struct tuntap *tt)
 {
 }
 
a9c802b2
 static inline bool
c67d59cd
 tun_standby (struct tuntap *tt)
 {
a9c802b2
   return true;
c67d59cd
 }
 
6fbf66fa
 #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 */