From patchwork Sat Nov 14 17:59:13 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 5702 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:6022:3119:b0:11a:a05e:cb97 with SMTP id e25csp943201laa; Sat, 14 Nov 2026 09:59:53 -0800 (PST) X-Forwarded-Encrypted: i=2; AL+hErFktWcvZLWUQ+puvLnnBnW7231hAKCJTOyEoQkv3A7ZOAEbsAUQGCtgxrjx1XHbFq+V5mMCOI1478U=@openvpn.net X-Received: by 2002:a05:7022:282:20b0:149:1feb:6da4 with SMTP id a92af1059eb24-1b5031244a9mr5475257c88.32.1794679192914; Sat, 14 Nov 2026 09:59:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1794679192; cv=none; d=google.com; s=arc-20260327; b=DwG1wwTfFcauZT6UsTIoBTg6osRc4Gk27Fo26LMDRiuqHlAE/aBYdEtKK7ussz7t1w 2nWmrGhjhN3Xyd/CSxDIfYG+B0J3ijwSVEBkKJL66MmMMW1woE5rKlWebMEM8XsGw0Ez 2DHq0eH2Jm+7JLoNeniOlx1rU1bAYZX2RE94xk0WXjFueZ10aqYnJcj3VfrTA7iRsYxH nKmwMmGx9IDv+VhKzKhqywSD/2hJxuCoh081UkK3tmafcHWjsPjcXptRdLiA9Lmz30dk RVguyA/PeQXuGMBtjSuEDBj/YKt696PlT8GRPb9i9Iy7rDHei/BKYWw6SAh90nRVtkEc FFAw== 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=NJaDO77jPfl1ybryftYpIjHE5z8Xpfjaq32JLVbUe5g=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=ZJ5gKEVeRc+kVBUsdtH8QeUVoUbHQ5i7INJMt4s87gmZS2pupD/h1j+g9xMhssmRQe 5/mkXpsFVkoDD2fsXlP46hOJnjYU/RgvdwcD9iW6Jfrf55K9R8h/BCznV7jnBIHPUgRX 7pwFGei1rVPYAbHxNpW5U6GSncIHdgw3n4+a5rgttYccIx5b/XZkWePs5neMbav3bRx7 LWZ1Hw8uOfKGlkfMOrZrWk3jTVtivfsxXI+WJQJAQ0nsWn0VD15DvkoVub1tqDV/iEOi LKJERM/9NSHm/X8KfUXtH9UsFTuXcauckrXwVp2auFdLrzq2CJFLbfgyp8TfqJvPOOJW hKmw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=C9PcBzor; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=P0kx6hBn; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=G1w9cRco; 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 a92af1059eb24-1b510c6c081si9898775c88.15.2026.11.14.09.59.52 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 14 Nov 2026 09:59:52 -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=C9PcBzor; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=P0kx6hBn; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=G1w9cRco; 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=NJaDO77jPfl1ybryftYpIjHE5z8Xpfjaq32JLVbUe5g=; b=C9PcBzor4lkMtf 71jy9ehSkbIRX8bm+mG5p+ypAgIuOI+Y0M+WybP/QXflOjHKKRCCOHhAhAlnKSAPrPXVC1bxW2EC1 LXCze2cbS/erpx50DSyhXGHwxW/cq9CFf6UI8oF+lZR7W+sm9PvR0idSVa42weC3W5gDMOPatciEB uxA=; 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.100.1) (envelope-from ) id 1xSI2Z-000000002Tk-2cB1; Sat, 14 Nov 2026 17:59:51 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.100.1) (envelope-from ) id 1xSI2H-000000002SA-04bJ for openvpn-devel@lists.sourceforge.net; Sat, 14 Nov 2026 17:59:33 +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=Dw8BVX9ArPbHRGzyOk9hrAUq3KhcEMW6Jv5FPqREbDs=; b=P0kx6hBnHWTig8ZJ2vLuqa+07+ bXHXW0rYLJmyRk+oLu0yV+7/9EhfqQg1U1TEsgZWjvA9oJlFplNds+c+flLbZ2U2/WTCKwpZrIsG0 9c/zCk+edtkpIIFq6CjOBvdyTD8dayqhdgI9bGGgPVEKl2YFAsZoxBU7j1R+MBOyUW70=; 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=Dw8BVX9ArPbHRGzyOk9hrAUq3KhcEMW6Jv5FPqREbDs=; b=G1w9cRco86OJdv4IDg3G1W3b3Q pqnWG36a1IBmVruLWViC3Gs4ddN+LRj79OLboyIS6DVHF8JCCWpjpOfDtssjq6xYI0kIjxj+TUriL 3qXtvpQCTiJefoFpCcZU8Q9jQ6tX8NQYaEHoOyCswNBORJUAfVwhDFwZtgWztjLDsPMI=; Received: from [193.149.48.129] (helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.100.1) id 1xSI2A-000000002ct-2zaQ for openvpn-devel@lists.sourceforge.net; Sat, 14 Nov 2026 17:59:27 +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 6AEHxJp7014249 for ; Sat, 14 Nov 2026 18:59:19 +0100 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.2/8.18.1/Submit) id 6AEHxJtg014248 for openvpn-devel@lists.sourceforge.net; Sat, 14 Nov 2026 18:59:19 +0100 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Sat, 14 Nov 2026 18:59:13 +0100 Message-ID: <20261114175919.14229-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 Remove affected DCO routes before changing virtual addresses, synchronize the changed families with the Linux DCO peer, and reinstall only iroutes still owned by this client. Preserve the userspace ir [...] 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: 1xSI2A-000000002ct-2zaQ Subject: [Openvpn-devel] [PATCH v3] PUSH_UPDATE: enable Linux DCO address and iroute updates 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: 1881857529185215202 X-GMAIL-MSGID: 1881857529185215202 From: Marco Baffo Remove affected DCO routes before changing virtual addresses, synchronize the changed families with the Linux DCO peer, and reinstall only iroutes still owned by this client. Preserve the userspace iroutes. Restart the client if updating the DCO peer fails. Change-Id: I24589d5158f67febd3c25af029944d3f1da32763 Signed-off-by: Marco Baffo Acked-by: Razvan Cojocaru Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2063 --- 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/+/2063 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Razvan Cojocaru diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a850e72..8a4b2e1 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -4496,6 +4496,7 @@ static void unlearn_ifconfig(struct multi_context *m, struct multi_instance *mi) { + multi_del_dco_iroutes_v4(m, mi); in_addr_t old_addr = 0; old_addr = htonl(mi->context.c2.push_ifconfig_local); multi_unlearn_in_addr_t(m, mi, old_addr); @@ -4508,6 +4509,7 @@ static void unlearn_ifconfig_ipv6(struct multi_context *m, struct multi_instance *mi) { + multi_del_dco_iroutes_v6(m, mi); struct in6_addr old_addr6; CLEAR(old_addr6); old_addr6 = mi->context.c2.push_ifconfig_ipv6_local; @@ -4517,9 +4519,54 @@ CLEAR(mi->reporting_addr_ipv6); } +/* Reinstall only routes that are still owned by this client. */ +static void +multi_reinstall_owned_dco_iroute(struct multi_context *m, struct multi_instance *mi, + const struct mroute_addr *addr) +{ + const struct multi_route *route = hash_lookup(m->vhash, addr); + if (route && route->instance == mi && multi_route_defined(m, route)) + { + dco_install_iroute(m, mi, addr); + } +} + +/* Userspace iroutes do not depend on the client's VPN address. Only their + * DCO routes need to be reinstalled when the gateway changes. */ +static void +multi_reinstall_dco_iroutes(struct multi_context *m, struct multi_instance *mi, int flags) +{ + if ((flags & (1 << AF_INET)) && mi->context.c2.push_ifconfig_defined) + { + for (const struct iroute *ir = mi->context.options.iroutes; ir; ir = ir->next) + { + struct mroute_addr addr = { 0 }; + mroute_extract_in_addr_t(&addr, ir->network); + addr.type |= MR_WITH_NETBITS; + addr.netbits = (uint8_t)ir->netbits; + multi_reinstall_owned_dco_iroute(m, mi, &addr); + } + } + + if ((flags & (1 << AF_INET6)) && mi->context.c2.push_ifconfig_ipv6_defined) + { + for (const struct iroute_ipv6 *ir6 = mi->context.options.iroutes_ipv6; ir6; ir6 = ir6->next) + { + struct mroute_addr addr = { 0 }; + addr.type = MR_ADDR_IPV6 | MR_WITH_NETBITS; + addr.len = 16; + addr.netbits = (uint8_t)ir6->netbits; + addr.v6.addr = ir6->network; + mroute_addr_mask_host_bits(&addr); + multi_reinstall_owned_dco_iroute(m, mi, &addr); + } + } +} + /** - * Update the vhash when a push-update message containing - * ifconfig/ifconfig-ipv6 options is sent from the server. + * Update the vhash and DCO peer addresses when a push-update message containing + * ifconfig/ifconfig-ipv6 options is sent from the server. Preserve userspace + * iroutes and reinstall their DCO routes with the new IP if needed. * * @param m The multi_context * @param mi The multi_instance of the client we are updating @@ -4531,15 +4578,20 @@ bool update_vaddr(struct multi_context *m, struct multi_instance *mi, const char *new_ip, const char *new_ipv6) { + /* Track changed address families to avoid resetting unchanged DCO addresses. */ + int update_flags = 0; + /* -ifconfig */ if (!new_ip && mi->context.c2.push_ifconfig_defined) { unlearn_ifconfig(m, mi); + update_flags |= (1 << AF_INET); } /* -ifconfig-ipv6 */ if (!new_ipv6 && mi->context.c2.push_ifconfig_ipv6_defined) { unlearn_ifconfig_ipv6(m, mi); + update_flags |= (1 << AF_INET6); } if (new_ip) @@ -4553,6 +4605,7 @@ if (mi->context.c2.push_ifconfig_defined) { unlearn_ifconfig(m, mi); + update_flags |= (1 << AF_INET); } /* DCO needs the new address while installing its on-link route. */ @@ -4562,6 +4615,7 @@ { /* set our client's VPN endpoint for status reporting purposes */ mi->reporting_addr = mi->context.c2.push_ifconfig_local; + update_flags |= (1 << AF_INET); } else { @@ -4589,6 +4643,7 @@ if (mi->context.c2.push_ifconfig_ipv6_defined) { unlearn_ifconfig_ipv6(m, mi); + update_flags |= (1 << AF_INET6); } /* DCO needs the new address while installing its on-link route. */ @@ -4598,6 +4653,7 @@ { /* set our client's VPN endpoint for status reporting purposes */ mi->reporting_addr_ipv6 = mi->context.c2.push_ifconfig_ipv6_local; + update_flags |= (1 << AF_INET6); } else { @@ -4613,6 +4669,24 @@ } } } + + if (!update_flags || !dco_enabled(&m->top.options)) + { + return true; + } + + int ret = dco_multi_update_peer_addr(&mi->context, update_flags); + if (ret < 0) + { + msg(M_WARN, "MULTI: failed to update DCO peer addresses (error %d)", ret); + /* PUSH_UPDATE is already queued, so reconnect to restore consistent state. */ + send_restart(&mi->context, NULL); + multi_schedule_context_wakeup(m, mi); + return false; + } + + multi_reinstall_dco_iroutes(m, mi, update_flags); + return true; } diff --git a/src/openvpn/push_util.c b/src/openvpn/push_util.c index cd940fb..aa77583 100644 --- a/src/openvpn/push_util.c +++ b/src/openvpn/push_util.c @@ -255,12 +255,14 @@ static int send_push_update(struct multi_context *m, const void *target, const char *msg, const push_update_type type, const size_t push_bundle_size) { +#if !defined(TARGET_LINUX) if (dco_enabled(&m->top.options)) { msg(M_WARN, "WARN: PUSH_UPDATE messages cannot currently be sent while DCO is enabled." " To send a PUSH_UPDATE message, be sure to use the --disable-dco option."); return 0; } +#endif if (!msg || !*msg || !m || (!target && type != UPT_BROADCAST)) { @@ -303,6 +305,7 @@ } if (!mi->halt + && !event_timeout_defined(&mi->context.c2.scheduled_exit) && send_single_push_update(m, mi, msgs)) { buffer_list_free(msgs); @@ -323,7 +326,9 @@ { struct multi_instance *curr_mi = m->instances[i]; - if (!curr_mi || curr_mi->halt || !support_push_update(curr_mi)) + if (!curr_mi || curr_mi->halt + || event_timeout_defined(&curr_mi->context.c2.scheduled_exit) + || !support_push_update(curr_mi)) { continue; }