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 */ |