src/openvpn/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.
  *
49979459
  *  Copyright (C) 2002-2018 OpenVPN 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.
  *
caa54ac3
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6fbf66fa
  */
 
 #ifndef TUN_H
 #define TUN_H
 
445b192a
 #ifdef _WIN32
6fbf66fa
 #include <winioctl.h>
8e3ca1f6
 #include <tap-windows.h>
6fbf66fa
 #endif
 
 #include "buffer.h"
 #include "error.h"
 #include "mtu.h"
 #include "win32.h"
 #include "event.h"
 #include "proto.h"
 #include "misc.h"
dc7fcd71
 #include "networking.h"
6fbf66fa
 
445b192a
 #if defined(_WIN32) || defined(TARGET_ANDROID)
6fbf66fa
 
12e46092
 #define TUN_ADAPTER_INDEX_INVALID ((DWORD)-1)
 
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 {
81d882d5
     /* --ip-win32 options */
     bool ip_win32_defined;
6fbf66fa
 
81d882d5
 #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_ADAPTIVE     4   /* "--ip-win32 adaptive" */
 #define IPW32_SET_N            5
     int ip_win32_type;
6fbf66fa
 
445b192a
 #ifdef _WIN32
81d882d5
     HANDLE msg_channel;
a24dd2e3
 #endif
 
81d882d5
     /* --ip-win32 dynamic options */
     bool dhcp_masq_custom_offset;
     int dhcp_masq_offset;
     int dhcp_lease_time;
6fbf66fa
 
81d882d5
     /* --tap-sleep option */
     int tap_sleep;
6fbf66fa
 
81d882d5
     /* --dhcp-option options */
6fbf66fa
 
81d882d5
     bool dhcp_options;
6fbf66fa
 
81d882d5
     const char *domain;      /* DOMAIN (15) */
6fbf66fa
 
81d882d5
     const char *netbios_scope; /* NBS (47) */
6fbf66fa
 
81d882d5
     int netbios_node_type;   /* NBT 1,2,4,8 (46) */
6fbf66fa
 
 #define N_DHCP_ADDR 4        /* Max # of addresses allowed for
81d882d5
                               * DNS, WINS, etc. */
6fbf66fa
 
81d882d5
     /* DNS (6) */
     in_addr_t dns[N_DHCP_ADDR];
     int dns_len;
6fbf66fa
 
81d882d5
     /* WINS (44) */
     in_addr_t wins[N_DHCP_ADDR];
     int wins_len;
6fbf66fa
 
81d882d5
     /* NTP (42) */
     in_addr_t ntp[N_DHCP_ADDR];
     int ntp_len;
6fbf66fa
 
81d882d5
     /* NBDD (45) */
     in_addr_t nbdd[N_DHCP_ADDR];
     int nbdd_len;
6fbf66fa
 
81d882d5
     /* DISABLE_NBT (43, Vendor option 001) */
     bool disable_nbt;
6fbf66fa
 
81d882d5
     bool dhcp_renew;
     bool dhcp_pre_release;
b90c6f17
 
81d882d5
     bool register_dns;
786e06ad
 
81d882d5
     struct in6_addr dns6[N_DHCP_ADDR];
     int dns6_len;
6fbf66fa
 };
 
 #elif TARGET_LINUX
 
 struct tuntap_options {
81d882d5
     int txqueuelen;
6fbf66fa
 };
 
81d882d5
 #else  /* if defined(_WIN32) || defined(TARGET_ANDROID) */
6fbf66fa
 
 struct tuntap_options {
81d882d5
     int dummy; /* not used */
6fbf66fa
 };
 
81d882d5
 #endif /* if defined(_WIN32) || defined(TARGET_ANDROID) */
