From patchwork Wed Jun 13 02:28:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 369 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id Hts9AUIOIVs3aQAAIUCqbw for ; Wed, 13 Jun 2018 08:29:54 -0400 Received: from proxy16.mail.iad3b.rsapps.net ([172.31.255.6]) by director7.mail.ord1d.rsapps.net (Dovecot) with LMTP id GVhZFkIOIVtMPAAAovjBpQ ; Wed, 13 Jun 2018 08:29:54 -0400 Received: from smtp36.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy16.mail.iad3b.rsapps.net with LMTP id yO1ZJ0IOIVtSLwAAPj+4aA ; Wed, 13 Jun 2018 08:29:54 -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: smtp36.gate.iad3b.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: 788e1d0a-6f05-11e8-95ab-5254003a7283-1-1 Received: from [216.105.38.7] ([216.105.38.7:64297] helo=lists.sourceforge.net) by smtp36.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 4B/D6-06288-04E012B5; Wed, 13 Jun 2018 08:29:53 -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 1fT4tl-0006vi-Fa; Wed, 13 Jun 2018 12:29:13 +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 1fT4tk-0006vc-4C for openvpn-devel@lists.sourceforge.net; Wed, 13 Jun 2018 12:29:12 +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=4oLkNI4DeYEaofuxkQXKHJ2B93L4XC8WjzB4EQmqhd0=; b=axcN7qbE6h71FjfTpPxN6WlQ/6 5hMkBaTyHRUxTW3haVwwmwTcfIvcvip73a4IM5j5tQbdku6ORaw5EzJjt6qeQpGYv3qOn/UHsevgb 86t2+hqHV4J97yoLV3aHKtKq6Frf+PA0EPOCEw1zhv8Qcp423i7wePAWQJ/iuFfmI5jg=; 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=4oLkNI4DeYEaofuxkQXKHJ2B93L4XC8WjzB4EQmqhd0=; b=IxCMJNicd2YZoknAdMA/VBJqFY 9RkzJss34OWHXVHlBYkBJZcXrJxZx3go9CTMNZmzNDqG33K2n/V3xcFJUgI0gYQe992IppMTz6C7m flQMpOs4nPyutVBbl1HAKpecqCXYlarKhU5Q2Vyal46kIb/CKLA2GjuShAy7x8VaJE9s=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-4.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fT4ti-005sOS-Ni for openvpn-devel@lists.sourceforge.net; Wed, 13 Jun 2018 12:29:12 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Wed, 13 Jun 2018 20:28:22 +0800 Message-Id: <20180613122824.4207-2-a@unstable.cc> In-Reply-To: <20180613122824.4207-1-a@unstable.cc> References: <20180613122824.4207-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.2 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1fT4ti-005sOS-Ni Subject: [Openvpn-devel] [PATCH v2 1/3] tun: ensure gc and argv are properly handled 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: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Antonio Quartulli Everytime a argv object is initialized with argv_new(), it has to be released with argv_reset() once not needed anymore. Ensure this kind of objects are always properly released to avoid memory leaks. At the same time, remove those gc_arena objects that are initialized but never used/released. Signed-off-by: Antonio Quartulli Acked-by: Gert Doering --- Changes from v1: - remove gc_arena at all when not used src/openvpn/tun.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 3eb0f78a..72506c4b 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -2600,7 +2600,6 @@ close_tun(struct tuntap *tt) } else if (tt) { - struct gc_arena gc = gc_new(); struct argv argv = argv_new(); /* setup command, close tun dev (clears tt->actual_name!), run command @@ -2615,6 +2614,7 @@ close_tun(struct tuntap *tt) openvpn_execve_check(&argv, NULL, 0, "OpenBSD 'destroy tun interface' failed (non-critical)"); free(tt); + argv_reset(&argv); } } @@ -2685,7 +2685,6 @@ close_tun(struct tuntap *tt) } else if (tt) { - struct gc_arena gc = gc_new(); struct argv argv = argv_new(); /* setup command, close tun dev (clears tt->actual_name!), run command @@ -2700,6 +2699,7 @@ close_tun(struct tuntap *tt) openvpn_execve_check(&argv, NULL, 0, "NetBSD 'destroy tun interface' failed (non-critical)"); free(tt); + argv_reset(&argv); } } @@ -2837,6 +2837,7 @@ close_tun(struct tuntap *tt) openvpn_execve_check(&argv, NULL, 0, "FreeBSD 'destroy tun interface' failed (non-critical)"); free(tt); + argv_reset(&argv); } } @@ -3308,6 +3309,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun env_set_add( es, "ODMDIR=/etc/objrepos" ); openvpn_execve_check(&argv, es, S_FATAL, "AIX 'create tun interface' failed"); env_set_destroy(es); + argv_reset(&argv); } else { @@ -3333,7 +3335,6 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { - struct gc_arena gc = gc_new(); struct argv argv = argv_new(); struct env_set *es = env_set_create(NULL); @@ -3362,6 +3363,7 @@ close_tun(struct tuntap *tt) free(tt); env_set_destroy(es); + argv_reset(&argv); } int From patchwork Wed Jun 13 02:28:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 372 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id g1i5GFgOIVs3aQAAIUCqbw for ; Wed, 13 Jun 2018 08:30:16 -0400 Received: from proxy10.mail.iad3b.rsapps.net ([172.31.255.6]) by director12.mail.ord1d.rsapps.net (Dovecot) with LMTP id rwpNAFgOIVvWcQAAIasKDg ; Wed, 13 Jun 2018 08:30:16 -0400 Received: from smtp38.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy10.mail.iad3b.rsapps.net with LMTP id uMg2EVgOIVuPPwAA/F5p9A ; Wed, 13 Jun 2018 08:30:16 -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: smtp38.gate.iad3b.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: 85be5fbc-6f05-11e8-b347-5254006f0979-1-1 Received: from [216.105.38.7] ([216.105.38.7:45342] helo=lists.sourceforge.net) by smtp38.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id CB/C7-28647-75E012B5; Wed, 13 Jun 2018 08:30:15 -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 1fT4to-0006w2-IZ; Wed, 13 Jun 2018 12:29:16 +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 1fT4tn-0006vt-8b for openvpn-devel@lists.sourceforge.net; Wed, 13 Jun 2018 12:29:15 +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=tO71a2GoiT9yv6tFseDHs93U1TWhSw/hMWg6d6Gx5WI=; b=cd6cXnIJTaiHvIH/Mdt2BPSPc8 a/lCtr0h2nzFAq/d0VcID1WKZi+nOnDU0NzNVxuTUntGz9VUNpdIlo/3IY/NjuVMc/D04ya0DA96U F7JblAYL2s0xfsD5Alg/abjo1m8Djg89exIPz3qhBBtvMAozuXLs0eGmXq1IqatGPBgc=; 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=tO71a2GoiT9yv6tFseDHs93U1TWhSw/hMWg6d6Gx5WI=; b=FDNkNN/QGXsA2nIdkmso3L6KFA 4Kv9WZIK5t/McLrYeIdk+Da7D3XOSQHx958Kuo60uUrKW4D0RAaY5InKYATDGVm+Lj4ptvAqxmfi9 PNLfEwGfKfUmD+i+aKC90wCdB/eKavnp7gpub2MwYf8Wvnx5I2HDkiavGR8m6YdkfS+Y=; 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 1fT4tl-007ToH-8S for openvpn-devel@lists.sourceforge.net; Wed, 13 Jun 2018 12:29:15 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Wed, 13 Jun 2018 20:28:23 +0800 Message-Id: <20180613122824.4207-3-a@unstable.cc> In-Reply-To: <20180613122824.4207-1-a@unstable.cc> References: <20180613122824.4207-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.2 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1fT4tl-007ToH-8S Subject: [Openvpn-devel] [PATCH v2 2/3] tun: always pass a valid tt pointer 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: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Antonio Quartulli This patch is a small "logic restyle" which basically moves the check for "tt != NULL" outside of the various close_tun() implementations and replaces it with an ASSERT. This way the check is done only once and the function can rely on the assumption that "tt" is always valid. This change is mainly to improve the code style inside close_tun() implementations by removing one level of indentation. No functional change is present. Signed-off-by: Antonio Quartulli Acked-by: Gert Doering --- Changes from v1: - remove ASSERT from solaris_error_close() - remove "if (tt)" block from solaris_close_tun() - restored "/* close and destroy */" comment in FreeBSD close_tun() src/openvpn/init.c | 7 +- src/openvpn/tun.c | 501 ++++++++++++++++++++++----------------------- 2 files changed, 252 insertions(+), 256 deletions(-) diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 36c1a4c4..b748357d 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -1847,8 +1847,11 @@ static void do_close_tun_simple(struct context *c) { msg(D_CLOSE, "Closing TUN/TAP interface"); - close_tun(c->c1.tuntap); - c->c1.tuntap = NULL; + if (c->c1.tuntap) + { + close_tun(c->c1.tuntap); + c->c1.tuntap = NULL; + } c->c1.tuntap_owned = false; #if P2MP CLEAR(c->c1.pulled_options_digest_save); diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 72506c4b..12b33ae7 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -1900,11 +1900,10 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { - if (tt) - { - close_tun_generic(tt); - free(tt); - } + ASSERT(tt); + + close_tun_generic(tt); + free(tt); } int @@ -2103,77 +2102,76 @@ tuncfg(const char *dev, const char *dev_type, const char *dev_node, int persist_ void close_tun(struct tuntap *tt) { - if (tt) + ASSERT(tt); + + if (tt->type != DEV_TYPE_NULL && tt->did_ifconfig) { - if (tt->type != DEV_TYPE_NULL && tt->did_ifconfig) - { - struct argv argv = argv_new(); - struct gc_arena gc = gc_new(); + struct argv argv = argv_new(); + struct gc_arena gc = gc_new(); #ifdef ENABLE_IPROUTE - if (is_tun_p2p(tt)) - { - argv_printf(&argv, - "%s addr del dev %s local %s peer %s", - iproute_path, - tt->actual_name, - print_in_addr_t(tt->local, 0, &gc), - print_in_addr_t(tt->remote_netmask, 0, &gc) - ); - } - else - { - argv_printf(&argv, - "%s addr del dev %s %s/%d", - iproute_path, - tt->actual_name, - print_in_addr_t(tt->local, 0, &gc), - netmask_to_netbits2(tt->remote_netmask) - ); - } -#else /* ifdef ENABLE_IPROUTE */ + if (is_tun_p2p(tt)) + { argv_printf(&argv, - "%s %s 0.0.0.0", - IFCONFIG_PATH, - tt->actual_name - ); + "%s addr del dev %s local %s peer %s", + iproute_path, + tt->actual_name, + print_in_addr_t(tt->local, 0, &gc), + print_in_addr_t(tt->remote_netmask, 0, &gc) + ); + } + else + { + argv_printf(&argv, + "%s addr del dev %s %s/%d", + iproute_path, + tt->actual_name, + print_in_addr_t(tt->local, 0, &gc), + netmask_to_netbits2(tt->remote_netmask) + ); + } +#else /* ifdef ENABLE_IPROUTE */ + argv_printf(&argv, + "%s %s 0.0.0.0", + IFCONFIG_PATH, + tt->actual_name + ); #endif /* ifdef ENABLE_IPROUTE */ - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, NULL, 0, "Linux ip addr del failed"); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, NULL, 0, "Linux ip addr del failed"); - if (tt->did_ifconfig_ipv6_setup) - { - const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc); + if (tt->did_ifconfig_ipv6_setup) + { + const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc); #ifdef ENABLE_IPROUTE - argv_printf(&argv, "%s -6 addr del %s/%d dev %s", - iproute_path, - ifconfig_ipv6_local, - tt->netbits_ipv6, - tt->actual_name - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, NULL, 0, "Linux ip -6 addr del failed"); + argv_printf(&argv, "%s -6 addr del %s/%d dev %s", + iproute_path, + ifconfig_ipv6_local, + tt->netbits_ipv6, + tt->actual_name + ); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, NULL, 0, "Linux ip -6 addr del failed"); #else /* ifdef ENABLE_IPROUTE */ - argv_printf(&argv, - "%s %s del %s/%d", - IFCONFIG_PATH, - tt->actual_name, - ifconfig_ipv6_local, - tt->netbits_ipv6 - ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, NULL, 0, "Linux ifconfig inet6 del failed"); + argv_printf(&argv, + "%s %s del %s/%d", + IFCONFIG_PATH, + tt->actual_name, + ifconfig_ipv6_local, + tt->netbits_ipv6 + ); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, NULL, 0, "Linux ifconfig inet6 del failed"); #endif - } - - argv_reset(&argv); - gc_free(&gc); } - close_tun_generic(tt); - free(tt); + + argv_reset(&argv); + gc_free(&gc); } + close_tun_generic(tt); + free(tt); } int @@ -2431,57 +2429,54 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun static void solaris_close_tun(struct tuntap *tt) { - if (tt) + /* IPv6 interfaces need to be 'manually' de-configured */ + if (tt->did_ifconfig_ipv6_setup) { - /* IPv6 interfaces need to be 'manually' de-configured */ - if (tt->did_ifconfig_ipv6_setup) + struct argv argv = argv_new(); + argv_printf( &argv, "%s %s inet6 unplumb", + IFCONFIG_PATH, tt->actual_name ); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, NULL, 0, "Solaris ifconfig inet6 unplumb failed"); + argv_reset(&argv); + } + + if (tt->ip_fd >= 0) + { + struct lifreq ifr; + CLEAR(ifr); + strncpynt(ifr.lifr_name, tt->actual_name, sizeof(ifr.lifr_name)); + + if (ioctl(tt->ip_fd, SIOCGLIFFLAGS, &ifr) < 0) { - struct argv argv = argv_new(); - argv_printf( &argv, "%s %s inet6 unplumb", - IFCONFIG_PATH, tt->actual_name ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, NULL, 0, "Solaris ifconfig inet6 unplumb failed"); - argv_reset(&argv); + msg(M_WARN | M_ERRNO, "Can't get iface flags"); } - if (tt->ip_fd >= 0) + if (ioctl(tt->ip_fd, SIOCGLIFMUXID, &ifr) < 0) { - struct lifreq ifr; - CLEAR(ifr); - strncpynt(ifr.lifr_name, tt->actual_name, sizeof(ifr.lifr_name)); - - if (ioctl(tt->ip_fd, SIOCGLIFFLAGS, &ifr) < 0) - { - msg(M_WARN | M_ERRNO, "Can't get iface flags"); - } - - if (ioctl(tt->ip_fd, SIOCGLIFMUXID, &ifr) < 0) - { - msg(M_WARN | M_ERRNO, "Can't get multiplexor id"); - } - - if (tt->type == DEV_TYPE_TAP) - { - if (ioctl(tt->ip_fd, I_PUNLINK, ifr.lifr_arp_muxid) < 0) - { - msg(M_WARN | M_ERRNO, "Can't unlink interface(arp)"); - } - } + msg(M_WARN | M_ERRNO, "Can't get multiplexor id"); + } - if (ioctl(tt->ip_fd, I_PUNLINK, ifr.lifr_ip_muxid) < 0) + if (tt->type == DEV_TYPE_TAP) + { + if (ioctl(tt->ip_fd, I_PUNLINK, ifr.lifr_arp_muxid) < 0) { - msg(M_WARN | M_ERRNO, "Can't unlink interface(ip)"); + msg(M_WARN | M_ERRNO, "Can't unlink interface(arp)"); } - - close(tt->ip_fd); - tt->ip_fd = -1; } - if (tt->fd >= 0) + if (ioctl(tt->ip_fd, I_PUNLINK, ifr.lifr_ip_muxid) < 0) { - close(tt->fd); - tt->fd = -1; + msg(M_WARN | M_ERRNO, "Can't unlink interface(ip)"); } + + close(tt->ip_fd); + tt->ip_fd = -1; + } + + if (tt->fd >= 0) + { + close(tt->fd); + tt->fd = -1; } } @@ -2491,18 +2486,17 @@ solaris_close_tun(struct tuntap *tt) void close_tun(struct tuntap *tt) { - if (tt) - { - solaris_close_tun(tt); + ASSERT(tt); - if (tt->actual_name) - { - free(tt->actual_name); - } + solaris_close_tun(tt); - clear_tuntap(tt); - free(tt); + if (tt->actual_name) + { + free(tt->actual_name); } + + clear_tuntap(tt); + free(tt); } static void @@ -2591,31 +2585,32 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { + ASSERT(tt); + /* only *TAP* devices need destroying, tun devices auto-self-destruct */ - if (tt && (tt->type == DEV_TYPE_TUN || tt->persistent_if ) ) + if (tt->type == DEV_TYPE_TUN || tt->persistent_if) { close_tun_generic(tt); free(tt); + return; } - else if (tt) - { - struct argv argv = argv_new(); - /* setup command, close tun dev (clears tt->actual_name!), run command - */ + struct argv argv = argv_new(); - argv_printf(&argv, "%s %s destroy", - IFCONFIG_PATH, tt->actual_name); + /* setup command, close tun dev (clears tt->actual_name!), run command + */ - close_tun_generic(tt); + argv_printf(&argv, "%s %s destroy", + IFCONFIG_PATH, tt->actual_name); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, NULL, 0, "OpenBSD 'destroy tun interface' failed (non-critical)"); + close_tun_generic(tt); - free(tt); - argv_reset(&argv); - } + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, NULL, 0, "OpenBSD 'destroy tun interface' failed (non-critical)"); + + free(tt); + argv_reset(&argv); } int @@ -2676,31 +2671,33 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { + ASSERT(tt); + /* only tun devices need destroying, tap devices auto-self-destruct */ - if (tt && ( tt->type != DEV_TYPE_TUN || tt->persistent_if ) ) + if (tt->type != DEV_TYPE_TUN || tt->persistent_if) { close_tun_generic(tt); free(tt); + return; } - else if (tt) - { - struct argv argv = argv_new(); - /* setup command, close tun dev (clears tt->actual_name!), run command - */ + struct gc_arena gc = gc_new(); + struct argv argv = argv_new(); - argv_printf(&argv, "%s %s destroy", - IFCONFIG_PATH, tt->actual_name); + /* setup command, close tun dev (clears tt->actual_name!), run command + */ - close_tun_generic(tt); + argv_printf(&argv, "%s %s destroy", + IFCONFIG_PATH, tt->actual_name); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, NULL, 0, "NetBSD 'destroy tun interface' failed (non-critical)"); + close_tun_generic(tt); - free(tt); - argv_reset(&argv); - } + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, NULL, 0, "NetBSD 'destroy tun interface' failed (non-critical)"); + + free(tt); + argv_reset(&argv); } static inline int @@ -2816,29 +2813,32 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { - if (tt && tt->persistent_if) /* keep pre-existing if around */ + ASSERT(tt); + + if (tt->persistent_if) /* keep pre-existing if around */ { close_tun_generic(tt); free(tt); + return; } - else if (tt) /* close and destroy */ - { - struct argv argv = argv_new(); - /* setup command, close tun dev (clears tt->actual_name!), run command - */ + /* close and destroy */ + struct argv argv = argv_new(); - argv_printf(&argv, "%s %s destroy", - IFCONFIG_PATH, tt->actual_name); + /* setup command, close tun dev (clears tt->actual_name!), run command + */ - close_tun_generic(tt); + argv_printf(&argv, "%s %s destroy", + IFCONFIG_PATH, tt->actual_name); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, NULL, 0, "FreeBSD 'destroy tun interface' failed (non-critical)"); + close_tun_generic(tt); - free(tt); - argv_reset(&argv); - } + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, NULL, 0, + "FreeBSD 'destroy tun interface' failed (non-critical)"); + + free(tt); + argv_reset(&argv); } int @@ -2929,11 +2929,10 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { - if (tt) - { - close_tun_generic(tt); - free(tt); - } + ASSERT(tt); + + close_tun_generic(tt); + free(tt); } int @@ -3186,27 +3185,26 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { - if (tt) - { - struct gc_arena gc = gc_new(); - struct argv argv = argv_new(); + ASSERT(tt); - if (tt->did_ifconfig_ipv6_setup) - { - const char *ifconfig_ipv6_local = - print_in6_addr(tt->local_ipv6, 0, &gc); + struct gc_arena gc = gc_new(); + struct argv argv = argv_new(); - argv_printf(&argv, "%s delete -inet6 %s", - ROUTE_PATH, ifconfig_ipv6_local ); - argv_msg(M_INFO, &argv); - openvpn_execve_check(&argv, NULL, 0, "MacOS X 'remove inet6 route' failed (non-critical)"); - } + if (tt->did_ifconfig_ipv6_setup) + { + const char *ifconfig_ipv6_local = + print_in6_addr(tt->local_ipv6, 0, &gc); - close_tun_generic(tt); - free(tt); - argv_reset(&argv); - gc_free(&gc); + argv_printf(&argv, "%s delete -inet6 %s", + ROUTE_PATH, ifconfig_ipv6_local ); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, NULL, 0, "MacOS X 'remove inet6 route' failed (non-critical)"); } + + close_tun_generic(tt); + free(tt); + argv_reset(&argv); + gc_free(&gc); } int @@ -3335,14 +3333,11 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { + ASSERT(tt); + struct argv argv = argv_new(); struct env_set *es = env_set_create(NULL); - if (!tt) - { - return; - } - /* persistent devices need IP address unconfig, others need destroyal */ if (tt->persistent_if) @@ -6181,104 +6176,103 @@ tun_show_debug(struct tuntap *tt) void close_tun(struct tuntap *tt) { + ASSERT(tt); + struct gc_arena gc = gc_new(); - if (tt) + if (tt->did_ifconfig_ipv6_setup) { - if (tt->did_ifconfig_ipv6_setup) - { - /* remove route pointing to interface */ - delete_route_connected_v6_net(tt, NULL); + /* remove route pointing to interface */ + delete_route_connected_v6_net(tt, NULL); - if (tt->options.msg_channel) + if (tt->options.msg_channel) + { + do_address_service(false, AF_INET6, tt); + if (tt->options.dns6_len > 0) { - do_address_service(false, AF_INET6, tt); - if (tt->options.dns6_len > 0) - { - do_dns6_service(false, tt); - } + do_dns6_service(false, tt); } - else - { - const char *ifconfig_ipv6_local; - struct argv argv = argv_new(); + } + else + { + const char *ifconfig_ipv6_local; + struct argv argv = argv_new(); - /* "store=active" is needed in Windows 8(.1) to delete the - * address we added (pointed out by Cedric Tabary). - */ + /* "store=active" is needed in Windows 8(.1) to delete the + * address we added (pointed out by Cedric Tabary). + */ + + /* netsh interface ipv6 delete address \"%s\" %s */ + ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc); + argv_printf(&argv, + "%s%sc interface ipv6 delete address %s %s store=active", + get_win_sys_path(), + NETSH_PATH_SUFFIX, + tt->actual_name, + ifconfig_ipv6_local); - /* netsh interface ipv6 delete address \"%s\" %s */ - ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc); + netsh_command(&argv, 1, M_WARN); + + /* delete ipv6 dns servers if any were set */ + if (tt->options.dns6_len > 0) + { argv_printf(&argv, - "%s%sc interface ipv6 delete address %s %s store=active", + "%s%sc interface ipv6 delete dns %s all", get_win_sys_path(), NETSH_PATH_SUFFIX, - tt->actual_name, - ifconfig_ipv6_local); - + tt->actual_name); netsh_command(&argv, 1, M_WARN); - - /* delete ipv6 dns servers if any were set */ - if (tt->options.dns6_len > 0) - { - argv_printf(&argv, - "%s%sc interface ipv6 delete dns %s all", - get_win_sys_path(), - NETSH_PATH_SUFFIX, - tt->actual_name); - netsh_command(&argv, 1, M_WARN); - } - argv_reset(&argv); } + argv_reset(&argv); } + } #if 1 - if (tt->ipapi_context_defined) + if (tt->ipapi_context_defined) + { + DWORD status; + if ((status = DeleteIPAddress(tt->ipapi_context)) != NO_ERROR) { - DWORD status; - if ((status = DeleteIPAddress(tt->ipapi_context)) != NO_ERROR) - { - msg(M_WARN, "Warning: DeleteIPAddress[%u] failed on TAP-Windows adapter, status=%u : %s", - (unsigned int)tt->ipapi_context, - (unsigned int)status, - strerror_win32(status, &gc)); - } + msg(M_WARN, "Warning: DeleteIPAddress[%u] failed on TAP-Windows adapter, status=%u : %s", + (unsigned int)tt->ipapi_context, + (unsigned int)status, + strerror_win32(status, &gc)); } + } #endif - dhcp_release(tt); + dhcp_release(tt); - if (tt->hand != NULL) + if (tt->hand != NULL) + { + dmsg(D_WIN32_IO_LOW, "Attempting CancelIO on TAP-Windows adapter"); + if (!CancelIo(tt->hand)) { - dmsg(D_WIN32_IO_LOW, "Attempting CancelIO on TAP-Windows adapter"); - if (!CancelIo(tt->hand)) - { - msg(M_WARN | M_ERRNO, "Warning: CancelIO failed on TAP-Windows adapter"); - } + msg(M_WARN | M_ERRNO, "Warning: CancelIO failed on TAP-Windows adapter"); } + } - dmsg(D_WIN32_IO_LOW, "Attempting close of overlapped read event on TAP-Windows adapter"); - overlapped_io_close(&tt->reads); - - dmsg(D_WIN32_IO_LOW, "Attempting close of overlapped write event on TAP-Windows adapter"); - overlapped_io_close(&tt->writes); + dmsg(D_WIN32_IO_LOW, "Attempting close of overlapped read event on TAP-Windows adapter"); + overlapped_io_close(&tt->reads); - if (tt->hand != NULL) - { - dmsg(D_WIN32_IO_LOW, "Attempting CloseHandle on TAP-Windows adapter"); - if (!CloseHandle(tt->hand)) - { - msg(M_WARN | M_ERRNO, "Warning: CloseHandle failed on TAP-Windows adapter"); - } - } + dmsg(D_WIN32_IO_LOW, "Attempting close of overlapped write event on TAP-Windows adapter"); + overlapped_io_close(&tt->writes); - if (tt->actual_name) + if (tt->hand != NULL) + { + dmsg(D_WIN32_IO_LOW, "Attempting CloseHandle on TAP-Windows adapter"); + if (!CloseHandle(tt->hand)) { - free(tt->actual_name); + msg(M_WARN | M_ERRNO, "Warning: CloseHandle failed on TAP-Windows adapter"); } + } - clear_tuntap(tt); - free(tt); + if (tt->actual_name) + { + free(tt->actual_name); } + + clear_tuntap(tt); + free(tt); gc_free(&gc); } @@ -6357,11 +6351,10 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun void close_tun(struct tuntap *tt) { - if (tt) - { - close_tun_generic(tt); - free(tt); - } + ASSERT(tt); + + close_tun_generic(tt); + free(tt); } int From patchwork Wed Jun 13 02:28:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 371 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id oz8yIFQOIVu4LwAAIUCqbw for ; Wed, 13 Jun 2018 08:30:12 -0400 Received: from proxy1.mail.ord1d.rsapps.net ([172.30.191.6]) by director12.mail.ord1d.rsapps.net (Dovecot) with LMTP id OfWzBlQOIVvbcQAAIasKDg ; Wed, 13 Jun 2018 08:30:12 -0400 Received: from smtp19.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy1.mail.ord1d.rsapps.net with LMTP id kMeDH1QOIVuoNAAAasrz9Q ; Wed, 13 Jun 2018 08:30:12 -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: smtp19.gate.ord1d.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: 8388ca7a-6f05-11e8-8c2e-525400d67fa8-1-1 Received: from [216.105.38.7] ([216.105.38.7:38381] helo=lists.sourceforge.net) by smtp19.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id FF/B0-02316-35E012B5; Wed, 13 Jun 2018 08:30:11 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fT4tq-0006QD-PW; Wed, 13 Jun 2018 12:29:18 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fT4tn-0006Pg-PK for openvpn-devel@lists.sourceforge.net; Wed, 13 Jun 2018 12:29:15 +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=CO5c6GZXIUxQ02iiVT7vqSEe21e6DaEOnwyxsJIR+24=; b=ak4QlOUKi+Vrp7NDA5OXTjFVga dmDw86RqvQ/Elzx7N5Qio1Yo7UwnfzQBl0ECw+Iis4XgMvl+mh0N473Y6taMAoGZjX+ASnxyV/HEs E+tTLN5h6by5xXSRVLJhBz9tsD7+Lw97IzW0sIghE9hcFSIHcu+v/4yk8KL4kopnQ3S8=; 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=CO5c6GZXIUxQ02iiVT7vqSEe21e6DaEOnwyxsJIR+24=; b=fWnngV6S5j5OjtuguWnkKU89ks pX1G5XCeyhkEOsUclmTB3nqie2AnEThb/Pvqtf/5ppuEnRZy1EeE6s/lCLysPX7J15KCKWH8zPlK7 2dAe5FTR/SJTP5yCC1wjl1djODbxVAqeH51Orq4ikm2G/NzBENID2nDzlbSs+C0XjBlA=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fT4tm-007MJz-BQ for openvpn-devel@lists.sourceforge.net; Wed, 13 Jun 2018 12:29:15 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Wed, 13 Jun 2018 20:28:24 +0800 Message-Id: <20180613122824.4207-4-a@unstable.cc> In-Reply-To: <20180613122824.4207-1-a@unstable.cc> References: <20180613122824.4207-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.1 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1fT4tm-007MJz-BQ Subject: [Openvpn-devel] [PATCH v2 3/3] tun: get rid of tt->did_ifconfig member 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: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Antonio Quartulli tt->did_ifconfig is currently only read by the Linux platform, but it is currently uselessly set also by every other system. The Linux platform does not actually even need this member and can directly rely on tt->did_ifconfig_setup. For the reasons above, remove the tt->did_ifconfig at all and use tt->did_ifconfig_setup where needed (close_tun() on Linux). Signed-off-by: Antonio Quartulli Acked-by: Gert Doering --- Changes from v1: - fix typ0 in commit message src/openvpn/tun.c | 12 +----------- src/openvpn/tun.h | 1 - 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 12b33ae7..48e7cc2e 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -987,7 +987,6 @@ do_ifconfig(struct tuntap *tt, 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) { @@ -1026,7 +1025,6 @@ do_ifconfig(struct tuntap *tt, argv_msg(M_INFO, &argv); openvpn_execve_check(&argv, es, S_FATAL, "Linux ifconfig inet6 failed"); } - tt->did_ifconfig = true; #endif /*ENABLE_IPROUTE*/ #elif defined(TARGET_ANDROID) @@ -1186,8 +1184,6 @@ do_ifconfig(struct tuntap *tt, add_route(&r, tt, 0, NULL, es); } - tt->did_ifconfig = true; - #elif defined(TARGET_OPENBSD) in_addr_t remote_end; /* for "virtual" subnet topology */ @@ -1265,7 +1261,6 @@ do_ifconfig(struct tuntap *tt, /* and, hooray, we explicitely need to add a route... */ add_route_connected_v6_net(tt, es); } - tt->did_ifconfig = true; #elif defined(TARGET_NETBSD) @@ -1327,7 +1322,6 @@ do_ifconfig(struct tuntap *tt, /* and, hooray, we explicitely need to add a route... */ add_route_connected_v6_net(tt, es); } - tt->did_ifconfig = true; #elif defined(TARGET_DARWIN) /* @@ -1384,7 +1378,6 @@ do_ifconfig(struct tuntap *tt, 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) @@ -1457,7 +1450,6 @@ do_ifconfig(struct tuntap *tt, argv_msg(M_INFO, &argv); openvpn_execve_check(&argv, es, S_FATAL, "FreeBSD ifconfig failed"); - tt->did_ifconfig = true; /* Add a network route for the local tun interface */ if (!tun && tt->topology == TOP_SUBNET) @@ -1507,7 +1499,6 @@ do_ifconfig(struct tuntap *tt, argv_msg(M_INFO, &argv); openvpn_execve_check(&argv, aix_es, S_FATAL, "AIX ifconfig failed"); - tt->did_ifconfig = true; if (do_ipv6) { @@ -1545,7 +1536,6 @@ do_ifconfig(struct tuntap *tt, break; } - tt->did_ifconfig = true; } if (do_ipv6) @@ -2104,7 +2094,7 @@ close_tun(struct tuntap *tt) { ASSERT(tt); - if (tt->type != DEV_TYPE_NULL && tt->did_ifconfig) + if (tt->type != DEV_TYPE_NULL && tt->did_ifconfig_setup) { struct argv argv = argv_new(); struct gc_arena gc = gc_new(); diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index 6c57ad0d..9495d602 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -138,7 +138,6 @@ struct tuntap bool did_ifconfig_setup; bool did_ifconfig_ipv6_setup; - bool did_ifconfig; bool persistent_if; /* if existed before, keep on program end */