Don't "undo" ifconfig on exit if it wasn't done

When running with --ifconfig-noexec, OpenVPN does not execute ifconfig,
but on exit, it still tries to "undo" the configuration it would have
done. This patch fixes it by extracting an undo_ifconfig() function from
close_tun(). The undo function is called before close_tun(), but only if
--ifconfig-noexec isn't set. This is symmetric to how open_tun() and
do_ifconfig() are used.

v2: Fix tabs-vs-spaces.
v3: Fix another style mistake.
v4: Move undo_ifconfig{4,6}() out of #ifdef TARGET_LINUX.
v5: Keep ctx argument in close_tun().
v6: Fix bug in non-Linux non-Windows version of undo_ifconfig_ipv6

Signed-off-by: Max Fillinger <maximilian.fillinger@foxcrypto.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20220810153006.18860-1-maximilian.fillinger@foxcrypto.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg24860.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
Max Fillinger 2022-08-10 17:30:06 +02:00 committed by Gert Doering
parent ddbe6a6fc2
commit 0c4d40cb83
3 changed files with 94 additions and 76 deletions

View file

@ -1920,6 +1920,10 @@ do_close_tun_simple(struct context *c)
msg(D_CLOSE, "Closing TUN/TAP interface");
if (c->c1.tuntap)
{
if (!c->options.ifconfig_noexec)
{
undo_ifconfig(c->c1.tuntap, &c->net_ctx);
}
close_tun(c->c1.tuntap, &c->net_ctx);
c->c1.tuntap = NULL;
}

View file

@ -1604,6 +1604,88 @@ do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu,
net_ctx_free(ctx);
}
static void
undo_ifconfig_ipv4(struct tuntap *tt, openvpn_net_ctx_t *ctx)
{
#if defined(TARGET_LINUX)
int netbits = netmask_to_netbits2(tt->remote_netmask);
if (is_tun_p2p(tt))
{
if (net_addr_ptp_v4_del(ctx, tt->actual_name, &tt->local,
&tt->remote_netmask) < 0)
{
msg(M_WARN, "Linux can't del IP from iface %s",
tt->actual_name);
}
}
else
{
if (net_addr_v4_del(ctx, tt->actual_name, &tt->local, netbits) < 0)
{
msg(M_WARN, "Linux can't del IP from iface %s",
tt->actual_name);
}
}
#elif !defined(_WIN32) /* if !defined(TARGET_LINUX) && !defined(_WIN32) */
struct argv argv = argv_new();
argv_printf(&argv, "%s %s 0.0.0.0", IFCONFIG_PATH, tt->actual_name);
argv_msg(M_INFO, &argv);
openvpn_execve_check(&argv, NULL, 0, "Generic ip addr del failed");
argv_free(&argv);
#endif /* if defined(TARGET_LINUX) */
/* Empty for _WIN32. */
}
static void
undo_ifconfig_ipv6(struct tuntap *tt, openvpn_net_ctx_t *ctx)
{
#if defined(TARGET_LINUX)
if (net_addr_v6_del(ctx, tt->actual_name, &tt->local_ipv6,
tt->netbits_ipv6) < 0)
{
msg(M_WARN, "Linux can't del IPv6 from iface %s", tt->actual_name);
}
#elif !defined(_WIN32) /* if !defined(TARGET_LINUX) && !defined(_WIN32) */
struct gc_arena gc = gc_new();
const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc);
struct argv argv = argv_new();
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, "Generic ip -6 addr del failed");
argv_free(&argv);
gc_free(&gc);
#endif /* if defined(TARGET_LINUX) */
/* Empty for _WIN32. */
}
void
undo_ifconfig(struct tuntap *tt, openvpn_net_ctx_t *ctx)
{
if (tt->type != DEV_TYPE_NULL)
{
if (tt->did_ifconfig_setup)
{
undo_ifconfig_ipv4(tt, ctx);
}
if (tt->did_ifconfig_ipv6_setup)
{
undo_ifconfig_ipv6(tt, ctx);
}
/* release resources potentially allocated during undo */
net_ctx_reset(ctx);
}
}
static void
clear_tuntap(struct tuntap *tuntap)
{
@ -2213,87 +2295,11 @@ tuncfg(const char *dev, const char *dev_type, const char *dev_node,
#endif /* ENABLE_FEATURE_TUN_PERSIST */
static void
undo_ifconfig_ipv4(struct tuntap *tt, openvpn_net_ctx_t *ctx)
{
#if defined(TARGET_LINUX)
int netbits = netmask_to_netbits2(tt->remote_netmask);
if (is_tun_p2p(tt))
{
if (net_addr_ptp_v4_del(ctx, tt->actual_name, &tt->local,
&tt->remote_netmask) < 0)
{
msg(M_WARN, "Linux can't del IP from iface %s",
tt->actual_name);
}
}
else
{
if (net_addr_v4_del(ctx, tt->actual_name, &tt->local, netbits) < 0)
{
msg(M_WARN, "Linux can't del IP from iface %s",
tt->actual_name);
}
}
#else /* ifndef TARGET_LINUX */
struct argv argv = argv_new();
argv_printf(&argv, "%s %s 0.0.0.0", IFCONFIG_PATH, tt->actual_name);
argv_msg(M_INFO, &argv);
openvpn_execve_check(&argv, NULL, 0, "Generic ip addr del failed");
argv_free(&argv);
#endif /* ifdef TARGET_LINUX */
}
static void
undo_ifconfig_ipv6(struct tuntap *tt, openvpn_net_ctx_t *ctx)
{
#if defined(TARGET_LINUX)
if (net_addr_v6_del(ctx, tt->actual_name, &tt->local_ipv6,
tt->netbits_ipv6) < 0)
{
msg(M_WARN, "Linux can't del IPv6 from iface %s", tt->actual_name);
}
#else /* ifndef TARGET_LINUX */
struct gc_arena gc = gc_new();
const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, gc);
struct argv argv = argv_new();
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 ip -6 addr del failed");
argv_free(&argv);
gc_free(&gc);
#endif /* ifdef TARGET_LINUX */
}
void
close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
{
ASSERT(tt);
if (tt->type != DEV_TYPE_NULL)
{
if (tt->did_ifconfig_setup)
{
undo_ifconfig_ipv4(tt, ctx);
}
if (tt->did_ifconfig_ipv6_setup)
{
undo_ifconfig_ipv6(tt, ctx);
}
/* release resources potentially allocated during undo */
net_ctx_reset(ctx);
}
#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
if (tun_dco_enabled(tt))
{

View file

@ -314,6 +314,14 @@ void do_ifconfig_setenv(const struct tuntap *tt,
void do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu,
const struct env_set *es, openvpn_net_ctx_t *ctx);
/**
* undo_ifconfig - undo configuration of the tunnel interface
*
* @param tt the tuntap interface context
* @param ctx the networking API opaque context
*/
void undo_ifconfig(struct tuntap *tt, openvpn_net_ctx_t *ctx);
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);