From patchwork Sat Nov 14 17:58:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 5701 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:6022:3119:b0:11a:a05e:cb97 with SMTP id e25csp942669laa; Sat, 14 Nov 2026 09:59:07 -0800 (PST) X-Forwarded-Encrypted: i=2; AL+hErHlxpuY/LCRliSunV/EWKW6r2JsAgMjeCd08wbN7ULQFOF/WR5MiQmZY+13YSvaGpkajmSRoOnFxgY=@openvpn.net X-Received: by 2002:a05:6820:338e:10b0:6dd:9d9d:50f8 with SMTP id 006d021491bc7-71ab50df208mr2538100eaf.38.1794679147104; Sat, 14 Nov 2026 09:59:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1794679147; cv=none; d=google.com; s=arc-20260327; b=B2L4N0l4IzSunfaorxg6g9cbX6zvsXQ5LIc8NA8kuQBHYPUWI2pUSQ5RPuHvETW8Xr vX5k+aiC+lolY0XoO9/+1loZt6t+g7YM7vXVHcaMrPmexWhrS9diNtopf34LafuuCc6s +6F9ufmuDoAnEFPgTSTIR2GMDcMK6U6+yg7f83Bf/8x38u3Q0dMXbFtGM6g7uwHoyT+j EcTX/NcUoJeJ0l4hPnAwkd/0z63oZoKH2lcMBgop01hq57dNlG28DGpFJqz15TCRnXbg ChlP+xlUfnq/Yt4bwawwzpLJZPGUCPQKxPQHGJLMtJZBg9pRceCotaoVV90zVHi2jEoB zkYA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=CiZA0B4ccOQqyDA78FWbUpJeo44OklAwGwn5r83dpCQ=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=FmDvusbsb/pk+/Lmf/kkj5n/iF6TeiIi2uEXxisHe/etdhUrMQlFDu9qOyZtyHE4xh nhXU+7NAb/r7Gcg86YAePoIG3O5gdJ0AoAOHOqF62PbU+K0KLfvDBMYY4S7HZbYMU6/a tDunSw3tKiqFlDmYC7tKelKsQLYRDwx146IyXd7XTG6oJe9anPlX+OLblR3o9InAIAQp f77zBzd3jeQ1SRxggZutsxXliQwp1O6sE3ueNf9vz2SjyUbMXPIgFYdFzDwLVfYv67B+ 6Tyn2v3DxqAXLd2LrNwBJ5LBVbxn+s2h98N+WJICMj9btJfc1SMpby36DuUzk+BB+THF 1bsA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b="RZAL/i9t"; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=fnXFgH58; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=lxuzllJu; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-4afe246ee3bsi8169781fac.187.2026.11.14.09.59.06 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 14 Nov 2026 09:59:07 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b="RZAL/i9t"; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=fnXFgH58; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=lxuzllJu; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Unsubscribe-Post: List-Owner; bh=CiZA0B4ccOQqyDA78FWbUpJeo44OklAwGwn5r83dpCQ=; b=RZAL/i9tLXZQDD nr+NsKCB5JayBp33sHnQ55seOgVmWswkugCT4XU5I2QK13XljlJsvHMhIzmfX0Y0A0W7hVA6Uj0VP NsrDnPQn6FmYHkqG1QzcnDHp8J+Z4nq+HCyHviBXB0iup1m0LPBWr74O2vuwXCwUZ7w4Gd/SGmmW3 HJ8=; Received: from [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.100.1) (envelope-from ) id 1xSI1o-000000000X8-1zYW; Sat, 14 Nov 2026 17:59:04 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.100.1) (envelope-from ) id 1xSI1o-000000000Vi-0JIy for openvpn-devel@lists.sourceforge.net; Sat, 14 Nov 2026 17:59:04 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Unsubscribe-Post:List-Subscribe:List-Post:List-Owner:List-Archive; bh=DBel12LlwhnpG6iF3mVtLRVGq3Uvq6ZcH/sYtjvepc0=; b=fnXFgH588T+j6dziFU+kG0iUgK dsysCo8YJV8Fun4PuTkgio+4q+T0tWVIGGTtDP+VgBZa4Rdf81kMTy2szNlCERpdXjm6pxvjzmz+A pvJ563YqzSzT8qsd53NpUdZK4wh7bXYx3NzFxThTy+mu2gtNFKB0Hsj3IG6Yc1174/7M=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Unsubscribe-Post: List-Subscribe:List-Post:List-Owner:List-Archive; bh=DBel12LlwhnpG6iF3mVtLRVGq3Uvq6ZcH/sYtjvepc0=; b=lxuzllJuzNe+zN4LJUMZVPEwJb bpcjFWrn1CflpQU7jUvyQ2/A9BQqyPy36Vcjerf2orf49oxZoGEOpZ0dVBxxxYez48G5lDM5srgES RaEgTvruRKav2MqFA/3VOEZOgVuK69Z+BBaHbBNDtwrbDaeqvy9XovvytSzAHI1hs7Rw=; Received: from [193.149.48.129] (helo=blue.greenie.muc.de) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.100.1) id 1xSI1m-0000000038K-206I for openvpn-devel@lists.sourceforge.net; Sat, 14 Nov 2026 17:59:04 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.18.1/8.18.1) with ESMTP id 6AEHwt6F014199 for ; Sat, 14 Nov 2026 18:58:55 +0100 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.2/8.18.1/Submit) id 6AEHwtbL014198 for openvpn-devel@lists.sourceforge.net; Sat, 14 Nov 2026 18:58:55 +0100 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Sat, 14 Nov 2026 18:58:48 +0100 Message-ID: <20261114175853.14185-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-2.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Marco Baffo Track successful route installation per address family and split route deletion into IPv4 and IPv6 helpers. Update delayed-exit cleanup. Return installation status from the Windows helpers and keep th [...] Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1xSI1m-0000000038K-206I Subject: [Openvpn-devel] [PATCH v3] dco: track installed iroutes separately for IPv4 and IPv6 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: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: 1881857481515959032 X-GMAIL-MSGID: 1881857481515959032 From: Marco Baffo Track successful route installation per address family and split route deletion into IPv4 and IPv6 helpers. Update delayed-exit cleanup. Return installation status from the Windows helpers and keep the non-DCO declarations compatible. Change-Id: Ic0b8b0a3249eb41e1de10f381932c1161cd75270 Signed-off-by: Marco Baffo Acked-by: Razvan Cojocaru Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2061 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2061 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Razvan Cojocaru diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index f3b5d44..f807002 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -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) { diff --git a/src/openvpn/dco.h b/src/openvpn/dco.h index c435f8c..ce44331 100644 --- a/src/openvpn/dco.h +++ b/src/openvpn/dco.h @@ -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) { } diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 12b0666..68ae7c5 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.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 diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index a92e5ad..28795b7 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -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); diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index eb41d03..6ef480e 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -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); diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 0027550..a850e72 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -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) diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index cdd02b6..72436fe 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -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. */