@@ -421,7 +421,7 @@
check_add_routes_action(struct context *c, const bool errors)
{
bool route_status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
- c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+ c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx, c->mode == CM_TOP);
int flags = (errors ? ISC_ERRORS : 0);
flags |= (!route_status ? ISC_ROUTE_ERRORS : 0);
@@ -1134,7 +1134,7 @@
tuncfg(options->dev, options->dev_type, options->dev_node,
options->persist_mode,
options->username, options->groupname, &options->tuntap_options,
- ctx);
+ ctx, options->mode == MODE_SERVER);
if (options->persist_mode && options->lladdr)
{
set_lladdr(ctx, options->dev, options->lladdr, NULL);
@@ -1689,13 +1689,14 @@
const struct tuntap *tt,
const struct plugin_list *plugins,
struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
bool ret = true;
if (!options->route_noexec && ( route_list || route_ipv6_list ) )
{
ret = add_routes(route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS(options),
- es, ctx);
+ es, ctx, is_multipoint);
setenv_int(es, "redirect_gateway", route_did_redirect_default_gateway(route_list));
}
#ifdef ENABLE_MANAGEMENT
@@ -1898,7 +1899,7 @@
c->options.dev_node,
&gc);
do_ifconfig(c->c1.tuntap, guess, c->c2.frame.tun_mtu, c->c2.es,
- &c->net_ctx);
+ &c->net_ctx, c->mode == CM_TOP);
}
/* possibly add routes */
@@ -1906,7 +1907,7 @@
{
/* Ignore route_delay, would cause ROUTE_BEFORE_TUN to be ignored */
bool status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
- c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+ c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx, c->mode == CM_TOP);
*error_flags |= (status ? 0 : ISC_ROUTE_ERRORS);
}
#ifdef TARGET_ANDROID
@@ -1934,7 +1935,7 @@
&& ifconfig_order() == IFCONFIG_AFTER_TUN_OPEN)
{
do_ifconfig(c->c1.tuntap, c->c1.tuntap->actual_name,
- c->c2.frame.tun_mtu, c->c2.es, &c->net_ctx);
+ c->c2.frame.tun_mtu, c->c2.es, &c->net_ctx, c->mode == CM_TOP);
}
/* run the up script */
@@ -1960,7 +1961,7 @@
if ((route_order() == ROUTE_AFTER_TUN) && (!c->options.route_delay_defined))
{
int status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
- c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+ c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx, c->mode == CM_TOP);
*error_flags |= (status ? 0 : ISC_ROUTE_ERRORS);
}
@@ -2017,7 +2018,7 @@
{
undo_ifconfig(c->c1.tuntap, &c->net_ctx);
}
- close_tun(c->c1.tuntap, &c->net_ctx);
+ close_tun(c->c1.tuntap, &c->net_ctx, c->mode == CM_TOP);
c->c1.tuntap = NULL;
}
c->c1.tuntap_owned = false;
@@ -2086,7 +2087,7 @@
delete_routes(c->c1.route_list, c->c1.route_ipv6_list,
c->c1.tuntap, ROUTE_OPTION_FLAGS(&c->options),
- c->c2.es, &c->net_ctx);
+ c->c2.es, &c->net_ctx, c->mode == CM_TOP);
}
/* actually close tun/tap device based on --down-pre flag */
@@ -74,7 +74,7 @@
bool do_route(const struct options *options, struct route_list *route_list,
struct route_ipv6_list *route_ipv6_list, const struct tuntap *tt,
const struct plugin_list *plugins, struct env_set *es,
- openvpn_net_ctx_t *ctx);
+ openvpn_net_ctx_t *ctx, const bool is_multipoint);
void close_instance(struct context *c);
@@ -77,7 +77,7 @@
static void delete_route(struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags,
const struct route_gateway_info *rgi, const struct env_set *es,
- openvpn_net_ctx_t *ctx);
+ openvpn_net_ctx_t *ctx, const bool is_multipoint);
static void get_bypass_addresses(struct route_bypass *rb, const unsigned int flags);
@@ -927,7 +927,8 @@
unsigned int flags,
const struct route_gateway_info *rgi,
const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
struct route_ipv4 r;
CLEAR(r);
@@ -935,7 +936,7 @@
r.network = network;
r.netmask = netmask;
r.gateway = gateway;
- return add_route(&r, tt, flags, rgi, es, ctx);
+ return add_route(&r, tt, flags, rgi, es, ctx, is_multipoint);
}
static void
@@ -946,7 +947,8 @@
unsigned int flags,
const struct route_gateway_info *rgi,
const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
struct route_ipv4 r;
CLEAR(r);
@@ -954,7 +956,7 @@
r.network = network;
r.netmask = netmask;
r.gateway = gateway;
- delete_route(&r, tt, flags, rgi, es, ctx);
+ delete_route(&r, tt, flags, rgi, es, ctx, is_multipoint);
}
static bool
@@ -964,7 +966,8 @@
unsigned int flags,
const struct route_gateway_info *rgi,
const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
int ret = true;
for (int i = 0; i < rb->n_bypass; ++i)
@@ -972,7 +975,7 @@
if (rb->bypass[i])
{
ret = add_route3(rb->bypass[i], IPV4_NETMASK_HOST, gateway, tt,
- flags | ROUTE_REF_GW, rgi, es, ctx) && ret;
+ flags | ROUTE_REF_GW, rgi, es, ctx, is_multipoint) && ret;
}
}
return ret;
@@ -985,7 +988,8 @@
unsigned int flags,
const struct route_gateway_info *rgi,
const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
int i;
for (i = 0; i < rb->n_bypass; ++i)
@@ -999,7 +1003,8 @@
flags | ROUTE_REF_GW,
rgi,
es,
- ctx);
+ ctx,
+ is_multipoint);
}
}
}
@@ -1007,7 +1012,7 @@
static bool
redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt,
unsigned int flags, const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
const char err[] = "NOTE: unable to redirect IPv4 default gateway --";
bool ret = true;
@@ -1059,7 +1064,7 @@
{
ret = add_route3(rl->spec.remote_host, IPV4_NETMASK_HOST,
rl->rgi.gateway.addr, tt, flags | ROUTE_REF_GW,
- &rl->rgi, es, ctx);
+ &rl->rgi, es, ctx, is_multipoint);
rl->iflags |= RL_DID_LOCAL;
}
else
@@ -1071,7 +1076,7 @@
/* route DHCP/DNS server traffic through original default gateway */
ret = add_bypass_routes(&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags,
- &rl->rgi, es, ctx) && ret;
+ &rl->rgi, es, ctx, is_multipoint) && ret;
if (rl->flags & RG_REROUTE_GW)
{
@@ -1079,11 +1084,11 @@
{
/* add new default route (1st component) */
ret = add_route3(0x00000000, 0x80000000, rl->spec.remote_endpoint,
- tt, flags, &rl->rgi, es, ctx) && ret;
+ tt, flags, &rl->rgi, es, ctx, is_multipoint) && ret;
/* add new default route (2nd component) */
ret = add_route3(0x80000000, 0x80000000, rl->spec.remote_endpoint,
- tt, flags, &rl->rgi, es, ctx) && ret;
+ tt, flags, &rl->rgi, es, ctx, is_multipoint) && ret;
}
else
{
@@ -1092,12 +1097,12 @@
{
/* delete default route */
del_route3(0, 0, rl->rgi.gateway.addr, tt,
- flags | ROUTE_REF_GW, &rl->rgi, es, ctx);
+ flags | ROUTE_REF_GW, &rl->rgi, es, ctx, is_multipoint);
}
/* add new default route */
ret = add_route3(0, 0, rl->spec.remote_endpoint, tt,
- flags, &rl->rgi, es, ctx) && ret;
+ flags, &rl->rgi, es, ctx, is_multipoint) && ret;
}
}
@@ -1112,7 +1117,8 @@
undo_redirect_default_route_to_vpn(struct route_list *rl,
const struct tuntap *tt, unsigned int flags,
const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
if (rl && rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY)
{
@@ -1126,13 +1132,14 @@
flags | ROUTE_REF_GW,
&rl->rgi,
es,
- ctx);
+ ctx,
+ is_multipoint);
rl->iflags &= ~RL_DID_LOCAL;
}
/* delete special DHCP/DNS bypass route */
del_bypass_routes(&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags,
- &rl->rgi, es, ctx);
+ &rl->rgi, es, ctx, is_multipoint);
if (rl->flags & RG_REROUTE_GW)
{
@@ -1146,7 +1153,8 @@
flags,
&rl->rgi,
es,
- ctx);
+ ctx,
+ is_multipoint);
/* delete default route (2nd component) */
del_route3(0x80000000,
@@ -1156,7 +1164,8 @@
flags,
&rl->rgi,
es,
- ctx);
+ ctx,
+ is_multipoint);
}
else
{
@@ -1168,12 +1177,13 @@
flags,
&rl->rgi,
es,
- ctx);
+ ctx,
+ is_multipoint);
/* restore original default route if there was any */
if (rl->rgi.flags & RGI_ADDR_DEFINED)
{
add_route3(0, 0, rl->rgi.gateway.addr, tt,
- flags | ROUTE_REF_GW, &rl->rgi, es, ctx);
+ flags | ROUTE_REF_GW, &rl->rgi, es, ctx, is_multipoint);
}
}
}
@@ -1185,9 +1195,10 @@
bool
add_routes(struct route_list *rl, struct route_ipv6_list *rl6,
const struct tuntap *tt, unsigned int flags,
- const struct env_set *es, openvpn_net_ctx_t *ctx)
+ const struct env_set *es, openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
- bool ret = redirect_default_route_to_vpn(rl, tt, flags, es, ctx);
+ bool ret = redirect_default_route_to_vpn(rl, tt, flags, es, ctx, is_multipoint);
if (rl && !(rl->iflags & RL_ROUTES_ADDED) )
{
struct route_ipv4 *r;
@@ -1218,9 +1229,9 @@
check_subnet_conflict(r->network, r->netmask, "route");
if (flags & ROUTE_DELETE_FIRST)
{
- delete_route(r, tt, flags, &rl->rgi, es, ctx);
+ delete_route(r, tt, flags, &rl->rgi, es, ctx, is_multipoint);
}
- ret = add_route(r, tt, flags, &rl->rgi, es, ctx) && ret;
+ ret = add_route(r, tt, flags, &rl->rgi, es, ctx, is_multipoint) && ret;
}
rl->iflags |= RL_ROUTES_ADDED;
}
@@ -1240,9 +1251,9 @@
{
if (flags & ROUTE_DELETE_FIRST)
{
- delete_route_ipv6(r, tt, flags, es, ctx);
+ delete_route_ipv6(r, tt, flags, es, ctx, is_multipoint);
}
- ret = add_route_ipv6(r, tt, flags, es, ctx) && ret;
+ ret = add_route_ipv6(r, tt, flags, es, ctx, is_multipoint) && ret;
}
rl6->iflags |= RL_ROUTES_ADDED;
}
@@ -1253,19 +1264,20 @@
void
delete_routes(struct route_list *rl, struct route_ipv6_list *rl6,
const struct tuntap *tt, unsigned int flags,
- const struct env_set *es, openvpn_net_ctx_t *ctx)
+ const struct env_set *es, openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
if (rl && rl->iflags & RL_ROUTES_ADDED)
{
struct route_ipv4 *r;
for (r = rl->routes; r; r = r->next)
{
- delete_route(r, tt, flags, &rl->rgi, es, ctx);
+ delete_route(r, tt, flags, &rl->rgi, es, ctx, is_multipoint);
}
rl->iflags &= ~RL_ROUTES_ADDED;
}
- undo_redirect_default_route_to_vpn(rl, tt, flags, es, ctx);
+ undo_redirect_default_route_to_vpn(rl, tt, flags, es, ctx, is_multipoint);
if (rl)
{
@@ -1277,7 +1289,7 @@
struct route_ipv6 *r6;
for (r6 = rl6->routes_ipv6; r6; r6 = r6->next)
{
- delete_route_ipv6(r6, tt, flags, es, ctx);
+ delete_route_ipv6(r6, tt, flags, es, ctx, is_multipoint);
}
rl6->iflags &= ~RL_ROUTES_ADDED;
}
@@ -1561,13 +1573,47 @@
}
#endif
+static bool
+is_gateway_needed_ipv4(const struct route_ipv4 *r4,
+ const struct route_gateway_info *rgi,
+ const struct tuntap *tt,
+ const bool is_multipoint)
+{
+
+#ifndef _WIN32
+
+ if (rgi && (rgi->flags & RGI_IFACE_DEFINED) && rgi->iface[0] != 0) /* vpn server special route */
+ {
+ if (rgi->flags & RGI_ADDR_DEFINED && r4->gateway != 0)
+ {
+ return true;
+ }
+ }
+
+#endif
+
+ if (tt->type == DEV_TYPE_TAP
+ && !( (r4->flags & RT_METRIC_DEFINED) && r4->metric == 0 ) )
+ {
+ return true;
+ }
+
+ if (is_multipoint && !tt->options.disable_dco)
+ {
+ return true;
+ }
+
+ return false;
+}
+
bool
add_route(struct route_ipv4 *r,
const struct tuntap *tt,
unsigned int flags,
const struct route_gateway_info *rgi, /* may be NULL */
const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
int status = 0;
int is_local_route;
@@ -1595,23 +1641,7 @@
goto done;
}
- #ifndef _WIN32
-
- if (rgi && (rgi->flags & RGI_IFACE_DEFINED) && rgi->iface[0] != 0) /* vpn server special route */
- {
- if (rgi->flags & RGI_ADDR_DEFINED && r->gateway != 0)
- {
- gateway_needed = true;
- }
- }
-
- #endif
-
- if (tt->type == DEV_TYPE_TAP
- && !( (r->flags & RT_METRIC_DEFINED) && r->metric == 0 ) )
- {
- gateway_needed = true;
- }
+ gateway_needed = is_gateway_needed_ipv4(r, rgi, tt, is_multipoint);
if (gateway_needed && r->gateway == 0)
{
@@ -1623,11 +1653,12 @@
goto done;
}
-#if defined(TARGET_LINUX)
- const char *iface = tt->actual_name;
+#if !defined(_WIN32) && !defined(TARGET_SOLARIS) \
+ && !defined(TARGET_AIX)
+ const char *device = tt->actual_name;
if (!gateway_needed && rgi && (rgi->flags & RGI_IFACE_DEFINED) && rgi->iface[0] != 0) /* vpn server special route */
{
- iface = rgi->iface;
+ device = rgi->iface;
}
#endif
@@ -1636,7 +1667,7 @@
if (is_on_link(is_local_route, flags, rgi))
{
- iface = rgi->iface;
+ device = rgi->iface;
}
if (r->flags & RT_METRIC_DEFINED)
@@ -1647,7 +1678,7 @@
status = RTA_SUCCESS;
int ret = net_route_v4_add(ctx, &r->network, netmask_to_netbits2(r->netmask),
gateway_needed ? &r->gateway : NULL,
- iface, 0, metric);
+ device, 0, metric);
if (ret == -EEXIST)
{
msg(D_ROUTE, "NOTE: Linux route add command failed because route exists");
@@ -1664,7 +1695,7 @@
if (rgi)
{
- snprintf(out, sizeof(out), "%s %s %s dev %s", network, netmask, gateway, rgi->iface);
+ snprintf(out, sizeof(out), "%s %s %s dev %s", network, netmask, gateway, device);
}
else
{
@@ -1768,9 +1799,9 @@
"ERROR: Solaris route add command failed");
status = ret ? RTA_SUCCESS : RTA_ERROR;
-#elif defined(TARGET_FREEBSD)
+#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
- argv_printf(&argv, "%s add",
+ argv_printf(&argv, "%s add ",
ROUTE_PATH);
#if 0
@@ -1780,45 +1811,28 @@
}
#endif
- argv_printf_cat(&argv, "-net %s %s %s",
- network,
- gateway,
- netmask);
-
- /* FIXME -- add on-link support for FreeBSD */
-
- argv_msg(D_ROUTE, &argv);
- bool ret = openvpn_execve_check(&argv, es, 0,
- "ERROR: FreeBSD route add command failed");
- status = ret ? RTA_SUCCESS : RTA_ERROR;
-
-#elif defined(TARGET_DRAGONFLY)
-
- argv_printf(&argv, "%s add",
- ROUTE_PATH);
-
-#if 0
- if (r->flags & RT_METRIC_DEFINED)
+ if (gateway_needed)
{
- argv_printf_cat(&argv, "-rtt %d", r->metric);
+ argv_printf_cat(&argv, "-net %s %s %s",
+ network,
+ gateway,
+ netmask);
}
-#endif
-
- argv_printf_cat(&argv, "-net %s %s %s",
- network,
- gateway,
- netmask);
-
- /* FIXME -- add on-link support for Dragonfly */
+ else
+ {
+ argv_printf_cat(&argv, "-net %s -iface %s",
+ network,
+ device);
+ }
argv_msg(D_ROUTE, &argv);
bool ret = openvpn_execve_check(&argv, es, 0,
- "ERROR: DragonFly route add command failed");
+ "ERROR: BSD route add command failed");
status = ret ? RTA_SUCCESS : RTA_ERROR;
#elif defined(TARGET_DARWIN)
- argv_printf(&argv, "%s add",
+ argv_printf(&argv, "%s add ",
ROUTE_PATH);
#if 0
@@ -1839,10 +1853,19 @@
}
else
{
- argv_printf_cat(&argv, "-net %s %s %s",
- network,
- gateway,
- netmask);
+ if (gateway_needed)
+ {
+ argv_printf_cat(&argv, "-net %s %s %s",
+ network,
+ gateway,
+ netmask);
+ }
+ else
+ {
+ argv_printf_cat(&argv, "-net %s -interface %s",
+ network,
+ device);
+ }
}
argv_msg(D_ROUTE, &argv);
@@ -1852,7 +1875,7 @@
#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
- argv_printf(&argv, "%s add",
+ argv_printf(&argv, "%s add ",
ROUTE_PATH);
#if 0
@@ -1862,12 +1885,20 @@
}
#endif
- argv_printf_cat(&argv, "-net %s %s -netmask %s",
- network,
- gateway,
- netmask);
-
- /* FIXME -- add on-link support for OpenBSD/NetBSD */
+ if (gateway_needed)
+ {
+ argv_printf_cat(&argv, "-net %s %s -netmask %s",
+ network,
+ gateway,
+ netmask);
+ }
+ else
+ {
+ argv_printf_cat(&argv, "-net %s -netmask %s -link -iface %s",
+ network,
+ netmask,
+ device);
+ }
argv_msg(D_ROUTE, &argv);
bool ret = openvpn_execve_check(&argv, es, 0,
@@ -1932,10 +1963,98 @@
}
}
+static inline struct in6_addr
+netbits_to_netmask_ipv6(const int netbits)
+{
+ struct in6_addr netmask = {{{0}}};
+
+ if (netbits > 0 && netbits <= 128)
+ {
+ const int full_bytes = netbits / 8;
+ int i;
+ for (i = 0; i < full_bytes; i++)
+ {
+ netmask.s6_addr[i] = 0xFF;
+ }
+ if (netbits % 8)
+ {
+ netmask.s6_addr[i] = (0xFF << (8 - (netbits % 8)));
+ }
+ }
+
+ return netmask;
+}
+
+static bool
+is_gateway_in_vpn_subnet_ipv6(const struct in6_addr *gateway,
+ const struct in6_addr *vpn_subnet,
+ int netbits)
+{
+ struct in6_addr netmask = netbits_to_netmask_ipv6(netbits);
+
+ for (int i = 0; i < 16; i++)
+ {
+ if ((gateway->s6_addr[i] & netmask.s6_addr[i]) != (vpn_subnet->s6_addr[i] & netmask.s6_addr[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool
+is_gateway_needed_ipv6(const struct route_ipv6 *r6,
+ const struct tuntap *tt,
+ const char *network,
+ const bool is_multipoint)
+{
+
+#ifndef _WIN32
+ if (r6->iface != NULL) /* VPN server special route */
+ {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&r6->gateway))
+ {
+ return true;
+ }
+ }
+#endif
+
+ /*
+ * Filter out routes which are essentially no-ops
+ * (not currently done for IPv6)
+ */
+
+ /* On "tun" interface, we never set a gateway if the operating system
+ * can do "route to interface" - it does not add value, as the target
+ * dev already fully qualifies the route destination on point-to-point
+ * interfaces. OTOH, on "tap" interface, we must always set the
+ * gateway unless the route is to be an on-link network
+ */
+ if (tt->type == DEV_TYPE_TAP
+ && !( (r6->flags & RT_METRIC_DEFINED) && r6->metric == 0 ) )
+ {
+ return true;
+ }
+
+ /* if is server and dco enabled, the gateway is needed*/
+ if (is_multipoint && !tt->options.disable_dco)
+ {
+ return true;
+ }
+
+ if (is_gateway_in_vpn_subnet_ipv6(&r6->gateway, &tt->local_ipv6, tt->netbits_ipv6))
+ {
+ msg(D_ROUTE, "Ignoring gateway in VPN subnet for route %s/%d", network, r6->netbits);
+ return false;
+ }
+
+ return false;
+}
+
bool
add_route_ipv6(struct route_ipv6 *r6, const struct tuntap *tt,
unsigned int flags, const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
int status = 0;
bool gateway_needed = false;
@@ -1948,22 +2067,12 @@
struct argv argv = argv_new();
struct gc_arena gc = gc_new();
-#ifndef _WIN32
- const char *device = tt->actual_name;
- if (r6->iface != NULL) /* vpn server special route */
- {
- device = r6->iface;
- if (!IN6_IS_ADDR_UNSPECIFIED(&r6->gateway) )
- {
- gateway_needed = true;
- }
- }
-#endif
-
route_ipv6_clear_host_bits(r6);
const char *network = print_in6_addr( r6->network, 0, &gc);
const char *gateway = print_in6_addr( r6->gateway, 0, &gc);
+ gateway_needed = is_gateway_needed_ipv6(r6, tt, network, is_multipoint);
+
#if defined(TARGET_DARWIN) \
|| defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
|| defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
@@ -1982,6 +2091,15 @@
}
#endif
+#if !defined(_WIN32)
+
+ const char *device = tt->actual_name;
+ if (r6->iface != NULL)
+ {
+ device = r6->iface;
+ }
+#endif
+
#ifndef _WIN32
msg(D_ROUTE, "add_route_ipv6(%s/%d -> %s metric %d) dev %s",
network, r6->netbits, gateway, r6->metric, device );
@@ -1991,23 +2109,6 @@
r6->adapter_index ? r6->adapter_index : tt->adapter_index);
#endif
- /*
- * Filter out routes which are essentially no-ops
- * (not currently done for IPv6)
- */
-
- /* On "tun" interface, we never set a gateway if the operating system
- * can do "route to interface" - it does not add value, as the target
- * dev already fully qualifies the route destination on point-to-point
- * interfaces. OTOH, on "tap" interface, we must always set the
- * gateway unless the route is to be an on-link network
- */
- if (tt->type == DEV_TYPE_TAP
- && !( (r6->flags & RT_METRIC_DEFINED) && r6->metric == 0 ) )
- {
- gateway_needed = true;
- }
-
if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&r6->gateway))
{
msg(M_WARN, "ROUTE6 WARNING: " PACKAGE_NAME " needs a gateway "
@@ -2020,6 +2121,7 @@
#if defined(TARGET_LINUX)
int metric = -1;
+
if ((r6->flags & RT_METRIC_DEFINED) && (r6->metric > 0))
{
metric = r6->metric;
@@ -2089,7 +2191,7 @@
#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
- argv_printf(&argv, "%s add -inet6 %s/%d",
+ argv_printf(&argv, "%s add -inet6 %s/%d ",
ROUTE_PATH,
network,
r6->netbits);
@@ -2110,7 +2212,7 @@
#elif defined(TARGET_DARWIN)
- argv_printf(&argv, "%s add -inet6 %s -prefixlen %d",
+ argv_printf(&argv, "%s add -inet6 %s -prefixlen %d ",
ROUTE_PATH,
network, r6->netbits );
@@ -2128,26 +2230,27 @@
"ERROR: MacOS X route add -inet6 command failed");
status = ret ? RTA_SUCCESS : RTA_ERROR;
-#elif defined(TARGET_OPENBSD)
+#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
- argv_printf(&argv, "%s add -inet6 %s -prefixlen %d %s",
+ argv_printf(&argv, "%s add -inet6 %s -prefixlen %d ",
ROUTE_PATH,
- network, r6->netbits, gateway );
+ network, r6->netbits);
+
+ if (gateway_needed)
+ {
+ argv_printf_cat(&argv, "%s", gateway);
+ }
+ else
+ {
+ argv_printf_cat(&argv, "-link -iface %s", device);
+ }
+ /* FIX ME: in NetBSD in TUN mode, the route is already added by ifconfig
+ * so add_route_ipv6 fail with 'Invalid argument' or 'File exists'
+ */
argv_msg(D_ROUTE, &argv);
bool ret = openvpn_execve_check(&argv, es, 0,
- "ERROR: OpenBSD route add -inet6 command failed");
- status = ret ? RTA_SUCCESS : RTA_ERROR;
-
-#elif defined(TARGET_NETBSD)
-
- argv_printf(&argv, "%s add -inet6 %s/%d %s",
- ROUTE_PATH,
- network, r6->netbits, gateway );
-
- argv_msg(D_ROUTE, &argv);
- bool ret = openvpn_execve_check(&argv, es, 0,
- "ERROR: NetBSD route add -inet6 command failed");
+ "ERROR: OpenBSD/NetBSD route add -inet6 command failed");
status = ret ? RTA_SUCCESS : RTA_ERROR;
#elif defined(TARGET_AIX)
@@ -2187,7 +2290,8 @@
unsigned int flags,
const struct route_gateway_info *rgi,
const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
#if !defined(TARGET_LINUX)
const char *network;
@@ -2202,6 +2306,21 @@
#endif
int is_local_route;
+#if defined(TARGET_DARWIN) || defined(TARGET_LINUX) \
+ || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
+ || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
+
+ bool gateway_needed = is_gateway_needed_ipv4(r, rgi, tt, is_multipoint);
+
+#if !defined(TARGET_OPENBSD) && !defined(TARGET_NETBSD)
+ const char *device = tt->actual_name;
+ if (!gateway_needed && rgi && (rgi->flags & RGI_IFACE_DEFINED) && rgi->iface[0] != 0) /* vpn server special route */
+ {
+ device = rgi->iface;
+ }
+#endif
+#endif
+
if ((r->flags & (RT_DEFINED|RT_ADDED)) != (RT_DEFINED|RT_ADDED))
{
return;
@@ -2228,13 +2347,20 @@
#if defined(TARGET_LINUX)
metric = -1;
+
+ if (is_on_link(is_local_route, flags, rgi))
+ {
+ device = rgi->iface;
+ }
+
if (r->flags & RT_METRIC_DEFINED)
{
metric = r->metric;
}
if (net_route_v4_del(ctx, &r->network, netmask_to_netbits2(r->netmask),
- &r->gateway, NULL, 0, metric) < 0)
+ gateway_needed ? &r->gateway : NULL,
+ device, 0, metric) < 0)
{
msg(M_WARN, "ERROR: Linux route delete command failed");
}
@@ -2293,27 +2419,26 @@
argv_msg(D_ROUTE, &argv);
openvpn_execve_check(&argv, es, 0, "ERROR: Solaris route delete command failed");
-#elif defined(TARGET_FREEBSD)
+#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
- argv_printf(&argv, "%s delete -net %s %s %s",
- ROUTE_PATH,
- network,
- gateway,
- netmask);
+ argv_printf(&argv, "%s delete", ROUTE_PATH);
+
+ if (gateway_needed)
+ {
+ argv_printf_cat(&argv, "-net %s %s %s",
+ network,
+ gateway,
+ netmask);
+ }
+ else
+ {
+ argv_printf_cat(&argv, "-net %s -iface %s",
+ network,
+ device);
+ }
argv_msg(D_ROUTE, &argv);
- openvpn_execve_check(&argv, es, 0, "ERROR: FreeBSD route delete command failed");
-
-#elif defined(TARGET_DRAGONFLY)
-
- argv_printf(&argv, "%s delete -net %s %s %s",
- ROUTE_PATH,
- network,
- gateway,
- netmask);
-
- argv_msg(D_ROUTE, &argv);
- openvpn_execve_check(&argv, es, 0, "ERROR: DragonFly route delete command failed");
+ openvpn_execve_check(&argv, es, 0, "ERROR: BSD route delete command failed");
#elif defined(TARGET_DARWIN)
@@ -2327,11 +2452,22 @@
}
else
{
- argv_printf(&argv, "%s delete -net %s %s %s",
- ROUTE_PATH,
- network,
- gateway,
- netmask);
+ argv_printf(&argv, "%s delete ",
+ ROUTE_PATH);
+
+ if (gateway_needed)
+ {
+ argv_printf_cat(&argv, "-net %s %s %s",
+ network,
+ gateway,
+ netmask);
+ }
+ else
+ {
+ argv_printf_cat(&argv, "-net %s -interface %s",
+ network,
+ device);
+ }
}
argv_msg(D_ROUTE, &argv);
@@ -2339,11 +2475,22 @@
#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
- argv_printf(&argv, "%s delete -net %s %s -netmask %s",
- ROUTE_PATH,
- network,
- gateway,
- netmask);
+ argv_printf(&argv, "%s delete ",
+ ROUTE_PATH);
+
+ if (gateway_needed)
+ {
+ argv_printf_cat(&argv, "-net %s %s -netmask %s",
+ network,
+ gateway,
+ netmask);
+ }
+ else
+ {
+ argv_printf_cat(&argv, "-net %s -netmask %s",
+ network,
+ netmask);
+ }
argv_msg(D_ROUTE, &argv);
openvpn_execve_check(&argv, es, 0, "ERROR: OpenBSD/NetBSD route delete command failed");
@@ -2378,7 +2525,7 @@
void
delete_route_ipv6(const struct route_ipv6 *r6, const struct tuntap *tt,
unsigned int flags, const struct env_set *es,
- openvpn_net_ctx_t *ctx)
+ openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
const char *network;
@@ -2391,23 +2538,15 @@
#if !defined(TARGET_LINUX)
const char *gateway;
#endif
-#if !defined(TARGET_SOLARIS)
- bool gateway_needed = false;
+#if defined(TARGET_DARWIN) || defined(TARGET_LINUX) \
+ || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
+
const char *device = tt->actual_name;
if (r6->iface != NULL) /* vpn server special route */
{
device = r6->iface;
- gateway_needed = true;
}
- /* if we used a gateway on "add route", we also need to specify it on
- * delete, otherwise some OSes will refuse to delete the route
- */
- if (tt->type == DEV_TYPE_TAP
- && !( (r6->flags & RT_METRIC_DEFINED) && r6->metric == 0 ) )
- {
- gateway_needed = true;
- }
#endif
#endif
@@ -2419,6 +2558,16 @@
gateway = print_in6_addr( r6->gateway, 0, &gc);
#endif
+#if defined(TARGET_DARWIN) || defined(TARGET_LINUX) \
+ || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
+ || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
+ /* if we used a gateway on "add route", we also need to specify it on
+ * delete, otherwise some OSes will refuse to delete the route
+ */
+ bool gateway_needed = false;
+ gateway_needed = is_gateway_needed_ipv6(r6, tt, network, is_multipoint);
+#endif
+
#if defined(TARGET_DARWIN) \
|| defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
|| defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
@@ -2513,23 +2662,19 @@
argv_msg(D_ROUTE, &argv);
openvpn_execve_check(&argv, es, 0, "ERROR: MacOS X route delete -inet6 command failed");
-#elif defined(TARGET_OPENBSD)
+#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
- argv_printf(&argv, "%s delete -inet6 %s -prefixlen %d %s",
+ argv_printf(&argv, "%s delete -inet6 %s -prefixlen %d",
ROUTE_PATH,
- network, r6->netbits, gateway );
+ network, r6->netbits);
+
+ if (gateway_needed)
+ {
+ argv_printf_cat(&argv, "%s", gateway);
+ }
argv_msg(D_ROUTE, &argv);
- openvpn_execve_check(&argv, es, 0, "ERROR: OpenBSD route delete -inet6 command failed");
-
-#elif defined(TARGET_NETBSD)
-
- argv_printf(&argv, "%s delete -inet6 %s/%d %s",
- ROUTE_PATH,
- network, r6->netbits, gateway );
-
- argv_msg(D_ROUTE, &argv);
- openvpn_execve_check(&argv, es, 0, "ERROR: NetBSD route delete -inet6 command failed");
+ openvpn_execve_check(&argv, es, 0, "ERROR: OpenBSD/NetBSD route delete -inet6 command failed");
#elif defined(TARGET_AIX)
@@ -271,13 +271,13 @@
void route_ipv6_clear_host_bits( struct route_ipv6 *r6 );
-bool add_route_ipv6(struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx);
+bool add_route_ipv6(struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint);
-void delete_route_ipv6(const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx);
+void delete_route_ipv6(const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint);
bool add_route(struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags,
const struct route_gateway_info *rgi, const struct env_set *es,
- openvpn_net_ctx_t *ctx);
+ openvpn_net_ctx_t *ctx, const bool is_multipoint);
void add_route_to_option_list(struct route_option_list *l,
const char *network,
@@ -312,14 +312,16 @@
bool add_routes(struct route_list *rl, struct route_ipv6_list *rl6,
const struct tuntap *tt, unsigned int flags,
- const struct env_set *es, openvpn_net_ctx_t *ctx);
+ const struct env_set *es, openvpn_net_ctx_t *ctx,
+ const bool is_multipoint);
void delete_routes(struct route_list *rl,
struct route_ipv6_list *rl6,
const struct tuntap *tt,
unsigned int flags,
const struct env_set *es,
- openvpn_net_ctx_t *ctx);
+ openvpn_net_ctx_t *ctx,
+ const bool is_multipoint);
void setenv_routes(struct env_set *es, const struct route_list *rl);
@@ -1020,7 +1020,7 @@
*/
static void
add_route_connected_v6_net(struct tuntap *tt,
- const struct env_set *es)
+ const struct env_set *es, const bool is_multipoint)
{
struct route_ipv6 r6;
@@ -1030,11 +1030,11 @@
r6.gateway = tt->local_ipv6;
r6.metric = 0; /* connected route */
r6.flags = RT_DEFINED | RT_METRIC_DEFINED;
- add_route_ipv6(&r6, tt, 0, es, NULL);
+ add_route_ipv6(&r6, tt, 0, es, NULL, is_multipoint);
}
void
-delete_route_connected_v6_net(const struct tuntap *tt)
+delete_route_connected_v6_net(const struct tuntap *tt, const bool is_multipoint)
{
struct route_ipv6 r6;
@@ -1045,7 +1045,7 @@
r6.metric = 0; /* connected route */
r6.flags = RT_DEFINED | RT_ADDED | RT_METRIC_DEFINED;
route_ipv6_clear_host_bits(&r6);
- delete_route_ipv6(&r6, tt, 0, NULL, NULL);
+ delete_route_ipv6(&r6, tt, 0, NULL, NULL, is_multipoint);
}
#endif /* if defined(_WIN32) || defined(TARGET_DARWIN) || defined(TARGET_NETBSD) || defined(TARGET_OPENBSD) */
@@ -1087,7 +1087,8 @@
*/
static void
do_ifconfig_ipv6(struct tuntap *tt, const char *ifname, int tun_mtu,
- const struct env_set *es, openvpn_net_ctx_t *ctx)
+ const struct env_set *es, openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
#if !defined(TARGET_LINUX)
struct argv argv = argv_new();
@@ -1205,7 +1206,7 @@
#if defined(TARGET_OPENBSD) || defined(TARGET_NETBSD) \
|| defined(TARGET_DARWIN)
/* and, hooray, we explicitly need to add a route... */
- add_route_connected_v6_net(tt, es);
+ add_route_connected_v6_net(tt, es, is_multipoint);
#endif
#elif defined(TARGET_AIX)
argv_printf(&argv, "%s %s inet6 %s/%d mtu %d up", IFCONFIG_PATH, ifname,
@@ -1231,7 +1232,7 @@
do_address_service(true, AF_INET6, tt);
if (tt->type == DEV_TYPE_TUN)
{
- add_route_connected_v6_net(tt, es);
+ add_route_connected_v6_net(tt, es, is_multipoint);
}
do_dns_service(true, AF_INET6, tt);
do_set_mtu_service(tt, AF_INET6, tun_mtu);
@@ -1259,7 +1260,7 @@
netsh_command(&argv, 4, M_FATAL);
if (tt->type == DEV_TYPE_TUN)
{
- add_route_connected_v6_net(tt, es);
+ add_route_connected_v6_net(tt, es, is_multipoint);
}
/* set ipv6 dns servers if any are specified */
netsh_set_dns6_servers(tt->options.dns6, tt->options.dns6_len, tt->adapter_index);
@@ -1291,7 +1292,7 @@
*/
static void
do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu,
- const struct env_set *es, openvpn_net_ctx_t *ctx)
+ const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
#if !defined(_WIN32) && !defined(TARGET_ANDROID)
/*
@@ -1415,7 +1416,7 @@
r.netmask = tt->remote_netmask;
r.gateway = tt->local;
r.metric = 0;
- add_route(&r, tt, 0, NULL, es, NULL);
+ add_route(&r, tt, 0, NULL, es, NULL, is_multipoint);
}
#elif defined(TARGET_OPENBSD)
@@ -1462,7 +1463,7 @@
r.network = tt->local & tt->remote_netmask;
r.netmask = tt->remote_netmask;
r.gateway = remote_end;
- add_route(&r, tt, 0, NULL, es, NULL);
+ add_route(&r, tt, 0, NULL, es, NULL, is_multipoint);
}
#elif defined(TARGET_NETBSD)
@@ -1504,7 +1505,7 @@
r.network = tt->local & tt->remote_netmask;
r.netmask = tt->remote_netmask;
r.gateway = remote_end;
- add_route(&r, tt, 0, NULL, es, NULL);
+ add_route(&r, tt, 0, NULL, es, NULL, is_multipoint);
}
#elif defined(TARGET_DARWIN)
@@ -1554,7 +1555,7 @@
r.network = tt->local & tt->remote_netmask;
r.netmask = tt->remote_netmask;
r.gateway = tt->local;
- add_route(&r, tt, 0, NULL, es, NULL);
+ add_route(&r, tt, 0, NULL, es, NULL, is_multipoint);
}
#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
@@ -1648,7 +1649,7 @@
/* execute the ifconfig command through the shell */
void
do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu,
- const struct env_set *es, openvpn_net_ctx_t *ctx)
+ const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
msg(D_LOW, "do_ifconfig, ipv4=%d, ipv6=%d", tt->did_ifconfig_setup,
tt->did_ifconfig_ipv6_setup);
@@ -1668,12 +1669,12 @@
if (tt->did_ifconfig_setup)
{
- do_ifconfig_ipv4(tt, ifname, tun_mtu, es, ctx);
+ do_ifconfig_ipv4(tt, ifname, tun_mtu, es, ctx, is_multipoint);
}
if (tt->did_ifconfig_ipv6_setup)
{
- do_ifconfig_ipv6(tt, ifname, tun_mtu, es, ctx);
+ do_ifconfig_ipv6(tt, ifname, tun_mtu, es, ctx, is_multipoint);
}
/* release resources potentially allocated during interface setup */
@@ -2138,12 +2139,13 @@
}
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
close_tun_generic(tt);
free(tt);
+ (void)is_multipoint;
}
int
@@ -2307,7 +2309,8 @@
void
tuncfg(const char *dev, const char *dev_type, const char *dev_node,
int persist_mode, const char *username, const char *groupname,
- const struct tuntap_options *options, openvpn_net_ctx_t *ctx)
+ const struct tuntap_options *options, openvpn_net_ctx_t *ctx,
+ const bool is_multipoint)
{
struct tuntap *tt;
@@ -2347,14 +2350,14 @@
msg(M_ERR, "Cannot ioctl TUNSETGROUP(%s) %s", groupname, dev);
}
}
- close_tun(tt, ctx);
+ close_tun(tt, ctx, is_multipoint);
msg(M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));
}
#endif /* ENABLE_FEATURE_TUN_PERSIST */
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
@@ -2366,6 +2369,7 @@
#endif
close_tun_generic(tt);
free(tt);
+ (void)is_multipoint;
}
int
@@ -2677,7 +2681,7 @@
* Close TUN device.
*/
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
@@ -2687,6 +2691,7 @@
clear_tuntap(tt);
free(tt);
+ (void)is_multipoint;
}
static void
@@ -2710,7 +2715,7 @@
argv_msg(M_INFO, &argv);
openvpn_execve_check(&argv, es, 0, "Solaris ifconfig unplumb failed");
- close_tun(tt, NULL);
+ close_tun(tt, NULL, false);
msg(M_FATAL, "Solaris ifconfig failed");
argv_free(&argv);
}
@@ -2774,10 +2779,12 @@
*/
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
+ (void)is_multipoint;
+
/* only *TAP* devices need destroying, tun devices auto-self-destruct
*/
if (tt->type == DEV_TYPE_TUN || tt->persistent_if)
@@ -2888,10 +2895,12 @@
* need to be explicitly destroyed
*/
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
+ (void)is_multipoint;
+
/* only tun devices need destroying, tap devices auto-self-destruct
*/
if (tt->type != DEV_TYPE_TUN || tt->persistent_if)
@@ -3044,10 +3053,12 @@
* we need to call "ifconfig ... destroy" for cleanup
*/
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
+ (void)is_multipoint;
+
if (tt->persistent_if) /* keep pre-existing if around */
{
close_tun_generic(tt);
@@ -3161,12 +3172,13 @@
}
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
close_tun_generic(tt);
free(tt);
+ (void)is_multipoint;
}
int
@@ -3428,7 +3440,7 @@
}
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
@@ -3450,6 +3462,7 @@
free(tt);
argv_free(&argv);
gc_free(&gc);
+ (void)is_multipoint;
}
int
@@ -3577,7 +3590,7 @@
/* tap devices need to be manually destroyed on AIX
*/
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
@@ -3605,6 +3618,7 @@
free(tt);
env_set_destroy(es);
argv_free(&argv);
+ (void)is_multipoint;
}
int
@@ -6892,7 +6906,7 @@
}
static void
-netsh_delete_address_dns(const struct tuntap *tt, bool ipv6, struct gc_arena *gc)
+netsh_delete_address_dns(const struct tuntap *tt, bool ipv6, struct gc_arena *gc, const bool is_multipoint)
{
const char *ifconfig_ip_local;
struct argv argv = argv_new();
@@ -6922,7 +6936,7 @@
if (ipv6 && tt->type == DEV_TYPE_TUN)
{
- delete_route_connected_v6_net(tt);
+ delete_route_connected_v6_net(tt, is_multipoint);
}
/* "store=active" is needed in Windows 8(.1) to delete the
@@ -6992,7 +7006,7 @@
}
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
@@ -7012,7 +7026,7 @@
do_dns_domain_service(false, tt);
}
do_dns_service(false, AF_INET6, tt);
- delete_route_connected_v6_net(tt);
+ delete_route_connected_v6_net(tt, is_multipoint);
do_address_service(false, AF_INET6, tt);
}
else
@@ -7022,7 +7036,7 @@
do_dns_domain_wmic(false, tt);
}
- netsh_delete_address_dns(tt, true, &gc);
+ netsh_delete_address_dns(tt, true, &gc, is_multipoint);
}
}
@@ -7049,7 +7063,7 @@
if (tt->options.ip_win32_type == IPW32_SET_NETSH)
{
- netsh_delete_address_dns(tt, false, &gc);
+ netsh_delete_address_dns(tt, false, &gc, is_multipoint);
}
}
}
@@ -7170,12 +7184,13 @@
}
void
-close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
+close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint)
{
ASSERT(tt);
close_tun_generic(tt);
free(tt);
+ (void)is_multipoint;
}
int
@@ -266,7 +266,7 @@
void open_tun(const char *dev, const char *dev_type, const char *dev_node,
struct tuntap *tt, openvpn_net_ctx_t *ctx);
-void close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx);
+void close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx, const bool is_multipoint);
void tun_open_device(struct tuntap *tt, const char *dev_node,
const char **device_guid, struct gc_arena *gc);
@@ -280,7 +280,7 @@
void tuncfg(const char *dev, const char *dev_type, const char *dev_node,
int persist_mode, const char *username,
const char *groupname, const struct tuntap_options *options,
- openvpn_net_ctx_t *ctx);
+ openvpn_net_ctx_t *ctx, const bool is_multipoint);
const char *guess_tuntap_dev(const char *dev,
const char *dev_type,
@@ -319,7 +319,7 @@
* @param ctx the networking API opaque context
*/
void do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu,
- const struct env_set *es, openvpn_net_ctx_t *ctx);
+ const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint);
/**
* undo_ifconfig - undo configuration of the tunnel interface
@@ -754,6 +754,7 @@
}
const char *tun_stat(const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc);
+
bool tun_name_is_fixed(const char *dev);
static inline bool
Attention is currently required from: flichtenheld, plaisthos. Hello plaisthos, flichtenheld, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/721?usp=email to review the following change. Change subject: route: extended logic to omit gateway when unnecessary ...................................................................... route: extended logic to omit gateway when unnecessary Extracted and extended the logic behind 'gateway_needed' both in add_route() and add_route_ipv6(). Other than checking the dev-type, special routes and if the gateway is on-link, - set gateway_needed to true if the vpn instance is a multipoint server and DCO is enabled. - set gateway_needed to false if the gateway is in the vpn subnet. Additionally, extended support for these checks and conditions to DARWIN and BSD-based operating systems. These changes ensure that the gateway is only included when necessary, optimizing route configuration and potentially reducing redundant route entries. Change-Id: I87777e74b1fd34781e1d72c9f994eb84f39d800c Signed-off-by: Marco Baffo <marco@mandelbit.com> --- M src/openvpn/forward.c M src/openvpn/init.c M src/openvpn/init.h M src/openvpn/route.c M src/openvpn/route.h M src/openvpn/tun.c M src/openvpn/tun.h 7 files changed, 420 insertions(+), 256 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/21/721/1