6fbf66fa
 
 /*
  * Define a TUN/TAP dev.
  */
 
 struct tuntap
 {
81d882d5
 #define TUNNEL_TYPE(tt) ((tt) ? ((tt)->type) : DEV_TYPE_UNDEF)
     int type; /* DEV_TYPE_x as defined in proto.h */
6fbf66fa
 
81d882d5
 #define TUNNEL_TOPOLOGY(tt) ((tt) ? ((tt)->topology) : TOP_UNDEF)
     int topology; /* one of the TOP_x values */
3c7f2f55
 
81d882d5
     bool did_ifconfig_setup;
     bool did_ifconfig_ipv6_setup;
6fbf66fa
 
81d882d5
     bool persistent_if;         /* if existed before, keep on program end */
3630a7a5
 
81d882d5
     struct tuntap_options options; /* options set on command line */
6fbf66fa
 
81d882d5
     char *actual_name; /* actual name of TUN/TAP dev, usually including unit number */
6fbf66fa
 
81d882d5
     /* number of TX buffers */
     int txqueuelen;
6fbf66fa
 
81d882d5
     /* ifconfig parameters */
     in_addr_t local;
     in_addr_t remote_netmask;
     in_addr_t broadcast;
6fbf66fa
 
81d882d5
     struct in6_addr local_ipv6;
     struct in6_addr remote_ipv6;
     int netbits_ipv6;
512cda46
 
445b192a
 #ifdef _WIN32
81d882d5
     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-Windows adapter,
      * ~0 if undefined */
     DWORD adapter_index;
 
     int standby_iter;
 #else  /* ifdef _WIN32 */
     int fd; /* file descriptor for TUN/TAP dev */
6fbf66fa
 #endif
 
 #ifdef TARGET_SOLARIS
81d882d5
     int ip_fd;
6fbf66fa
 #endif
 
fbc04bed
 #ifdef HAVE_NET_IF_UTUN_H
81d882d5
     bool is_utun;
fbc04bed
 #endif
81d882d5
     /* used for printing status info only */
     unsigned int rwflags_debug;
6fbf66fa
 
81d882d5
     /* Some TUN/TAP drivers like to be ioctled for mtu
      * after open */
     int post_open_mtu;
6fbf66fa
 };
 
 static inline bool
81d882d5
 tuntap_defined(const struct tuntap *tt)
6fbf66fa
 {
445b192a
 #ifdef _WIN32
81d882d5
     return tt && tt->hand != NULL;
6fbf66fa
 #else
81d882d5
     return tt && tt->fd >= 0;
6fbf66fa
 #endif
 }
 
 /*
  * Function prototypes
  */
 
81d882d5
 void open_tun(const char *dev, const char *dev_type, const char *dev_node,
               struct tuntap *tt);
6fbf66fa
 
dc7fcd71
 void close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx);
6fbf66fa
 
81d882d5
 int write_tun(struct tuntap *tt, uint8_t *buf, int len);
6fbf66fa
 
81d882d5
 int read_tun(struct tuntap *tt, uint8_t *buf, int len);
6fbf66fa
 
81d882d5
 void tuncfg(const char *dev, const char *dev_type, const char *dev_node,
             int persist_mode, const char *username,
dc7fcd71
             const char *groupname, const struct tuntap_options *options,
             openvpn_net_ctx_t *ctx);
6fbf66fa
 
81d882d5
 const char *guess_tuntap_dev(const char *dev,
                              const char *dev_type,
                              const char *dev_node,
                              struct gc_arena *gc);
6fbf66fa
 
81d882d5
 struct tuntap *init_tun(const char *dev,        /* --dev option */
                         const char *dev_type,   /* --dev-type option */
                         int topology,           /* one of the TOP_x values */
                         const char *ifconfig_local_parm,           /* --ifconfig parm 1 */
                         const char *ifconfig_remote_netmask_parm,  /* --ifconfig parm 2 */
                         const char *ifconfig_ipv6_local_parm,      /* --ifconfig parm 1 / IPv6 */
                         int ifconfig_ipv6_netbits_parm,            /* --ifconfig parm 1 / bits */
                         const char *ifconfig_ipv6_remote_parm,     /* --ifconfig parm 2 / IPv6 */
                         struct addrinfo *local_public,
                         struct addrinfo *remote_public,
                         const bool strict_warn,
dc7fcd71
                         struct env_set *es,
                         openvpn_net_ctx_t *ctx);
6fbf66fa
 
81d882d5
 void init_tun_post(struct tuntap *tt,
                    const struct frame *frame,
                    const struct tuntap_options *options);
6fbf66fa
 
81d882d5
 void do_ifconfig_setenv(const struct tuntap *tt,
                         struct env_set *es);
db950be8
 
611fcbc4
 /**
  * do_ifconfig - configure the tunnel interface
  *
  * @param tt        the tuntap interface context
  * @param ifname    the human readable interface name
  * @param mtu       the MTU value to set the interface to
  * @param es        the environment to be used when executing the commands
dc7fcd71
  * @param ctx       the networking API opaque context
611fcbc4
  */
 void do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu,
