@@ -706,8 +706,8 @@
if (addrtype == MR_ADDR_IPV6)
{
#if defined(_WIN32)
- dco_win_add_iroute_ipv6(&c->c1.tuntap->dco, addr->v6.addr, addr->netbits,
- c->c2.tls_multi->rx_peer_id);
+ bool installed = dco_win_add_iroute_ipv6(&c->c1.tuntap->dco, addr->v6.addr, addr->netbits,
+ c->c2.tls_multi->rx_peer_id);
#else
const struct in6_addr *gateway = &mi->context.c2.push_ifconfig_ipv6_local;
if (addr->type & MR_ONLINK_DCO_ADDR)
@@ -715,16 +715,18 @@
gateway = NULL;
}
- net_route_v6_add(&m->top.net_ctx, &addr->v6.addr, addr->netbits,
- gateway, c->c1.tuntap->actual_name, 0,
- DCO_IROUTE_METRIC);
+ bool installed = net_route_v6_add(&m->top.net_ctx, &addr->v6.addr, addr->netbits,
+ gateway, c->c1.tuntap->actual_name, 0,
+ DCO_IROUTE_METRIC)
+ == 0;
#endif
+ mi->context.did_dco_iroutes_v6 |= installed;
}
else if (addrtype == MR_ADDR_IPV4)
{
#if defined(_WIN32)
- dco_win_add_iroute_ipv4(&c->c1.tuntap->dco, addr->v4.addr, addr->netbits,
- c->c2.tls_multi->rx_peer_id);
+ bool installed = dco_win_add_iroute_ipv4(&c->c1.tuntap->dco, addr->v4.addr, addr->netbits,
+ c->c2.tls_multi->rx_peer_id);
#else
in_addr_t dest = htonl(addr->v4.addr);
const in_addr_t *gateway = &mi->context.c2.push_ifconfig_local;
@@ -733,15 +735,17 @@
gateway = NULL;
}
- net_route_v4_add(&m->top.net_ctx, &dest, addr->netbits, gateway,
- c->c1.tuntap->actual_name, 0, DCO_IROUTE_METRIC);
+ bool installed = net_route_v4_add(&m->top.net_ctx, &dest, addr->netbits, gateway,
+ c->c1.tuntap->actual_name, 0, DCO_IROUTE_METRIC)
+ == 0;
#endif
+ mi->context.did_dco_iroutes_v4 |= installed;
}
#endif /* if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(_WIN32) */
}
void
-dco_delete_iroutes(openvpn_net_ctx_t *net_ctx, const struct context *c)
+dco_delete_iroutes_v4(openvpn_net_ctx_t *net_ctx, const struct context *c)
{
#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(_WIN32)
if (!dco_enabled(&c->options))
@@ -750,7 +754,7 @@
}
ASSERT(TUNNEL_TYPE(c->c1.tuntap) == DEV_TYPE_TUN);
- msg(D_DCO, "DCO: attempt removing iroutes from system table");
+ msg(D_DCO, "DCO: attempt removing IPv4 iroutes from system table");
if (c->c2.push_ifconfig_defined)
{
@@ -778,6 +782,20 @@
}
#endif
}
+#endif /* if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(_WIN32) */
+}
+
+void
+dco_delete_iroutes_v6(openvpn_net_ctx_t *net_ctx, const struct context *c)
+{
+#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(_WIN32)
+ if (!dco_enabled(&c->options))
+ {
+ return;
+ }
+ ASSERT(TUNNEL_TYPE(c->c1.tuntap) == DEV_TYPE_TUN);
+
+ msg(D_DCO, "DCO: attempt removing IPv6 iroutes from system table");
if (c->c2.push_ifconfig_ipv6_defined)
{
@@ -218,12 +218,20 @@
const struct mroute_addr *addr);
/**
- * Remove all routes added through the specified client
+ * Remove all IPv4 routes added through the specified client
*
* @param net_ctx the iface networking context
* @param c the client context for which routes have to be removed
*/
-void dco_delete_iroutes(openvpn_net_ctx_t *net_ctx, const struct context *c);
+void dco_delete_iroutes_v4(openvpn_net_ctx_t *net_ctx, const struct context *c);
+
+/**
+ * Remove all IPv6 routes added through the specified client
+ *
+ * @param net_ctx the iface networking context
+ * @param c the client context for which routes have to be removed
+ */
+void dco_delete_iroutes_v6(openvpn_net_ctx_t *net_ctx, const struct context *c);
/**
* Update traffic statistics for all peers
@@ -356,12 +364,17 @@
}
static inline void
-dco_install_iroute(struct multi_context *m, struct multi_instance *mi, struct mroute_addr *addr)
+dco_install_iroute(struct multi_context *m, struct multi_instance *mi, const struct mroute_addr *addr)
{
}
static inline void
-dco_delete_iroutes(openvpn_net_ctx_t *net_ctx, const struct context *c)
+dco_delete_iroutes_v4(openvpn_net_ctx_t *net_ctx, const struct context *c)
+{
+}
+
+static inline void
+dco_delete_iroutes_v6(openvpn_net_ctx_t *net_ctx, const struct context *c)
{
}
@@ -1007,7 +1007,7 @@
return dco_get_version(&ver) && ver.Major >= 2;
}
-void
+bool
dco_win_add_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits,
unsigned int peer_id)
{
@@ -1021,16 +1021,18 @@
netbits, peer_id);
DWORD bytes_returned = 0;
- if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_MP_ADD_IROUTE, &route, sizeof(route), NULL, 0,
- &bytes_returned, NULL))
+ bool installed = DeviceIoControl(dco->tt->hand, OVPN_IOCTL_MP_ADD_IROUTE, &route, sizeof(route), NULL, 0,
+ &bytes_returned, NULL);
+ if (!installed)
{
msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_MP_ADD_IROUTE) failed");
}
gc_free(&gc);
+ return installed;
}
-void
+bool
dco_win_add_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int netbits,
unsigned int peer_id)
{
@@ -1042,13 +1044,15 @@
netbits, peer_id);
DWORD bytes_returned = 0;
- if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_MP_ADD_IROUTE, &route, sizeof(route), NULL, 0,
- &bytes_returned, NULL))
+ bool installed = DeviceIoControl(dco->tt->hand, OVPN_IOCTL_MP_ADD_IROUTE, &route, sizeof(route), NULL, 0,
+ &bytes_returned, NULL);
+ if (!installed)
{
msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_MP_ADD_IROUTE) failed");
}
gc_free(&gc);
+ return installed;
}
void
@@ -67,10 +67,10 @@
bool dco_win_supports_multipeer(void);
-void dco_win_add_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits,
+bool dco_win_add_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits,
unsigned int peer_id);
-void dco_win_add_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int netbits,
+bool dco_win_add_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int netbits,
unsigned int peer_id);
void dco_win_del_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits);
@@ -555,10 +555,17 @@
* last connecting client claiming the iroutes takes ownership. Therefore
* they are not removed during delayed cleanup.
*/
- if (c->did_dco_iroutes)
+
+ if (c->did_dco_iroutes_v4)
{
- c->did_dco_iroutes = false;
- dco_delete_iroutes(&c->net_ctx, c);
+ c->did_dco_iroutes_v4 = false;
+ dco_delete_iroutes_v4(&c->net_ctx, c);
+ }
+
+ if (c->did_dco_iroutes_v6)
+ {
+ c->did_dco_iroutes_v6 = false;
+ dco_delete_iroutes_v6(&c->net_ctx, c);
}
tls_set_single_session(c->c2.tls_multi);
@@ -479,6 +479,28 @@
set_prefix(mi);
}
+static void
+multi_del_dco_iroutes_v4(struct multi_context *m, struct multi_instance *mi)
+{
+ /* Only remove DCO IPv4 iroutes this instance installed. */
+ if (mi->context.did_dco_iroutes_v4)
+ {
+ mi->context.did_dco_iroutes_v4 = false;
+ dco_delete_iroutes_v4(&m->top.net_ctx, &mi->context);
+ }
+}
+
+static void
+multi_del_dco_iroutes_v6(struct multi_context *m, struct multi_instance *mi)
+{
+ /* Only remove DCO IPv6 iroutes this instance installed. */
+ if (mi->context.did_dco_iroutes_v6)
+ {
+ mi->context.did_dco_iroutes_v6 = false;
+ dco_delete_iroutes_v6(&m->top.net_ctx, &mi->context);
+ }
+}
+
/*
* Tell the route helper about deleted iroutes so
* that it can update its mask of currently used
@@ -490,12 +512,8 @@
const struct iroute *ir;
const struct iroute_ipv6 *ir6;
- /* check if DCO iroutes were already removed when scheduling a delayed exit */
- if (mi->context.did_dco_iroutes)
- {
- mi->context.did_dco_iroutes = false;
- dco_delete_iroutes(&m->top.net_ctx, &mi->context);
- }
+ multi_del_dco_iroutes_v4(m, mi);
+ multi_del_dco_iroutes_v6(m, mi);
if (TUNNEL_TYPE(mi->context.c1.tuntap) == DEV_TYPE_TUN)
{
@@ -1309,8 +1327,6 @@
if (TUNNEL_TYPE(mi->context.c1.tuntap) == DEV_TYPE_TUN)
{
mi->did_iroutes = true;
- /* multi_learn_in{6}_addr_t takes care of installing the DCO iroute */
- mi->context.did_dco_iroutes = true;
for (ir = mi->context.options.iroutes; ir != NULL; ir = ir->next)
{
if (ir->netbits >= 0)
@@ -507,7 +507,8 @@
bool did_we_daemonize; /**< Whether demonization has already
* taken place. */
- bool did_dco_iroutes; /**< Whether DCO iroutes have been installed */
+ bool did_dco_iroutes_v4; /**< Whether DCO IPv4 iroutes have been installed */
+ bool did_dco_iroutes_v6; /**< Whether DCO IPv6 iroutes have been installed */
struct context_persist persist;
/**< Persistent %context. */