mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-11-30 21:24:13 +08:00
0aee9ca7e7
by allowing openvpn --mktun to be used with --user and --group to set the UID/GID of the tun device node. Also added --iproute option to allow an alternative command to be executed in place of the default iproute2 command (Alon Bar-Lev). git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@2639 e7ae566f-a301-0410-adde-c780ea21d3b5
447 lines
10 KiB
C
447 lines
10 KiB
C
/*
|
|
* 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
|
|
|
|
/* time constants for --ip-win32 adaptive */
|
|
#define IPW32_SET_ADAPTIVE_DELAY_WINDOW 300
|
|
#define IPW32_SET_ADAPTIVE_TRY_NETSH 20
|
|
|
|
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_ADAPTIVE 4 /* "--ip-win32 adaptive" */
|
|
# define IPW32_SET_N 5
|
|
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 */
|
|
|
|
# define TUNNEL_TOPOLOGY(tt) ((tt) ? ((tt)->topology) : TOP_UNDEF)
|
|
int topology; /* one of the TOP_x values */
|
|
|
|
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;
|
|
|
|
int standby_iter;
|
|
#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 *username,
|
|
const char *groupname, const struct tuntap_options *options);
|
|
|
|
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 */
|
|
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 */
|
|
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);
|
|
|
|
bool is_tun_p2p (const struct tuntap *tt);
|
|
|
|
/*
|
|
* 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);
|
|
|
|
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);
|
|
const IP_ADAPTER_INFO *get_adapter (const IP_ADAPTER_INFO *ai, DWORD index);
|
|
|
|
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 tap_allow_nonadmin_access (const char *dev_node);
|
|
|
|
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);
|
|
|
|
void tun_standby_init (struct tuntap *tt);
|
|
bool tun_standby (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);
|
|
|
|
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;
|
|
}
|
|
|
|
static inline void
|
|
tun_standby_init (struct tuntap *tt)
|
|
{
|
|
}
|
|
|
|
static inline bool
|
|
tun_standby (struct tuntap *tt)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
#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 */
|