From patchwork Thu Feb 20 08:09:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4154 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:9b51:b0:5e7:b9eb:58e8 with SMTP id b17csp3423482max; Thu, 20 Feb 2025 00:09:25 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXAK4XJmVkP5nm00f9UPhwnn2lMouyz79YR8Uir63uRif5nzT7oWUrk7XAcgitqzOSF1sB0sXsGAXk=@openvpn.net X-Google-Smtp-Source: AGHT+IGf9ImSjOVaAAiFm3ObOZTYBDm2ab66lnVdTw4toBS3lZz+IR0h84mMZZre2Nf7EeqsilFT X-Received: by 2002:a05:6830:6709:b0:727:2306:a7fe with SMTP id 46e09a7af769-727377a2338mr5078091a34.19.1740038964837; Thu, 20 Feb 2025 00:09:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1740038964; cv=none; d=google.com; s=arc-20240605; b=g7zaRHAaSmztEbixLqhrsHmxgBgyVyQSCupgEh80XfLevP5UIPoREVnC6JBvqto2HC rQH9r5Rto7vFD2QEialK0r6HhYnoWHTVMX+WYSziiIV4uT+EU+s7fzipx5b/S3tYW1RC iUEPaJm96oaQx+q5oNVbtibi0vi2D5wkf7+UAHuC+KCfL7i7EqtjJfOfw4eXxuqTz99t E2Z1Hc9PBN6+yODIfqBfZ4xhk0J1/9tyyIXijH5sdX9hPEfxwO64heh4qhCPC2K1UIB8 S3OS4f1PpsDzpdwguuIDs47lm/cteSfxKK0hYrkEddfy5e5APbKbLSqADLeHJkv6CAgB o0iA== 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=1WyIzExTnLj9qoZl2nx+BgPtjMPQIJO3aXaShc2Uwcs=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=eNcIqLsf3uDb0a13S1AW+F0iyV5zJq+TPDxtMiLwm0YVPfdyTASFOHUPUNU26K+rcG LdcDtMeydFmG6KtoehxIAVvV8UxJuZ5fObXJGRWEHMNEz+gOKPB0MexXWE6BM/3wr2gX /wK0sbgJFTCi/BAR2GU2BqxaeSqa+BGe1tZgEb9NKkK9AZqLTzwN6NqLG6c5zhRFamtF gWJOVztNLCOPVj9VFSSPBbcCGycgRe84+8iowI+okupXPRIh/1zUbQwaVVHwO0z6C45g 0BI3HKMVUjfdCO1f1PYXFSnHmCIZdx75B3l2p4vsJgOktfqDCNA9inNnddYCktblwVrS kQdg==; 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=kN+sOil7; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=M87RzJM6; 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 46e09a7af769-72740ec6105si1651495a34.0.2025.02.20.00.09.24 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 20 Feb 2025 00:09:24 -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=kN+sOil7; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=M87RzJM6; 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-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1tl1cY-0000Kv-MY; Thu, 20 Feb 2025 08:09:22 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1tl1cW-0000Kj-Oh for openvpn-devel@lists.sourceforge.net; Thu, 20 Feb 2025 08:09: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=0e7M9kDXgBlPohxuAzSiWyJZram/DU6x7yPHW6J946k=; b=kN+sOil7rVVONeDep9JxZKAujR NzV6cJPQUuQJSnQT3f7JmySKlWeoB7iOB9EHL6AVSc8F655fTfMq0EOZlahjqruWffjL+q1yVC0+f QLxwadaJP39k464WceZxuMmOQkl9b4S1Ql8E+n6vPiBKKYVGdQwDLrf5lTb6dPWXo1VY=; 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=0e7M9kDXgBlPohxuAzSiWyJZram/DU6x7yPHW6J946k=; b=M87RzJM6Z486maUQns26rCSgRO tO3qDI73G8SpIRQhx4vnvurNB4Ol0SnTDz4ocAzSgeDw2hNUObICcMvXiKt/O7L1QIVOsY66kQ/po IvnymfpexzevkVWVL4aJwwLl+X+lqMfBbFjMZGgylepGkMNAoCUFlZAWEWHpPe8YZrsM=; 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 1tl1cV-0007Mz-Jz for openvpn-devel@lists.sourceforge.net; Thu, 20 Feb 2025 08:09: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 51K898FH009321 for ; Thu, 20 Feb 2025 09:09:08 +0100 Received: (from gert@localhost) by blue.greenie.muc.de (8.17.1.9/8.17.1.9/Submit) id 51K898Xu009320 for openvpn-devel@lists.sourceforge.net; Thu, 20 Feb 2025 09:09:08 +0100 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Thu, 20 Feb 2025 09:09:07 +0100 Message-ID: <20250220080907.9298-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 The driver supports notifications mechanism, which is used to notify userspace about various events, such as peer keepalive timeout, key expire and so on. This uses existing framework of subscribing and receiving dco notifications, used by FreeBSD and Linux implementations. On Windows we use overlapped IO, which state we keep in DCO context. We create a [...] Content analysis details: (0.0 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 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 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] X-Headers-End: 1tl1cV-0007Mz-Jz Subject: [Openvpn-devel] [PATCH v21] dco-win: kernel notifications 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?1824563097798995495?= X-GMAIL-MSGID: =?utf-8?q?1824563097798995495?= From: Lev Stipakov The driver supports notifications mechanism, which is used to notify userspace about various events, such as peer keepalive timeout, key expire and so on. This uses existing framework of subscribing and receiving dco notifications, used by FreeBSD and Linux implementations. On Windows we use overlapped IO, which state we keep in DCO context. We create an event, which is associated with overlapped operation, and inject it into openvpn event loop. When event is signalled, we read overlapped result into DCO context, which is later used by already existing code which handles peer deletion. Change-Id: Iedc10616225f6769c66d3c29d4a462b622ebbc6e 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/+/816 This mail reflects revision 21 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index a3c7b63..f46c93d 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -126,6 +126,17 @@ ASSERT(dco->ifmode == DCO_MODE_UNINIT); dco->ifmode = DCO_MODE_MP; + /* Use manual reset event so it remains signalled until + * explicitly reset. This way we won't lose notifications + */ + dco->ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (dco->ov.hEvent == NULL) + { + msg(M_ERR, "Error: ovpn_dco_init: CreateEvent failed"); + } + + dco->rwhandle.read = dco->ov.hEvent; + /* open DCO device */ struct gc_arena gc = gc_new(); const char *device_guid; @@ -629,11 +640,74 @@ } } +/** + * @brief Handles successful completion of overlapped operation. + * + * We use overlapped I/O (Windows term for asynchronous I/O) to get + * notifications from kernel to userspace. This gets the result of overlapped + * operation and, in case of success, copies data from kernel-filled buffer + * into userspace-provided dco context. + * + * @param dco Pointer to the dco context + * @param queued true if operation was queued, false if it has completed immediately + */ +static void +dco_handle_overlapped_success(dco_context_t *dco, bool queued) +{ + DWORD bytes_read = 0; + BOOL res = GetOverlappedResult(dco->tt->hand, &dco->ov, &bytes_read, FALSE); + if (res) + { + msg(D_DCO_DEBUG, "%s: completion%s success [%ld]", __func__, queued ? "" : " non-queued", bytes_read); + + dco->dco_message_peer_id = dco->notif_buf.PeerId; + dco->dco_message_type = dco->notif_buf.Cmd; + dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + } + else + { + msg(D_DCO_DEBUG | M_ERRNO, "%s: completion%s error", __func__, queued ? "" : " non-queued"); + } +} + int dco_do_read(dco_context_t *dco) { - /* no-op on windows */ - ASSERT(0); + if (dco->ifmode != DCO_MODE_MP) + { + ASSERT(false); + } + + dco->dco_message_peer_id = -1; + dco->dco_message_type = 0; + + switch (dco->iostate) + { + case IOSTATE_QUEUED: + dco_handle_overlapped_success(dco, true); + + ASSERT(ResetEvent(dco->ov.hEvent)); + dco->iostate = IOSTATE_INITIAL; + + break; + + case IOSTATE_IMMEDIATE_RETURN: + dco->iostate = IOSTATE_INITIAL; + ASSERT(ResetEvent(dco->ov.hEvent)); + + if (dco->ov_ret == ERROR_SUCCESS) + { + dco_handle_overlapped_success(dco, false); + } + else + { + SetLastError(dco->ov_ret); + msg(D_DCO_DEBUG | M_ERRNO, "%s: completion non-queued error", __func__); + } + + break; + } + return 0; } @@ -676,8 +750,48 @@ void dco_event_set(dco_context_t *dco, struct event_set *es, void *arg) { - /* no-op on windows */ - ASSERT(0); + if (dco->ifmode != DCO_MODE_MP) + { + /* mp only */ + return; + } + + event_ctl(es, &dco->rwhandle, EVENT_READ, arg); + + if (dco->iostate == IOSTATE_INITIAL) + { + /* the overlapped IOCTL will signal this event on I/O completion */ + ASSERT(ResetEvent(dco->ov.hEvent)); + + if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_NOTIFY_EVENT, NULL, 0, &dco->notif_buf, sizeof(dco->notif_buf), NULL, &dco->ov)) + { + DWORD err = GetLastError(); + if (err == ERROR_IO_PENDING) /* operation queued? */ + { + dco->iostate = IOSTATE_QUEUED; + dco->ov_ret = ERROR_SUCCESS; + + msg(D_DCO_DEBUG, "%s: notify ioctl queued", __func__); + } + else + { + /* error occured */ + ASSERT(SetEvent(dco->ov.hEvent)); + dco->iostate = IOSTATE_IMMEDIATE_RETURN; + dco->ov_ret = err; + + msg(D_DCO_DEBUG | M_ERRNO, "%s: notify ioctl error", __func__); + } + } + else + { + ASSERT(SetEvent(dco->ov.hEvent)); + dco->iostate = IOSTATE_IMMEDIATE_RETURN; + dco->ov_ret = ERROR_SUCCESS; + + msg(D_DCO_DEBUG, "%s: notify ioctl immediate return", __func__); + } + } } const char * diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index dc7fbc1..309badf 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -41,6 +41,18 @@ struct tuntap *tt; dco_mode_type ifmode; + OVPN_NOTIFY_EVENT notif_buf; /**< Buffer for incoming notifications. */ + OVERLAPPED ov; /**< Used by overlapped I/O for async IOCTL. */ + int iostate; /**< State of overlapped I/O; see definitions in win32.h. */ + struct rw_handle rwhandle; /**< Used to hook async I/O to the OpenVPN event loop. */ + int ov_ret; /**< Win32 error code for overlapped operation, 0 for success */ + + int dco_message_peer_id; + int dco_message_type; + int dco_del_peer_reason; + + uint64_t dco_read_bytes; + uint64_t dco_write_bytes; }; typedef struct dco_context dco_context_t; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 82c54c2..8b94469 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -2083,8 +2083,8 @@ #ifdef ENABLE_ASYNC_PUSH static uintptr_t file_shift = FILE_SHIFT; #endif -#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) - static uintptr_t dco_shift = DCO_SHIFT; /* Event from DCO linux kernel module */ +#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(TARGET_WIN32) + static uintptr_t dco_shift = DCO_SHIFT; /* Event from DCO kernel module */ #endif /* @@ -2197,7 +2197,7 @@ &c->c2.link_sockets[i]->ev_arg, NULL); } tun_set(c->c1.tuntap, c->c2.event_set, tuntap, (void *)tun_shift, NULL); -#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) +#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(TARGET_WIN32) if (socket & EVENT_READ && c->c2.did_open_tun) { dco_event_set(&c->c1.tuntap->dco, c->c2.event_set, (void *)dco_shift); diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 5f43db9..e0b27af 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -406,7 +406,8 @@ multi_process_file_closed(m, mpp_flags); } #endif -#if defined(ENABLE_DCO) && (defined(TARGET_LINUX) || defined(TARGET_FREEBSD)) +#if defined(ENABLE_DCO) \ + && (defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(TARGET_WIN32)) else if (status & DCO_READ) { if (!IS_SIG(&m->top)) diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index f76dad8..7ab9289 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3234,7 +3234,8 @@ } #endif -#if defined(ENABLE_DCO) && (defined(TARGET_LINUX) || defined(TARGET_FREEBSD)) +#if defined(ENABLE_DCO) \ + && (defined(TARGET_LINUX) || defined(TARGET_FREEBSD) || defined(TARGET_WIN32)) static void process_incoming_del_peer(struct multi_context *m, struct multi_instance *mi, dco_context_t *dco)