summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2007-04-22 21:42:24 +0000
committerChristian Pointner <equinox@anytun.org>2007-04-22 21:42:24 +0000
commit69c04f4f3e0186b70cefe82952a31dadc58406ea (patch)
tree78893c2a2b0e98bf2631d42522f2bf616bb4c43b
parentenc (diff)
initial checkin tunDevice.cpp and h
-rw-r--r--openvpn/tun.c3446
-rw-r--r--openvpn/tun.c.flc4
-rw-r--r--openvpn/tun.h413
-rw-r--r--tunDevice.cpp25
-rw-r--r--tunDevice.h18
5 files changed, 3906 insertions, 0 deletions
diff --git a/openvpn/tun.c b/openvpn/tun.c
new file mode 100644
index 0000000..e904a0c
--- /dev/null
+++ b/openvpn/tun.c
@@ -0,0 +1,3446 @@
+/*
+ * 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
+ */
+
+/*
+ * Support routines for configuring and accessing TUN/TAP
+ * virtual network adapters.
+ *
+ * This file is based on the TUN/TAP driver interface routines
+ * from VTun by Maxim Krasnyansky <max_mk@yahoo.com>.
+ */
+
+#ifdef WIN32
+#include "config-win32.h"
+#else
+#include "config.h"
+#endif
+
+#include "syshead.h"
+
+#include "tun.h"
+#include "fdmisc.h"
+#include "common.h"
+#include "misc.h"
+#include "socket.h"
+#include "manage.h"
+
+#include "memdbg.h"
+
+#ifdef TARGET_SOLARIS
+static void solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual);
+#endif
+
+bool
+is_dev_type (const char *dev, const char *dev_type, const char *match_type)
+{
+ ASSERT (match_type);
+ if (!dev)
+ return false;
+ if (dev_type)
+ return !strcmp (dev_type, match_type);
+ else
+ return !strncmp (dev, match_type, strlen (match_type));
+}
+
+int
+dev_type_enum (const char *dev, const char *dev_type)
+{
+ if (is_dev_type (dev, dev_type, "tun"))
+ return DEV_TYPE_TUN;
+ else if (is_dev_type (dev, dev_type, "tap"))
+ return DEV_TYPE_TAP;
+ else if (is_dev_type (dev, dev_type, "null"))
+ return DEV_TYPE_NULL;
+ else
+ return DEV_TYPE_UNDEF;
+}
+
+const char *
+dev_type_string (const char *dev, const char *dev_type)
+{
+ switch (dev_type_enum (dev, dev_type))
+ {
+ case DEV_TYPE_TUN:
+ return "tun";
+ case DEV_TYPE_TAP:
+ return "tap";
+ case DEV_TYPE_NULL:
+ return "null";
+ default:
+ return "[unknown-dev-type]";
+ }
+}
+
+const char *
+dev_component_in_dev_node (const char *dev_node)
+{
+ const char *ret;
+ const int dirsep = OS_SPECIFIC_DIRSEP;
+
+ if (dev_node)
+ {
+ ret = strrchr (dev_node, dirsep);
+ if (ret && *ret)
+ ++ret;
+ else
+ ret = dev_node;
+ if (*ret)
+ return ret;
+ }
+ return NULL;
+}
+
+/*
+ * Try to predict the actual TUN/TAP device instance name,
+ * before the device is actually opened.
+ */
+const char *
+guess_tuntap_dev (const char *dev,
+ const char *dev_type,
+ const char *dev_node,
+ struct gc_arena *gc)
+{
+#ifdef WIN32
+ const int dt = dev_type_enum (dev, dev_type);
+ if (dt == DEV_TYPE_TUN || dt == DEV_TYPE_TAP)
+ {
+ return get_netsh_id (dev_node, gc);
+ }
+#endif
+
+ /* default case */
+ return dev;
+}
+
+/*
+ * Called by the open_tun function of OSes to check if we
+ * explicitly support IPv6.
+ *
+ * In this context, explicit means that the OS expects us to
+ * do something special to the tun socket in order to support
+ * IPv6, i.e. it is not transparent.
+ *
+ * ipv6_explicitly_supported should be set to false if we don't
+ * have any explicit IPv6 code in the tun device handler.
+ *
+ * If ipv6_explicitly_supported is true, then we have explicit
+ * OS-specific tun dev code for handling IPv6. If so, tt->ipv6
+ * is set according to the --tun-ipv6 command line option.
+ */
+static void
+ipv6_support (bool ipv6, bool ipv6_explicitly_supported, struct tuntap* tt)
+{
+ tt->ipv6 = false;
+ if (ipv6_explicitly_supported)
+ tt->ipv6 = ipv6;
+ else if (ipv6)
+ msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
+}
+
+/* --ifconfig-nowarn disables some options sanity checking */
+static const char ifconfig_warn_how_to_silence[] = "(silence this warning with --ifconfig-nowarn)";
+
+/*
+ * If !tun, make sure ifconfig_remote_netmask looks
+ * like a netmask.
+ *
+ * If tun, make sure ifconfig_remote_netmask looks
+ * like an IPv4 address.
+ */
+static void
+ifconfig_sanity_check (bool tun, in_addr_t addr)
+{
+ struct gc_arena gc = gc_new ();
+ const bool looks_like_netmask = ((addr & 0xFF000000) == 0xFF000000);
+ if (tun)
+ {
+ if (looks_like_netmask)
+ msg (M_WARN, "WARNING: Since you are using --dev tun, the second argument to --ifconfig must be an IP address. You are using something (%s) that looks more like a netmask. %s",
+ print_in_addr_t (addr, 0, &gc),
+ ifconfig_warn_how_to_silence);
+ }
+ else /* tap */
+ {
+ if (!looks_like_netmask)
+ msg (M_WARN, "WARNING: Since you are using --dev tap, the second argument to --ifconfig must be a netmask, for example something like 255.255.255.0. %s",
+ ifconfig_warn_how_to_silence);
+ }
+ gc_free (&gc);
+}
+
+/*
+ * For TAP-style devices, generate a broadcast address.
+ */
+static in_addr_t
+generate_ifconfig_broadcast_addr (in_addr_t local,
+ in_addr_t netmask)
+{
+ return local | ~netmask;
+}
+
+/*
+ * Check that --local and --remote addresses do not
+ * clash with ifconfig addresses or subnet.
+ */
+static void
+check_addr_clash (const char *name,
+ int type,
+ in_addr_t public,
+ in_addr_t local,
+ in_addr_t remote_netmask)
+{
+ struct gc_arena gc = gc_new ();
+#if 0
+ msg (M_INFO, "CHECK_ADDR_CLASH type=%d public=%s local=%s, remote_netmask=%s",
+ type,
+ print_in_addr_t (public, 0, &gc),
+ print_in_addr_t (local, 0, &gc),
+ print_in_addr_t (remote_netmask, 0, &gc));
+#endif
+
+ if (public)
+ {
+ if (type == DEV_TYPE_TUN)
+ {
+ const in_addr_t test_netmask = 0xFFFFFF00;
+ const in_addr_t public_net = public & test_netmask;
+ const in_addr_t local_net = local & test_netmask;
+ const in_addr_t remote_net = remote_netmask & test_netmask;
+
+ if (public == local || public == remote_netmask)
+ msg (M_WARN,
+ "WARNING: --%s address [%s] conflicts with --ifconfig address pair [%s, %s]. %s",
+ name,
+ print_in_addr_t (public, 0, &gc),
+ print_in_addr_t (local, 0, &gc),
+ print_in_addr_t (remote_netmask, 0, &gc),
+ ifconfig_warn_how_to_silence);
+
+ if (public_net == local_net || public_net == remote_net)
+ msg (M_WARN,
+ "WARNING: potential conflict between --%s address [%s] and --ifconfig address pair [%s, %s] -- this is a warning only that is triggered when local/remote addresses exist within the same /24 subnet as --ifconfig endpoints. %s",
+ name,
+ print_in_addr_t (public, 0, &gc),
+ print_in_addr_t (local, 0, &gc),
+ print_in_addr_t (remote_netmask, 0, &gc),
+ ifconfig_warn_how_to_silence);
+ }
+ else if (type == DEV_TYPE_TAP)
+ {
+ const in_addr_t public_network = public & remote_netmask;
+ const in_addr_t virtual_network = local & remote_netmask;
+ if (public_network == virtual_network)
+ msg (M_WARN,
+ "WARNING: --%s address [%s] conflicts with --ifconfig subnet [%s, %s] -- local and remote addresses cannot be inside of the --ifconfig subnet. %s",
+ name,
+ print_in_addr_t (public, 0, &gc),
+ print_in_addr_t (local, 0, &gc),
+ print_in_addr_t (remote_netmask, 0, &gc),
+ ifconfig_warn_how_to_silence);
+ }
+ }
+ gc_free (&gc);
+}
+
+/*
+ * Complain if --dev tap and --ifconfig is used on an OS for which
+ * we don't have a custom tap ifconfig template below.
+ */
+static void
+no_tap_ifconfig ()
+{
+ msg (M_FATAL, "Sorry but you cannot use --dev tap and --ifconfig together on this OS because I have not yet been programmed to understand the appropriate ifconfig syntax to use for TAP-style devices on this OS. Your best alternative is to use an --up script and do the ifconfig command manually.");
+}
+
+/*
+ * Return a string to be used for options compatibility check
+ * between peers.
+ */
+const char *
+ifconfig_options_string (const struct tuntap* tt, bool remote, bool disable, struct gc_arena *gc)
+{
+ struct buffer out = alloc_buf_gc (256, gc);
+ if (tt->did_ifconfig_setup && !disable)
+ {
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ const char *l, *r;
+ if (remote)
+ {
+ r = print_in_addr_t (tt->local, 0, gc);
+ l = print_in_addr_t (tt->remote_netmask, 0, gc);
+ }
+ else
+ {
+ l = print_in_addr_t (tt->local, 0, gc);
+ r = print_in_addr_t (tt->remote_netmask, 0, gc);
+ }
+ buf_printf (&out, "%s %s", r, l);
+ }
+ else if (tt->type == DEV_TYPE_TAP)
+ {
+ buf_printf (&out, "%s %s",
+ print_in_addr_t (tt->local & tt->remote_netmask, 0, gc),
+ print_in_addr_t (tt->remote_netmask, 0, gc));
+ }
+ else
+ buf_printf (&out, "[undef]");
+ }
+ return BSTR (&out);
+}
+
+/*
+ * Return a status string describing wait state.
+ */
+const char *
+tun_stat (const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc)
+{
+ struct buffer out = alloc_buf_gc (64, gc);
+ if (tt)
+ {
+ if (rwflags & EVENT_READ)
+ {
+ buf_printf (&out, "T%s",
+ (tt->rwflags_debug & EVENT_READ) ? "R" : "r");
+#ifdef WIN32
+ buf_printf (&out, "%s",
+ overlapped_io_state_ascii (&tt->reads));
+#endif
+ }
+ if (rwflags & EVENT_WRITE)
+ {
+ buf_printf (&out, "T%s",
+ (tt->rwflags_debug & EVENT_WRITE) ? "W" : "w");
+#ifdef WIN32
+ buf_printf (&out, "%s",
+ overlapped_io_state_ascii (&tt->writes));
+#endif
+ }
+ }
+ else
+ {
+ buf_printf (&out, "T?");
+ }
+ return BSTR (&out);
+}
+
+/*
+ * Init tun/tap object.
+ *
+ * Set up tuntap structure for ifconfig,
+ * but don't execute yet.
+ */
+struct tuntap *
+init_tun (const char *dev, /* --dev option */
+ const char *dev_type, /* --dev-type option */
+ 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)
+{
+ struct gc_arena gc = gc_new ();
+ struct tuntap *tt;
+
+ ALLOC_OBJ (tt, struct tuntap);
+ clear_tuntap (tt);
+
+ tt->type = dev_type_enum (dev, dev_type);
+
+ if (ifconfig_local_parm && ifconfig_remote_netmask_parm)
+ {
+ bool tun = false;
+ const char *ifconfig_local = NULL;
+ const char *ifconfig_remote_netmask = NULL;
+ const char *ifconfig_broadcast = NULL;
+
+ /*
+ * We only handle TUN/TAP devices here, not --dev null devices.
+ */
+ if (tt->type == DEV_TYPE_TUN)
+ tun = true;
+ else if (tt->type == DEV_TYPE_TAP)
+ tun = false;
+ else
+ msg (M_FATAL, "'%s' is not a TUN/TAP device. The --ifconfig option works only for TUN/TAP devices.", dev);
+
+ /*
+ * Convert arguments to binary IPv4 addresses.
+ */
+
+ tt->local = getaddr (
+ GETADDR_RESOLVE
+ | GETADDR_HOST_ORDER
+ | GETADDR_FATAL_ON_SIGNAL
+ | GETADDR_FATAL,
+ ifconfig_local_parm,
+ 0,
+ NULL,
+ NULL);
+
+ tt->remote_netmask = getaddr (
+ (tun ? GETADDR_RESOLVE : 0)
+ | GETADDR_HOST_ORDER
+ | GETADDR_FATAL_ON_SIGNAL
+ | GETADDR_FATAL,
+ ifconfig_remote_netmask_parm,
+ 0,
+ NULL,
+ NULL);
+
+ /*
+ * Look for common errors in --ifconfig parms
+ */
+ if (strict_warn)
+ {
+ ifconfig_sanity_check (tun, tt->remote_netmask);
+
+ /*
+ * If local_public or remote_public addresses are defined,
+ * make sure they do not clash with our virtual subnet.
+ */
+
+ check_addr_clash ("local",
+ tt->type,
+ local_public,
+ tt->local,
+ tt->remote_netmask);
+
+ check_addr_clash ("remote",
+ tt->type,
+ remote_public,
+ tt->local,
+ tt->remote_netmask);
+ }
+
+ /*
+ * Set ifconfig parameters
+ */
+ ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
+ ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
+
+ /*
+ * If TAP-style interface, generate broadcast address.
+ */
+ if (!tun)
+ {
+ tt->broadcast = generate_ifconfig_broadcast_addr (tt->local, tt->remote_netmask);
+ ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc);
+ }
+
+ /*
+ * Set environmental variables with ifconfig parameters.
+ */
+ if (es)
+ {
+ setenv_str (es, "ifconfig_local", ifconfig_local);
+ if (tun)
+ {
+ setenv_str (es, "ifconfig_remote", ifconfig_remote_netmask);
+ }
+ else
+ {
+ setenv_str (es, "ifconfig_netmask", ifconfig_remote_netmask);
+ setenv_str (es, "ifconfig_broadcast", ifconfig_broadcast);
+ }
+ }
+
+ tt->did_ifconfig_setup = true;
+ }
+ gc_free (&gc);
+ return tt;
+}
+
+/*
+ * Platform specific tun initializations
+ */
+void
+init_tun_post (struct tuntap *tt,
+ const struct frame *frame,
+ const struct tuntap_options *options)
+{
+ tt->options = *options;
+#ifdef WIN32
+ overlapped_io_init (&tt->reads, frame, FALSE, true);
+ overlapped_io_init (&tt->writes, frame, TRUE, true);
+ tt->rw_handle.read = tt->reads.overlapped.hEvent;
+ tt->rw_handle.write = tt->writes.overlapped.hEvent;
+ tt->adapter_index = ~0;
+#endif
+}
+
+/* execute the ifconfig command through the shell */
+void
+do_ifconfig (struct tuntap *tt,
+ const char *actual, /* actual device name */
+ int tun_mtu,
+ const struct env_set *es)
+{
+ struct gc_arena gc = gc_new ();
+
+ if (tt->did_ifconfig_setup)
+ {
+ bool tun = false;
+ const char *ifconfig_local = NULL;
+ const char *ifconfig_remote_netmask = NULL;
+ const char *ifconfig_broadcast = NULL;
+ char command_line[256];
+
+ /*
+ * We only handle TUN/TAP devices here, not --dev null devices.
+ */
+ if (tt->type == DEV_TYPE_TUN)
+ tun = true;
+ else if (tt->type == DEV_TYPE_TAP)
+ tun = false;
+ else
+ ASSERT (0); /* should have been caught in init_tun */
+
+ /*
+ * Set ifconfig parameters
+ */
+ ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
+ ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
+
+ /*
+ * If TAP-style device, generate broadcast address.
+ */
+ if (!tun)
+ ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc);
+
+#ifdef ENABLE_MANAGEMENT
+ if (management)
+ {
+ management_set_state (management,
+ OPENVPN_STATE_ASSIGN_IP,
+ NULL,
+ tt->local);
+ }
+#endif
+
+
+#if defined(TARGET_LINUX)
+#ifdef CONFIG_FEATURE_IPROUTE
+ /*
+ * Set the MTU for the device
+ */
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IPROUTE_PATH " link set dev %s up mtu %d",
+ actual,
+ tun_mtu
+ );
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "Linux ip link set failed");
+
+ if (tun) {
+
+ /*
+ * Set the address for the device
+ */
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IPROUTE_PATH " addr add dev %s local %s peer %s",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask
+ );
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "Linux ip addr add failed");
+ } else {
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IPROUTE_PATH " addr add dev %s %s/%d broadcast %s",
+ actual,
+ ifconfig_local,
+ count_netmask_bits(ifconfig_remote_netmask),
+ ifconfig_broadcast
+ );
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "Linux ip addr add failed");
+ }
+ tt->did_ifconfig = true;
+#else
+ if (tun)
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s pointopoint %s mtu %d",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+ else
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu,
+ ifconfig_broadcast
+ );
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "Linux ifconfig failed");
+ tt->did_ifconfig = true;
+
+#endif /*CONFIG_FEATURE_IPROUTE*/
+#elif defined(TARGET_SOLARIS)
+
+ /* Solaris 2.6 (and 7?) cannot set all parameters in one go...
+ * example:
+ * ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 up
+ * ifconfig tun2 netmask 255.255.255.255
+ */
+ if (tun)
+ {
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s %s mtu %d up",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+
+ msg (M_INFO, "%s", command_line);
+ if (!system_check (command_line, es, 0, "Solaris ifconfig phase-1 failed"))
+ solaris_error_close (tt, es, actual);
+
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s netmask 255.255.255.255",
+ actual
+ );
+ }
+ else
+ no_tap_ifconfig ();
+
+ msg (M_INFO, "%s", command_line);
+ if (!system_check (command_line, es, 0, "Solaris ifconfig phase-2 failed"))
+ solaris_error_close (tt, es, actual);
+
+ tt->did_ifconfig = true;
+
+#elif defined(TARGET_OPENBSD)
+
+ /*
+ * OpenBSD tun devices appear to be persistent by default. It seems in order
+ * to make this work correctly, we need to delete the previous instance
+ * (if it exists), and re-ifconfig. Let me know if you know a better way.
+ */
+
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s destroy",
+ actual);
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, 0, NULL);
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s create",
+ actual);
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, 0, NULL);
+ msg (M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure");
+
+ /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
+ if (tun)
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+ else
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s link0",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu,
+ ifconfig_broadcast
+ );
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "OpenBSD ifconfig failed");
+ tt->did_ifconfig = true;
+
+#elif defined(TARGET_NETBSD)
+
+ if (tun)
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+ else
+ /*
+ * NetBSD has distinct tun and tap devices
+ * so we don't need the "link0" extra parameter to specify we want to do
+ * tunneling at the ethernet level
+ */
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu,
+ ifconfig_broadcast
+ );
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "NetBSD ifconfig failed");
+ tt->did_ifconfig = true;
+
+#elif defined(TARGET_DARWIN)
+
+ /*
+ * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD...
+ */
+
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s delete",
+ actual);
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, 0, NULL);
+ msg (M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure");
+
+
+ /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
+ if (tun)
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+ else
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s netmask %s mtu %d up",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "Mac OS X ifconfig failed");
+ tt->did_ifconfig = true;
+
+#elif defined(TARGET_FREEBSD)
+
+ /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
+ if (tun)
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+ else
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s %s netmask %s mtu %d up",
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "FreeBSD ifconfig failed");
+ tt->did_ifconfig = true;
+
+#elif defined (WIN32)
+ {
+ const char *netmask;
+
+ /*
+ * Make sure that both ifconfig addresses are part of the
+ * same .252 subnet.
+ */
+ if (tun)
+ {
+ verify_255_255_255_252 (tt->local, tt->remote_netmask);
+ tt->adapter_netmask = ~3;
+ netmask = print_in_addr_t (tt->adapter_netmask, 0, &gc);
+ }
+ else
+ {
+ netmask = ifconfig_remote_netmask;
+ tt->adapter_netmask = tt->remote_netmask;
+ }
+
+ /* example: netsh interface ip set address my-tap static 10.3.0.1 255.255.255.0 */
+ openvpn_snprintf (command_line, sizeof (command_line),
+ "netsh interface ip set address \"%s\" static %s %s",
+ actual,
+ ifconfig_local,
+ netmask);
+
+ switch (tt->options.ip_win32_type)
+ {
+ case IPW32_SET_MANUAL:
+ msg (M_INFO, "******** NOTE: Please manually set the IP/netmask of '%s' to %s/%s (if it is not already set)",
+ actual,
+ ifconfig_local,
+ netmask);
+ break;
+ case IPW32_SET_NETSH:
+ if (!strcmp (actual, "NULL"))
+ msg (M_FATAL, "Error: When using --ip-win32 netsh, if you have more than one TAP-Win32 adapter, you must also specify --dev-node");
+ netcmd_semaphore_lock ();
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, S_FATAL, "ERROR: netsh command failed");
+ netcmd_semaphore_release ();
+ break;
+ }
+ tt->did_ifconfig = true;
+ }
+
+#else
+ msg (M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script.");
+#endif
+ }
+ gc_free (&gc);
+}
+
+void
+clear_tuntap (struct tuntap *tuntap)
+{
+ CLEAR (*tuntap);
+#ifdef WIN32
+ tuntap->hand = NULL;
+#else
+ tuntap->fd = -1;
+#endif
+#ifdef TARGET_SOLARIS
+ tuntap->ip_fd = -1;
+#endif
+ tuntap->ipv6 = false;
+}
+
+static void
+open_null (struct tuntap *tt)
+{
+ tt->actual_name = string_alloc ("null", NULL);
+}
+
+#ifndef WIN32
+static void
+open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
+ bool ipv6, bool ipv6_explicitly_supported, bool dynamic,
+ struct tuntap *tt)
+{
+ char tunname[256];
+ char dynamic_name[256];
+ bool dynamic_opened = false;
+
+ ipv6_support (ipv6, ipv6_explicitly_supported, tt);
+
+ if (tt->type == DEV_TYPE_NULL)
+ {
+ open_null (tt);
+ }
+ else
+ {
+ /*
+ * --dev-node specified, so open an explicit device node
+ */
+ if (dev_node)
+ {
+ openvpn_snprintf (tunname, sizeof (tunname), "%s", dev_node);
+ }
+ else
+ {
+ /*
+ * dynamic open is indicated by --dev specified without
+ * explicit unit number. Try opening /dev/[dev]n
+ * where n = [0, 255].
+ */
+ if (dynamic && !has_digit(dev))
+ {
+ int i;
+ for (i = 0; i < 256; ++i)
+ {
+ openvpn_snprintf (tunname, sizeof (tunname),
+ "/dev/%s%d", dev, i);
+ openvpn_snprintf (dynamic_name, sizeof (dynamic_name),
+ "%s%d", dev, i);
+ if ((tt->fd = open (tunname, O_RDWR)) > 0)
+ {
+ dynamic_opened = true;
+ break;
+ }
+ msg (D_READ_WRITE | M_ERRNO, "Tried opening %s (failed)", tunname);
+ }
+ if (!dynamic_opened)
+ msg (M_FATAL, "Cannot allocate TUN/TAP dev dynamically");
+ }
+ /*
+ * explicit unit number specified
+ */
+ else
+ {
+ openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s", dev);
+ }
+ }
+
+ if (!dynamic_opened)
+ {
+ if ((tt->fd = open (tunname, O_RDWR)) < 0)
+ msg (M_ERR, "Cannot open TUN/TAP dev %s", tunname);
+ }
+
+ set_nonblock (tt->fd);
+ set_cloexec (tt->fd); /* don't pass fd to scripts */
+ msg (M_INFO, "TUN/TAP device %s opened", tunname);
+
+ /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
+ tt->actual_name = string_alloc (dynamic_opened ? dynamic_name : dev, NULL);
+ }
+}
+
+static void
+close_tun_generic (struct tuntap *tt)
+{
+ if (tt->fd >= 0)
+ close (tt->fd);
+ if (tt->actual_name)
+ free (tt->actual_name);
+ clear_tuntap (tt);
+}
+
+#endif
+
+#if defined(TARGET_LINUX)
+
+#ifdef HAVE_LINUX_IF_TUN_H /* New driver support */
+
+#ifndef HAVE_LINUX_SOCKIOS_H
+#error header file linux/sockios.h required
+#endif
+
+#if defined(HAVE_TUN_PI) && defined(HAVE_IPHDR) && defined(HAVE_IOVEC) && defined(ETH_P_IPV6) && defined(ETH_P_IP) && defined(HAVE_READV) && defined(HAVE_WRITEV)
+#define LINUX_IPV6 1
+/* #warning IPv6 ON */
+#else
+#define LINUX_IPV6 0
+/* #warning IPv6 OFF */
+#endif
+
+#if !PEDANTIC
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ struct ifreq ifr;
+
+ /*
+ * Set tt->ipv6 to true if
+ * (a) we have the capability of supporting --tun-ipv6, and
+ * (b) --tun-ipv6 was specified.
+ */
+ ipv6_support (ipv6, LINUX_IPV6, tt);
+
+ /*
+ * We handle --dev null specially, we do not open /dev/null for this.
+ */
+ if (tt->type == DEV_TYPE_NULL)
+ {
+ open_null (tt);
+ }
+ else
+ {
+ /*
+ * Process --dev-node
+ */
+ const char *node = dev_node;
+ if (!node)
+ node = "/dev/net/tun";
+
+ /*
+ * Open the interface
+ */
+ if ((tt->fd = open (node, O_RDWR)) < 0)
+ {
+ msg (M_WARN | M_ERRNO, "Note: Cannot open TUN/TAP dev %s", node);
+ goto linux_2_2_fallback;
+ }
+
+ /*
+ * Process --tun-ipv6
+ */
+ CLEAR (ifr);
+ if (!tt->ipv6)
+ ifr.ifr_flags = IFF_NO_PI;
+
+#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
+ ifr.ifr_flags |= IFF_ONE_QUEUE;
+#endif
+
+ /*
+ * Figure out if tun or tap device
+ */
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ ifr.ifr_flags |= IFF_TUN;
+ }
+ else if (tt->type == DEV_TYPE_TAP)
+ {
+ ifr.ifr_flags |= IFF_TAP;
+ }
+ else
+ {
+ msg (M_FATAL, "I don't recognize device %s as a tun or tap device",
+ dev);
+ }
+
+ /*
+ * Set an explicit name, if --dev is not tun or tap
+ */
+ if (strcmp(dev, "tun") && strcmp(dev, "tap"))
+ strncpynt (ifr.ifr_name, dev, IFNAMSIZ);
+
+ /*
+ * Use special ioctl that configures tun/tap device with the parms
+ * we set in ifr
+ */
+ if (ioctl (tt->fd, TUNSETIFF, (void *) &ifr) < 0)
+ {
+ msg (M_WARN | M_ERRNO, "Note: Cannot ioctl TUNSETIFF %s", dev);
+ goto linux_2_2_fallback;
+ }
+
+ msg (M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);
+
+ /*
+ * Try making the TX send queue bigger
+ */
+#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
+ {
+ struct ifreq netifr;
+ int ctl_fd;
+
+ if ((ctl_fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0)
+ {
+ CLEAR (netifr);
+ strncpynt (netifr.ifr_name, ifr.ifr_name, IFNAMSIZ);
+ netifr.ifr_qlen = tt->options.txqueuelen;
+ if (ioctl (ctl_fd, SIOCSIFTXQLEN, (void *) &netifr) >= 0)
+ msg (D_OSBUF, "TUN/TAP TX queue length set to %d", tt->options.txqueuelen);
+ else
+ msg (M_WARN | M_ERRNO, "Note: Cannot set tx queue length on %s", ifr.ifr_name);
+ close (ctl_fd);
+ }
+ else
+ {
+ msg (M_WARN | M_ERRNO, "Note: Cannot open control socket on %s", ifr.ifr_name);
+ }
+ }
+#endif
+
+ set_nonblock (tt->fd);
+ set_cloexec (tt->fd);
+ tt->actual_name = string_alloc (ifr.ifr_name, NULL);
+ }
+ return;
+
+ linux_2_2_fallback:
+ msg (M_INFO, "Note: Attempting fallback to kernel 2.2 TUN/TAP interface");
+ if (tt->fd >= 0)
+ {
+ close (tt->fd);
+ tt->fd = -1;
+ }
+ open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
+}
+
+#else
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ ASSERT (0);
+}
+
+#endif
+
+#else
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
+}
+
+#endif /* HAVE_LINUX_IF_TUN_H */
+
+#ifdef TUNSETPERSIST
+
+void
+tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode)
+{
+ struct tuntap *tt;
+
+ ALLOC_OBJ (tt, struct tuntap);
+ clear_tuntap (tt);
+ tt->type = dev_type_enum (dev, dev_type);
+ open_tun (dev, dev_type, dev_node, ipv6, tt);
+ if (ioctl (tt->fd, TUNSETPERSIST, persist_mode) < 0)
+ msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
+ close_tun (tt);
+ msg (M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));
+}
+
+#endif /* TUNSETPERSIST */
+
+void
+close_tun (struct tuntap *tt)
+{
+ if (tt)
+ {
+ close_tun_generic (tt);
+ free (tt);
+ }
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+#if LINUX_IPV6
+ if (tt->ipv6)
+ {
+ struct tun_pi pi;
+ struct iphdr *iph;
+ struct iovec vect[2];
+ int ret;
+
+ iph = (struct iphdr *)buf;
+
+ pi.flags = 0;
+
+ if(iph->version == 6)
+ pi.proto = htons(ETH_P_IPV6);
+ else
+ pi.proto = htons(ETH_P_IP);
+
+ vect[0].iov_len = sizeof(pi);
+ vect[0].iov_base = &pi;
+ vect[1].iov_len = len;
+ vect[1].iov_base = buf;
+
+ ret = writev(tt->fd, vect, 2);
+ return(ret - sizeof(pi));
+ }
+ else
+#endif
+ return write (tt->fd, buf, len);
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+#if LINUX_IPV6
+ if (tt->ipv6)
+ {
+ struct iovec vect[2];
+ struct tun_pi pi;
+ int ret;
+
+ vect[0].iov_len = sizeof(pi);
+ vect[0].iov_base = &pi;
+ vect[1].iov_len = len;
+ vect[1].iov_base = buf;
+
+ ret = readv(tt->fd, vect, 2);
+ return(ret - sizeof(pi));
+ }
+ else
+#endif
+ return read (tt->fd, buf, len);
+}
+
+#elif defined(TARGET_SOLARIS)
+
+#ifndef TUNNEWPPA
+#error I need the symbol TUNNEWPPA from net/if_tun.h
+#endif
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ int if_fd, muxid, ppa = -1;
+ struct ifreq ifr;
+ const char *ptr;
+ const char *ip_node;
+ const char *dev_tuntap_type;
+ int link_type;
+ bool is_tun;
+
+ ipv6_support (ipv6, false, tt);
+
+ if (tt->type == DEV_TYPE_NULL)
+ {
+ open_null (tt);
+ return;
+ }
+
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ ip_node = "/dev/udp";
+ if (!dev_node)
+ dev_node = "/dev/tun";
+ dev_tuntap_type = "tun";
+ link_type = I_PLINK;
+ is_tun = true;
+ }
+ else if (tt->type == DEV_TYPE_TAP)
+ {
+ ip_node = "/dev/ip";
+ if (!dev_node)
+ dev_node = "/dev/tap";
+ dev_tuntap_type = "tap";
+ link_type = I_PLINK; /* was: I_LINK */
+ is_tun = false;
+ }
+ else
+ {
+ msg (M_FATAL, "I don't recognize device %s as a tun or tap device",
+ dev);
+ }
+
+ /* get unit number */
+ if (*dev)
+ {
+ ptr = dev;
+ while (*ptr && !isdigit ((int) *ptr))
+ ptr++;
+ ppa = atoi (ptr);
+ }
+
+ if ((tt->ip_fd = open (ip_node, O_RDWR, 0)) < 0)
+ msg (M_ERR, "Can't open %s", ip_node);
+
+ if ((tt->fd = open (dev_node, O_RDWR, 0)) < 0)
+ msg (M_ERR, "Can't open %s", dev_node);
+
+ /* Assign a new PPA and get its unit number. */
+ if ((ppa = ioctl (tt->fd, TUNNEWPPA, ppa)) < 0)
+ msg (M_ERR, "Can't assign new interface");
+
+ if ((if_fd = open (dev_node, O_RDWR, 0)) < 0)
+ msg (M_ERR, "Can't open %s (2)", dev_node);
+
+ if (ioctl (if_fd, I_PUSH, "ip") < 0)
+ msg (M_ERR, "Can't push IP module");
+
+ /* Assign ppa according to the unit number returned by tun device */
+ if (ioctl (if_fd, IF_UNITSEL, (char *) &ppa) < 0)
+ msg (M_ERR, "Can't set PPA %d", ppa);
+
+ if ((muxid = ioctl (tt->ip_fd, link_type, if_fd)) < 0)
+ msg (M_ERR, "Can't link %s device to IP", dev_tuntap_type);
+
+ close (if_fd);
+
+ tt->actual_name = (char *) malloc (32);
+ check_malloc_return (tt->actual_name);
+
+ openvpn_snprintf (tt->actual_name, 32, "%s%d", dev_tuntap_type, ppa);
+
+ CLEAR (ifr);
+ strncpynt (ifr.ifr_name, tt->actual_name, sizeof (ifr.ifr_name));
+ ifr.ifr_ip_muxid = muxid;
+
+ if (ioctl (tt->ip_fd, SIOCSIFMUXID, &ifr) < 0)
+ {
+ ioctl (tt->ip_fd, I_PUNLINK, muxid);
+ msg (M_ERR, "Can't set multiplexor id");
+ }
+
+ set_nonblock (tt->fd);
+ set_cloexec (tt->fd);
+ set_cloexec (tt->ip_fd);
+
+ msg (M_INFO, "TUN/TAP device %s opened", tt->actual_name);
+}
+
+static void
+solaris_close_tun (struct tuntap *tt)
+{
+ if (tt)
+ {
+ if (tt->ip_fd >= 0)
+ {
+ struct ifreq ifr;
+ CLEAR (ifr);
+ strncpynt (ifr.ifr_name, tt->actual_name, sizeof (ifr.ifr_name));
+
+ if (ioctl (tt->ip_fd, SIOCGIFFLAGS, &ifr) < 0)
+ msg (M_WARN | M_ERRNO, "Can't get iface flags");
+
+ if (ioctl (tt->ip_fd, SIOCGIFMUXID, &ifr) < 0)
+ msg (M_WARN | M_ERRNO, "Can't get multiplexor id");
+
+ if (ioctl (tt->ip_fd, I_PUNLINK, ifr.ifr_ip_muxid) < 0)
+ msg (M_WARN | M_ERRNO, "Can't unlink interface");
+
+ close (tt->ip_fd);
+ tt->ip_fd = -1;
+ }
+
+ if (tt->fd >= 0)
+ {
+ close (tt->fd);
+ tt->fd = -1;
+ }
+ }
+}
+
+/*
+ * Close TUN device.
+ */
+void
+close_tun (struct tuntap *tt)
+{
+ if (tt)
+ {
+ solaris_close_tun (tt);
+
+ if (tt->actual_name)
+ free (tt->actual_name);
+
+ clear_tuntap (tt);
+ free (tt);
+ }
+}
+
+static void
+solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual)
+{
+ char command_line[256];
+
+ openvpn_snprintf (command_line, sizeof (command_line),
+ IFCONFIG_PATH " %s unplumb",
+ actual);
+
+ msg (M_INFO, "%s", command_line);
+ system_check (command_line, es, 0, "Solaris ifconfig unplumb failed");
+ close_tun (tt);
+ msg (M_FATAL, "Solaris ifconfig failed");
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ struct strbuf sbuf;
+ sbuf.len = len;
+ sbuf.buf = (char *)buf;
+ return putmsg (tt->fd, NULL, &sbuf, 0) >= 0 ? sbuf.len : -1;
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ struct strbuf sbuf;
+ int f = 0;
+
+ sbuf.maxlen = len;
+ sbuf.buf = (char *)buf;
+ return getmsg (tt->fd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1;
+}
+
+#elif defined(TARGET_OPENBSD)
+
+#if !defined(HAVE_READV) || !defined(HAVE_WRITEV)
+#error openbsd build requires readv & writev library functions
+#endif
+
+/*
+ * OpenBSD has a slightly incompatible TUN device from
+ * the rest of the world, in that it prepends a
+ * uint32 to the beginning of the IP header
+ * to designate the protocol (why not just
+ * look at the version field in the IP header to
+ * determine v4 or v6?).
+ *
+ * We strip off this field on reads and
+ * put it back on writes.
+ *
+ * I have not tested TAP devices on OpenBSD,
+ * but I have conditionalized the special
+ * TUN handling code described above to
+ * go away for TAP devices.
+ */
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
+
+ /* Enable multicast on the interface */
+ if (tt->fd >= 0)
+ {
+ struct tuninfo info;
+
+ if (ioctl (tt->fd, TUNGIFINFO, &info) < 0) {
+ msg (M_WARN | M_ERRNO, "Can't get interface info: %s",
+ strerror(errno));
+ }
+
+ info.flags |= IFF_MULTICAST;
+
+ if (ioctl (tt->fd, TUNSIFINFO, &info) < 0) {
+ msg (M_WARN | M_ERRNO, "Can't set interface info: %s",
+ strerror(errno));
+ }
+ }
+}
+
+void
+close_tun (struct tuntap* tt)
+{
+ if (tt)
+ {
+ close_tun_generic (tt);
+ free (tt);
+ }
+}
+
+static inline int
+openbsd_modify_read_write_return (int len)
+{
+ if (len > 0)
+ return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
+ else
+ return len;
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ u_int32_t type;
+ struct iovec iv[2];
+ struct ip *iph;
+
+ iph = (struct ip *) buf;
+
+ if (tt->ipv6 && iph->ip_v == 6)
+ type = htonl (AF_INET6);
+ else
+ type = htonl (AF_INET);
+
+ iv[0].iov_base = &type;
+ iv[0].iov_len = sizeof (type);
+ iv[1].iov_base = buf;
+ iv[1].iov_len = len;
+
+ return openbsd_modify_read_write_return (writev (tt->fd, iv, 2));
+ }
+ else
+ return write (tt->fd, buf, len);
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ u_int32_t type;
+ struct iovec iv[2];
+
+ iv[0].iov_base = &type;
+ iv[0].iov_len = sizeof (type);
+ iv[1].iov_base = buf;
+ iv[1].iov_len = len;
+
+ return openbsd_modify_read_write_return (readv (tt->fd, iv, 2));
+ }
+ else
+ return read (tt->fd, buf, len);
+}
+
+#elif defined(TARGET_NETBSD)
+
+/*
+ * NetBSD does not support IPv6 on tun out of the box,
+ * but there exists a patch. When this patch is applied,
+ * only two things are left to openvpn:
+ * 1. Activate multicasting (this has already been done
+ * before by the kernel, but we make sure that nobody
+ * has deactivated multicasting inbetween.
+ * 2. Deactivate "link layer mode" (otherwise NetBSD
+ * prepends the address family to the packet, and we
+ * would run into the same trouble as with OpenBSD.
+ */
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
+ if (tt->fd >= 0)
+ {
+ int i = IFF_POINTOPOINT|IFF_MULTICAST;
+ ioctl (tt->fd, TUNSIFMODE, &i); /* multicast on */
+ i = 0;
+ ioctl (tt->fd, TUNSLMODE, &i); /* link layer mode off */
+ }
+}
+
+void
+close_tun (struct tuntap *tt)
+{
+ if (tt)
+ {
+ close_tun_generic (tt);
+ free (tt);
+ }
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ return write (tt->fd, buf, len);
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ return read (tt->fd, buf, len);
+}
+
+#elif defined(TARGET_FREEBSD)
+
+static inline int
+freebsd_modify_read_write_return (int len)
+{
+ if (len > 0)
+ return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
+ else
+ return len;
+}
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
+
+ if (tt->fd >= 0)
+ {
+ int i = 0;
+
+ /* Disable extended modes */
+ ioctl (tt->fd, TUNSLMODE, &i);
+ i = 1;
+ ioctl (tt->fd, TUNSIFHEAD, &i);
+ }
+}
+
+void
+close_tun (struct tuntap *tt)
+{
+ if (tt)
+ {
+ close_tun_generic (tt);
+ free (tt);
+ }
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ u_int32_t type;
+ struct iovec iv[2];
+ struct ip *iph;
+
+ iph = (struct ip *) buf;
+
+ if (tt->ipv6 && iph->ip_v == 6)
+ type = htonl (AF_INET6);
+ else
+ type = htonl (AF_INET);
+
+ iv[0].iov_base = (char *)&type;
+ iv[0].iov_len = sizeof (type);
+ iv[1].iov_base = buf;
+ iv[1].iov_len = len;
+
+ return freebsd_modify_read_write_return (writev (tt->fd, iv, 2));
+ }
+ else
+ return write (tt->fd, buf, len);
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ u_int32_t type;
+ struct iovec iv[2];
+
+ iv[0].iov_base = (char *)&type;
+ iv[0].iov_len = sizeof (type);
+ iv[1].iov_base = buf;
+ iv[1].iov_len = len;
+
+ return freebsd_modify_read_write_return (readv (tt->fd, iv, 2));
+ }
+ else
+ return read (tt->fd, buf, len);
+}
+
+#elif defined(WIN32)
+
+int
+tun_read_queue (struct tuntap *tt, int maxsize)
+{
+ if (tt->reads.iostate == IOSTATE_INITIAL)
+ {
+ DWORD len;
+ BOOL status;
+ int err;
+
+ /* reset buf to its initial state */
+ tt->reads.buf = tt->reads.buf_init;
+
+ len = maxsize ? maxsize : BLEN (&tt->reads.buf);
+ ASSERT (len <= BLEN (&tt->reads.buf));
+
+ /* the overlapped read will signal this event on I/O completion */
+ ASSERT (ResetEvent (tt->reads.overlapped.hEvent));
+
+ status = ReadFile(
+ tt->hand,
+ BPTR (&tt->reads.buf),
+ len,
+ &tt->reads.size,
+ &tt->reads.overlapped
+ );
+
+ if (status) /* operation completed immediately? */
+ {
+ /* since we got an immediate return, we must signal the event object ourselves */
+ ASSERT (SetEvent (tt->reads.overlapped.hEvent));
+
+ tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
+ tt->reads.status = 0;
+
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read immediate return [%d,%d]",
+ (int) len,
+ (int) tt->reads.size);
+ }
+ else
+ {
+ err = GetLastError ();
+ if (err == ERROR_IO_PENDING) /* operation queued? */
+ {
+ tt->reads.iostate = IOSTATE_QUEUED;
+ tt->reads.status = err;
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read queued [%d]",
+ (int) len);
+ }
+ else /* error occurred */
+ {
+ struct gc_arena gc = gc_new ();
+ ASSERT (SetEvent (tt->reads.overlapped.hEvent));
+ tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
+ tt->reads.status = err;
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read error [%d] : %s",
+ (int) len,
+ strerror_win32 (status, &gc));
+ gc_free (&gc);
+ }
+ }
+ }
+ return tt->reads.iostate;
+}
+
+int
+tun_write_queue (struct tuntap *tt, struct buffer *buf)
+{
+ if (tt->writes.iostate == IOSTATE_INITIAL)
+ {
+ BOOL status;
+ int err;
+
+ /* make a private copy of buf */
+ tt->writes.buf = tt->writes.buf_init;
+ tt->writes.buf.len = 0;
+ ASSERT (buf_copy (&tt->writes.buf, buf));
+
+ /* the overlapped write will signal this event on I/O completion */
+ ASSERT (ResetEvent (tt->writes.overlapped.hEvent));
+
+ status = WriteFile(
+ tt->hand,
+ BPTR (&tt->writes.buf),
+ BLEN (&tt->writes.buf),
+ &tt->writes.size,
+ &tt->writes.overlapped
+ );
+
+ if (status) /* operation completed immediately? */
+ {
+ tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN;
+
+ /* since we got an immediate return, we must signal the event object ourselves */
+ ASSERT (SetEvent (tt->writes.overlapped.hEvent));
+
+ tt->writes.status = 0;
+
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write immediate return [%d,%d]",
+ BLEN (&tt->writes.buf),
+ (int) tt->writes.size);
+ }
+ else
+ {
+ err = GetLastError ();
+ if (err == ERROR_IO_PENDING) /* operation queued? */
+ {
+ tt->writes.iostate = IOSTATE_QUEUED;
+ tt->writes.status = err;
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write queued [%d]",
+ BLEN (&tt->writes.buf));
+ }
+ else /* error occurred */
+ {
+ struct gc_arena gc = gc_new ();
+ ASSERT (SetEvent (tt->writes.overlapped.hEvent));
+ tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN;
+ tt->writes.status = err;
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write error [%d] : %s",
+ BLEN (&tt->writes.buf),
+ strerror_win32 (err, &gc));
+ gc_free (&gc);
+ }
+ }
+ }
+ return tt->writes.iostate;
+}
+
+int
+tun_finalize (
+ HANDLE h,
+ struct overlapped_io *io,
+ struct buffer *buf)
+{
+ int ret = -1;
+ BOOL status;
+
+ switch (io->iostate)
+ {
+ case IOSTATE_QUEUED:
+ status = GetOverlappedResult(
+ h,
+ &io->overlapped,
+ &io->size,
+ FALSE
+ );
+ if (status)
+ {
+ /* successful return for a queued operation */
+ if (buf)
+ *buf = io->buf;
+ ret = io->size;
+ io->iostate = IOSTATE_INITIAL;
+ ASSERT (ResetEvent (io->overlapped.hEvent));
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion success [%d]", ret);
+ }
+ else
+ {
+ /* error during a queued operation */
+ ret = -1;
+ if (GetLastError() != ERROR_IO_INCOMPLETE)
+ {
+ /* if no error (i.e. just not finished yet),
+ then DON'T execute this code */
+ io->iostate = IOSTATE_INITIAL;
+ ASSERT (ResetEvent (io->overlapped.hEvent));
+ msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion error");
+ }
+ }
+ break;
+
+ case IOSTATE_IMMEDIATE_RETURN:
+ io->iostate = IOSTATE_INITIAL;
+ ASSERT (ResetEvent (io->overlapped.hEvent));
+ if (io->status)
+ {
+ /* error return for a non-queued operation */
+ SetLastError (io->status);
+ ret = -1;
+ msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion non-queued error");
+ }
+ else
+ {
+ /* successful return for a non-queued operation */
+ if (buf)
+ *buf = io->buf;
+ ret = io->size;
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion non-queued success [%d]", ret);
+ }
+ break;
+
+ case IOSTATE_INITIAL: /* were we called without proper queueing? */
+ SetLastError (ERROR_INVALID_FUNCTION);
+ ret = -1;
+ dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion BAD STATE");
+ break;
+
+ default:
+ ASSERT (0);
+ }
+
+ if (buf)
+ buf->len = ret;
+ return ret;
+}
+
+const struct tap_reg *
+get_tap_reg (struct gc_arena *gc)
+{
+ HKEY adapter_key;
+ LONG status;
+ DWORD len;
+ struct tap_reg *first = NULL;
+ struct tap_reg *last = NULL;
+ int i = 0;
+
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ ADAPTER_KEY,
+ 0,
+ KEY_READ,
+ &adapter_key);
+
+ if (status != ERROR_SUCCESS)
+ msg (M_FATAL, "Error opening registry key: %s", ADAPTER_KEY);
+
+ while (true)
+ {
+ char enum_name[256];
+ char unit_string[256];
+ HKEY unit_key;
+ char component_id_string[] = "ComponentId";
+ char component_id[256];
+ char net_cfg_instance_id_string[] = "NetCfgInstanceId";
+ char net_cfg_instance_id[256];
+ DWORD data_type;
+
+ len = sizeof (enum_name);
+ status = RegEnumKeyEx(
+ adapter_key,
+ i,
+ enum_name,
+ &len,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (status == ERROR_NO_MORE_ITEMS)
+ break;
+ else if (status != ERROR_SUCCESS)
+ msg (M_FATAL, "Error enumerating registry subkeys of key: %s",
+ ADAPTER_KEY);
+
+ openvpn_snprintf (unit_string, sizeof(unit_string), "%s\\%s",
+ ADAPTER_KEY, enum_name);
+
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ unit_string,
+ 0,
+ KEY_READ,
+ &unit_key);
+
+ if (status != ERROR_SUCCESS)
+ dmsg (D_REGISTRY, "Error opening registry key: %s", unit_string);
+ else
+ {
+ len = sizeof (component_id);
+ status = RegQueryValueEx(
+ unit_key,
+ component_id_string,
+ NULL,
+ &data_type,
+ component_id,
+ &len);
+
+ if (status != ERROR_SUCCESS || data_type != REG_SZ)
+ dmsg (D_REGISTRY, "Error opening registry key: %s\\%s",
+ unit_string, component_id_string);
+ else
+ {
+ len = sizeof (net_cfg_instance_id);
+ status = RegQueryValueEx(
+ unit_key,
+ net_cfg_instance_id_string,
+ NULL,
+ &data_type,
+ net_cfg_instance_id,
+ &len);
+
+ if (status == ERROR_SUCCESS && data_type == REG_SZ)
+ {
+ if (!strcmp (component_id, TAP_COMPONENT_ID))
+ {
+ struct tap_reg *reg;
+ ALLOC_OBJ_CLEAR_GC (reg, struct tap_reg, gc);
+ reg->guid = string_alloc (net_cfg_instance_id, gc);
+
+ /* link into return list */
+ if (!first)
+ first = reg;
+ if (last)
+ last->next = reg;
+ last = reg;
+ }
+ }
+ }
+ RegCloseKey (unit_key);
+ }
+ ++i;
+ }
+
+ RegCloseKey (adapter_key);
+ return first;
+}
+
+const struct panel_reg *
+get_panel_reg (struct gc_arena *gc)
+{
+ LONG status;
+ HKEY network_connections_key;
+ DWORD len;
+ struct panel_reg *first = NULL;
+ struct panel_reg *last = NULL;
+ int i = 0;
+
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ NETWORK_CONNECTIONS_KEY,
+ 0,
+ KEY_READ,
+ &network_connections_key);
+
+ if (status != ERROR_SUCCESS)
+ msg (M_FATAL, "Error opening registry key: %s", NETWORK_CONNECTIONS_KEY);
+
+ while (true)
+ {
+ char enum_name[256];
+ char connection_string[256];
+ HKEY connection_key;
+ char name_data[256];
+ DWORD name_type;
+ const char name_string[] = "Name";
+
+ len = sizeof (enum_name);
+ status = RegEnumKeyEx(
+ network_connections_key,
+ i,
+ enum_name,
+ &len,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (status == ERROR_NO_MORE_ITEMS)
+ break;
+ else if (status != ERROR_SUCCESS)
+ msg (M_FATAL, "Error enumerating registry subkeys of key: %s",
+ NETWORK_CONNECTIONS_KEY);
+
+ openvpn_snprintf (connection_string, sizeof(connection_string),
+ "%s\\%s\\Connection",
+ NETWORK_CONNECTIONS_KEY, enum_name);
+
+ status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ connection_string,
+ 0,
+ KEY_READ,
+ &connection_key);
+
+ if (status != ERROR_SUCCESS)
+ dmsg (D_REGISTRY, "Error opening registry key: %s", connection_string);
+ else
+ {
+ len = sizeof (name_data);
+ status = RegQueryValueEx(
+ connection_key,
+ name_string,
+ NULL,
+ &name_type,
+ name_data,
+ &len);
+
+ if (status != ERROR_SUCCESS || name_type != REG_SZ)
+ dmsg (D_REGISTRY, "Error opening registry key: %s\\%s\\%s",
+ NETWORK_CONNECTIONS_KEY, connection_string, name_string);
+ else
+ {
+ struct panel_reg *reg;
+
+ ALLOC_OBJ_CLEAR_GC (reg, struct panel_reg, gc);
+ reg->name = string_alloc (name_data, gc);
+ reg->guid = string_alloc (enum_name, gc);
+
+ /* link into return list */
+ if (!first)
+ first = reg;
+ if (last)
+ last->next = reg;
+ last = reg;
+ }
+ RegCloseKey (connection_key);
+ }
+ ++i;
+ }
+
+ RegCloseKey (network_connections_key);
+
+ return first;
+}
+
+/*
+ * Check that two addresses are part of the same 255.255.255.252 subnet.
+ */
+void
+verify_255_255_255_252 (in_addr_t local, in_addr_t remote)
+{
+ struct gc_arena gc = gc_new ();
+ const unsigned int mask = 3;
+ const char *err = NULL;
+
+ if (local == remote)
+ {
+ err = "must be different";
+ goto error;
+ }
+ if ((local & (~mask)) != (remote & (~mask)))
+ {
+ err = "must exist within the same 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver";
+ goto error;
+ }
+ if ((local & mask) == 0
+ || (local & mask) == 3
+ || (remote & mask) == 0
+ || (remote & mask) == 3)
+ {
+ err = "cannot use the first or last address within a given 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver";
+ goto error;
+ }
+
+ gc_free (&gc);
+ return;
+
+ error:
+ msg (M_FATAL, "There is a problem in your selection of --ifconfig endpoints [local=%s, remote=%s]. The local and remote VPN endpoints %s. Try '" PACKAGE " --show-valid-subnets' option for more info.",
+ print_in_addr_t (local, 0, &gc),
+ print_in_addr_t (remote, 0, &gc),
+ err);
+ gc_free (&gc);
+}
+
+void show_valid_win32_tun_subnets (void)
+{
+ int i;
+ int col = 0;
+
+ printf ("On Windows, point-to-point IP support (i.e. --dev tun)\n");
+ printf ("is emulated by the TAP-Win32 driver. The major limitation\n");
+ printf ("imposed by this approach is that the --ifconfig local and\n");
+ printf ("remote endpoints must be part of the same 255.255.255.252\n");
+ printf ("subnet. The following list shows examples of endpoint\n");
+ printf ("pairs which satisfy this requirement. Only the final\n");
+ printf ("component of the IP address pairs is at issue.\n\n");
+ printf ("As an example, the following option would be correct:\n");
+ printf (" --ifconfig 10.7.0.5 10.7.0.6 (on host A)\n");
+ printf (" --ifconfig 10.7.0.6 10.7.0.5 (on host B)\n");
+ printf ("because [5,6] is part of the below list.\n\n");
+
+ for (i = 0; i < 256; i += 4)
+ {
+ printf("[%3d,%3d] ", i+1, i+2);
+ if (++col > 4)
+ {
+ col = 0;
+ printf ("\n");
+ }
+ }
+ if (col)
+ printf ("\n");
+}
+
+void
+show_tap_win32_adapters (int msglev, int warnlev)
+{
+ struct gc_arena gc = gc_new ();
+
+ bool warn_panel_null = false;
+ bool warn_panel_dup = false;
+ bool warn_tap_dup = false;
+
+ int links;
+
+ const struct tap_reg *tr;
+ const struct tap_reg *tr1;
+ const struct panel_reg *pr;
+
+ const struct tap_reg *tap_reg = get_tap_reg (&gc);
+ const struct panel_reg *panel_reg = get_panel_reg (&gc);
+
+ msg (msglev, "Available TAP-WIN32 adapters [name, GUID]:");
+
+ /* loop through each TAP-Win32 adapter registry entry */
+ for (tr = tap_reg; tr != NULL; tr = tr->next)
+ {
+ links = 0;
+
+ /* loop through each network connections entry in the control panel */
+ for (pr = panel_reg; pr != NULL; pr = pr->next)
+ {
+ if (!strcmp (tr->guid, pr->guid))
+ {
+ msg (msglev, "'%s' %s", pr->name, tr->guid);
+ ++links;
+ }
+ }
+
+ if (links > 1)
+ {
+ warn_panel_dup = true;
+ }
+ else if (links == 0)
+ {
+ /* a TAP adapter exists without a link from the network
+ connections control panel */
+ warn_panel_null = true;
+ msg (msglev, "[NULL] %s", tr->guid);
+ }
+ }
+
+ /* check for TAP-Win32 adapter duplicated GUIDs */
+ for (tr = tap_reg; tr != NULL; tr = tr->next)
+ {
+ for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next)
+ {
+ if (tr != tr1 && !strcmp (tr->guid, tr1->guid))
+ warn_tap_dup = true;
+ }
+ }
+
+ /* warn on registry inconsistencies */
+ if (warn_tap_dup)
+ msg (warnlev, "WARNING: Some TAP-Win32 adapters have duplicate GUIDs");
+
+ if (warn_panel_dup)
+ msg (warnlev, "WARNING: Some TAP-Win32 adapters have duplicate links from the Network Connections control panel");
+
+ if (warn_panel_null)
+ msg (warnlev, "WARNING: Some TAP-Win32 adapters have no link from the Network Connections control panel");
+
+ gc_free (&gc);
+}
+
+/*
+ * Confirm that GUID is a TAP-Win32 adapter.
+ */
+static bool
+is_tap_win32 (const char *guid, const struct tap_reg *tap_reg)
+{
+ const struct tap_reg *tr;
+
+ for (tr = tap_reg; tr != NULL; tr = tr->next)
+ {
+ if (guid && !strcmp (tr->guid, guid))
+ return true;
+ }
+
+ return false;
+}
+
+static const char *
+guid_to_name (const char *guid, const struct panel_reg *panel_reg)
+{
+ const struct panel_reg *pr;
+
+ for (pr = panel_reg; pr != NULL; pr = pr->next)
+ {
+ if (guid && !strcmp (pr->guid, guid))
+ return pr->name;
+ }
+
+ return NULL;
+}
+
+static const char *
+name_to_guid (const char *name, const struct tap_reg *tap_reg, const struct panel_reg *panel_reg)
+{
+ const struct panel_reg *pr;
+
+ for (pr = panel_reg; pr != NULL; pr = pr->next)
+ {
+ if (name && !strcmp (pr->name, name) && is_tap_win32 (pr->guid, tap_reg))
+ return pr->guid;
+ }
+
+ return NULL;
+}
+
+static void
+at_least_one_tap_win32 (const struct tap_reg *tap_reg)
+{
+ if (!tap_reg)
+ msg (M_FATAL, "There are no TAP-Win32 adapters on this system. You should be able to create a TAP-Win32 adapter by going to Start -> All Programs -> " PACKAGE_NAME " -> Add a new TAP-Win32 virtual ethernet adapter.");
+}
+
+/*
+ * Get an adapter GUID and optional actual_name from the
+ * registry for the TAP device # = device_number.
+ */
+static const char *
+get_unspecified_device_guid (const int device_number,
+ char *actual_name,
+ int actual_name_size,
+ const struct tap_reg *tap_reg_src,
+ const struct panel_reg *panel_reg_src,
+ struct gc_arena *gc)
+{
+ const struct tap_reg *tap_reg = tap_reg_src;
+ struct buffer ret = clear_buf ();
+ struct buffer actual = clear_buf ();
+ int i;
+
+ ASSERT (device_number >= 0);
+
+ /* Make sure we have at least one TAP adapter */
+ if (!tap_reg)
+ return NULL;
+
+ /* The actual_name output buffer may be NULL */
+ if (actual_name)
+ {
+ ASSERT (actual_name_size > 0);
+ buf_set_write (&actual, actual_name, actual_name_size);
+ }
+
+ /* Move on to specified device number */
+ for (i = 0; i < device_number; i++)
+ {
+ tap_reg = tap_reg->next;
+ if (!tap_reg)
+ return NULL;
+ }
+
+ /* Save Network Panel name (if exists) in actual_name */
+ if (actual_name)
+ {
+ const char *act = guid_to_name (tap_reg->guid, panel_reg_src);
+ if (act)
+ buf_printf (&actual, "%s", act);
+ else
+ buf_printf (&actual, "NULL");
+ }
+
+ /* Save GUID for return value */
+ ret = alloc_buf_gc (256, gc);
+ buf_printf (&ret, "%s", tap_reg->guid);
+ return BSTR (&ret);
+}
+
+/*
+ * Lookup a --dev-node adapter name in the registry
+ * returning the GUID and optional actual_name.
+ */
+static const char *
+get_device_guid (const char *name,
+ char *actual_name,
+ int actual_name_size,
+ const struct tap_reg *tap_reg,
+ const struct panel_reg *panel_reg,
+ struct gc_arena *gc)
+{
+ struct buffer ret = alloc_buf_gc (256, gc);
+ struct buffer actual = clear_buf ();
+
+ /* Make sure we have at least one TAP adapter */
+ if (!tap_reg)
+ return NULL;
+
+ /* The actual_name output buffer may be NULL */
+ if (actual_name)
+ {
+ ASSERT (actual_name_size > 0);
+ buf_set_write (&actual, actual_name, actual_name_size);
+ }
+
+ /* Check if GUID was explicitly specified as --dev-node parameter */
+ if (is_tap_win32 (name, tap_reg))
+ {
+ const char *act = guid_to_name (name, panel_reg);
+ buf_printf (&ret, "%s", name);
+ if (act)
+ buf_printf (&actual, "%s", act);
+ else
+ buf_printf (&actual, "NULL");
+ return BSTR (&ret);
+ }
+
+ /* Lookup TAP adapter in network connections list */
+ {
+ const char *guid = name_to_guid (name, tap_reg, panel_reg);
+ if (guid)
+ {
+ buf_printf (&actual, "%s", name);
+ buf_printf (&ret, "%s", guid);
+ return BSTR (&ret);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Return a TAP name for netsh commands.
+ */
+const char *
+get_netsh_id (const char *dev_node, struct gc_arena *gc)
+{
+ const struct tap_reg *tap_reg = get_tap_reg (gc);
+ const struct panel_reg *panel_reg = get_panel_reg (gc);
+ struct buffer actual = alloc_buf_gc (256, gc);
+ const char *guid;
+
+ at_least_one_tap_win32 (tap_reg);
+
+ if (dev_node)
+ {
+ guid = get_device_guid (dev_node, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc);
+ }
+ else
+ {
+ guid = get_unspecified_device_guid (0, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc);
+
+ if (get_unspecified_device_guid (1, NULL, 0, tap_reg, panel_reg, gc)) /* ambiguous if more than one TAP-Win32 adapter */
+ guid = NULL;
+ }
+
+ if (!guid)
+ return "NULL"; /* not found */
+ else if (strcmp (BPTR (&actual), "NULL"))
+ return BPTR (&actual); /* control panel name */
+ else
+ return guid; /* no control panel name, return GUID instead */
+}
+
+/*
+ * Get adapter info list
+ */
+const IP_ADAPTER_INFO *
+get_adapter_info_list (struct gc_arena *gc)
+{
+ ULONG size = 0;
+ IP_ADAPTER_INFO *pi = NULL;
+ DWORD status;
+
+ if ((status = GetAdaptersInfo (NULL, &size)) != ERROR_BUFFER_OVERFLOW)
+ {
+ msg (M_INFO, "GetAdaptersInfo #1 failed (status=%u) : %s",
+ (unsigned int)status,
+ strerror_win32 (status, gc));
+ }
+ else
+ {
+ pi = (PIP_ADAPTER_INFO) gc_malloc (size, false, gc);
+ if ((status = GetAdaptersInfo (pi, &size)) == NO_ERROR)
+ return pi;
+ else
+ {
+ msg (M_INFO, "GetAdaptersInfo #2 failed (status=%u) : %s",
+ (unsigned int)status,
+ strerror_win32 (status, gc));
+ }
+ }
+ return pi;
+}
+
+static const IP_INTERFACE_INFO *
+get_interface_info_list (struct gc_arena *gc)
+{
+ ULONG size = 0;
+ IP_INTERFACE_INFO *ii = NULL;
+ DWORD status;
+
+ if ((status = GetInterfaceInfo (NULL, &size)) != ERROR_INSUFFICIENT_BUFFER)
+ {
+ msg (M_INFO, "GetInterfaceInfo #1 failed (status=%u) : %s",
+ (unsigned int)status,
+ strerror_win32 (status, gc));
+ }
+ else
+ {
+ ii = (PIP_INTERFACE_INFO) gc_malloc (size, false, gc);
+ if ((status = GetInterfaceInfo (ii, &size)) == NO_ERROR)
+ return ii;
+ else
+ {
+ msg (M_INFO, "GetInterfaceInfo #2 failed (status=%u) : %s",
+ (unsigned int)status,
+ strerror_win32 (status, gc));
+ }
+ }
+ return ii;
+}
+
+static const IP_ADAPTER_INDEX_MAP *
+get_interface_info (DWORD index, struct gc_arena *gc)
+{
+ const IP_INTERFACE_INFO *list = get_interface_info_list (gc);
+ if (list)
+ {
+ int i;
+ for (i = 0; i < list->NumAdapters; ++i)
+ {
+ const IP_ADAPTER_INDEX_MAP *inter = &list->Adapter[i];
+ if (index == inter->Index)
+ return inter;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Given an adapter index, return a pointer to the
+ * IP_ADAPTER_INFO structure for that adapter.
+ */
+
+static const IP_ADAPTER_INFO *
+get_adapter (const IP_ADAPTER_INFO *ai, DWORD index)
+{
+ if (ai && index != (DWORD)~0)
+ {
+ const IP_ADAPTER_INFO *a;
+
+ /* find index in the linked list */
+ for (a = ai; a != NULL; a = a->Next)
+ {
+ if (a->Index == index)
+ return a;
+ }
+ }
+ return NULL;
+}
+
+static const IP_ADAPTER_INFO *
+get_adapter_info (DWORD index, struct gc_arena *gc)
+{
+ return get_adapter (get_adapter_info_list (gc), index);
+}
+
+static int
+get_adapter_n_ip_netmask (const IP_ADAPTER_INFO *ai)
+{
+ if (ai)
+ {
+ int n = 0;
+ const IP_ADDR_STRING *ip = &ai->IpAddressList;
+
+ while (ip)
+ {
+ ++n;
+ ip = ip->Next;
+ }
+ return n;
+ }
+ else
+ return 0;
+}
+
+static bool
+get_adapter_ip_netmask (const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, in_addr_t *netmask)
+{
+ bool ret = false;
+ *ip = 0;
+ *netmask = 0;
+
+ if (ai)
+ {
+ const IP_ADDR_STRING *iplist = &ai->IpAddressList;
+ int i = 0;
+
+ while (iplist)
+ {
+ if (i == n)
+ break;
+ ++i;
+ iplist = iplist->Next;
+ }
+
+ if (iplist)
+ {
+ const unsigned int getaddr_flags = GETADDR_HOST_ORDER;
+ const char *ip_str = iplist->IpAddress.String;
+ const char *netmask_str = iplist->IpMask.String;
+ bool succeed1 = false;
+ bool succeed2 = false;
+
+ if (ip_str && netmask_str && strlen (ip_str) && strlen (netmask_str))
+ {
+ *ip = getaddr (getaddr_flags, ip_str, 0, &succeed1, NULL);
+ *netmask = getaddr (getaddr_flags, netmask_str, 0, &succeed2, NULL);
+ ret = (succeed1 == true && succeed2 == true);
+ }
+ }
+ }
+
+ return ret;
+}
+
+const IP_ADAPTER_INFO *
+get_tun_adapter (const struct tuntap *tt, const IP_ADAPTER_INFO *list)
+{
+ if (list && tt)
+ return get_adapter (list, tt->adapter_index);
+ else
+ return NULL;
+}
+
+bool
+is_adapter_up (const struct tuntap *tt, const IP_ADAPTER_INFO *list)
+{
+ int i;
+ bool ret = false;
+
+ const IP_ADAPTER_INFO *ai = get_tun_adapter (tt, list);
+
+ if (ai)
+ {
+ const int n = get_adapter_n_ip_netmask (ai);
+
+ /* loop once for every IP/netmask assigned to adapter */
+ for (i = 0; i < n; ++i)
+ {
+ in_addr_t ip, netmask;
+ if (get_adapter_ip_netmask (ai, i, &ip, &netmask))
+ {
+ if (tt->local && tt->adapter_netmask)
+ {
+ /* wait for our --ifconfig parms to match the actual adapter parms */
+ if (tt->local == ip && tt->adapter_netmask == netmask)
+ ret = true;
+ }
+ else
+ {
+ /* --ifconfig was not defined, maybe using a real DHCP server */
+ if (ip && netmask)
+ ret = true;
+ }
+ }
+ }
+ }
+ else
+ ret = true; /* this can occur when TAP adapter is bridged */
+
+ return ret;
+}
+
+bool
+is_ip_in_adapter_subnet (const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask)
+{
+ int i;
+ bool ret = false;
+
+ if (highest_netmask)
+ *highest_netmask = 0;
+
+ if (ai)
+ {
+ const int n = get_adapter_n_ip_netmask (ai);
+ for (i = 0; i < n; ++i)
+ {
+ in_addr_t adapter_ip, adapter_netmask;
+ if (get_adapter_ip_netmask (ai, i, &adapter_ip, &adapter_netmask))
+ {
+ if (adapter_ip && adapter_netmask && (ip & adapter_netmask) == (adapter_ip & adapter_netmask))
+ {
+ if (highest_netmask && adapter_netmask > *highest_netmask)
+ *highest_netmask = adapter_netmask;
+ ret = true;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+DWORD
+adapter_index_of_ip (const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count)
+{
+ struct gc_arena gc = gc_new ();
+ DWORD ret = ~0;
+ in_addr_t highest_netmask = 0;
+ bool first = true;
+
+ if (count)
+ *count = 0;
+
+ while (list)
+ {
+ in_addr_t hn;
+
+ if (is_ip_in_adapter_subnet (list, ip, &hn))
+ {
+ if (first || hn > highest_netmask)
+ {
+ highest_netmask = hn;
+ if (count)
+ *count = 1;
+ ret = list->Index;
+ first = false;
+ }
+ else if (hn == highest_netmask)
+ {
+ if (count)
+ ++*count;
+ }
+ }
+ list = list->Next;
+ }
+
+ dmsg (D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d",
+ print_in_addr_t (ip, 0, &gc),
+ print_in_addr_t (highest_netmask, 0, &gc),
+ (int)ret,
+ count ? *count : -1);
+
+ if (ret == ~0 && count)
+ *count = 0;
+
+ gc_free (&gc);
+ return ret;
+}
+
+/*
+ * Given an adapter index, return true if the adapter
+ * is DHCP disabled.
+ */
+static bool
+dhcp_disabled (DWORD index)
+{
+ struct gc_arena gc = gc_new ();
+ const IP_ADAPTER_INFO *ai = get_adapter_info (index, &gc);
+ bool ret = false;
+
+ if (ai && !ai->DhcpEnabled)
+ ret = true;
+
+ gc_free (&gc);
+ return ret;
+}
+
+/*
+ * Delete all temporary address/netmask pairs which were added
+ * to adapter (given by index) by previous calls to AddIPAddress.
+ */
+static void
+delete_temp_addresses (DWORD index)
+{
+ struct gc_arena gc = gc_new ();
+ const IP_ADAPTER_INFO *a = get_adapter_info (index, &gc);
+
+ if (a)
+ {
+ const IP_ADDR_STRING *ip = &a->IpAddressList;
+ while (ip)
+ {
+ DWORD status;
+ const DWORD context = ip->Context;
+
+ if ((status = DeleteIPAddress ((ULONG) context)) == NO_ERROR)
+ {
+ msg (M_INFO, "Successfully deleted previously set dynamic IP/netmask: %s/%s",
+ ip->IpAddress.String,
+ ip->IpMask.String);
+ }
+ else
+ {
+ const char *empty = "0.0.0.0";
+ if (strcmp (ip->IpAddress.String, empty)
+ || strcmp (ip->IpMask.String, empty))
+ msg (M_INFO, "NOTE: could not delete previously set dynamic IP/netmask: %s/%s (status=%u)",
+ ip->IpAddress.String,
+ ip->IpMask.String,
+ (unsigned int)status);
+ }
+ ip = ip->Next;
+ }
+ }
+ gc_free (&gc);
+}
+
+/*
+ * Get interface index for use with IP Helper API functions.
+ */
+static DWORD
+get_interface_index (const char *guid)
+{
+ struct gc_arena gc = gc_new ();
+ ULONG index;
+ DWORD status;
+ wchar_t wbuf[256];
+ snwprintf (wbuf, SIZE (wbuf), L"\\DEVICE\\TCPIP_%S", guid);
+ wbuf [SIZE(wbuf) - 1] = 0;
+ if ((status = GetAdapterIndex (wbuf, &index)) != NO_ERROR)
+ {
+ msg (M_INFO, "NOTE: could not get adapter index for %S, status=%u : %s",
+ wbuf,
+ (unsigned int)status,
+ strerror_win32 (status, &gc));
+ gc_free (&gc);
+ return (DWORD)~0;
+ }
+ else
+ {
+ gc_free (&gc);
+ return index;
+ }
+}
+
+/*
+ * Return a string representing a PIP_ADDR_STRING
+ */
+static const char *
+format_ip_addr_string (const IP_ADDR_STRING *ip, struct gc_arena *gc)
+{
+ struct buffer out = alloc_buf_gc (256, gc);
+ while (ip)
+ {
+ buf_printf (&out, "%s", ip->IpAddress.String);
+ if (strlen (ip->IpMask.String))
+ {
+ buf_printf (&out, "/");
+ buf_printf (&out, "%s", ip->IpMask.String);
+ }
+ buf_printf (&out, " ");
+ ip = ip->Next;
+ }
+ return BSTR (&out);
+}
+
+/*
+ * Show info for a single adapter
+ */
+static void
+show_adapter (int msglev, const IP_ADAPTER_INFO *a, struct gc_arena *gc)
+{
+ msg (msglev, "%s", a->Description);
+ msg (msglev, " Index = %d", (int)a->Index);
+ msg (msglev, " GUID = %s", a->AdapterName);
+ msg (msglev, " IP = %s", format_ip_addr_string (&a->IpAddressList, gc));
+ msg (msglev, " MAC = %s", format_hex_ex (a->Address, a->AddressLength, 0, 1, ":", gc));
+ msg (msglev, " GATEWAY = %s", format_ip_addr_string (&a->GatewayList, gc));
+ if (a->DhcpEnabled)
+ {
+ msg (msglev, " DHCP SERV = %s", format_ip_addr_string (&a->DhcpServer, gc));
+ msg (msglev, " DHCP LEASE OBTAINED = %s", time_string (a->LeaseObtained, 0, false, gc));
+ msg (msglev, " DHCP LEASE EXPIRES = %s", time_string (a->LeaseExpires, 0, false, gc));
+ }
+ if (a->HaveWins)
+ {
+ msg (msglev, " PRI WINS = %s", format_ip_addr_string (&a->PrimaryWinsServer, gc));
+ msg (msglev, " SEC WINS = %s", format_ip_addr_string (&a->SecondaryWinsServer, gc));
+ }
+}
+
+/*
+ * Show current adapter list
+ */
+void
+show_adapters (int msglev)
+{
+ struct gc_arena gc = gc_new ();
+ const IP_ADAPTER_INFO *ai = get_adapter_info_list (&gc);
+
+ msg (msglev, "SYSTEM ADAPTER LIST");
+ if (ai)
+ {
+ const IP_ADAPTER_INFO *a;
+
+ /* find index in the linked list */
+ for (a = ai; a != NULL; a = a->Next)
+ {
+ show_adapter (msglev, a, &gc);
+ }
+ }
+ gc_free (&gc);
+}
+
+/*
+ * DHCP release/renewal
+ */
+
+bool
+dhcp_release (const struct tuntap *tt)
+{
+ struct gc_arena gc = gc_new ();
+ bool ret = false;
+ if (tt && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ && tt->adapter_index != ~0)
+ {
+ const IP_ADAPTER_INDEX_MAP *inter = get_interface_info (tt->adapter_index, &gc);
+ if (inter)
+ {
+ DWORD status = IpReleaseAddress ((IP_ADAPTER_INDEX_MAP *)inter);
+ if (status == NO_ERROR)
+ {
+ msg (D_TUNTAP_INFO, "TAP: DHCP address released");
+ ret = true;
+ }
+ else
+ msg (M_WARN, "NOTE: Release of DHCP-assigned IP address lease on TAP-Win32 adapter failed: %s (code=%u)",
+ strerror_win32 (status, &gc),
+ (unsigned int)status);
+ }
+ }
+ gc_free (&gc);
+ return ret;
+}
+
+bool
+dhcp_renew (const struct tuntap *tt)
+{
+ struct gc_arena gc = gc_new ();
+ bool ret = false;
+ if (tt && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ && tt->adapter_index != ~0)
+ {
+ const IP_ADAPTER_INDEX_MAP *inter = get_interface_info (tt->adapter_index, &gc);
+ if (inter)
+ {
+ DWORD status = IpRenewAddress ((IP_ADAPTER_INDEX_MAP *)inter);
+ if (status == NO_ERROR)
+ {
+ msg (D_TUNTAP_INFO, "TAP: DHCP address renewal succeeded");
+ ret = true;
+ }
+ else
+ msg (M_WARN, "WARNING: Failed to renew DHCP IP address lease on TAP-Win32 adapter: %s (code=%u)",
+ strerror_win32 (status, &gc),
+ (unsigned int)status);
+ }
+ }
+ gc_free (&gc);
+ return ret;
+}
+
+/*
+ * Convert DHCP options from the command line / config file
+ * into a raw DHCP-format options string.
+ */
+
+static void
+write_dhcp_u8 (struct buffer *buf, const int type, const int data)
+{
+ if (!buf_safe (buf, 3))
+ msg (M_FATAL, "write_dhcp_u8: buffer overflow building DHCP options");
+ buf_write_u8 (buf, type);
+ buf_write_u8 (buf, 1);
+ buf_write_u8 (buf, data);
+}
+
+static void
+write_dhcp_u32_array (struct buffer *buf, const int type, const uint32_t *data, const unsigned int len)
+{
+ if (len > 0)
+ {
+ int i;
+ const int size = len * sizeof (uint32_t);
+
+ if (!buf_safe (buf, 2 + size))
+ msg (M_FATAL, "write_dhcp_u32_array: buffer overflow building DHCP options");
+ if (size < 1 || size > 255)
+ msg (M_FATAL, "write_dhcp_u32_array: size (%d) must be > 0 and <= 255", size);
+ buf_write_u8 (buf, type);
+ buf_write_u8 (buf, size);
+ for (i = 0; i < len; ++i)
+ buf_write_u32 (buf, data[i]);
+ }
+}
+
+static void
+write_dhcp_str (struct buffer *buf, const int type, const char *str)
+{
+ const int len = strlen (str);
+ if (!buf_safe (buf, 2 + len))
+ msg (M_FATAL, "write_dhcp_str: buffer overflow building DHCP options");
+ if (len < 1 || len > 255)
+ msg (M_FATAL, "write_dhcp_str: string '%s' must be > 0 bytes and <= 255 bytes", str);
+ buf_write_u8 (buf, type);
+ buf_write_u8 (buf, len);
+ buf_write (buf, str, len);
+}
+
+static void
+build_dhcp_options_string (struct buffer *buf, const struct tuntap_options *o)
+{
+ if (o->domain)
+ write_dhcp_str (buf, 15, o->domain);
+
+ if (o->netbios_scope)
+ write_dhcp_str (buf, 47, o->netbios_scope);
+
+ if (o->netbios_node_type)
+ write_dhcp_u8 (buf, 46, o->netbios_node_type);
+
+ write_dhcp_u32_array (buf, 6, (uint32_t*)o->dns, o->dns_len);
+ write_dhcp_u32_array (buf, 44, (uint32_t*)o->wins, o->wins_len);
+ write_dhcp_u32_array (buf, 42, (uint32_t*)o->ntp, o->ntp_len);
+ write_dhcp_u32_array (buf, 45, (uint32_t*)o->nbdd, o->nbdd_len);
+
+ /* the MS DHCP server option 'Disable Netbios-over-TCP/IP
+ is implemented as vendor option 001, value 002.
+ A value of 001 means 'leave NBT alone' which is the default */
+ if (o->disable_nbt)
+ {
+ buf_write_u8 (buf, 43);
+ buf_write_u8 (buf, 6); /* total length field */
+ buf_write_u8 (buf, 0x001);
+ buf_write_u8 (buf, 4); /* length of the vendor specified field */
+ buf_write_u32 (buf, 0x002);
+ }
+}
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ struct gc_arena gc = gc_new ();
+ char device_path[256];
+ const char *device_guid = NULL;
+ DWORD len;
+
+ /*netcmd_semaphore_lock ();*/
+
+ ipv6_support (ipv6, false, tt);
+
+ if (tt->type == DEV_TYPE_NULL)
+ {
+ open_null (tt);
+ gc_free (&gc);
+ return;
+ }
+ else if (tt->type == DEV_TYPE_TAP || tt->type == DEV_TYPE_TUN)
+ {
+ ;
+ }
+ else
+ {
+ msg (M_FATAL|M_NOPREFIX, "Unknown virtual device type: '%s'", dev);
+ }
+
+ /*
+ * Lookup the device name in the registry, using the --dev-node high level name.
+ */
+ {
+ const struct tap_reg *tap_reg = get_tap_reg (&gc);
+ const struct panel_reg *panel_reg = get_panel_reg (&gc);
+ char guid_buffer[256];
+
+ at_least_one_tap_win32 (tap_reg);
+
+ if (dev_node)
+ {
+ /* Get the device GUID for the device specified with --dev-node. */
+ device_guid = get_device_guid (dev_node, guid_buffer, sizeof (guid_buffer), tap_reg, panel_reg, &gc);
+
+ if (!device_guid)
+ msg (M_FATAL, "TAP-Win32 adapter '%s' not found", dev_node);
+
+ /* Open Windows TAP-Win32 adapter */
+ openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s",
+ USERMODEDEVICEDIR,
+ device_guid,
+ TAPSUFFIX);
+
+ tt->hand = CreateFile (
+ device_path,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, /* was: FILE_SHARE_READ */
+ 0,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
+ 0
+ );
+
+ if (tt->hand == INVALID_HANDLE_VALUE)
+ msg (M_ERR, "CreateFile failed on TAP device: %s", device_path);
+ }
+ else
+ {
+ int device_number = 0;
+
+ /* Try opening all TAP devices until we find one available */
+ while (true)
+ {
+ device_guid = get_unspecified_device_guid (device_number,
+ guid_buffer,
+ sizeof (guid_buffer),
+ tap_reg,
+ panel_reg,
+ &gc);
+
+ if (!device_guid)
+ msg (M_FATAL, "All TAP-Win32 adapters on this system are currently in use.");
+
+ /* Open Windows TAP-Win32 adapter */
+ openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s",
+ USERMODEDEVICEDIR,
+ device_guid,
+ TAPSUFFIX);
+
+ tt->hand = CreateFile (
+ device_path,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, /* was: FILE_SHARE_READ */
+ 0,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
+ 0
+ );
+
+ if (tt->hand == INVALID_HANDLE_VALUE)
+ msg (D_TUNTAP_INFO, "CreateFile failed on TAP device: %s", device_path);
+ else
+ break;
+
+ device_number++;
+ }
+ }
+
+ /* translate high-level device name into a device instance
+ GUID using the registry */
+ tt->actual_name = string_alloc (guid_buffer, NULL);
+ }
+
+ msg (M_INFO, "TAP-WIN32 device [%s] opened: %s", tt->actual_name, device_path);
+
+ /* get driver version info */
+ {
+ ULONG info[3];
+ CLEAR (info);
+ if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_VERSION,
+ &info, sizeof (info),
+ &info, sizeof (info), &len, NULL))
+ {
+ msg (D_TUNTAP_INFO, "TAP-Win32 Driver Version %d.%d %s",
+ (int) info[0],
+ (int) info[1],
+ (info[2] ? "(DEBUG)" : ""));
+
+ }
+ if ( !(info[0] > TAP_WIN32_MIN_MAJOR
+ || (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) )
+ msg (M_FATAL, "ERROR: This version of " PACKAGE_NAME " requires a TAP-Win32 driver that is at least version %d.%d -- If you recently upgraded your " PACKAGE_NAME " distribution, a reboot is probably required at this point to get Windows to see the new driver.",
+ TAP_WIN32_MIN_MAJOR,
+ TAP_WIN32_MIN_MINOR);
+ }
+
+ /* get driver MTU */
+ {
+ ULONG mtu;
+ if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_MTU,
+ &mtu, sizeof (mtu),
+ &mtu, sizeof (mtu), &len, NULL))
+ {
+ tt->post_open_mtu = (int) mtu;
+ msg (D_MTU_INFO, "TAP-Win32 MTU=%d", (int) mtu);
+ }
+ }
+
+ /* set point-to-point mode if TUN device */
+
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ in_addr_t ep[2];
+ ep[0] = htonl (tt->local);
+ ep[1] = htonl (tt->remote_netmask);
+ if (!tt->did_ifconfig_setup)
+ {
+ msg (M_FATAL, "ERROR: --dev tun also requires --ifconfig");
+ }
+ if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_POINT_TO_POINT,
+ ep, sizeof (ep),
+ ep, sizeof (ep), &len, NULL))
+ msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set Point-to-Point mode, which is required for --dev tun");
+ }
+
+ /* should we tell the TAP-Win32 driver to masquerade as a DHCP server as a means
+ of setting the adapter address? */
+ if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ)
+ {
+ uint32_t ep[4];
+
+ /* We will answer DHCP requests with a reply to set IP/subnet to these values */
+ ep[0] = htonl (tt->local);
+ ep[1] = htonl (tt->adapter_netmask);
+
+ /* At what IP address should the DHCP server masquerade at? */
+ if (tt->type == DEV_TYPE_TUN)
+ {
+ ep[2] = htonl (tt->remote_netmask);
+ if (tt->options.dhcp_masq_custom_offset)
+ msg (M_WARN, "WARNING: because you are using '--dev tun' mode, the '--ip-win32 dynamic [offset]' option is ignoring the offset parameter");
+ }
+ else
+ {
+ in_addr_t dsa; /* DHCP server addr */
+
+ ASSERT (tt->type == DEV_TYPE_TAP);
+
+ if (tt->options.dhcp_masq_offset < 0)
+ dsa = (tt->local | (~tt->adapter_netmask)) + tt->options.dhcp_masq_offset;
+ else
+ dsa = (tt->local & tt->adapter_netmask) + tt->options.dhcp_masq_offset;
+
+ if (dsa == tt->local)
+ msg (M_FATAL, "ERROR: There is a clash between the --ifconfig local address and the internal DHCP server address -- both are set to %s -- please use the --ip-win32 dynamic option to choose a different free address from the --ifconfig subnet for the internal DHCP server", print_in_addr_t (dsa, 0, &gc));
+
+ if ((tt->local & tt->adapter_netmask) != (dsa & tt->adapter_netmask))
+ msg (M_FATAL, "ERROR: --tap-win32 dynamic [offset] : offset is outside of --ifconfig subnet");
+
+ ep[2] = htonl (dsa);
+ }
+
+ /* lease time in seconds */
+ ep[3] = (uint32_t) tt->options.dhcp_lease_time;
+
+ ASSERT (ep[3] > 0);
+
+ if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_MASQ,
+ ep, sizeof (ep),
+ ep, sizeof (ep), &len, NULL))
+ msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set TAP_IOCTL_CONFIG_DHCP_MASQ mode");
+
+ msg (M_INFO, "Notified TAP-Win32 driver to set a DHCP IP/netmask of %s/%s on interface %s [DHCP-serv: %s, lease-time: %d]",
+ print_in_addr_t (tt->local, 0, &gc),
+ print_in_addr_t (tt->adapter_netmask, 0, &gc),
+ device_guid,
+ print_in_addr_t (ep[2], IA_NET_ORDER, &gc),
+ ep[3]
+ );
+
+ /* user-supplied DHCP options capability */
+ if (tt->options.dhcp_options)
+ {
+ struct buffer buf = alloc_buf (256);
+ build_dhcp_options_string (&buf, &tt->options);
+ msg (D_DHCP_OPT, "DHCP option string: %s", format_hex (BPTR (&buf), BLEN (&buf), 0, &gc));
+ if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_SET_OPT,
+ BPTR (&buf), BLEN (&buf),
+ BPTR (&buf), BLEN (&buf), &len, NULL))
+ msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a TAP_IOCTL_CONFIG_DHCP_SET_OPT DeviceIoControl call");
+ free_buf (&buf);
+ }
+ }
+
+ /* set driver media status to 'connected' */
+ {
+ ULONG status = TRUE;
+ if (!DeviceIoControl (tt->hand, TAP_IOCTL_SET_MEDIA_STATUS,
+ &status, sizeof (status),
+ &status, sizeof (status), &len, NULL))
+ msg (M_WARN, "WARNING: The TAP-Win32 driver rejected a TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.");
+ }
+
+ /* possible wait for adapter to come up */
+ {
+ int s = tt->options.tap_sleep;
+ if (s > 0)
+ {
+ msg (M_INFO, "Sleeping for %d seconds...", s);
+ openvpn_sleep (s);
+ }
+ }
+
+ /* possibly use IP Helper API to set IP address on adapter */
+ {
+ DWORD index = get_interface_index (device_guid);
+ tt->adapter_index = index;
+
+ /* flush arp cache */
+ if (index != (DWORD)~0)
+ {
+ DWORD status;
+
+ if ((status = FlushIpNetTable (index)) == NO_ERROR)
+ msg (M_INFO, "Successful ARP Flush on interface [%u] %s",
+ (unsigned int)index,
+ device_guid);
+ else
+ msg (M_WARN, "NOTE: FlushIpNetTable failed on interface [%u] %s (status=%u) : %s",
+ (unsigned int)index,
+ device_guid,
+ (unsigned int)status,
+ strerror_win32 (status, &gc));
+ }
+
+ /*
+ * If the TAP-Win32 driver is masquerading as a DHCP server
+ * make sure the TCP/IP properties for the adapter are
+ * set correctly.
+ */
+ if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ)
+ {
+ /* check dhcp enable status */
+ if (dhcp_disabled (index))
+ msg (M_WARN, "WARNING: You have selected '--ip-win32 dynamic', which will not work unless the TAP-Win32 TCP/IP properties are set to 'Obtain an IP address automatically'");
+
+ /* force an explicit DHCP lease renewal on TAP adapter? */
+ if (tt->options.dhcp_pre_release)
+ dhcp_release (tt);
+ if (tt->options.dhcp_renew)
+ dhcp_renew (tt);
+ }
+
+ if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_IPAPI)
+ {
+ DWORD status;
+ const char *error_suffix = "I am having trouble using the Windows 'IP helper API' to automatically set the IP address -- consider using other --ip-win32 methods (not 'ipapi')";
+
+ /* couldn't get adapter index */
+ if (index == (DWORD)~0)
+ {
+ msg (M_FATAL, "ERROR: unable to get adapter index for interface %s -- %s",
+ device_guid,
+ error_suffix);
+ }
+
+ /* check dhcp enable status */
+ if (dhcp_disabled (index))
+ msg (M_WARN, "NOTE: You have selected (explicitly or by default) '--ip-win32 ipapi', which has a better chance of working correctly if the TAP-Win32 TCP/IP properties are set to 'Obtain an IP address automatically'");
+
+ /* delete previously added IP addresses which were not
+ correctly deleted */
+ delete_temp_addresses (index);
+
+ /* add a new IP address */
+ if ((status = AddIPAddress (htonl(tt->local),
+ htonl(tt->adapter_netmask),
+ index,
+ &tt->ipapi_context,
+ &tt->ipapi_instance)) == NO_ERROR)
+ msg (M_INFO, "Succeeded in adding a temporary IP/netmask of %s/%s to interface %s using the Win32 IP Helper API",
+ print_in_addr_t (tt->local, 0, &gc),
+ print_in_addr_t (tt->adapter_netmask, 0, &gc),
+ device_guid
+ );
+ else
+ msg (M_FATAL, "ERROR: AddIPAddress %s/%s failed on interface %s, index=%d, status=%u (windows error: '%s') -- %s",
+ print_in_addr_t (tt->local, 0, &gc),
+ print_in_addr_t (tt->adapter_netmask, 0, &gc),
+ device_guid,
+ (int)index,
+ (unsigned int)status,
+ strerror_win32 (status, &gc),
+ error_suffix);
+ tt->ipapi_context_defined = true;
+ }
+ }
+ /*netcmd_semaphore_release ();*/
+ gc_free (&gc);
+}
+
+const char *
+tap_win32_getinfo (const struct tuntap *tt, struct gc_arena *gc)
+{
+ if (tt && tt->hand != NULL)
+ {
+ struct buffer out = alloc_buf_gc (256, gc);
+ DWORD len;
+ if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_INFO,
+ BSTR (&out), BCAP (&out),
+ BSTR (&out), BCAP (&out),
+ &len, NULL))
+ {
+ return BSTR (&out);
+ }
+ }
+ return NULL;
+}
+
+void
+tun_show_debug (struct tuntap *tt)
+{
+ if (tt && tt->hand != NULL)
+ {
+ struct buffer out = alloc_buf (1024);
+ DWORD len;
+ while (DeviceIoControl (tt->hand, TAP_IOCTL_GET_LOG_LINE,
+ BSTR (&out), BCAP (&out),
+ BSTR (&out), BCAP (&out),
+ &len, NULL))
+ {
+ msg (D_TAP_WIN32_DEBUG, "TAP-Win32: %s", BSTR (&out));
+ }
+ free_buf (&out);
+ }
+}
+
+void
+close_tun (struct tuntap *tt)
+{
+ struct gc_arena gc = gc_new ();
+
+ if (tt)
+ {
+#if 1
+ if (tt->ipapi_context_defined)
+ {
+ DWORD status;
+ if ((status = DeleteIPAddress (tt->ipapi_context)) != NO_ERROR)
+ {
+ msg (M_WARN, "Warning: DeleteIPAddress[%u] failed on TAP-Win32 adapter, status=%u : %s",
+ (unsigned int)tt->ipapi_context,
+ (unsigned int)status,
+ strerror_win32 (status, &gc));
+ }
+ }
+#endif
+
+ if (tt->options.dhcp_release)
+ dhcp_release (tt);
+
+ if (tt->hand != NULL)
+ {
+ dmsg (D_WIN32_IO_LOW, "Attempting CancelIO on TAP-Win32 adapter");
+ if (!CancelIo (tt->hand))
+ msg (M_WARN | M_ERRNO, "Warning: CancelIO failed on TAP-Win32 adapter");
+ }
+
+ dmsg (D_WIN32_IO_LOW, "Attempting close of overlapped read event on TAP-Win32 adapter");
+ overlapped_io_close (&tt->reads);
+
+ dmsg (D_WIN32_IO_LOW, "Attempting close of overlapped write event on TAP-Win32 adapter");
+ overlapped_io_close (&tt->writes);
+
+ if (tt->hand != NULL)
+ {
+ dmsg (D_WIN32_IO_LOW, "Attempting CloseHandle on TAP-Win32 adapter");
+ if (!CloseHandle (tt->hand))
+ msg (M_WARN | M_ERRNO, "Warning: CloseHandle failed on TAP-Win32 adapter");
+ }
+
+ if (tt->actual_name)
+ free (tt->actual_name);
+
+ clear_tuntap (tt);
+ free (tt);
+ }
+ gc_free (&gc);
+}
+
+/*
+ * Convert --ip-win32 constants between index and ascii form.
+ */
+
+struct ipset_names {
+ const char *short_form;
+};
+
+/* Indexed by IPW32_SET_x */
+static const struct ipset_names ipset_names[] = {
+ {"manual"},
+ {"netsh"},
+ {"ipapi"},
+ {"dynamic"}
+};
+
+int
+ascii2ipset (const char* name)
+{
+ int i;
+ ASSERT (IPW32_SET_N == SIZE (ipset_names));
+ for (i = 0; i < IPW32_SET_N; ++i)
+ if (!strcmp (name, ipset_names[i].short_form))
+ return i;
+ return -1;
+}
+
+const char *
+ipset2ascii (int index)
+{
+ ASSERT (IPW32_SET_N == SIZE (ipset_names));
+ if (index < 0 || index >= IPW32_SET_N)
+ return "[unknown --ip-win32 type]";
+ else
+ return ipset_names[index].short_form;
+}
+
+const char *
+ipset2ascii_all (struct gc_arena *gc)
+{
+ struct buffer out = alloc_buf_gc (256, gc);
+ int i;
+
+ ASSERT (IPW32_SET_N == SIZE (ipset_names));
+ for (i = 0; i < IPW32_SET_N; ++i)
+ {
+ if (i)
+ buf_printf(&out, " ");
+ buf_printf(&out, "[%s]", ipset2ascii(i));
+ }
+ return BSTR (&out);
+}
+
+#else /* generic */
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
+{
+ open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
+}
+
+void
+close_tun (struct tuntap* tt)
+{
+ if (tt)
+ {
+ close_tun_generic (tt);
+ free (tt);
+ }
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ return write (tt->fd, buf, len);
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ return read (tt->fd, buf, len);
+}
+
+#endif
diff --git a/openvpn/tun.c.flc b/openvpn/tun.c.flc
new file mode 100644
index 0000000..66cbb76
--- /dev/null
+++ b/openvpn/tun.c.flc
@@ -0,0 +1,4 @@
+
+(fast-lock-cache-data 3 (quote (17963 . 52656)) (quote nil) (quote nil) (quote (t ("^\\(\\sw+\\)[ ]*(" (1 font-lock-function-name-face)) ("^#[ ]*error[ ]+\\(.+\\)" (1 font-lock-warning-face prepend)) ("^#[ ]*\\(import\\|include\\)[ ]*\\(<[^>\"
+]*>?\\)" (2 font-lock-string-face)) ("^#[ ]*define[ ]+\\(\\sw+\\)(" (1 font-lock-function-name-face)) ("^#[ ]*\\(elif\\|if\\)\\>" ("\\<\\(defined\\)\\>[ ]*(?\\(\\sw+\\)?" nil nil (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t))) ("^#[ ]*\\(define\\|e\\(?:l\\(?:if\\|se\\)\\|ndif\\|rror\\)\\|file\\|i\\(?:f\\(?:n?def\\)?\\|nclude\\)\\|line\\|pragma\\|undef\\)\\>[ !]*\\(\\sw+\\)?" (1 font-lock-builtin-face) (2 font-lock-variable-name-face nil t)) ("\\<\\(c\\(?:har\\|omplex\\)\\|double\\|float\\|int\\|long\\|s\\(?:hort\\|igned\\)\\|\\(?:unsigne\\|voi\\)d\\|FILE\\|\\sw+_t\\|Lisp_Object\\)\\>" (0 font-lock-type-face)) ("\\<\\(auto\\|break\\|con\\(?:st\\|tinue\\)\\|do\\|e\\(?:lse\\|xtern\\)\\|for\\|if\\|re\\(?:gister\\|strict\\|turn\\)\\|s\\(?:izeof\\|tatic\\|witch\\)\\|typedef\\|\\(?:volat\\|wh\\)ile\\|enum\\|struct\\|union\\)\\>" (0 font-lock-keyword-face)) ("\\<\\(case\\|goto\\)\\>" (1 font-lock-keyword-face) ("\\(-[0-9]+\\|\\sw+\\)" (save-excursion (skip-chars-forward "^:
+") (point)) nil (1 font-lock-constant-face nil t))) (":" ("^[ ]*\\(\\sw+\\)[ ]*:[ ]*$" (beginning-of-line) (end-of-line) (1 font-lock-constant-face))) ("\\<\\(c\\(?:har\\|omplex\\)\\|double\\|float\\|int\\|long\\|s\\(?:hort\\|igned\\)\\|\\(?:unsigne\\|voi\\)d\\|FILE\\|\\sw+_t\\|Lisp_Object\\)\\>\\([ *&]+\\sw+\\>\\)*" (font-lock-match-c-style-declaration-item-and-skip-to-next (goto-char (or (match-beginning 2) (match-end 1))) (goto-char (match-end 1)) (1 (if (match-beginning 2) font-lock-function-name-face font-lock-variable-name-face)))) ("\\<\\(enum\\|struct\\|union\\)\\>[ ]*\\(\\sw+\\)?" (1 font-lock-keyword-face) (2 font-lock-type-face nil t) (font-lock-match-c-style-declaration-item-and-skip-to-next nil (if (match-end 2) (goto-char (match-end 2))) (1 (if (match-beginning 2) font-lock-function-name-face font-lock-variable-name-face) nil t))) ("\\(}\\)[ *]*\\sw" (font-lock-match-c-style-declaration-item-and-skip-to-next (goto-char (match-end 1)) nil (1 font-lock-type-face))) ("^\\(\\sw+\\)\\>\\([ *]+\\sw+\\>\\)*" (1 font-lock-type-face) (font-lock-match-c-style-declaration-item-and-skip-to-next (goto-char (or (match-beginning 2) (match-end 1))) nil (1 (if (match-beginning 2) font-lock-function-name-face font-lock-variable-name-face)))))) (quote (((font-lock-warning-face) 34876 34931 30626 30671 25283 25319) (font-lock-constant-face 50882 50887 50839 50844 50531 50536 50317 50322 45248 45255 45042 45057 44505 44529 43700 43714 28297 28315 27344 27362 26374 26392 22154 22169 21957 21973 2492 2499 2452 2465 2409 2421 2366 2378) (font-lock-function-name-face 87092 87100 86995 87004 86887 86896 86707 86715 86381 86396 86163 86174 85943 85954 84361 84370 83970 83984 83602 83619 72506 72514 71512 71537 71084 71098 70517 70537 70251 70264 69428 69438 68719 68731 68320 68333 67301 67313 66858 66879 66232 66251 65283 65304 64908 64921 63937 63956 63266 63289 62410 62423 62237 62252 61341 61363 61092 61116 60966 60982 60653 60664 60182 60200 59496 59519 58827 58848 57868 57880 56681 56696 55327 55354 54893 54915 54571 54583 54308 54320 54056 54068 52204 52227 51213 51241 50091 50113 47821 47834 45353 45364 43536 43548 41830 41845 40137 40151 39716 39724 39144 39153 39036 39045 38684 38692 38525 38557 38383 38391 38284 38293 38176 38185 37769 37777 36863 36871 36313 36322 36156 36188 36034 36043 35444 35452 34584 34592 34393 34402 33992 34011 33791 33800 33119 33136 30685 30693 30158 30166 29559 29568 29451 29460 28926 28932 28690 28698 28550 28558 25613 25621 25005 25022 23126 23142 23016 23025 22800 22812 13279 13290 12813 12826 9762 9770 8986 8994 8096 8119 7670 7685 5506 5522 5283 5315 4468 4489 3869 3881 2964 2980 2558 2583 2252 2267 1933 1946 1669 1680 1569 1588) (font-lock-type-face 87135 87138 87121 87128 87109 87115 87088 87091 87039 87042 87025 87032 87013 87019 86991 86994 86905 86911 86882 86886 86796 86802 86762 86766 86740 86744 86723 86727 86702 86706 86469 86472 86430 86436 86405 86413 86374 86378 86176 86179 86156 86160 85978 85981 85962 85966 85939 85942 85851 85862 85780 85784 85758 85769 84730 84733 84721 84729 84692 84695 84683 84691 84402 84410 84379 84385 84356 84360 84056 84062 83993 83999 83965 83969 83718 83724 83653 83661 83634 83640 83595 83599 83414 83417 83405 83413 83385 83388 83308 83323 83263 83278 83053 83068 83008 83023 81934 81938 81100 81103 81091 81099 81050 81053 81041 81049 80907 80910 80898 80906 80405 80408 79562 79568 79401 79416 79333 79348 79292 79307 78845 78853 78561 78576 77974 77983 77437 77445 76746 76755 76631 76634 76582 76585 75894 75897 75873 75876 74254 74257 73283 73287 73235 73244 73180 73187 72676 72680 72645 72649 72618 72626 72595 72601 72561 72565 72539 72543 72522 72526 72501 72505 72035 72043 71970 71978 71903 71911 71838 71846 71572 71586 71546 71552 71507 71511 71163 71166 71142 71146 71126 71129 71107 71113 71079 71083 70694 70702 70669 70672 70650 70653 70612 70615 70603 70611 70581 70589 70565 70568 70546 70552 70512 70516 70308 70311 70292 70295 70273 70279 70246 70250 70073 70076 70064 70072 69476 69484 69453 69459 69423 69427 69367 69370 69358 69366 68769 68777 68746 68752 68714 68718 68358 68366 68335 68338 68315 68319 67446 67449 67360 67368 67315 67318 67296 67300 66939 66945 66914 66922 66851 66855 66620 66623 66611 66619 66340 66347 66282 66290 66259 66263 66084 66087 66075 66083 65803 65807 65330 65338 65278 65282 64947 64955 64698 64701 64647 64662 64610 64625 64185 64194 64075 64084 64030 64038 64007 64010 63993 64002 63931 63936 63551 63560 63476 63479 63370 63373 63338 63347 63324 63333 63261 63265 62737 62746 62598 62601 62483 62486 62438 62444 62405 62409 62267 62273 61808 61812 61758 61762 61709 61712 61700 61708 61569 61572 61420 61429 61405 61414 61398 61401 61169 61172 61088 61091 61004 61012 60326 60329 60222 60230 60071 60074 60062 60070 59775 59778 59766 59774 59528 59536 59388 59391 59379 59387 59096 59099 59087 59095 58857 58865 58094 58098 58046 58052 57994 58003 57942 57949 57911 57919 57888 57892 57861 57865 57612 57616 57338 57342 56916 56922 56870 56876 56845 56853 56813 56822 56779 56786 56741 56744 56719 56723 56704 56708 56674 56678 56265 56269 55704 55707 55672 55678 55636 55642 55595 55602 55564 55572 55516 55525 55473 55480 55430 55433 55396 55400 55362 55365 55320 55324 54930 54937 54888 54892 54686 54695 54647 54656 54616 54623 54591 54595 54564 54568 54392 54401 54353 54362 54328 54332 54301 54305 54136 54143 54101 54108 54076 54080 52554 52563 52501 52508 52470 52479 52441 52448 52413 52420 52386 52389 52265 52273 52241 52244 52229 52232 52199 52203 51262 51265 51253 51256 51243 51247 51208 51212 51141 51156 51101 51116 50225 50229 50203 50206 50194 50202 50161 50169 50132 50141 50115 50124 50086 50090 49636 49645 49580 49589 48408 48412 48352 48356 48290 48294 48263 48267 47988 47991 47962 47971 47928 47937 47843 47851 47809 47818 47467 47474 47413 47420 45960 45964 45898 45902 45868 45872 45818 45822 45768 45772 45741 45745 45502 45505 45478 45485 45446 45453 45373 45381 45343 45350 43632 43635 43615 43621 43582 43595 43532 43535 43167 43175 42805 42808 41964 41967 41873 41879 41854 41860 41826 41829 41711 41714 41476 41484 41408 41411 41131 41134 41112 41115 40279 40282 40172 40175 40160 40166 40133 40136 39881 39885 39843 39848 39814 39823 39759 39762 39745 39752 39733 39739 39712 39715 39480 39484 39328 39330 39298 39300 39272 39277 39243 39252 39188 39191 39174 39181 39162 39168 39140 39143 39054 39060 39031 39035 38887 38890 38773 38779 38739 38743 38717 38721 38700 38704 38679 38683 38637 38646 38610 38619 38559 38562 38521 38524 38426 38429 38412 38419 38400 38406 38379 38382 38328 38331 38314 38321 38302 38308 38280 38283 38194 38200 38171 38175 37979 37982 37858 37864 37824 37828 37802 37806 37785 37789 37764 37768 36990 36995 36961 36970 36906 36909 36892 36899 36880 36886 36859 36862 36497 36499 36467 36469 36441 36446 36412 36421 36357 36360 36343 36350 36331 36337 36309 36312 36267 36276 36240 36249 36190 36193 36152 36155 36052 36058 36029 36033 35696 35703 35533 35539 35499 35503 35477 35481 35460 35464 35439 35443 34709 34713 34662 34665 34647 34653 34627 34630 34613 34620 34601 34607 34580 34583 34502 34506 34457 34463 34437 34440 34423 34430 34411 34417 34389 34392 34082 34086 34064 34068 34045 34052 34020 34026 33987 33991 33809 33815 33786 33790 33214 33219 33145 33151 33114 33118 32566 32570 32343 32347 31673 31676 30913 30916 30888 30892 30865 30869 30846 30850 30827 30832 30790 30793 30774 30780 30740 30744 30718 30722 30701 30705 30680 30684 30307 30310 30290 30296 30262 30267 30201 30204 30187 30194 30175 30181 30154 30157 29764 29769 29734 29737 29713 29718 29688 29693 29664 29670 29603 29606 29589 29596 29577 29583 29555 29558 29469 29475 29446 29450 29072 29078 29035 29041 29006 29009 28979 28983 28957 28961 28940 28944 28921 28925 28779 28785 28745 28749 28723 28727 28706 28710 28685 28689 28639 28645 28605 28609 28583 28587 28566 28570 28545 28549 27817 27821 27579 27582 27564 27569 27247 27251 26136 26140 25725 25730 25702 25708 25668 25672 25646 25650 25629 25633 25608 25612 25031 25037 25000 25004 23892 23895 23314 23318 23293 23297 23277 23283 23189 23193 23167 23171 23150 23154 23121 23125 23034 23040 23011 23015 22821 22827 22795 22799 21502 21517 21274 21278 14246 14261 14084 14099 14015 14030 13655 13659 13616 13620 13566 13570 13525 13529 13427 13435 13403 13410 13371 13374 13323 13327 13299 13305 13274 13278 12903 12917 12868 12873 12835 12841 12808 12812 12231 12246 11976 11991 11907 11922 10457 10461 10407 10411 10366 10370 10189 10195 10152 10158 10118 10126 10094 10101 10032 10041 10005 10014 9942 9946 9873 9877 9823 9827 9778 9782 9753 9759 9075 9081 9050 9058 9030 9033 9021 9029 9009 9015 8979 8983 8795 8810 8730 8745 8556 8571 8509 8524 8431 8446 8384 8399 8338 8342 8205 8211 8180 8188 8134 8140 8089 8093 7665 7669 7424 7439 7388 7403 7351 7366 7076 7085 7015 7024 6887 6902 6851 6866 6814 6829 6417 6432 6381 6396 6344 6359 6122 6131 6069 6078 6014 6023 5968 5977 5853 5868 5813 5828 5772 5787 5640 5648 5603 5612 5582 5591 5560 5569 5546 5549 5530 5534 5501 5505 5340 5349 5317 5326 5273 5282 4856 4871 4528 4536 4501 4510 4463 4467 4209 4213 3933 3939 3864 3868 3099 3102 3062 3070 3035 3039 3009 3013 2988 2992 2957 2961 2636 2639 2617 2621 2591 2595 2551 2555 2292 2296 2275 2279 2245 2249 1971 1975 1954 1958 1929 1932 1727 1731 1705 1709 1688 1692 1664 1668 1641 1645 1622 1629 1597 1603 1564 1568) (font-lock-keyword-face 87148 87154 87102 87108 87052 87058 87006 87012 86921 86923 86898 86904 86789 86795 86756 86761 86734 86739 86717 86722 86658 86664 86571 86573 86525 86528 86423 86429 86398 86404 86368 86373 86327 86333 86318 86322 86280 86286 86237 86239 86150 86155 86136 86142 86124 86130 86071 86073 86033 86036 85956 85961 85844 85850 85838 85843 85831 85837 85774 85779 85751 85757 85566 85568 85446 85448 85345 85347 84957 84959 84859 84861 84802 84804 84510 84512 84456 84458 84430 84432 84395 84401 84372 84378 84110 84115 84049 84055 84009 84011 83986 83992 83949 83955 83918 83924 83778 83780 83711 83717 83671 83673 83646 83652 83627 83633 83621 83626 83589 83594 83132 83136 82715 82717 82323 82325 82141 82143 81928 81933 81828 81830 81767 81769 81710 81712 81445 81447 81324 81326 80941 80945 80776 80778 80727 80729 80440 80442 80204 80210 80173 80179 80099 80101 79740 79742 79555 79561 79519 79521 79013 79019 78989 78995 78918 78920 78597 78599 78262 78264 78176 78180 78055 78057 77963 77967 77768 77770 77693 77695 77345 77347 77048 77054 77024 77030 76948 76950 76844 76846 76704 76706 76525 76531 76501 76507 76441 76443 75956 75958 75772 75778 75746 75752 75681 75683 75297 75302 75278 75282 75141 75143 74781 74787 74585 74587 74492 74498 74356 74361 74232 74236 74107 74109 73729 73735 73560 73562 73510 73516 73350 73352 73228 73234 73222 73227 73173 73179 73167 73172 72973 72977 72893 72895 72888 72892 72872 72878 72786 72788 72670 72675 72611 72617 72588 72594 72555 72560 72533 72538 72516 72521 72252 72254 71727 71729 71654 71656 71595 71597 71565 71571 71559 71564 71539 71545 71500 71506 71297 71299 71189 71191 71157 71162 71136 71141 71120 71125 71100 71106 71072 71078 71006 71009 70828 70830 70712 70714 70686 70692 70663 70668 70625 70627 70597 70602 70575 70580 70559 70564 70539 70545 70505 70511 70322 70324 70302 70307 70286 70291 70266 70272 70239 70245 70114 70120 69919 69923 69792 69794 69709 69711 69622 69627 69523 69525 69469 69475 69446 69452 69440 69445 69408 69414 69205 69209 69087 69089 69002 69004 68915 68920 68816 68818 68762 68768 68739 68745 68733 68738 68579 68582 68504 68509 68484 68486 68385 68390 68351 68357 68065 68067 67756 67758 67353 67359 67327 67332 67289 67295 67225 67231 67054 67056 66978 66983 66932 66938 66907 66913 66881 66886 66845 66850 66838 66844 66758 66764 66720 66724 66694 66700 66452 66454 66275 66281 66253 66258 66219 66225 65835 65837 65797 65802 65778 65782 65562 65564 65523 65528 65489 65494 65437 65442 65418 65420 65357 65362 65323 65329 65271 65277 65120 65126 65056 65058 64974 64979 64940 64946 64896 64902 64799 64805 64739 64741 64464 64466 64423 64425 64418 64422 64335 64337 64257 64259 64206 64208 64160 64165 64130 64132 64023 64029 63987 63992 63958 63963 63916 63922 63777 63779 63674 63676 63593 63595 63521 63524 63470 63475 63450 63452 63400 63402 63318 63323 63291 63296 63246 63252 63173 63177 63114 63116 63032 63036 62948 62950 62828 62830 62763 62765 62707 62710 62592 62597 62572 62574 62513 62518 62450 62455 62431 62437 62425 62430 62389 62395 62380 62384 62332 62338 62312 62314 62279 62284 62260 62266 62254 62259 62213 62218 62198 62204 61907 61909 61802 61807 61752 61757 61694 61699 61676 61678 61625 61630 61608 61610 61587 61592 61512 61517 61492 61494 61392 61397 61365 61370 61329 61335 61316 61322 61307 61311 61289 61295 61240 61245 61186 61191 61149 61151 61118 61123 61081 61087 61022 61028 60997 61003 60942 60947 60935 60941 60919 60925 60898 60904 60870 60872 60827 60830 60752 60757 60710 60712 60666 60671 60629 60634 60622 60628 60500 60506 60475 60481 60443 60445 60385 60390 60339 60342 60304 60306 60240 60245 60215 60221 60153 60158 60146 60152 60132 60138 59982 59986 59965 59971 59907 59909 59829 59833 59613 59615 59521 59527 59470 59475 59463 59469 59449 59455 59300 59304 59283 59289 59226 59228 59150 59154 58940 58942 58850 58856 58803 58808 58696 58702 58687 58691 58637 58643 58596 58598 58591 58595 58550 58556 58535 58537 58391 58393 58271 58275 58146 58148 58088 58093 58039 58045 57987 57993 57981 57986 57935 57941 57929 57934 57904 57910 57882 57887 57855 57860 57791 57797 57756 57762 57670 57672 57606 57611 57516 57522 57474 57478 57425 57427 57332 57337 57286 57288 57084 57086 57018 57024 57000 57002 56909 56915 56863 56869 56838 56844 56806 56812 56800 56805 56772 56778 56766 56771 56698 56703 56668 56673 56661 56667 56531 56537 56377 56381 56328 56330 56259 56264 56230 56232 56149 56155 56134 56136 56055 56058 55881 55883 55815 55821 55797 55799 55665 55671 55629 55635 55588 55594 55582 55587 55557 55563 55509 55515 55503 55508 55466 55472 55460 55465 55356 55361 55314 55319 55307 55313 54952 54954 54923 54929 54917 54922 54881 54887 54865 54871 54839 54845 54764 54766 54704 54707 54679 54685 54673 54678 54640 54646 54634 54639 54609 54615 54603 54608 54585 54590 54558 54563 54551 54557 54535 54541 54509 54515 54470 54472 54410 54413 54385 54391 54379 54384 54346 54352 54340 54345 54322 54327 54295 54300 54288 54294 54271 54277 54249 54255 54210 54212 54152 54155 54129 54135 54123 54128 54094 54100 54088 54093 54070 54075 54044 54050 53839 53841 53697 53699 53600 53602 53473 53475 53417 53420 53359 53362 53114 53116 53109 53113 53056 53058 52930 52932 52876 52879 52723 52726 52547 52553 52541 52546 52494 52500 52488 52493 52463 52469 52457 52462 52434 52440 52428 52433 52406 52412 52400 52405 52258 52264 52168 52170 52109 52111 52030 52033 50872 50878 50834 50838 50546 50548 50526 50530 50332 50334 50312 50316 50246 50248 50219 50224 50188 50193 50154 50160 49989 49995 49835 49837 49801 49803 49629 49635 49573 49579 49554 49558 49373 49375 49213 49219 49196 49200 49088 49090 48854 48860 48685 48687 48680 48684 48667 48672 48631 48633 48450 48456 48402 48407 48238 48243 48128 48130 47955 47961 47921 47927 47836 47842 47802 47808 47796 47801 47779 47785 47630 47632 47594 47596 47460 47466 47406 47412 47344 47346 47284 47286 47063 47069 47031 47035 46877 46879 46709 46715 46692 46696 46590 46592 46401 46407 46250 46252 46245 46249 46232 46237 46196 46198 46027 46033 45716 45721 45618 45620 45471 45477 45439 45445 45366 45372 45336 45342 45330 45335 45315 45321 45284 45286 45236 45241 45037 45041 45025 45030 44887 44889 44822 44826 44625 44627 44500 44504 44488 44493 44175 44177 44110 44114 43901 43903 43833 43835 43695 43699 43664 43670 43608 43614 43575 43581 43502 43508 43160 43166 43120 43124 42883 42885 42845 42849 42423 42425 41890 41892 41866 41872 41847 41853 41797 41803 41469 41475 41429 41433 41208 41210 41170 41174 40767 40769 40189 40191 40153 40159 40076 40082 40067 40071 39994 40000 39917 39923 39836 39842 39772 39774 39726 39732 39676 39682 39667 39671 39593 39599 39516 39522 39417 39421 39346 39348 39321 39327 39291 39297 39265 39271 39201 39203 39155 39161 39070 39072 39047 39053 38858 38860 38766 38772 38733 38738 38711 38716 38694 38699 38664 38670 38655 38659 38629 38635 38602 38608 38589 38595 38572 38574 38507 38513 38441 38447 38393 38399 38343 38349 38295 38301 38210 38212 38187 38193 37946 37948 37851 37857 37818 37823 37796 37801 37779 37784 37215 37221 37206 37210 37133 37139 37056 37062 36983 36989 36919 36921 36873 36879 36823 36829 36814 36818 36740 36746 36663 36669 36579 36583 36515 36517 36490 36496 36460 36466 36434 36440 36370 36372 36324 36330 36294 36300 36285 36289 36259 36265 36232 36238 36219 36225 36202 36204 36138 36144 36068 36070 36045 36051 35890 35892 35717 35719 35689 35695 35660 35662 35526 35532 35493 35498 35471 35476 35454 35459 34723 34729 34640 34646 34594 34600 34516 34522 34450 34456 34404 34410 34141 34147 34058 34063 34038 34044 34032 34037 34013 34019 33980 33986 33876 33878 33825 33827 33802 33808 33690 33692 33527 33529 33419 33421 33314 33316 33286 33292 33207 33213 33181 33183 33161 33163 33138 33144 33107 33113 32816 32818 32761 32767 32407 32409 32312 32314 32160 32162 32063 32065 31965 31967 31821 31823 31726 31728 31647 31652 31608 31610 31478 31482 31333 31335 31264 31266 31259 31263 31133 31135 31063 31065 31046 31052 30981 30983 30882 30887 30859 30864 30840 30845 30820 30826 30767 30773 30734 30739 30712 30717 30695 30700 30535 30541 30519 30523 30498 30504 30485 30491 30341 30347 30283 30289 30255 30261 30229 30231 30168 30174 30118 30124 30102 30106 30081 30087 30068 30074 29923 29929 29864 29868 29805 29807 29757 29763 29706 29712 29681 29687 29657 29663 29631 29633 29570 29576 29485 29487 29462 29468 29196 29198 29065 29071 29028 29034 28973 28978 28951 28956 28934 28939 28772 28778 28739 28744 28717 28722 28700 28705 28632 28638 28599 28604 28577 28582 28560 28565 28396 28398 28287 28293 28047 28051 27928 27932 27782 27784 27593 27595 27557 27563 27339 27343 27216 27218 27006 27008 26826 26830 26755 26757 26750 26754 26679 26681 26470 26472 26369 26373 26254 26256 26165 26167 26130 26135 26066 26070 25999 26001 25718 25724 25695 25701 25662 25667 25640 25645 25623 25628 25086 25088 25047 25049 25024 25030 24993 24999 24557 24559 24530 24532 24478 24484 24432 24436 24291 24293 24193 24198 24103 24105 24051 24057 23967 23973 23906 23909 23846 23848 23684 23688 23640 23646 23593 23595 23494 23498 23427 23429 23270 23276 23183 23188 23161 23166 23144 23149 23114 23120 23027 23033 23004 23010 22814 22820 22532 22537 22176 22178 22149 22153 22139 22144 21952 21956 21909 21915 21775 21781 21555 21559 21381 21383 21268 21273 20930 20936 20892 20896 20712 20718 20670 20672 20237 20243 20199 20203 20019 20025 19977 19979 19626 19632 19118 19124 18890 18894 18710 18716 18668 18670 18286 18292 18248 18252 18068 18074 18026 18028 17676 17682 17483 17489 17003 17005 16930 16934 16822 16828 16667 16669 16464 16470 16417 16419 15805 15811 15767 15771 15602 15608 15560 15562 15205 15211 15164 15168 14895 14901 14802 14804 14585 14591 14315 14317 14214 14216 13879 13883 13829 13831 13824 13828 13775 13777 13610 13615 13560 13565 13519 13524 13455 13457 13420 13426 13396 13402 13390 13395 13317 13322 13292 13298 12896 12902 12890 12895 12861 12867 12855 12860 12828 12834 12746 12752 12526 12530 12432 12434 12364 12366 12109 12111 11389 11391 10690 10694 10640 10642 10635 10639 10586 10588 10451 10456 10401 10406 10360 10365 10267 10269 10182 10188 10145 10151 10111 10117 10087 10093 10060 10065 9936 9941 9867 9872 9817 9822 9772 9777 9746 9752 9622 9628 9572 9576 9350 9352 9133 9135 9113 9115 9068 9074 9043 9049 9002 9008 8996 9001 8973 8978 8894 8900 8850 8854 8659 8661 8654 8658 8486 8490 8354 8356 8332 8337 8296 8298 8244 8246 8198 8204 8173 8179 8127 8133 8121 8126 8083 8088 7658 7664 7131 7133 7070 7075 7009 7014 6977 6979 6972 6976 6497 6499 6180 6182 6116 6121 6063 6068 6008 6013 5962 5967 5930 5932 5906 5908 5633 5639 5524 5529 5494 5500 5363 5369 5266 5272 4960 4962 4933 4937 4647 4649 4626 4628 4555 4560 4521 4527 4456 4462 4203 4208 4196 4202 4028 4030 4023 4027 3969 3971 3926 3932 3857 3863 3272 3278 3199 3205 3141 3143 3093 3098 3055 3061 3029 3034 3003 3008 2982 2987 2951 2956 2828 2834 2808 2814 2797 2799 2769 2773 2738 2740 2672 2674 2630 2635 2611 2616 2585 2590 2545 2550 2507 2513 2473 2479 2447 2451 2429 2435 2404 2408 2386 2392 2361 2365 2312 2318 2286 2291 2269 2274 2239 2244 2213 2219 2204 2208 2180 2186 2135 2137 2130 2134 2107 2113 2063 2065 2058 2062 2035 2041 1991 1993 1965 1970 1948 1953 1870 1876 1861 1865 1820 1826 1802 1804 1786 1792 1772 1774 1721 1726 1699 1704 1682 1687 1635 1640 1615 1621 1609 1614 1590 1596 1557 1563) (font-lock-string-face 86625 86631 86596 86599 86287 86314 85924 85933 85911 85918 85898 85905 85884 85892 85503 85553 85395 85440 85229 85294 85093 85157 85011 85058 84909 84951 84601 84675 84290 84305 83154 83253 82899 82998 82366 82568 82189 82248 81955 82103 81488 81645 80962 81030 80844 80887 80473 80501 80253 80344 79895 79986 79663 79687 79177 79286 79054 79154 78686 78764 78303 78559 77827 77951 77089 77210 76893 76936 76610 76628 76239 76337 76130 76225 76090 76116 75937 75939 75925 75934 75829 75864 75536 75570 75213 75250 74802 74810 74624 74685 74167 74204 73750 73758 73597 73631 73015 73050 71341 71405 71237 71292 70871 70927 70758 70819 70364 70418 69942 70025 69850 69887 69228 69319 69145 69173 68458 68479 68197 68214 68107 68124 67981 68009 67885 67913 67801 67819 67690 67706 67664 67667 67599 67611 67523 67534 67476 67489 67429 67443 67391 67395 67190 67193 67137 67141 67110 67113 67019 67023 66536 66594 66392 66412 65933 66010 65817 65826 65651 65714 64552 64601 60006 60051 59714 59759 59324 59368 59036 59080 58624 58630 58557 58563 57742 57746 57710 57714 57501 57507 57456 57460 57406 57410 56507 56511 56404 56410 56359 56363 55135 55186 54984 55121 53878 53968 53735 53833 53636 53691 53270 53281 52991 53000 52614 52658 52189 52193 52150 52154 52078 52090 51978 52024 51917 51965 51856 51904 51786 51843 51721 51773 51651 51708 51580 51638 51506 51567 51432 51493 51357 51419 51286 51344 51046 51092 50905 51037 50678 50826 50395 50518 50285 50304 49448 49488 49136 49168 48884 48904 48729 48776 48429 48435 48175 48207 46952 46988 46638 46670 46422 46430 46294 46341 45934 45952 45847 45860 45665 45697 45190 45227 44957 45008 44766 44810 44436 44469 44053 44093 43360 43398 43044 43078 42715 42762 41666 41703 41367 41400 41055 41101 35959 35989 35786 35816 34358 34383 34288 34321 34230 34234 34184 34197 33611 33635 33494 33520 33389 33412 33058 33084 32930 32956 32670 32676 32478 32506 32378 32396 32213 32235 32186 32190 32125 32144 32029 32057 31884 31899 31791 31806 31509 31561 31396 31401 31360 31370 31316 31325 31196 31201 31160 31170 31115 31125 29406 29411 29399 29403 29355 29381 29265 29300 28332 28391 28085 28125 27963 28003 27861 27896 27387 27413 27295 27328 27044 27049 27022 27027 26851 26903 26323 26357 26184 26198 24768 24794 24617 24645 24496 24505 24328 24369 24241 24268 24082 24088 23993 24004 23658 23662 23082 23088 22605 22759 22461 22490 22394 22398 22227 22342 22197 22203 21993 22089 21803 21855 21177 21202 21109 21113 20972 21001 20754 20799 20483 20509 20415 20419 20279 20308 20061 20106 19799 19877 19711 19715 19666 19678 19398 19422 19330 19334 19160 19199 18752 18797 18572 18597 18504 18508 18328 18373 18110 18155 17849 17927 17761 17765 17716 17728 17569 17573 17523 17536 17043 17076 16976 16980 16866 16895 16707 16740 16643 16647 16508 16529 16085 16108 16017 16021 15847 15886 15644 15674 15490 15516 15424 15428 15247 15284 15132 15158 15066 15070 14937 14972 14771 14797 14706 14710 14626 14654 12630 12650 12561 12579 12471 12488 12394 12410 11733 11741 11618 11625 10710 10796 9607 9611 9498 9502 9458 9461 9452 9455 9401 9406 9279 9283 9239 9242 9233 9236 9183 9188 8874 8883 8713 8720 8629 8636 7707 7990 7191 7337 6575 6800 6250 6330 5686 5750 4999 5138 4685 4848 4247 4294 4055 4128 2514 2534 2480 2486 2436 2441 2393 2398 2167 2173 2095 2100 2023 2028 1523 1533 1502 1512 1482 1492 1464 1472 1444 1454 1424 1434 1407 1414 1385 1396 1357 1367 1325 1341) (font-lock-variable-name-face 87139 87142 87130 87133 87117 87119 87043 87046 87034 87037 87021 87023 86913 86915 86804 86806 86778 86782 86768 86776 86746 86754 86729 86732 86473 86474 86437 86440 86415 86417 86180 86185 85982 85983 85968 85972 85863 85874 85786 85796 84448 84449 84411 84413 84387 84389 84063 84066 84001 84003 83725 83728 83663 83665 83642 83644 81940 81952 80409 80410 79569 79572 77984 77987 77446 77448 76756 76758 74258 74271 73288 73299 73246 73255 73189 73196 72682 72693 72650 72661 72627 72629 72603 72605 72577 72581 72567 72575 72545 72553 72528 72531 71588 71589 71554 71557 71167 71170 71148 71151 71130 71134 71115 71118 70673 70677 70654 70655 70616 70619 70591 70595 70569 70573 70554 70557 70312 70316 70296 70300 70281 70284 69485 69487 69461 69463 68778 68780 68754 68756 68367 68369 68339 68345 67370 67372 67319 67325 66946 66949 66924 66926 66348 66352 66291 66293 66265 66269 66226 66231 65809 65814 65339 65341 64956 64958 64903 64907 64195 64197 64085 64100 64039 64041 64012 64017 64003 64005 63573 63588 63561 63571 63480 63481 63374 63375 63349 63364 63334 63336 62751 62758 62747 62749 62602 62603 62487 62488 62446 62448 62275 62277 62219 62234 61814 61825 61764 61770 61713 61726 61573 61574 61431 61438 61416 61418 61402 61403 61336 61340 61173 61174 61014 61016 60948 60963 60635 60650 60330 60331 60232 60234 60159 60179 59538 59540 59476 59493 58867 58869 58809 58824 58100 58104 58053 58059 58005 58014 57951 57958 57921 57923 57894 57902 57618 57622 57344 57347 56923 56929 56877 56880 56855 56857 56824 56833 56788 56795 56745 56761 56725 56736 56710 56714 56271 56274 55708 55709 55679 55685 55643 55646 55604 55611 55574 55576 55527 55540 55482 55493 55434 55450 55402 55413 55366 55379 54939 54946 54697 54699 54658 54667 54625 54632 54597 54601 54403 54405 54364 54373 54334 54338 54145 54147 54110 54117 54082 54086 54051 54055 52565 52574 52510 52517 52481 52483 52450 52453 52422 52424 52390 52395 52274 52276 52245 52252 52233 52239 51266 51269 51257 51258 50231 50234 50207 50211 50170 50172 50142 50148 50125 50130 49591 49594 48413 48424 48357 48366 48295 48312 48268 48277 47992 47993 47973 47977 47939 47944 47853 47855 47422 47425 45965 45984 45903 45929 45873 45885 45823 45842 45773 45784 45746 45755 45506 45507 45487 45491 45455 45460 45383 45385 43636 43639 43623 43626 43597 43599 43176 43178 41968 41971 41881 41884 41862 41864 41485 41487 40283 40286 40176 40183 40168 40170 40125 40130 39849 39851 39824 39828 39763 39766 39754 39757 39741 39743 39302 39305 39278 39280 39253 39257 39192 39195 39183 39186 39170 39172 39062 39064 38891 38892 38781 38783 38755 38759 38745 38753 38723 38731 38706 38709 38563 38566 38490 38504 38430 38433 38421 38424 38408 38410 38332 38335 38323 38326 38310 38312 38202 38204 37983 37984 37866 37868 37840 37844 37830 37838 37808 37816 37791 37794 37264 37277 36996 36998 36971 36975 36910 36913 36901 36904 36888 36890 36471 36474 36447 36449 36422 36426 36361 36364 36352 36355 36339 36341 36194 36197 36060 36062 35704 35708 35541 35543 35515 35519 35505 35513 35483 35491 35466 35469 34856 34867 34832 34842 34802 34816 34666 34667 34654 34658 34631 34634 34622 34625 34609 34611 34464 34468 34441 34444 34432 34435 34419 34421 34087 34099 34070 34076 34054 34056 34028 34030 33817 33819 33220 33223 33153 33155 30917 30926 30894 30909 30871 30878 30852 30855 30833 30836 30808 30811 30801 30806 30794 30799 30782 30784 30756 30760 30746 30754 30724 30732 30707 30710 30609 30618 30584 30598 30311 30314 30297 30299 30268 30272 30216 30226 30205 30208 30196 30199 30183 30185 29738 29741 29719 29723 29695 29698 29671 29673 29618 29628 29607 29610 29598 29601 29585 29587 29477 29479 29043 29045 29010 29022 28995 28999 28985 28993 28963 28971 28946 28949 28906 28919 28787 28789 28761 28765 28751 28759 28729 28737 28712 28715 28647 28649 28621 28625 28611 28619 28589 28597 28572 28575 27583 27589 27570 27576 27533 27546 27507 27520 26552 26565 26526 26539 26142 26146 25731 25734 25710 25712 25684 25688 25674 25682 25652 25660 25635 25638 25598 25606 25548 25558 25498 25508 25477 25488 25454 25464 25433 25441 25410 25420 25387 25397 25364 25374 25340 25351 25255 25275 25201 25220 25179 25191 25039 25041 23896 23897 23319 23331 23298 23305 23285 23287 23195 23203 23173 23181 23156 23159 23108 23113 23042 23044 22933 22947 22865 22870 22829 22835 21280 21287 21252 21257 20558 20572 19471 19484 18646 18659 17165 17179 16191 16205 14489 14511 14468 14480 14295 14312 13660 13672 13622 13640 13572 13595 13531 13545 13436 13438 13412 13414 13375 13382 13329 13335 13307 13309 12963 12968 12919 12926 12875 12880 12843 12845 10463 10481 10413 10436 10372 10386 10160 10162 10127 10129 10103 10105 10042 10055 10015 10027 9948 9976 9879 9898 9829 9837 9784 9787 9471 9476 9252 9257 9082 9085 9060 9062 9034 9041 9017 9019 8348 8349 8344 8345 8212 8215 8190 8192 8159 8163 8146 8150 8142 8144 7086 7101 7025 7039 6132 6142 6079 6088 6024 6034 5978 5990 5669 5670 5649 5651 5613 5627 5592 5597 5570 5576 5550 5554 5536 5540 5350 5357 5327 5332 4537 4539 4511 4515 4214 4242 3941 3943 3103 3105 3085 3090 3072 3074 3041 3049 3015 3023 2994 2997 2640 2646 2623 2626 2597 2605 2298 2306 2281 2284 1977 1985 1960 1963 1733 1743 1711 1719 1694 1697 1647 1653 1631 1633 1605 1607 1542 1556 1310 1315) (font-lock-builtin-face 87184 87189 86682 86686 84789 84794 84445 84447 40117 40124 40112 40116 38482 38489 38477 38481 37256 37263 37251 37255 34933 34938 34870 34875 34848 34855 34824 34831 34820 34822 34794 34801 34789 34793 30673 30678 30620 30625 30602 30608 30576 30583 30571 30575 30525 30530 30213 30215 30108 30113 29615 29617 29419 29424 28900 28905 28866 28871 28679 28683 28671 28676 28539 28543 28156 28161 27525 27532 27499 27506 27496 27498 26606 26611 26544 26551 26518 26525 26515 26517 25594 25596 25586 25591 25541 25547 25535 25539 25491 25497 25469 25476 25446 25453 25425 25432 25402 25409 25379 25386 25356 25363 25332 25339 25329 25331 25321 25326 25277 25282 25248 25254 25195 25200 25171 25178 25168 25170 25160 25165 23101 23107 22971 22976 22927 22932 22920 22925 22895 22899 22859 22864 22763 22768 22580 22584 21243 21250 21238 21242 20550 20557 20545 20549 19463 19470 19458 19462 18638 18645 18633 18637 17157 17164 17152 17156 16183 16190 16178 16182 16144 16149 15549 15553 14483 14488 14460 14467 14457 14459 14448 14453 14289 14294 13212 13217 12957 12962 9555 9560 9465 9470 9335 9340 9246 9251 5897 5902 5666 5668 3242 3247 3079 3084 1657 1662 1536 1541 1515 1522 1494 1501 1474 1481 1456 1463 1436 1443 1416 1423 1399 1406 1377 1384 1369 1374 1349 1356 1343 1347 1317 1324 1304 1309) (font-lock-comment-face 86687 86700 85802 85830 85681 85749 83536 83568 82687 82713 82573 82652 82291 82321 82107 82139 81650 81708 81413 81443 81164 81319 80701 80722 80542 80603 80354 80396 80021 80065 79469 79512 78802 78829 77989 78011 77624 77686 77460 77540 77222 77342 76657 76700 76397 76417 75606 75635 75367 75459 74997 75023 74701 74737 74286 74347 73952 73978 73653 73689 73380 73447 73067 73158 72718 72747 72419 72461 72333 72357 72071 72249 70129 70237 68682 68712 68537 68572 68279 68314 67248 67288 66781 66837 66151 66218 65135 65270 64814 64895 63194 63242 63045 63109 62874 62943 62644 62700 60785 60820 60516 60620 58771 58802 58719 58767 58660 58684 58573 58588 58461 58511 57807 57854 57545 57597 57215 57283 57034 57081 56949 56997 56554 56660 56422 56454 56171 56227 56012 56052 55831 55878 55746 55794 55192 55306 53992 54043 53559 53597 53306 53356 53136 53226 52799 52869 52664 52720 50006 50085 49766 49793 47558 47585 45059 45104 44833 44883 44647 44692 44232 44311 44121 44158 43851 43897 43125 43145 42912 42935 42531 42612 42435 42473 42143 42210 41981 42013 41434 41454 41237 41260 40824 40905 40779 40817 40482 40548 40295 40331 38905 38933 38134 38159 38059 38077 37280 37762 35618 35657 34940 35437 33757 33785 32241 32309 31915 31962 31584 31605 31430 31447 29425 29444 28872 28897 27437 27494 27101 27209 26929 26999 26619 26672 26404 26444 26207 26247 26083 26123 25916 25996 25739 25873 25561 25584 25511 25533 25221 25245 24813 24901 24718 24748 24382 24428 23695 23842 23511 23586 21659 21741 21291 21379 20581 20663 19888 19970 19493 19586 18901 19083 17937 18019 17188 17443 16214 16410 16150 16176 14816 14860 14513 14551 14137 14207 13946 13991 13897 13938 13686 13768 13340 13364 13221 13273 12760 12807 12282 12357 12029 12102 11838 11883 11465 11595 11318 11382 10811 10876 10497 10579 9978 10001 9909 9932 9840 9863 9795 9813 9645 9745 8917 8972 7996 8082 7529 7657 5391 5493 5203 5265 4938 4947 4297 4455 4134 4195 3287 3856 3251 3269 2844 2950 1088 1301 1 1086))))
diff --git a/openvpn/tun.h b/openvpn/tun.h
new file mode 100644
index 0000000..76c4867
--- /dev/null
+++ b/openvpn/tun.h
@@ -0,0 +1,413 @@
+/*
+ * 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
+
+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_N 4
+ 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 */
+
+ 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;
+#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 *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 */
+ 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);
+
+/*
+ * 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);
+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 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);
+
+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);
+
+const char *get_netsh_id (const char *dev_node, struct gc_arena *gc);
+
+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;
+}
+
+#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 */
diff --git a/tunDevice.cpp b/tunDevice.cpp
new file mode 100644
index 0000000..66cf395
--- /dev/null
+++ b/tunDevice.cpp
@@ -0,0 +1,25 @@
+
+#include "openvpn/tun.h"
+#include "tunDevice.h"
+
+
+TunDevice::TunDevice(string dev_name)
+{
+// dev = init_tun(dev_name.c_str(), ... );
+
+}
+
+TunDevice::~TunDevice()
+{
+ close_tun(dev);
+}
+
+int TunDevice::read(uint8_t *buf, int len)
+{
+ return read_tun(dev, buf, len);
+}
+
+int TunDevice::write(uint8_t *buf, int len)
+{
+ return write_tun(dev, buf, len);
+}
diff --git a/tunDevice.h b/tunDevice.h
new file mode 100644
index 0000000..e1386b2
--- /dev/null
+++ b/tunDevice.h
@@ -0,0 +1,18 @@
+
+#include "openvpn/tun.h"
+
+class TunDevice
+{
+public:
+ TunDevice(string dev_name);
+ ~TunDevice();
+
+ int read(uint8_t *buf, int len);
+ int write(uint8_t *buf, int len);
+
+private:
+ void operator=(const TunDevice &src);
+ TunDevice(const TunDevice &src);
+
+ struct tuntap *dev_;
+}