From patchwork Thu Jun 7 19:20:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 363 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.28.255.1]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id DTPoDHASGlu5YwAAIUCqbw for ; Fri, 08 Jun 2018 01:21:52 -0400 Received: from director3.mail.ord1c.rsapps.net ([172.28.255.1]) by director8.mail.ord1d.rsapps.net (Dovecot) with LMTP id E/AVK3ASGlvvKAAAfY0hYg ; Fri, 08 Jun 2018 01:21:52 -0400 Received: from smtp4.gate.ord1c ([172.28.255.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by director3.mail.ord1c.rsapps.net with LMTP id IPbcKnASGluSJgAAdSFV8w ; Fri, 08 Jun 2018 01:21:52 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp4.gate.ord1c.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: d99fbc3a-6adb-11e8-9345-0024e87f2f2c-1-1 Received: from [216.105.38.7] ([216.105.38.7:29339] helo=lists.sourceforge.net) by smtp4.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 6C/16-17429-0721A1B5; Fri, 08 Jun 2018 01:21:52 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fR9pa-0006r2-PP; Fri, 08 Jun 2018 05:20:58 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fR9pZ-0006qv-CD for openvpn-devel@lists.sourceforge.net; Fri, 08 Jun 2018 05:20:57 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=bCf5XkVHEXTCUo2oCYxDBZo5pjeWkzxJjzhs7Rivk6U=; b=WOV3/d34wu4a+/EzF9I/CLUXN6 WB++4YzhZPZaS/U1OcMFsccSH2FLT7lpRRo/NKPygi7bE24EK0+6iQ+jrUf7sdF8NuC02WbPYZxnK 3g4fPhaFZ5SYgak0jm5fdQNGDDP/B4g2NOpyfhkpg2UdXwfmw0GaKb/5gKB2CH+o7dHQ=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=bCf5XkVHEXTCUo2oCYxDBZo5pjeWkzxJjzhs7Rivk6U=; b=mSc9OpxxldgeiT444LBtisaC2b rLKWoJ1aNl2sZ4wO975Jxr7SDcwMVuSc66XJKef+Jb0xQGnaJ4GYEObJRFYW59iL75Ecvy0iI8MVz JzM3yKYyIDpg4iHxZ0KTC/phPGWwEN5n/Db53uiiLGSqwAHkNyNoSkcPWTNsp/zDLr6E=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fR9pX-003Twd-03 for openvpn-devel@lists.sourceforge.net; Fri, 08 Jun 2018 05:20:57 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Fri, 8 Jun 2018 13:20:10 +0800 Message-Id: <20180608052017.6696-2-a@unstable.cc> In-Reply-To: <20180608052017.6696-1-a@unstable.cc> References: <20180608052017.6696-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1fR9pX-003Twd-03 Subject: [Openvpn-devel] [PATCH v2 1/8] tun: ensure interface can be configured with IPv6 only X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gert Doering , Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Antonio Quartulli This change ensures that an interface is properly brought up even when only IPv6 settings are configured/pushed. Trac: #208 Cc: Gert Doering Signed-off-by: Antonio Quartulli --- src/openvpn/tun.c | 1118 ++++++++++++++++++++------------------------- src/openvpn/tun.h | 12 +- 2 files changed, 492 insertions(+), 638 deletions(-) diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 263cacdf..8509d489 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -871,724 +871,572 @@ create_arbitrary_remote( struct tuntap *tt ) } #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) +/** + * do_ifconfig_ipv6 - perform platform specific ifconfig6 commands + * + * @param tt the tuntap interface context + * @param ifname the human readable interface name + * @param mtu the MTU value to set the interface to + * @param es the environment to be used when executing the commands + */ +static void +do_ifconfig_ipv6(struct tuntap *tt, const char *ifname, int tun_mtu, + const struct env_set *es) { + const char *ifconfig_ipv6_local = NULL; + struct argv argv = argv_new(); 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; - const char *ifconfig_ipv6_local = NULL; - bool do_ipv6 = false; - struct argv argv = argv_new(); + ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc); - msg( M_DEBUG, "do_ifconfig, tt->did_ifconfig_ipv6_setup=%d", - tt->did_ifconfig_ipv6_setup ); +#if defined(TARGET_LINUX) +#ifdef ENABLE_IPROUTE + /* set the MTU for the device and bring it up */ + argv_printf(&argv, "%s link set dev %s up mtu %d", iproute_path, ifname, + tun_mtu); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "Linux ip link set failed"); - /* - * We only handle TUN/TAP devices here, not --dev null devices. - */ - tun = is_tun_p2p(tt); + argv_printf(&argv, "%s -6 addr add %s/%d dev %s", iproute_path, + ifconfig_ipv6_local, tt->netbits_ipv6, ifname); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "Linux ip -6 addr add failed"); +#else + argv_printf(&argv, "%s %s add %s/%d mtu %d up", IFCONFIG_PATH, ifname, + ifconfig_ipv6_local, tt->netbits_ipv6, tun_mtu); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "Linux ifconfig inet6 failed"); +#endif +#elif defined(TARGET_ANDROID) + char out6[64]; - /* - * 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); + openvpn_snprintf(out6, sizeof(out6), "%s/%d", + ifconfig_ipv6_local,tt->netbits_ipv6); + management_android_control(management, "IFCONFIG6", out6); +#elif defined(TARGET_SOLARIS) + argv_printf(&argv, "%s %s inet6 unplumb", IFCONFIG_PATH, ifname); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, 0, NULL); - if (tt->did_ifconfig_ipv6_setup) + if (tt->type == DEV_TYPE_TUN) + { + const char *ifconfig_ipv6_remote = print_in6_addr(tt->remote_ipv6, 0, + gc); + + argv_printf(&argv, "%s %s inet6 plumb %s/%d %s mtu %d up", + IFCONFIG_PATH, ifname, ifconfig_ipv6_local, + tt->netbits_ipv6, ifconfig_ipv6_remote, tun_mtu); + } + else /* tap mode */ + { + /* base IPv6 tap interface needs to be brought up first */ + argv_printf(&argv, "%s %s inet6 plumb up", IFCONFIG_PATH, ifname); + argv_msg(M_INFO, &argv); + + if (!openvpn_execve_check(&argv, es, 0, + "Solaris ifconfig IPv6 (prepare) failed")) { - ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc); - do_ipv6 = true; + solaris_error_close(tt, es, ifname, true); } - /* - * If TAP-style device, generate broadcast address. + /* we might need to do "ifconfig %s inet6 auto-dhcp drop" + * after the system has noticed the interface and fired up + * the DHCPv6 client - but this takes quite a while, and the + * server will ignore the DHCPv6 packets anyway. So we don't. */ - 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, - &tt->local_ipv6, - NULL, - NULL); - } + /* static IPv6 addresses need to go to a subinterface (tap0:1) */ + argv_printf(&argv, "%s %s inet6 addif %s/%d mtu %d up", IFCONFIG_PATH, + ifname, ifconfig_ipv6_local, tt->netbits_ipv6, tun_mtu); + } + argv_msg(M_INFO, &argv); + + if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig IPv6 failed")) + { + solaris_error_close(tt, es, ifname, true); + } +#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD) \ + || defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) \ + || defined(TARGET_DRAGONFLY) || defined(TARGET_AIX) + argv_printf(&argv, "%s %s inet6 %s/%d mtu %d up", IFCONFIG_PATH, ifname, + ifconfig_ipv6_local, tt->netbits_ipv6, tun_mtu); + argv_msg(M_INFO, &argv); + +#if defined(TARGET_AIX) + /* AIX ifconfig will complain if it can't find ODM path in env */ + es = env_set_create(NULL); + env_set_add(es, "ODMDIR=/etc/objrepos"); #endif + openvpn_execve_check(&argv, es, S_FATAL, + "generic BSD ifconfig inet6 failed"); + +#if defined(TARGET_AIX) + env_set_destroy(es); +#endif + +#if !defined(TARGET_FREEBSD) && !defined(TARGET_DRAGONFLY) \ + && !defined(TARGET_AIX) + /* and, hooray, we explicitely need to add a route... */ + add_route_connected_v6_net(tt, es); +#endif +#elif defined (_WIN32) + if (tt->options.ip_win32_type == IPW32_SET_MANUAL) + { + msg(M_INFO, "******** NOTE: Please manually set the v6 IP of '%s' to %s (if it is not already set)", + ifname, ifconfig_ipv6_local); + } + else if (tt->options.msg_channel) + { + do_address_service(true, AF_INET6, tt); + do_dns6_service(true, tt); + } + else + { + /* example: netsh interface ipv6 set address interface=42 + * 2001:608:8003::d store=active + */ + char iface[64]; + + openvpn_snprintf(iface, sizeof(iface), "interface=%lu", + tt->adapter_index); + argv_printf(&argv, "%s%sc interface ipv6 set address %s %s store=active", + get_win_sys_path(), NETSH_PATH_SUFFIX, iface, + ifconfig_ipv6_local); + netsh_command(&argv, 4, M_FATAL); + /* set ipv6 dns servers if any are specified */ + netsh_set_dns6_servers(tt->options.dns6, tt->options.dns6_len, ifname); + } + + /* explicit route needed */ + if (tt->options.ip_win32_type != IPW32_SET_MANUAL) + { + add_route_connected_v6_net(tt, es); + } +#else /* if defined(TARGET_LINUX) */ + msg(M_FATAL, "Sorry, but I don't know how to do IPv6 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script."); +#endif /* if defined(TARGET_LINUX) */ + + gc_free(&gc); + argv_reset(&argv); +} + +/** + * do_ifconfig_ipv4 - perform platform specific ifconfig commands + * + * @param tt the tuntap interface context + * @param ifname the human readable interface name + * @param mtu the MTU value to set the interface to + * @param es the environment to be used when executing the commands + */ +static void +do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu, + const struct env_set *es) +{ + bool tun = false; + const char *ifconfig_local = NULL; + const char *ifconfig_remote_netmask = NULL; + const char *ifconfig_broadcast = NULL; + struct argv argv = argv_new(); + struct gc_arena gc = gc_new(); + + /* + * We only handle TUN/TAP devices here, not --dev null devices. + */ + tun = is_tun_p2p(tt); + + /* + * 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); + } #if defined(TARGET_LINUX) #ifdef ENABLE_IPROUTE + /* + * Set the MTU for the device + */ + argv_printf(&argv, "%s link set dev %s up mtu %d", iproute_path, ifname, + tun_mtu); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "Linux ip link set failed"); + + if (tun) + { + /* - * Set the MTU for the device + * Set the address for the device */ - argv_printf(&argv, - "%s link set dev %s up mtu %d", - iproute_path, - actual, - tun_mtu - ); + argv_printf(&argv, "%s addr add dev %s local %s peer %s", iproute_path, + ifname, ifconfig_local, ifconfig_remote_netmask); argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "Linux ip link set failed"); - - if (tun) - { - - /* - * Set the address for the device - */ - argv_printf(&argv, - "%s addr add dev %s local %s peer %s", - iproute_path, - actual, - ifconfig_local, - ifconfig_remote_netmask - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "Linux ip addr add failed"); - } - else - { - argv_printf(&argv, - "%s addr add dev %s %s/%d broadcast %s", - iproute_path, - actual, - ifconfig_local, - netmask_to_netbits2(tt->remote_netmask), - ifconfig_broadcast - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "Linux ip addr add failed"); - } - if (do_ipv6) - { - argv_printf( &argv, - "%s -6 addr add %s/%d dev %s", - iproute_path, - ifconfig_ipv6_local, - tt->netbits_ipv6, - actual - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "Linux ip -6 addr add failed"); - } - tt->did_ifconfig = true; -#else /* ifdef ENABLE_IPROUTE */ - if (tun) - { - argv_printf(&argv, - "%s %s %s pointopoint %s mtu %d", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - } - else - { - argv_printf(&argv, - "%s %s %s netmask %s mtu %d broadcast %s", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu, - ifconfig_broadcast - ); - } + openvpn_execve_check(&argv, es, S_FATAL, "Linux ip addr add failed"); + } + else + { + argv_printf(&argv, "%s addr add dev %s %s/%d broadcast %s", + iproute_path, ifname, ifconfig_local, + netmask_to_netbits2(tt->remote_netmask), + ifconfig_broadcast); argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "Linux ifconfig failed"); - if (do_ipv6) - { - argv_printf(&argv, - "%s %s add %s/%d", - IFCONFIG_PATH, - actual, - ifconfig_ipv6_local, - tt->netbits_ipv6 - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "Linux ifconfig inet6 failed"); - } - tt->did_ifconfig = true; + openvpn_execve_check(&argv, es, S_FATAL, "Linux ip addr add failed"); + } + tt->did_ifconfig = true; +#else /* ifdef ENABLE_IPROUTE */ + if (tun) + { + argv_printf(&argv, "%s %s %s pointopoint %s mtu %d", IFCONFIG_PATH, + ifname, ifconfig_local, ifconfig_remote_netmask, tun_mtu); + } + else + { + argv_printf(&argv, "%s %s %s netmask %s mtu %d broadcast %s", + IFCONFIG_PATH, ifname, ifconfig_local, + ifconfig_remote_netmask, tun_mtu, ifconfig_broadcast); + } + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "Linux ifconfig failed"); + tt->did_ifconfig = true; #endif /*ENABLE_IPROUTE*/ #elif defined(TARGET_ANDROID) + char out[64]; - if (do_ipv6) - { - char out6[64]; - openvpn_snprintf(out6, sizeof(out6), "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6); - management_android_control(management, "IFCONFIG6", out6); - } - - char out[64]; - - char *top; - switch (tt->topology) - { - case TOP_NET30: - top = "net30"; - break; + char *top; + switch (tt->topology) + { + case TOP_NET30: + top = "net30"; + break; - case TOP_P2P: - top = "p2p"; - break; + case TOP_P2P: + top = "p2p"; + break; - case TOP_SUBNET: - top = "subnet"; - break; + case TOP_SUBNET: + top = "subnet"; + break; - default: - top = "undef"; - } + default: + top = "undef"; + } - openvpn_snprintf(out, sizeof(out), "%s %s %d %s", ifconfig_local, ifconfig_remote_netmask, tun_mtu, top); - management_android_control(management, "IFCONFIG", out); + openvpn_snprintf(out, sizeof(out), "%s %s %d %s", ifconfig_local, + ifconfig_remote_netmask, tun_mtu, top); + management_android_control(management, "IFCONFIG", out); #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) - { - argv_printf(&argv, - "%s %s %s %s mtu %d up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - - argv_msg(M_INFO, &argv); - if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig phase-1 failed")) - { - solaris_error_close(tt, es, actual, false); - } - - argv_printf(&argv, - "%s %s netmask 255.255.255.255", - IFCONFIG_PATH, - actual - ); - } - else if (tt->topology == TOP_SUBNET) - { - argv_printf(&argv, - "%s %s %s %s netmask %s mtu %d up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - } - else - { - argv_printf(&argv, - " %s %s %s netmask %s broadcast + up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask - ); - } + /* 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) + { + argv_printf(&argv, "%s %s %s %s mtu %d up", IFCONFIG_PATH, ifname, + ifconfig_local, ifconfig_remote_netmask, tun_mtu); argv_msg(M_INFO, &argv); - if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig phase-2 failed")) + if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig phase-1 failed")) { - solaris_error_close(tt, es, actual, false); + solaris_error_close(tt, es, ifname, false); } - if (do_ipv6) - { - argv_printf(&argv, "%s %s inet6 unplumb", - IFCONFIG_PATH, actual ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, 0, NULL); - - if (tt->type == DEV_TYPE_TUN) - { - const char *ifconfig_ipv6_remote = - print_in6_addr(tt->remote_ipv6, 0, &gc); - - argv_printf(&argv, - "%s %s inet6 plumb %s/%d %s up", - IFCONFIG_PATH, - actual, - ifconfig_ipv6_local, - tt->netbits_ipv6, - ifconfig_ipv6_remote - ); - } - else /* tap mode */ - { - /* base IPv6 tap interface needs to be brought up first - */ - argv_printf(&argv, "%s %s inet6 plumb up", - IFCONFIG_PATH, actual ); - argv_msg(M_INFO, &argv); - if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig IPv6 (prepare) failed")) - { - solaris_error_close(tt, es, actual, true); - } - - /* we might need to do "ifconfig %s inet6 auto-dhcp drop" - * after the system has noticed the interface and fired up - * the DHCPv6 client - but this takes quite a while, and the - * server will ignore the DHCPv6 packets anyway. So we don't. - */ + argv_printf(&argv, "%s %s netmask 255.255.255.255", IFCONFIG_PATH, + ifname); + } + else if (tt->topology == TOP_SUBNET) + { + argv_printf(&argv, "%s %s %s %s netmask %s mtu %d up", IFCONFIG_PATH, + ifname, ifconfig_local, ifconfig_local, + ifconfig_remote_netmask, tun_mtu); + } + else + { + argv_printf(&argv, "%s %s %s netmask %s broadcast + up", + IFCONFIG_PATH, ifname, ifconfig_local, + ifconfig_remote_netmask); + } - /* static IPv6 addresses need to go to a subinterface (tap0:1) - */ - argv_printf(&argv, - "%s %s inet6 addif %s/%d up", - IFCONFIG_PATH, actual, - ifconfig_ipv6_local, tt->netbits_ipv6 ); - } - argv_msg(M_INFO, &argv); - if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig IPv6 failed")) - { - solaris_error_close(tt, es, actual, true); - } - } + argv_msg(M_INFO, &argv); + if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig phase-2 failed")) + { + solaris_error_close(tt, es, ifname, false); + } - if (!tun && tt->topology == TOP_SUBNET) - { - /* Add a network route for the local tun interface */ - struct route_ipv4 r; - CLEAR(r); - r.flags = RT_DEFINED | RT_METRIC_DEFINED; - r.network = tt->local & tt->remote_netmask; - r.netmask = tt->remote_netmask; - r.gateway = tt->local; - r.metric = 0; - add_route(&r, tt, 0, NULL, es); - } + if (!tun && tt->topology == TOP_SUBNET) + { + /* Add a network route for the local tun interface */ + struct route_ipv4 r; + CLEAR(r); + r.flags = RT_DEFINED | RT_METRIC_DEFINED; + r.network = tt->local & tt->remote_netmask; + r.netmask = tt->remote_netmask; + r.gateway = tt->local; + r.metric = 0; + add_route(&r, tt, 0, NULL, es); + } - tt->did_ifconfig = true; + tt->did_ifconfig = true; #elif defined(TARGET_OPENBSD) - in_addr_t remote_end; /* for "virtual" subnet topology */ + in_addr_t remote_end; /* for "virtual" subnet topology */ - /* - * On OpenBSD, tun interfaces are persistent if created with - * "ifconfig tunX create", and auto-destroyed if created by - * opening "/dev/tunX" (so we just use the /dev/tunX) - */ - - /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ - if (tun) - { - argv_printf(&argv, - "%s %s %s %s mtu %d netmask 255.255.255.255 up -link0", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - } - else if (tt->topology == TOP_SUBNET) - { - remote_end = create_arbitrary_remote( tt ); - argv_printf(&argv, - "%s %s %s %s mtu %d netmask %s up -link0", - IFCONFIG_PATH, - actual, - ifconfig_local, - print_in_addr_t(remote_end, 0, &gc), - tun_mtu, - ifconfig_remote_netmask - ); - } - else - { - argv_printf(&argv, - "%s %s %s netmask %s mtu %d broadcast %s link0", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu, - ifconfig_broadcast - ); - } - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "OpenBSD ifconfig failed"); + /* + * On OpenBSD, tun interfaces are persistent if created with + * "ifconfig tunX create", and auto-destroyed if created by + * opening "/dev/tunX" (so we just use the /dev/tunX) + */ - /* Add a network route for the local tun interface */ - if (!tun && tt->topology == TOP_SUBNET) - { - struct route_ipv4 r; - CLEAR(r); - r.flags = RT_DEFINED; - r.network = tt->local & tt->remote_netmask; - r.netmask = tt->remote_netmask; - r.gateway = remote_end; - add_route(&r, tt, 0, NULL, es); - } + /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ + if (tun) + { + argv_printf(&argv, + "%s %s %s %s mtu %d netmask 255.255.255.255 up -link0", + IFCONFIG_PATH, ifname, ifconfig_local, + ifconfig_remote_netmask, tun_mtu); + } + else if (tt->topology == TOP_SUBNET) + { + remote_end = create_arbitrary_remote( tt ); + argv_printf(&argv, "%s %s %s %s mtu %d netmask %s up -link0", + IFCONFIG_PATH, ifname, ifconfig_local, + print_in_addr_t(remote_end, 0, &gc), tun_mtu, + ifconfig_remote_netmask); + } + else + { + argv_printf(&argv, "%s %s %s netmask %s mtu %d broadcast %s link0", + IFCONFIG_PATH, ifname, ifconfig_local, + ifconfig_remote_netmask, tun_mtu, ifconfig_broadcast); + } + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "OpenBSD ifconfig failed"); - if (do_ipv6) - { - argv_printf(&argv, - "%s %s inet6 %s/%d", - IFCONFIG_PATH, - actual, - ifconfig_ipv6_local, - tt->netbits_ipv6 - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "OpenBSD ifconfig inet6 failed"); + /* Add a network route for the local tun interface */ + if (!tun && tt->topology == TOP_SUBNET) + { + struct route_ipv4 r; + CLEAR(r); + r.flags = RT_DEFINED; + r.network = tt->local & tt->remote_netmask; + r.netmask = tt->remote_netmask; + r.gateway = remote_end; + add_route(&r, tt, 0, NULL, es); + } - /* and, hooray, we explicitely need to add a route... */ - add_route_connected_v6_net(tt, es); - } - tt->did_ifconfig = true; + tt->did_ifconfig = true; #elif defined(TARGET_NETBSD) - if (tun) - { - argv_printf(&argv, - "%s %s %s %s mtu %d netmask 255.255.255.255 up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - } - else if (tt->topology == TOP_SUBNET) - { - argv_printf(&argv, - "%s %s %s %s mtu %d netmask %s up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_local, - tun_mtu, - ifconfig_remote_netmask - ); - } - 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 - */ - argv_printf(&argv, - "%s %s %s netmask %s mtu %d broadcast %s", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu, - ifconfig_broadcast - ); - } - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "NetBSD ifconfig failed"); - - if (do_ipv6) - { - argv_printf(&argv, - "%s %s inet6 %s/%d", - IFCONFIG_PATH, - actual, - ifconfig_ipv6_local, - tt->netbits_ipv6 - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "NetBSD ifconfig inet6 failed"); + if (tun) + { + argv_printf(&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up", + IFCONFIG_PATH, ifname, ifconfig_local, + ifconfig_remote_netmask, tun_mtu); + } + else if (tt->topology == TOP_SUBNET) + { + argv_printf(&argv, "%s %s %s %s mtu %d netmask %s up", IFCONFIG_PATH, + ifname, ifconfig_local, ifconfig_local, tun_mtu, + ifconfig_remote_netmask); + } + 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 + */ + argv_printf(&argv, "%s %s %s netmask %s mtu %d broadcast %s", + IFCONFIG_PATH, ifname, ifconfig_local, + ifconfig_remote_netmask, tun_mtu, ifconfig_broadcast); + } + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "NetBSD ifconfig failed"); - /* and, hooray, we explicitely need to add a route... */ - add_route_connected_v6_net(tt, es); - } - tt->did_ifconfig = true; + tt->did_ifconfig = true; #elif defined(TARGET_DARWIN) - /* - * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD... - */ + /* + * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD... + */ - argv_printf(&argv, - "%s %s delete", - IFCONFIG_PATH, - actual); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, 0, NULL); - msg(M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure"); + argv_printf(&argv, "%s %s delete", IFCONFIG_PATH, ifname); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, 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) + /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ + if (tun) + { + argv_printf(&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up", + IFCONFIG_PATH, ifname, ifconfig_local, + ifconfig_remote_netmask, tun_mtu); + } + else + { + if (tt->topology == TOP_SUBNET) { - argv_printf(&argv, - "%s %s %s %s mtu %d netmask 255.255.255.255 up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); + argv_printf(&argv, "%s %s %s %s netmask %s mtu %d up", + IFCONFIG_PATH, ifname, ifconfig_local, ifconfig_local, + ifconfig_remote_netmask, tun_mtu); } else { - if (tt->topology == TOP_SUBNET) - { - argv_printf(&argv, - "%s %s %s %s netmask %s mtu %d up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - } - else - { - argv_printf(&argv, - "%s %s %s netmask %s mtu %d up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - } + argv_printf(&argv, "%s %s %s netmask %s mtu %d up", IFCONFIG_PATH, + ifname, ifconfig_local, ifconfig_remote_netmask, + tun_mtu); } + } - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "Mac OS X ifconfig failed"); - tt->did_ifconfig = true; + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "Mac OS X ifconfig failed"); + tt->did_ifconfig = true; - /* Add a network route for the local tun interface */ - if (!tun && tt->topology == TOP_SUBNET) - { - struct route_ipv4 r; - CLEAR(r); - r.flags = RT_DEFINED; - r.network = tt->local & tt->remote_netmask; - r.netmask = tt->remote_netmask; - r.gateway = tt->local; - add_route(&r, tt, 0, NULL, es); - } + /* Add a network route for the local tun interface */ + if (!tun && tt->topology == TOP_SUBNET) + { + struct route_ipv4 r; + CLEAR(r); + r.flags = RT_DEFINED; + r.network = tt->local & tt->remote_netmask; + r.netmask = tt->remote_netmask; + r.gateway = tt->local; + add_route(&r, tt, 0, NULL, es); + } - if (do_ipv6) - { - argv_printf(&argv, - "%s %s inet6 %s/%d", - IFCONFIG_PATH, - actual, - ifconfig_ipv6_local, - tt->netbits_ipv6 - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "MacOS X ifconfig inet6 failed"); +#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) - /* and, hooray, we explicitely need to add a route... */ - add_route_connected_v6_net(tt, es); - } + in_addr_t remote_end; /* for "virtual" subnet topology */ -#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) + /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ + if (tun) + { + argv_printf(&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up", + IFCONFIG_PATH, ifname, ifconfig_local, + ifconfig_remote_netmask, tun_mtu); + } + else if (tt->topology == TOP_SUBNET) + { + remote_end = create_arbitrary_remote( tt ); + argv_printf(&argv, "%s %s %s %s mtu %d netmask %s up", IFCONFIG_PATH, + ifname, ifconfig_local, print_in_addr_t(remote_end, 0, &gc), + tun_mtu, ifconfig_remote_netmask); + } + else + { + argv_printf(&argv, "%s %s %s netmask %s mtu %d up", IFCONFIG_PATH, + ifname, ifconfig_local, ifconfig_remote_netmask, tun_mtu); + } + + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, es, S_FATAL, "FreeBSD ifconfig failed"); + tt->did_ifconfig = true; - in_addr_t remote_end; /* for "virtual" subnet topology */ + /* Add a network route for the local tun interface */ + if (!tun && tt->topology == TOP_SUBNET) + { + struct route_ipv4 r; + CLEAR(r); + r.flags = RT_DEFINED; + r.network = tt->local & tt->remote_netmask; + r.netmask = tt->remote_netmask; + r.gateway = remote_end; + add_route(&r, tt, 0, NULL, es); + } + +#elif defined(TARGET_AIX) + { + /* AIX ifconfig will complain if it can't find ODM path in env */ + struct env_set *aix_es = env_set_create(NULL); + env_set_add( aix_es, "ODMDIR=/etc/objrepos" ); - /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ if (tun) { - argv_printf(&argv, - "%s %s %s %s mtu %d netmask 255.255.255.255 up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - } - else if (tt->topology == TOP_SUBNET) - { - remote_end = create_arbitrary_remote( tt ); - argv_printf(&argv, - "%s %s %s %s mtu %d netmask %s up", - IFCONFIG_PATH, - actual, - ifconfig_local, - print_in_addr_t(remote_end, 0, &gc), - tun_mtu, - ifconfig_remote_netmask - ); - } - else - { - argv_printf(&argv, - "%s %s %s netmask %s mtu %d up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); + msg(M_FATAL, "no tun support on AIX (canthappen)"); } + /* example: ifconfig tap0 172.30.1.1 netmask 255.255.254.0 up */ + argv_printf(&argv, "%s %s %s netmask %s mtu %d up", IFCONFIG_PATH, + ifname, ifconfig_local, ifconfig_remote_netmask, tun_mtu); + argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "FreeBSD ifconfig failed"); + openvpn_execve_check(&argv, aix_es, S_FATAL, "AIX ifconfig failed"); tt->did_ifconfig = true; - /* Add a network route for the local tun interface */ - if (!tun && tt->topology == TOP_SUBNET) - { - struct route_ipv4 r; - CLEAR(r); - r.flags = RT_DEFINED; - r.network = tt->local & tt->remote_netmask; - r.netmask = tt->remote_netmask; - r.gateway = remote_end; - add_route(&r, tt, 0, NULL, es); - } - - if (do_ipv6) - { - argv_printf(&argv, - "%s %s inet6 %s/%d", - IFCONFIG_PATH, - actual, - ifconfig_ipv6_local, - tt->netbits_ipv6 - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, es, S_FATAL, "FreeBSD ifconfig inet6 failed"); - } + env_set_destroy(aix_es); + } +#elif defined (_WIN32) + { + ASSERT(ifname != NULL); -#elif defined(TARGET_AIX) + switch (tt->options.ip_win32_type) { - /* AIX ifconfig will complain if it can't find ODM path in env */ - struct env_set *aix_es = env_set_create(NULL); - env_set_add( aix_es, "ODMDIR=/etc/objrepos" ); - - if (tun) - { - msg(M_FATAL, "no tun support on AIX (canthappen)"); - } - - /* example: ifconfig tap0 172.30.1.1 netmask 255.255.254.0 up */ - argv_printf(&argv, - "%s %s %s netmask %s mtu %d up", - IFCONFIG_PATH, - actual, - ifconfig_local, - ifconfig_remote_netmask, - tun_mtu - ); - - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, aix_es, S_FATAL, "AIX ifconfig failed"); - tt->did_ifconfig = true; + 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)", + ifname, ifconfig_local, + print_in_addr_t(tt->adapter_netmask, 0, &gc)); + break; + case IPW32_SET_NETSH: + netsh_ifconfig(&tt->options, ifname, tt->local, + tt->adapter_netmask, NI_IP_NETMASK|NI_OPTIONS); - if (do_ipv6) - { - argv_printf(&argv, - "%s %s inet6 %s/%d", - IFCONFIG_PATH, - actual, - ifconfig_ipv6_local, - tt->netbits_ipv6 - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, aix_es, S_FATAL, "AIX ifconfig inet6 failed"); - } - env_set_destroy(aix_es); + break; } -#elif defined (_WIN32) - { - ASSERT(actual != NULL); + tt->did_ifconfig = true; + } - 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, - print_in_addr_t(tt->adapter_netmask, 0, &gc)); - break; +#else /* if defined(TARGET_LINUX) */ + 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 /* if defined(TARGET_LINUX) */ - case IPW32_SET_NETSH: - netsh_ifconfig(&tt->options, - actual, - tt->local, - tt->adapter_netmask, - NI_IP_NETMASK|NI_OPTIONS); + gc_free(&gc); + argv_reset(&argv); +} - break; - } - tt->did_ifconfig = true; - } +/* execute the ifconfig command through the shell */ +void +do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu, + const struct env_set *es) +{ + msg(M_DEBUG, "do_ifconfig, ipv4=%d, ipv6=%d", tt->did_ifconfig_setup, + tt->did_ifconfig_ipv6_setup); - if (do_ipv6) - { - if (tt->options.ip_win32_type == IPW32_SET_MANUAL) - { - msg(M_INFO, "******** NOTE: Please manually set the v6 IP of '%s' to %s (if it is not already set)", - actual, - ifconfig_ipv6_local); - } - else if (tt->options.msg_channel) - { - do_address_service(true, AF_INET6, tt); - do_dns6_service(true, tt); - } - else - { - /* example: netsh interface ipv6 set address interface=42 2001:608:8003::d store=active */ - char iface[64]; - openvpn_snprintf(iface, sizeof(iface), "interface=%lu", tt->adapter_index ); - argv_printf(&argv, - "%s%sc interface ipv6 set address %s %s store=active", - get_win_sys_path(), - NETSH_PATH_SUFFIX, - iface, - ifconfig_ipv6_local ); - netsh_command(&argv, 4, M_FATAL); - /* set ipv6 dns servers if any are specified */ - netsh_set_dns6_servers(tt->options.dns6, tt->options.dns6_len, actual); - } +#ifdef ENABLE_MANAGEMENT + if (management) + { + management_set_state(management, + OPENVPN_STATE_ASSIGN_IP, + NULL, + &tt->local, + &tt->local_ipv6, + NULL, + NULL); + } +#endif - /* explicit route needed */ - if (tt->options.ip_win32_type != IPW32_SET_MANUAL) - { - add_route_connected_v6_net(tt, es); - } - } -#else /* if defined(TARGET_LINUX) */ - 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 /* if defined(TARGET_LINUX) */ - argv_reset(&argv); + if (tt->did_ifconfig_setup) + { + do_ifconfig_ipv4(tt, ifname, tun_mtu, es); + } + + if (tt->did_ifconfig_ipv6_setup) + { + do_ifconfig_ipv6(tt, ifname, tun_mtu, es); } - gc_free(&gc); } static void @@ -5865,7 +5713,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun if (tt->type == DEV_TYPE_TUN) { - if (!tt->did_ifconfig_setup) + if (!tt->did_ifconfig_setup && !tt->did_ifconfig_ipv6_setup) { msg(M_FATAL, "ERROR: --dev tun also requires --ifconfig"); } diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index 6c57ad0d..448a7738 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -247,9 +247,15 @@ void init_tun_post(struct tuntap *tt, void do_ifconfig_setenv(const struct tuntap *tt, struct env_set *es); -void do_ifconfig(struct tuntap *tt, - const char *actual, /* actual device name */ - int tun_mtu, +/** + * do_ifconfig - configure the tunnel interface + * + * @param tt the tuntap interface context + * @param ifname the human readable interface name + * @param mtu the MTU value to set the interface to + * @param es the environment to be used when executing the commands + */ +void do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu, const struct env_set *es); bool is_dev_type(const char *dev, const char *dev_type, const char *match_type);