dc7fcd71
                  const struct env_set *es, openvpn_net_ctx_t *ctx);
6fbf66fa
 
81d882d5
 bool is_dev_type(const char *dev, const char *dev_type, const char *match_type);
6fbf66fa
 
81d882d5
 int dev_type_enum(const char *dev, const char *dev_type);
6fbf66fa
 
81d882d5
 const char *dev_type_string(const char *dev, const char *dev_type);
3c7f2f55
 
81d882d5
 const char *ifconfig_options_string(const struct tuntap *tt, bool remote, bool disable, struct gc_arena *gc);
f77c60d3
 
81d882d5
 bool is_tun_p2p(const struct tuntap *tt);
 
 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);
f77c60d3
 
6fbf66fa
 /*
  * Inline functions
  */
 
 static inline void
81d882d5
 tun_adjust_frame_parameters(struct frame *frame, int size)
6fbf66fa
 {
81d882d5
     frame_add_to_extra_tun(frame, size);
6fbf66fa
 }
 
 /*
  * 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)
81d882d5
     return IFCONFIG_AFTER_TUN_OPEN;
6fbf66fa
 #elif defined(TARGET_SOLARIS)
81d882d5
     return IFCONFIG_AFTER_TUN_OPEN;
6fbf66fa
 #elif defined(TARGET_OPENBSD)
81d882d5
     return IFCONFIG_AFTER_TUN_OPEN;
6fbf66fa
 #elif defined(TARGET_DARWIN)
81d882d5
     return IFCONFIG_AFTER_TUN_OPEN;
6fbf66fa
 #elif defined(TARGET_NETBSD)
81d882d5
     return IFCONFIG_AFTER_TUN_OPEN;
445b192a
 #elif defined(_WIN32)
81d882d5
     return IFCONFIG_AFTER_TUN_OPEN;
a55b3cdb
 #elif defined(TARGET_ANDROID)
81d882d5
     return IFCONFIG_BEFORE_TUN_OPEN;
 #else  /* if defined(TARGET_LINUX) */
     return IFCONFIG_DEFAULT;
6fbf66fa
 #endif
 }
 
94e6a2da
 #define ROUTE_BEFORE_TUN 0
 #define ROUTE_AFTER_TUN 1
 #define ROUTE_ORDER_DEFAULT ROUTE_AFTER_TUN
 
 static inline int
 route_order(void)
 {
a55b3cdb
 #if defined(TARGET_ANDROID)
     return ROUTE_BEFORE_TUN;
 #else
94e6a2da
     return ROUTE_ORDER_DEFAULT;
a55b3cdb
 #endif
94e6a2da
 }
 
 
445b192a
 #ifdef _WIN32
6fbf66fa
 
 #define TUN_PASS_BUFFER
 
 struct tap_reg
 {
81d882d5
     const char *guid;
     struct tap_reg *next;
6fbf66fa
 };
 
 struct panel_reg
 {
81d882d5
     const char *name;
     const char *guid;
     struct panel_reg *next;
6fbf66fa
 };
 
81d882d5
 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);
 
 const IP_ADAPTER_INFO *get_adapter_info(DWORD index, struct gc_arena *gc);
6fbf66fa
 
81d882d5
 const IP_PER_ADAPTER_INFO *get_per_adapter_info(const DWORD index, struct gc_arena *gc);
6fbf66fa
 
81d882d5
 const IP_ADAPTER_INFO *get_adapter(const IP_ADAPTER_INFO *ai, DWORD index);
3c7f2f55
 
81d882d5
 bool is_adapter_up(const struct tuntap *tt, const IP_ADAPTER_INFO *list);
3c7f2f55
 
81d882d5
 bool is_ip_in_adapter_subnet(const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask);
f77c60d3
 
81d882d5
 DWORD adapter_index_of_ip(const IP_ADAPTER_INFO *list,
                           const in_addr_t ip,
                           int *count,
                           in_addr_t *netmask);
6fbf66fa
 
81d882d5
 void show_tap_win_adapters(int msglev, int warnlev);
6fbf66fa
 
81d882d5
 void show_adapters(int msglev);
3c7f2f55
 
81d882d5
 void tap_allow_nonadmin_access(const char *dev_node);
 
 void show_valid_win32_tun_subnets(void);
 
 const char *tap_win_getinfo(const struct tuntap *tt, struct gc_arena *gc);
 
 void tun_show_debug(struct tuntap *tt);
