summaryrefslogtreecommitdiff
path: root/src/openvpn/tun.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/tun.h')
-rw-r--r--src/openvpn/tun.h508
1 files changed, 266 insertions, 242 deletions
diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h
index 9b5a1b7..f4b600c 100644
--- a/src/openvpn/tun.h
+++ b/src/openvpn/tun.h
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@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
@@ -47,84 +47,84 @@
#define IPW32_SET_ADAPTIVE_TRY_NETSH 20
struct tuntap_options {
- /* --ip-win32 options */
- bool ip_win32_defined;
+ /* --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;
+#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;
#ifdef _WIN32
- HANDLE msg_channel;
+ HANDLE msg_channel;
#endif
- /* --ip-win32 dynamic options */
- bool dhcp_masq_custom_offset;
- int dhcp_masq_offset;
- int dhcp_lease_time;
+ /* --ip-win32 dynamic options */
+ bool dhcp_masq_custom_offset;
+ int dhcp_masq_offset;
+ int dhcp_lease_time;
- /* --tap-sleep option */
- int tap_sleep;
+ /* --tap-sleep option */
+ int tap_sleep;
- /* --dhcp-option options */
+ /* --dhcp-option options */
- bool dhcp_options;
+ bool dhcp_options;
- const char *domain; /* DOMAIN (15) */
+ const char *domain; /* DOMAIN (15) */
- const char *netbios_scope; /* NBS (47) */
+ const char *netbios_scope; /* NBS (47) */
- int netbios_node_type; /* NBT 1,2,4,8 (46) */
+ int netbios_node_type; /* NBT 1,2,4,8 (46) */
#define N_DHCP_ADDR 4 /* Max # of addresses allowed for
- DNS, WINS, etc. */
+ * DNS, WINS, etc. */
- /* DNS (6) */
- in_addr_t dns[N_DHCP_ADDR];
- int dns_len;
+ /* DNS (6) */
+ in_addr_t dns[N_DHCP_ADDR];
+ int dns_len;
- /* WINS (44) */
- in_addr_t wins[N_DHCP_ADDR];
- int wins_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;
+ /* NTP (42) */
+ in_addr_t ntp[N_DHCP_ADDR];
+ int ntp_len;
- /* NBDD (45) */
- in_addr_t nbdd[N_DHCP_ADDR];
- int nbdd_len;
+ /* NBDD (45) */
+ in_addr_t nbdd[N_DHCP_ADDR];
+ int nbdd_len;
- /* DISABLE_NBT (43, Vendor option 001) */
- bool disable_nbt;
+ /* DISABLE_NBT (43, Vendor option 001) */
+ bool disable_nbt;
- bool dhcp_renew;
- bool dhcp_pre_release;
- bool dhcp_release;
+ bool dhcp_renew;
+ bool dhcp_pre_release;
+ bool dhcp_release;
- bool register_dns;
+ bool register_dns;
- struct in6_addr dns6[N_DHCP_ADDR];
- int dns6_len;
+ struct in6_addr dns6[N_DHCP_ADDR];
+ int dns6_len;
};
#elif TARGET_LINUX
struct tuntap_options {
- int txqueuelen;
+ int txqueuelen;
};
-#else
+#else /* if defined(_WIN32) || defined(TARGET_ANDROID) */
struct tuntap_options {
- int dummy; /* not used */
+ int dummy; /* not used */
};
-#endif
+#endif /* if defined(_WIN32) || defined(TARGET_ANDROID) */
/*
* Define a TUN/TAP dev.
@@ -132,78 +132,78 @@ struct tuntap_options {
struct tuntap
{
-# define TUNNEL_TYPE(tt) ((tt) ? ((tt)->type) : DEV_TYPE_UNDEF)
- int type; /* DEV_TYPE_x as defined in proto.h */
+#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 */
+#define TUNNEL_TOPOLOGY(tt) ((tt) ? ((tt)->topology) : TOP_UNDEF)
+ int topology; /* one of the TOP_x values */
- bool did_ifconfig_setup;
- bool did_ifconfig_ipv6_setup;
- bool did_ifconfig;
+ bool did_ifconfig_setup;
+ bool did_ifconfig_ipv6_setup;
+ bool did_ifconfig;
- bool persistent_if; /* if existed before, keep on program end */
+ bool persistent_if; /* if existed before, keep on program end */
- struct tuntap_options options; /* options set on command line */
+ struct tuntap_options options; /* options set on command line */
- char *actual_name; /* actual name of TUN/TAP dev, usually including unit number */
+ char *actual_name; /* actual name of TUN/TAP dev, usually including unit number */
- /* number of TX buffers */
- int txqueuelen;
+ /* number of TX buffers */
+ int txqueuelen;
- /* ifconfig parameters */
- in_addr_t local;
- in_addr_t remote_netmask;
- in_addr_t broadcast;
+ /* ifconfig parameters */
+ in_addr_t local;
+ in_addr_t remote_netmask;
+ in_addr_t broadcast;
- struct in6_addr local_ipv6;
- struct in6_addr remote_ipv6;
- int netbits_ipv6;
+ struct in6_addr local_ipv6;
+ struct in6_addr remote_ipv6;
+ int netbits_ipv6;
#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-Windows adapter,
- ~0 if undefined */
- DWORD adapter_index;
-
- int standby_iter;
-#else
- int fd; /* file descriptor for TUN/TAP dev */
+ 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 */
#endif
#ifdef TARGET_SOLARIS
- int ip_fd;
+ int ip_fd;
#endif
#ifdef HAVE_NET_IF_UTUN_H
- bool is_utun;
+ bool is_utun;
#endif
- /* used for printing status info only */
- unsigned int rwflags_debug;
+ /* 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;
+ /* 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)
+tuntap_defined(const struct tuntap *tt)
{
#ifdef _WIN32
- return tt && tt->hand != NULL;
+ return tt && tt->hand != NULL;
#else
- return tt && tt->fd >= 0;
+ return tt && tt->fd >= 0;
#endif
}
@@ -211,71 +211,73 @@ tuntap_defined (const struct tuntap *tt)
* Function prototypes
*/
-void open_tun (const char *dev, const char *dev_type, const char *dev_node,
- struct tuntap *tt);
+void open_tun(const char *dev, const char *dev_type, const char *dev_node,
+ struct tuntap *tt);
-void close_tun (struct tuntap *tt);
+void close_tun(struct tuntap *tt);
-int write_tun (struct tuntap* tt, uint8_t *buf, int len);
+int write_tun(struct tuntap *tt, uint8_t *buf, int len);
-int read_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,
- int persist_mode, const char *username,
- const char *groupname, const struct tuntap_options *options);
+void tuncfg(const char *dev, const char *dev_type, const char *dev_node,
+ 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);
+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 */
- 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,
- struct env_set *es);
+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,
+ struct env_set *es);
-void init_tun_post (struct tuntap *tt,
- const struct frame *frame,
- const struct tuntap_options *options);
+void init_tun_post(struct tuntap *tt,
+ const struct frame *frame,
+ const struct tuntap_options *options);
-void do_ifconfig_setenv (const struct tuntap *tt,
- struct env_set *es);
+void do_ifconfig_setenv(const struct tuntap *tt,
+ struct env_set *es);
-void do_ifconfig (struct tuntap *tt,
- const char *actual, /* actual device name */
- int tun_mtu,
- const struct env_set *es);
+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);
+bool is_dev_type(const char *dev, const char *dev_type, const char *match_type);
-const char *ifconfig_options_string (const struct tuntap* tt, bool remote, bool disable, struct gc_arena *gc);
+int dev_type_enum(const char *dev, const char *dev_type);
-bool is_tun_p2p (const struct tuntap *tt);
+const char *dev_type_string(const char *dev, const char *dev_type);
-void check_subnet_conflict (const in_addr_t ip,
- const in_addr_t netmask,
- const char *prefix);
+const char *ifconfig_options_string(const struct tuntap *tt, bool remote, bool disable, struct gc_arena *gc);
-void warn_on_use_of_common_subnets (void);
+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);
/*
* Inline functions
*/
static inline void
-tun_adjust_frame_parameters (struct frame* frame, int size)
+tun_adjust_frame_parameters(struct frame *frame, int size)
{
- frame_add_to_extra_tun (frame, size);
+ frame_add_to_extra_tun(frame, size);
}
/*
@@ -292,21 +294,21 @@ static inline int
ifconfig_order(void)
{
#if defined(TARGET_LINUX)
- return IFCONFIG_AFTER_TUN_OPEN;
+ return IFCONFIG_AFTER_TUN_OPEN;
#elif defined(TARGET_SOLARIS)
- return IFCONFIG_AFTER_TUN_OPEN;
+ return IFCONFIG_AFTER_TUN_OPEN;
#elif defined(TARGET_OPENBSD)
- return IFCONFIG_AFTER_TUN_OPEN;
+ return IFCONFIG_AFTER_TUN_OPEN;
#elif defined(TARGET_DARWIN)
- return IFCONFIG_AFTER_TUN_OPEN;
+ return IFCONFIG_AFTER_TUN_OPEN;
#elif defined(TARGET_NETBSD)
- return IFCONFIG_AFTER_TUN_OPEN;
+ return IFCONFIG_AFTER_TUN_OPEN;
#elif defined(_WIN32)
- return IFCONFIG_AFTER_TUN_OPEN;
+ return IFCONFIG_AFTER_TUN_OPEN;
#elif defined(TARGET_ANDROID)
- return IFCONFIG_BEFORE_TUN_OPEN;
-#else
- return IFCONFIG_DEFAULT;
+ return IFCONFIG_BEFORE_TUN_OPEN;
+#else /* if defined(TARGET_LINUX) */
+ return IFCONFIG_DEFAULT;
#endif
}
@@ -331,186 +333,208 @@ route_order(void)
struct tap_reg
{
- const char *guid;
- struct tap_reg *next;
+ const char *guid;
+ struct tap_reg *next;
};
struct panel_reg
{
- const char *name;
- const char *guid;
- struct panel_reg *next;
+ 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);
+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);
-void verify_255_255_255_252 (in_addr_t local, in_addr_t remote);
+const IP_PER_ADAPTER_INFO *get_per_adapter_info(const DWORD index, struct gc_arena *gc);
-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(const IP_ADAPTER_INFO *ai, DWORD index);
-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_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);
+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,
- in_addr_t *netmask);
+DWORD adapter_index_of_ip(const IP_ADAPTER_INFO *list,
+ const in_addr_t ip,
+ int *count,
+ in_addr_t *netmask);
-void show_tap_win_adapters (int msglev, int warnlev);
-void show_adapters (int msglev);
+void show_tap_win_adapters(int msglev, int warnlev);
-void tap_allow_nonadmin_access (const char *dev_node);
+void show_adapters(int msglev);
-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);
+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);
bool dhcp_release_by_adapter_index(const DWORD adapter_index);
-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);
+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);
-void tun_standby_init (struct tuntap *tt);
-bool tun_standby (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);
+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)
+tuntap_stop(int status)
{
- /*
- * This corresponds to the STATUS_NO_SUCH_DEVICE
- * error in tapdrvr.c.
- */
- if (status < 0)
+ /*
+ * This corresponds to the STATUS_NO_SUCH_DEVICE
+ * error in tapdrvr.c.
+ */
+ if (status < 0)
{
- return openvpn_errno () == ERROR_FILE_NOT_FOUND;
+ return openvpn_errno() == ERROR_FILE_NOT_FOUND;
}
- return false;
+ return false;
}
static inline bool
tuntap_abort(int status)
{
- /*
- * Typically generated when driver is halted.
- */
- if (status < 0)
+ /*
+ * Typically generated when driver is halted.
+ */
+ if (status < 0)
{
- return openvpn_errno() == ERROR_OPERATION_ABORTED;
+ return openvpn_errno() == ERROR_OPERATION_ABORTED;
}
- return false;
+ return false;
}
static inline int
-tun_write_win32 (struct tuntap *tt, struct buffer *buf)
+tun_write_win32(struct tuntap *tt, struct buffer *buf)
{
- int err = 0;
- int status = 0;
- if (overlapped_io_active (&tt->writes))
+ 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)
{
- status = tun_finalize (tt->hand, &tt->writes, NULL);
- if (status < 0)
- err = GetLastError ();
+ SetLastError(err);
+ return status;
}
- tun_write_queue (tt, buf);
- if (status < 0)
+ else
{
- SetLastError (err);
- return status;
+ return BLEN(buf);
}
- else
- return BLEN (buf);
}
static inline int
-read_tun_buffered (struct tuntap *tt, struct buffer *buf, int maxsize)
+read_tun_buffered(struct tuntap *tt, struct buffer *buf, int maxsize)
{
- return tun_finalize (tt->hand, &tt->reads, buf);
+ return tun_finalize(tt->hand, &tt->reads, buf);
}
static inline int
-write_tun_buffered (struct tuntap *tt, struct buffer *buf)
+write_tun_buffered(struct tuntap *tt, struct buffer *buf)
{
- return tun_write_win32 (tt, buf);
+ return tun_write_win32(tt, buf);
}
-#else
+#else /* ifdef _WIN32 */
static inline bool
-tuntap_stop (int status)
+tuntap_stop(int status)
{
- return false;
+ return false;
}
static inline bool
tuntap_abort(int status)
{
- return false;
+ return false;
}
static inline void
-tun_standby_init (struct tuntap *tt)
+tun_standby_init(struct tuntap *tt)
{
}
static inline bool
-tun_standby (struct tuntap *tt)
+tun_standby(struct tuntap *tt)
{
- return true;
+ return true;
}
-#endif
+#endif /* ifdef _WIN32 */
/*
* TUN/TAP I/O wait functions
*/
static inline event_t
-tun_event_handle (const struct tuntap *tt)
+tun_event_handle(const struct tuntap *tt)
{
#ifdef _WIN32
- return &tt->rw_handle;
+ return &tt->rw_handle;
#else
- return tt->fd;
+ 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)
+tun_set(struct tuntap *tt,
+ struct event_set *es,
+ unsigned int rwflags,
+ void *arg,
+ unsigned int *persistent)
{
- if (tuntap_defined (tt))
+ 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;
- }
+ /* 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);
+ if (rwflags & EVENT_READ)
+ {
+ tun_read_queue(tt, 0);
+ }
#endif
- tt->rwflags_debug = rwflags;
+ tt->rwflags_debug = rwflags;
}
- return rwflags;
+ return rwflags;
}
-const char *tun_stat (const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc);
+const char *tun_stat(const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc);
#endif /* TUN_H */