From patchwork Thu Feb 20 12:42:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4155 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:9501:b0:5e7:b9eb:58e8 with SMTP id b1csp13176mai; Thu, 20 Feb 2025 04:42:26 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCVcsjUcBiENIP/ay/alOaIGehO3ALrr91wpVxUHKRYtUqLJYkfEDBrVH47ndz2Epc9bXXfhaM47YPw=@openvpn.net X-Google-Smtp-Source: AGHT+IFtCELGv730KZvTqL3xG+V57B1Rgz9zfI/0BkEufU8fq1RDTfd0qzBm9FOs0q0nxfeugRIL X-Received: by 2002:a05:6602:1414:b0:832:480d:6fe1 with SMTP id ca18e2360f4ac-855b38a2b68mr782308339f.0.1740055346287; Thu, 20 Feb 2025 04:42:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1740055346; cv=none; d=google.com; s=arc-20240605; b=Crm5WaXB5xa3aTv4uZLI4llQ5DtsQALDmNwu1dhWx9sIZSv+nt3eJTD8W12Y1f5KUa zwTxo5lzFSSzB8LagouV4f/tJRAEj0SzbBdaCZDkUlutV9o6kVOB/dbrFYWu4hqHa9jD GANk65lS1WTl+ff82xYWZO+GuWEK0X3sxfdkLTC9lBEiBoefDTkoXCc4PsE8UNZ7OYrh z8MdsOpwr2J5UCIAqYCUX8jK886ZTtRsRkboxAENNpPk/L2h778JKFMqj1TujU0e+vRo m87isQgZ7qvO6YBfM6akO7rdy1MV6NT5jT5p4YHpRDMzYOAY926WYklalZ/KJiREOMeI cyZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; 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; bh=Ele06MbLn0JUjK+TeYLIjo/FtISwMPKxNwiRiGB5wFU=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=XSMwxRdBGmZ3b4/3EZGGDykUmxjIg9Q9779/FVWkWNMTdCNtDHY9ya7FsvdgXYWpU1 YfvI4mLkYJ0MOsgjUbpYSA+UdlVGTFw2XNl26dUlPDT+lBfY4C7o4cu1LRgHNroel/p9 bm8FRWJmYiX3FzhwnZt8cX/yt56gB/zPs5X5BCgqBCAnC4XSWg3v/F98IzjUlo8OveXH ls0hSjIm0q7xXV4y4G0jRwlFLjYgE0HL2iNpmtFDUKy95a6qD2O5SAsbeqqYYyZ9j/YH uR9XOko0QaXZK+RZ0+FIfQX26v+d2CH6Sn9UL/1AfzJizQa3CJPCt9JTaBXOMBhNgZ+c U4mw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=m1pjD6rO; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=NEKA8h9h; 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 ca18e2360f4ac-855accf7796si585749139f.64.2025.02.20.04.42.25 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 20 Feb 2025 04:42:26 -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=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=m1pjD6rO; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=NEKA8h9h; 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 [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1tl5sl-0001tG-If; Thu, 20 Feb 2025 12:42:22 +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.95) (envelope-from ) id 1tl5si-0001tA-VD for openvpn-devel@lists.sourceforge.net; Thu, 20 Feb 2025 12:42:20 +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-Subscribe:List-Post:List-Owner:List-Archive; bh=S7QCMQjhCSEsScFU4AQz+hvY/9SpUqXsnqtd5jdJlEo=; b=m1pjD6rOdkv7tgBwXaBOssqzu8 kTBvhGpZJIFQKpxMFjrZA+2IX0GOGufz/2JQAgr+2spjpO65Zi0ktjvzs+lnHnjU1sCJirRyDu5es VrfC1CKV4vERoFEy26qqeG+fkzA1Sdtvnny0xL7SNzsA91hHWBopbsAGp4esH8UN/d+w=; 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-Subscribe: List-Post:List-Owner:List-Archive; bh=S7QCMQjhCSEsScFU4AQz+hvY/9SpUqXsnqtd5jdJlEo=; b=NEKA8h9hPMB8++/32mtIZRWdiN zz8QHzec/dr2daPmB9bIM/LHx3d6D5/bUO4bnxsk3alXFv++5HIxpKqJ8X3+/x+501RjqcjLE0Dx7 p8tVY5hBXhzi53ulAANeC3zf9I6Eg2kea9teTRJr1qfTJlKYHTMqyCkJYNI4doXfbWpI=; Received: from dhcp-174.greenie.muc.de ([193.149.48.174] 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.95) id 1tl5sg-0003iU-FT for openvpn-devel@lists.sourceforge.net; Thu, 20 Feb 2025 12:42:20 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.17.1.9/8.17.1.9) with ESMTP id 51KCg6hn027515 for ; Thu, 20 Feb 2025 13:42:06 +0100 Received: (from gert@localhost) by blue.greenie.muc.de (8.17.1.9/8.17.1.9/Submit) id 51KCg6BN027514 for openvpn-devel@lists.sourceforge.net; Thu, 20 Feb 2025 13:42:06 +0100 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Thu, 20 Feb 2025 13:42:05 +0100 Message-ID: <20250220124205.27502-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 0.0 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", 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: Lev Stipakov Unlike Linux/FreeBSD, dco-win doesn't have access to a system routing table, so we have to maintain internal routing table in the driver. For that, we have 4 ioctls to add/delete IPv4/IPv6 iroutes. Wh [...] Content analysis details: (0.0 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [193.149.48.174 listed in bl.score.senderscore.com] 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [193.149.48.174 listed in sa-trusted.bondedsender.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record X-Headers-End: 1tl5sg-0003iU-FT Subject: [Openvpn-devel] [PATCH v15] dco-win: support for iroutes 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: =?utf-8?q?1824580274988506537?= X-GMAIL-MSGID: =?utf-8?q?1824580274988506537?= From: Lev Stipakov Unlike Linux/FreeBSD, dco-win doesn't have access to a system routing table, so we have to maintain internal routing table in the driver. For that, we have 4 ioctls to add/delete IPv4/IPv6 iroutes. When adding iroute, we pass peer-id, so that the driver is able to associate a subnet with a peer context. Change-Id: I36a5442c0a5667628f419bc64efe5fb562ad3b57 Signed-off-by: Lev Stipakov Acked-by: Gert Doering --- 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/+/857 This mail reflects revision 15 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index c65aece..02fae81 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -649,7 +649,7 @@ dco_install_iroute(struct multi_context *m, struct multi_instance *mi, struct mroute_addr *addr) { -#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) +#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(_WIN32) if (!dco_enabled(&m->top.options)) { return; @@ -665,28 +665,34 @@ } struct context *c = &mi->context; - const char *dev = c->c1.tuntap->actual_name; - 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->peer_id); +#else net_route_v6_add(&m->top.net_ctx, &addr->v6.addr, addr->netbits, - &mi->context.c2.push_ifconfig_ipv6_local, dev, 0, + &mi->context.c2.push_ifconfig_ipv6_local, c->c1.tuntap->actual_name, 0, DCO_IROUTE_METRIC); +#endif } 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->peer_id); +#else in_addr_t dest = htonl(addr->v4.addr); net_route_v4_add(&m->top.net_ctx, &dest, addr->netbits, - &mi->context.c2.push_ifconfig_local, dev, 0, + &mi->context.c2.push_ifconfig_local, c->c1.tuntap->actual_name, 0, DCO_IROUTE_METRIC); +#endif } -#endif /* if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) */ +#endif /* if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(_WIN32) */ } void dco_delete_iroutes(struct multi_context *m, struct multi_instance *mi) { -#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) +#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(_WIN32) if (!dco_enabled(&m->top.options)) { return; @@ -694,7 +700,6 @@ ASSERT(TUNNEL_TYPE(mi->context.c1.tuntap) == DEV_TYPE_TUN); struct context *c = &mi->context; - const char *dev = c->c1.tuntap->actual_name; if (mi->context.c2.push_ifconfig_defined) { @@ -702,9 +707,13 @@ ir; ir = ir->next) { +#if defined(_WIN32) + dco_win_del_iroute_ipv4(&c->c1.tuntap->dco, htonl(ir->network), ir->netbits); +#else net_route_v4_del(&m->top.net_ctx, &ir->network, ir->netbits, - &mi->context.c2.push_ifconfig_local, dev, + &mi->context.c2.push_ifconfig_local, c->c1.tuntap->actual_name, 0, DCO_IROUTE_METRIC); +#endif } } @@ -714,12 +723,16 @@ ir6; ir6 = ir6->next) { +#if defined(_WIN32) + dco_win_del_iroute_ipv6(&c->c1.tuntap->dco, ir6->network, ir6->netbits); +#else net_route_v6_del(&m->top.net_ctx, &ir6->network, ir6->netbits, - &mi->context.c2.push_ifconfig_ipv6_local, dev, + &mi->context.c2.push_ifconfig_ipv6_local, c->c1.tuntap->actual_name, 0, DCO_IROUTE_METRIC); +#endif } } -#endif /* if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) */ +#endif /* if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(_WIN32) */ } #endif /* defined(ENABLE_DCO) */ diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index f46c93d..45cb919 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -823,4 +823,80 @@ return dco_get_version(&ver) && ver.Major >= 2; } +void +dco_win_add_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits, unsigned int peer_id) +{ + struct gc_arena gc = gc_new(); + + OVPN_MP_IROUTE route = {.Addr.Addr4.S_un.S_addr = dst, .Netbits = netbits, .PeerId = peer_id, .IPv6 = 0}; + + msg(D_DCO_DEBUG, "%s: %s/%d -> peer %d", __func__, print_in_addr_t(dst, IA_NET_ORDER, &gc), 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)) + { + msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_MP_ADD_IROUTE) failed"); + } + + gc_free(&gc); +} + +void +dco_win_add_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int netbits, unsigned int peer_id) +{ + struct gc_arena gc = gc_new(); + + OVPN_MP_IROUTE route = { .Addr.Addr6 = dst, .Netbits = netbits, .PeerId = peer_id, .IPv6 = 1 }; + + msg(D_DCO_DEBUG, "%s: %s/%d -> peer %d", __func__, print_in6_addr(dst, IA_NET_ORDER, &gc), 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)) + { + msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_MP_ADD_IROUTE) failed"); + } + + gc_free(&gc); +} + +void +dco_win_del_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits) +{ + struct gc_arena gc = gc_new(); + + OVPN_MP_IROUTE route = { .Addr.Addr4.S_un.S_addr = dst, .Netbits = netbits, .PeerId = -1, .IPv6 = 0 }; + + msg(D_DCO_DEBUG, "%s: %s/%d", __func__, print_in_addr_t(dst, IA_NET_ORDER, &gc), netbits); + + DWORD bytes_returned = 0; + if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_MP_DEL_IROUTE, &route, + sizeof(route), NULL, 0, &bytes_returned, NULL)) + { + msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_MP_DEL_IROUTE) failed"); + } + + gc_free(&gc); +} + +void +dco_win_del_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int netbits) +{ + struct gc_arena gc = gc_new(); + + OVPN_MP_IROUTE route = { .Addr.Addr6 = dst, .Netbits = netbits, .PeerId = -1, .IPv6 = 1 }; + + msg(D_DCO_DEBUG, "%s: %s/%d", __func__, print_in6_addr(dst, IA_NET_ORDER, &gc), netbits); + + DWORD bytes_returned = 0; + if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_MP_DEL_IROUTE, &route, + sizeof(route), NULL, 0, &bytes_returned, NULL)) + { + msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_MP_DEL_IROUTE) failed"); + } + + gc_free(&gc); +} + #endif /* defined(_WIN32) */ diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 309badf..95c95c8 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -24,6 +24,8 @@ #if defined(ENABLE_DCO) && defined(_WIN32) +#include + #include "buffer.h" #include "ovpn_dco_win.h" #include "sig.h" @@ -69,6 +71,18 @@ bool dco_win_supports_multipeer(void); +void +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, unsigned int peer_id); + +void +dco_win_del_iroute_ipv4(dco_context_t *dco, in_addr_t dst, unsigned int netbits); + +void +dco_win_del_iroute_ipv6(dco_context_t *dco, struct in6_addr dst, unsigned int netbits); + #else /* if defined(ENABLE_DCO) && defined(_WIN32) */ static inline void diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index bfe939d..f6d745c 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -174,6 +174,16 @@ int PeerId; } OVPN_MP_SWAP_KEYS, * POVPN_MP_SWAP_KEYS; +typedef struct _OVPN_MP_IROUTE { + union { + IN_ADDR Addr4; + IN6_ADDR Addr6; + } Addr; + int Netbits; + int PeerId; + int IPv6; +} OVPN_MP_IROUTE, * POVPN_MP_IROUTE; + #define OVPN_IOCTL_NEW_PEER CTL_CODE(FILE_DEVICE_UNKNOWN, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) #define OVPN_IOCTL_GET_STATS CTL_CODE(FILE_DEVICE_UNKNOWN, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) #define OVPN_IOCTL_NEW_KEY CTL_CODE(FILE_DEVICE_UNKNOWN, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) @@ -193,3 +203,6 @@ #define OVPN_IOCTL_MP_DEL_PEER CTL_CODE(FILE_DEVICE_UNKNOWN, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) #define OVPN_IOCTL_MP_SWAP_KEYS CTL_CODE(FILE_DEVICE_UNKNOWN, 16, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define OVPN_IOCTL_MP_ADD_IROUTE CTL_CODE(FILE_DEVICE_UNKNOWN, 17, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define OVPN_IOCTL_MP_DEL_IROUTE CTL_CODE(FILE_DEVICE_UNKNOWN, 18, METHOD_BUFFERED, FILE_ANY_ACCESS)