6fbf66fa
 
5c30df12
 bool dhcp_release_by_adapter_index(const DWORD adapter_index);
6fbf66fa
 
81d882d5
 bool dhcp_renew_by_adapter_index(const DWORD adapter_index);
 
 void fork_register_dns_action(struct tuntap *tt);
 
 void ipconfig_register_dns(const struct env_set *es);
 
 void tun_standby_init(struct tuntap *tt);
b90c6f17
 
81d882d5
 bool tun_standby(struct tuntap *tt);
c67d59cd
 
81d882d5
 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);
6fbf66fa
 
 static inline bool
81d882d5
 tuntap_stop(int status)
6fbf66fa
 {
81d882d5
     /*
      * This corresponds to the STATUS_NO_SUCH_DEVICE
      * error in tapdrvr.c.
      */
     if (status < 0)
6fbf66fa
     {
81d882d5
         return openvpn_errno() == ERROR_FILE_NOT_FOUND;
6fbf66fa
     }
81d882d5
     return false;
6fbf66fa
 }
 
7aa17838
 static inline bool
 tuntap_abort(int status)
 {
81d882d5
     /*
      * Typically generated when driver is halted.
      */
     if (status < 0)
7aa17838
     {
81d882d5
         return openvpn_errno() == ERROR_OPERATION_ABORTED;
7aa17838
     }
81d882d5
     return false;
7aa17838
 }
 
6fbf66fa
 static inline int
81d882d5
 tun_write_win32(struct tuntap *tt, struct buffer *buf)
6fbf66fa
 {
81d882d5
     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)
6fbf66fa
     {
81d882d5
         SetLastError(err);
         return status;
6fbf66fa
     }
81d882d5
     else
6fbf66fa
     {
81d882d5
         return BLEN(buf);
6fbf66fa
     }
 }
 
 static inline int
91ba1add
 read_tun_buffered(struct tuntap *tt, struct buffer *buf)
6fbf66fa
 {
81d882d5
     return tun_finalize(tt->hand, &tt->reads, buf);
6fbf66fa
 }
 
 static inline int
81d882d5
 write_tun_buffered(struct tuntap *tt, struct buffer *buf)
6fbf66fa
 {
81d882d5
     return tun_write_win32(tt, buf);
6fbf66fa
 }
 
81d882d5
 #else  /* ifdef _WIN32 */
6fbf66fa
 
 static inline bool
81d882d5
 tuntap_stop(int status)
7aa17838
 {
81d882d5
     return false;
7aa17838
 }
 
 static inline bool
 tuntap_abort(int status)
6fbf66fa
 {
81d882d5
     return false;
6fbf66fa
 }
 
c67d59cd
 static inline void
81d882d5
 tun_standby_init(struct tuntap *tt)
c67d59cd
 {
 }
 
a9c802b2
 static inline bool
81d882d5
 tun_standby(struct tuntap *tt)
c67d59cd
 {
81d882d5
     return true;
c67d59cd
 }
 
81d882d5
 #endif /* ifdef _WIN32 */
6fbf66fa
 
 /*
  * TUN/TAP I/O wait functions
  */
 
 static inline event_t
81d882d5
 tun_event_handle(const struct tuntap *tt)
6fbf66fa
 {
445b192a
 #ifdef _WIN32
81d882d5
     return &tt->rw_handle;
6fbf66fa
 #else
81d882d5
     return tt->fd;
6fbf66fa
 #endif
 }
 
 static inline unsigned int
81d882d5
 tun_set(struct tuntap *tt,
         struct event_set *es,
         unsigned int rwflags,
         void *arg,
         unsigned int *persistent)
6fbf66fa
 {
81d882d5
     if (tuntap_defined(tt))
6fbf66fa
     {
81d882d5
         /* 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;
             }
         }
445b192a
 #ifdef _WIN32
81d882d5
         if (rwflags & EVENT_READ)
         {
             tun_read_queue(tt, 0);
         }
6fbf66fa
 #endif
81d882d5
         tt->rwflags_debug = rwflags;
6fbf66fa
     }
81d882d5
     return rwflags;
6fbf66fa
 }
 
81d882d5
 const char *tun_stat(const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc);
6fbf66fa
 
 #endif /* TUN_H */