From patchwork Wed Nov 15 13:45:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "its_Giaan (Code Review)" X-Patchwork-Id: 3439 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7300:3c06:b0:f2:62eb:61c1 with SMTP id e6csp2926073dys; Wed, 15 Nov 2023 05:45:54 -0800 (PST) X-Google-Smtp-Source: AGHT+IGH86DF02AU9Cq5KFN/IRNyq5dvl7qDbzRa0zxtN40M7xVI37H7aJTLoMvuopGI121A5f+g X-Received: by 2002:a05:6a20:7f8c:b0:186:fdb:5cd with SMTP id d12-20020a056a207f8c00b001860fdb05cdmr2397169pzj.2.1700055954600; Wed, 15 Nov 2023 05:45:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700055954; cv=none; d=google.com; s=arc-20160816; b=e79w8e1jcrClj0JCyBb9/AY9XHiiB7WUe2hZ0deyYSISTSHRSKa46FEKenSFdQVMra ACEXsMAM0w3poQhjtCH53nR40Jcg4v4+uVmJCxk05XytSda95hsvk820MUtOWpbbykqF Jmf54heBZX388/YH0hBQdiTknpr/u8Fdief0+t372BRN4+HDZ2V0Lvxd7PwiZFxtEtg7 G8SoKYJtWc/OtpuIe4zQD27anL/MDTCw+PNEbl78KJHx9ZZChAxz048ry2JyFKFkQb1g Hm4tryeXvDsA5BYZJyZ33iZAs03v53kCaJx1cyKrxVpg8H1fOzeo/cXPSoClV1gDPlYi TLWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:cc:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:user-agent :mime-version:message-id:references:auto-submitted:to:date:from :dkim-signature:dkim-signature:dkim-signature; bh=lGwSvtgf/ZtNg81ki7zVjSAKyYsTm4OXo2xvSV+REU4=; fh=U7wEyxtwz2o5+UdevFSA47vNeG9knhWH0KV//QhD5a0=; b=XK3hC621mLVMeZLgYeDoL3rjs8kBxXlacowAVfuAGgYdTGGP/u+uwtGQ0/de2a1Can /EjSxkaqhJYPw5oTJpyu3bgFAbznLE7LCxWvndF0T+0mEf4Rot0uKllxGmftMpYZD4HF 4tElGDhjUdly5CeQQPw5XWKKbdcfRmY9MNPp3jFYxFqcds8RnxY0RrHQ7GEZNMq/SMqt C+bsPIK05Imqn7oUFRSVb4Afw8hlz6tV1Fg3rfvW6QlVWQZ1YutoTwQJoNe82LGHAotA w9AZxCC8NDVwriD/0GoJfFnp/xMPXacnYIWxG3ldqwg2eQcSoP02cmwtvK/eG+Utn+Ef R0vQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=MdLVg8rw; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=i6L9O4Bt; dkim=neutral (body hash did not verify) header.i=@openvpn.net header.s=google header.b=QDWE8hN4; 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=openvpn.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id e21-20020a635455000000b005b8de051ac6si9684053pgm.111.2023.11.15.05.45.54 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Nov 2023 05:45:54 -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=MdLVg8rw; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=i6L9O4Bt; dkim=neutral (body hash did not verify) header.i=@openvpn.net header.s=google header.b=QDWE8hN4; 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=openvpn.net 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 1r3GCx-00010k-RR; Wed, 15 Nov 2023 13:45:30 +0000 Received: from [172.30.20.202] (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 1r3GCw-00010T-5f for openvpn-devel@lists.sourceforge.net; Wed, 15 Nov 2023 13:45:29 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Type:Content-Transfer-Encoding:MIME-Version :Message-ID:Reply-To:References:Subject:List-Unsubscribe:List-Id:Cc:To:Date: From:Sender:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:List-Help: List-Subscribe:List-Post:List-Owner:List-Archive; bh=nvK6N7pq2Dn9BZanQFirPvaWG97CYM9eIVjeEdj+QpM=; b=MdLVg8rwFODtiS6hXOBINfJKF0 iRSNjcGtWvLFGKfWiFTfk/XtcQj/go6iZMuucqq720++f+fNuG6RaLbeVf0TvEaWdaNxB6gHEPamy 4LXcXmdQ05G7MB+mYVzD+nN87+ELe00ZZHSO/LI2R1dgEeixBHNEnZa04ngbepyPqrmE=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Type:Content-Transfer-Encoding:MIME-Version:Message-ID:Reply-To: References:Subject:List-Unsubscribe:List-Id:Cc:To:Date:From:Sender:Content-ID :Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To: Resent-Cc:Resent-Message-ID:In-Reply-To:List-Help:List-Subscribe:List-Post: List-Owner:List-Archive; bh=nvK6N7pq2Dn9BZanQFirPvaWG97CYM9eIVjeEdj+QpM=; b=i 6L9O4Bt5Dt0nNvXZhQdU4YJXy1+x95EcfTLRfSi9KRzZOscFsZ7vTWmqfUS0oiHXEu2suNB6CSFP6 qosvq9pA8Pgx2z3QHW6AU+xG1HlQKvvYb/D1jdfKi1um0tORHujZN62aeHaQfpYD8Yi2TD2b0p+EX OADnTDpzRTSMqsS4=; Received: from mail-wm1-f47.google.com ([209.85.128.47]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.95) id 1r3GCs-006Vpp-Fw for openvpn-devel@lists.sourceforge.net; Wed, 15 Nov 2023 13:45:29 +0000 Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-4084b0223ccso53116815e9.2 for ; Wed, 15 Nov 2023 05:45:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvpn.net; s=google; t=1700055920; x=1700660720; darn=lists.sourceforge.net; h=user-agent:content-disposition:content-transfer-encoding :mime-version:message-id:reply-to:references:subject :list-unsubscribe:list-id:auto-submitted:cc:to:date:from:from:to:cc :subject:date:message-id:reply-to; bh=nvK6N7pq2Dn9BZanQFirPvaWG97CYM9eIVjeEdj+QpM=; b=QDWE8hN4c1bKaKPMKyCd5RjDICrOX2TG8ofRdp+pM/VZdKwdf8FJzveWa1PS538nNO nWOMotSr8x+hRV37xfoKCuz5fnKD2GAPNwbjGNMOZIMZXOn8WN5eqBO1kN24rEb8e59U 0ocrq8vSfD2lPL2dexir55xthdk/c9CollRKQtBxWYtLgmedWv63Vgtjv7NkPcll/0a+ ArAjJcJpcNBqMGqBlyOvYrsCeIx9yhQHxiQtguPNghRTqOW9LC6bPCISJH1D+LVFU9A+ 9lwl/UT2K4aHvHY1KB0td1o/Hmtu40CGnwzWiW+sg0H00N2HVZXy+TG24B2FrF7vk+Vy fthg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700055920; x=1700660720; h=user-agent:content-disposition:content-transfer-encoding :mime-version:message-id:reply-to:references:subject :list-unsubscribe:list-id:auto-submitted:cc:to:date:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=nvK6N7pq2Dn9BZanQFirPvaWG97CYM9eIVjeEdj+QpM=; b=mudEoaIVtPrsIlerZJqlLNnnarWr7nYWD91CBpn88yRKMrz0gMPXBrpQ+P3Xa62UrN dEfE6SaF5tyWooValFj9eDxfcRntG999eNp9eJ+YnP04jcqTH6aMhVKioXYNkamqDRqm 1ll65miwNrZa8dvZBkUm25nsjr4ZWL+PR7eQUcuUIReSQrLco4LxWqPS3pIH9p1fSpY/ dZ/S840q7hbIfqCJHLRNm+A8G+sX2X9T3uclUmo6QZlgWCunYgQInCz/Q5NuWhZNgpFf RZW2ioJoows5UBa5fd5tvShIJJTztVYfsm3O4wtp2t+cALvZ+av3Ujgh5MONp+JdwSXr ZI9g== X-Gm-Message-State: AOJu0YxP0aRyIrDqZAxdpUOTYowev4xUDWzYrQ43V5Txce1Knx1qW0bW RQAj2s7/c/Z2wcLoByznbZen5RLVdM4x7QLyZPM= X-Received: by 2002:a05:600c:3c8e:b0:40a:5b3c:403 with SMTP id bg14-20020a05600c3c8e00b0040a5b3c0403mr4212532wmb.14.1700055919797; Wed, 15 Nov 2023 05:45:19 -0800 (PST) Received: from gerrit.openvpn.in (ec2-18-159-0-78.eu-central-1.compute.amazonaws.com. [18.159.0.78]) by smtp.gmail.com with ESMTPSA id bh7-20020a05600c3d0700b004068de50c64sm15290005wmb.46.2023.11.15.05.45.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 05:45:19 -0800 (PST) From: "ordex (Code Review)" X-Google-Original-From: "ordex (Code Review)" X-Gerrit-PatchSet: 1 Date: Wed, 15 Nov 2023 13:45:18 +0000 To: plaisthos , flichtenheld Auto-Submitted: auto-generated X-Gerrit-MessageType: newchange X-Gerrit-Change-Id: I81ec69d12abc9a661875c93c7f1bd97e525df55f X-Gerrit-Change-Number: 440 X-Gerrit-Project: openvpn X-Gerrit-ChangeURL: X-Gerrit-Commit: 31df3e484be25bed43e2f133aad9f39d375565b9 References: Message-ID: MIME-Version: 1.0 User-Agent: Gerrit/3.8.2 X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-2.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: Attention is currently required from: flichtenheld, plaisthos. Hello plaisthos, flichtenheld, I'd like you to do a code review. Please visit Content analysis details: (-0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.128.47 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.128.47 listed in wl.mailspike.net] 0.0 WEIRD_PORT URI: Uses non-standard port number for HTTP 0.0 HTML_MESSAGE BODY: HTML included in message -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.0 T_SCC_BODY_TEXT_LINE No description available. 0.0 T_KAM_HTML_FONT_INVALID Test for Invalidly Named or Formatted Colors in HTML X-Headers-End: 1r3GCs-006Vpp-Fw Subject: [Openvpn-devel] [L] Change in openvpn[master]: Using the same wait function for both TCP and UDP 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: , Reply-To: a@unstable.cc, arne-openvpn@rfc2549.org, openvpn-devel@lists.sourceforge.net, frank@lichtenheld.com Cc: openvpn-devel Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1782637872884816296?= X-GMAIL-MSGID: =?utf-8?q?1782637872884816296?= X-getmail-filter-classifier: gerrit message type newchange Attention is currently required from: flichtenheld, plaisthos. Hello plaisthos, flichtenheld, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/440?usp=email to review the following change. Change subject: Using the same wait function for both TCP and UDP ...................................................................... Using the same wait function for both TCP and UDP FORWARD: added a new function to collect UDP flags. MTCP: the mtcp structure has been modified to carry around those flags. The second wait function (in UDP case) has been removed. MULTI: properly remove TCP instances by checking the multi_instance protocol instead of the global one. TLS: set the tls_option xmit_hold bool value to true only in case of TCP child instance to avoid checking the global protocol value. INIT: initialize the c->c2.event_set in the inherit_context_top() by default and not only in case of UDP since we could have multiple different sockets. Change-Id: I81ec69d12abc9a661875c93c7f1bd97e525df55f Signed-off-by: Gianmarco De Gregori --- M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/init.c M src/openvpn/mtcp.c M src/openvpn/mtcp.h M src/openvpn/mudp.c M src/openvpn/multi.c M src/openvpn/options.c M src/openvpn/options.h 9 files changed, 177 insertions(+), 244 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/40/440/1 diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 63a684b..ee18f8b 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -2053,48 +2053,20 @@ */ void -io_wait_dowork_udp(struct context *c, struct multi_tcp *mtcp, const unsigned int flags) +get_io_flags_dowork_udp(struct context *c, struct multi_tcp *mtcp, const unsigned int flags) { unsigned int socket = 0; unsigned int tuntap = 0; - struct event_set_return esr[4]; - - /* These shifts all depend on EVENT_READ and EVENT_WRITE */ - static uintptr_t socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */ - static uintptr_t tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */ - static uintptr_t err_shift = 4; /* depends on ES_ERROR */ -#ifdef ENABLE_MANAGEMENT - static uintptr_t management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */ -#endif -#ifdef ENABLE_ASYNC_PUSH - static int file_shift = FILE_SHIFT; -#endif -#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) - static int dco_shift = DCO_SHIFT; /* Event from DCO linux kernel module */ -#endif - int i; + static uintptr_t err_shift = 4; /* - * Decide what kind of events we want to wait for. - */ - /*c->c2.event_set = mtcp->es; */ - /*event_reset(mtcp->es); */ - /*event_reset(c->c2.event_set); */ - - /* - * On win32 we use the keyboard or an event object as a source - * of asynchronous signals. + * Calculate the flags based on the provided 'flags' argument. */ if (flags & IOW_WAIT_SIGNAL) { wait_signal(mtcp->es, (void *)err_shift); } - /* - * If outgoing data (for TCP/UDP port) pending, wait for ready-to-send - * status from TCP/UDP port. Otherwise, wait for incoming data on - * TUN/TAP device. - */ if (flags & IOW_TO_LINK) { if (flags & IOW_SHAPER) @@ -2180,117 +2152,68 @@ /* * Configure event wait based on socket, tuntap flags. */ - for (i = 0; i < c->c1.link_sockets_num; i++) + for (int i = 0; i < c->c1.link_sockets_num; i++) { - socket_set(c->c2.link_sockets[i], mtcp->es, socket, - &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 (socket & EVENT_READ && c->c2.did_open_tun) - { - dco_event_set(&c->c1.tuntap->dco, mtcp->es, (void *)&dco_shift); - } -#endif - -#ifdef ENABLE_MANAGEMENT - if (management) - { - management_socket_set(management, mtcp->es, (void *)management_shift, NULL); - } -#endif - -#ifdef ENABLE_ASYNC_PUSH - /* arm inotify watcher */ - if (c->options.mode == MODE_SERVER) - { - event_ctl(mtcp->es, c->c2.inotify_fd, EVENT_READ, (void *)&file_shift); - } -#endif - - /* - * Possible scenarios: - * (1) tcp/udp port has data available to read - * (2) tcp/udp port is ready to accept more data to write - * (3) tun dev has data available to read - * (4) tun dev is ready to accept more data to write - * (5) we received a signal (handler sets signal_received) - * (6) timeout (tv) expired - */ - - mtcp->event_set_status = ES_ERROR; - - if (!c->sig->signal_received) - { - if (!(flags & IOW_CHECK_RESIDUAL) || !sockets_read_residual(c)) + if (proto_is_dgram(c->c2.link_sockets[i]->info.proto)) { - int status; - -#ifdef ENABLE_DEBUG - if (check_debug_level(D_EVENT_WAIT)) - { - show_wait_status(c); - } -#endif - - /* - * Wait for something to happen. - */ - status = event_wait(mtcp->es, &c->c2.timeval, esr, SIZE(esr)); - - check_status(status, "event_wait", NULL, NULL); - - if (status > 0) - { - /*printf("\nstatus: %d\n", status); */ - int i; - mtcp->event_set_status = 0; - for (i = 0; i < status; ++i) - { - const struct event_set_return *e = &esr[i]; - uintptr_t shift; - - if (e->arg >= MULTI_N) - { - struct event_arg *ev_arg = (struct event_arg *)e->arg; - if (ev_arg->type != EVENT_ARG_LINK_SOCKET) - { - mtcp->event_set_status = ES_ERROR; - msg(D_LINK_ERRORS, - "io_work: non socket event delivered"); - return; - } - - shift = socket_shift; - /* mark socket so that the multi code knows where we - * have pending i/o */ - ev_arg->pending = true; - } - else - { - shift = (uintptr_t)e->arg; - } - - mtcp->event_set_status |= ((e->rwflags & 3) << shift); - } - } - else if (status == 0) - { - mtcp->event_set_status = ES_TIMEOUT; - } + socket_set(c->c2.link_sockets[i], mtcp->es, socket, + &c->c2.link_sockets[i]->ev_arg, NULL); } } + mtcp->udp_flags = socket | tuntap; +} - /* 'now' should always be a reasonably up-to-date timestamp */ - update_time(); - - /* set signal_received if a signal was received */ - if (mtcp->event_set_status & ES_ERROR) +void +get_io_flags_udp(struct context *c, struct multi_tcp *mtcp, const unsigned int flags) +{ + mtcp->udp_flags = ES_ERROR; + if (c->c2.fast_io && (flags & (IOW_TO_TUN | IOW_TO_LINK | IOW_MBUF))) { - get_signal(&c->sig->signal_received); + /* fast path -- only for TUN/TAP/UDP writes */ + unsigned int ret = 0; + if (flags & IOW_TO_TUN) + { + ret |= TUN_WRITE; + } + if (flags & (IOW_TO_LINK | IOW_MBUF)) + { + ret |= SOCKET_WRITE; + } + mtcp->udp_flags = ret; } - - dmsg(D_EVENT_WAIT, "I/O WAIT status=0x%04x", mtcp->event_set_status); + else + { +#ifdef _WIN32 + bool skip_iowait = flags & IOW_TO_TUN; + if (flags & IOW_READ_TUN) + { + /* + * don't read from tun if we have pending write to link, + * since every tun read overwrites to_link buffer filled + * by previous tun read + */ + skip_iowait = !(flags & IOW_TO_LINK); + } + if (tuntap_is_wintun(c->c1.tuntap) && skip_iowait) + { + unsigned int ret = 0; + if (flags & IOW_TO_TUN) + { + ret |= TUN_WRITE; + } + if (flags & IOW_READ_TUN) + { + ret |= TUN_READ; + } + mtcp->udp_flags = ret; + } + else +#endif /* ifdef _WIN32 */ + { + /* slow path - delegate to io_wait_dowork_udp to calculate flags */ + get_io_flags_dowork_udp(c, mtcp, flags); + } + } } void @@ -2308,10 +2231,10 @@ static uintptr_t management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */ #endif #ifdef ENABLE_ASYNC_PUSH - static int file_shift = FILE_SHIFT; + static uintptr_t file_shift = FILE_SHIFT; #endif #if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) - static int dco_shift = DCO_SHIFT; /* Event from DCO linux kernel module */ + static uintptr_t dco_shift = DCO_SHIFT; /* Event from DCO linux kernel module */ #endif int i; @@ -2428,7 +2351,7 @@ #if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) if (socket & EVENT_READ && c->c2.did_open_tun) { - dco_event_set(&c->c1.tuntap->dco, c->c2.event_set, (void *)&dco_shift); + dco_event_set(&c->c1.tuntap->dco, c->c2.event_set, (void *)dco_shift); } #endif @@ -2443,7 +2366,7 @@ /* arm inotify watcher */ if (c->options.mode == MODE_SERVER) { - event_ctl(c->c2.event_set, c->c2.inotify_fd, EVENT_READ, (void *)&file_shift); + event_ctl(c->c2.event_set, c->c2.inotify_fd, EVENT_READ, (void *)file_shift); } #endif diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index cb184a8..39ac975 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -69,7 +69,9 @@ extern counter_type link_write_bytes_global; -void io_wait_dowork_udp(struct context *c, struct multi_tcp *mtcp, const unsigned int flags); +void get_io_flags_dowork_udp(struct context *c, struct multi_tcp *mtcp, const unsigned int flags); + +void get_io_flags_udp(struct context *c, struct multi_tcp *mtcp, const unsigned int flags); void io_wait_dowork(struct context *c, const unsigned int flags); @@ -366,58 +368,6 @@ return flags; } -static inline void -io_wait_udp(struct context *c, struct multi_tcp *mtcp, const unsigned int flags) -{ - if (c->c2.fast_io && (flags & (IOW_TO_TUN|IOW_TO_LINK|IOW_MBUF))) - { - /* fast path -- only for TUN/TAP/UDP writes */ - unsigned int ret = 0; - if (flags & IOW_TO_TUN) - { - ret |= TUN_WRITE; - } - if (flags & (IOW_TO_LINK|IOW_MBUF)) - { - ret |= SOCKET_WRITE; - } - mtcp->event_set_status = ret; - } - else - { -#ifdef _WIN32 - bool skip_iowait = flags & IOW_TO_TUN; - if (flags & IOW_READ_TUN) - { - /* - * don't read from tun if we have pending write to link, - * since every tun read overwrites to_link buffer filled - * by previous tun read - */ - skip_iowait = !(flags & IOW_TO_LINK); - } - if (tuntap_is_wintun(c->c1.tuntap) && skip_iowait) - { - unsigned int ret = 0; - if (flags & IOW_TO_TUN) - { - ret |= TUN_WRITE; - } - if (flags & IOW_READ_TUN) - { - ret |= TUN_READ; - } - mtcp->event_set_status = ret; - } - else -#endif /* ifdef _WIN32 */ - { - /* slow path */ - io_wait_dowork_udp(c, mtcp, flags); - } - } -} - /* * This is the core I/O wait function, used for all I/O waits except * for TCP in server mode. diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 762793a..2b88551 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -230,7 +230,7 @@ if (streq(p[1], "HTTP")) { struct http_proxy_options *ho; - if (ce->proto != PROTO_TCP && ce->proto != PROTO_TCP_CLIENT) + if (ce->proto != PROTO_TCP && c->mode != CM_CHILD_TCP) { msg(M_WARN, "HTTP proxy support only works for TCP based connections"); return false; @@ -607,7 +607,10 @@ ce_defined = false; } + int proto = c->options.ce.proto; c->options.ce = *ce; + c->options.ce.proto = proto; + #ifdef ENABLE_MANAGEMENT if (ce_defined && management && management_query_remote_enabled(management)) { @@ -2628,7 +2631,7 @@ if (found & OPT_P_EXPLICIT_NOTIFY) { - if (!proto_is_udp(c->options.ce.proto) && c->options.ce.explicit_exit_notification) + if (!proto_is_udp(c->c2.link_sockets[0]->info.proto) && c->options.ce.explicit_exit_notification) { msg(D_PUSH, "OPTIONS IMPORT: --explicit-exit-notify can only be used with --proto udp"); c->options.ce.explicit_exit_notification = 0; @@ -2788,14 +2791,21 @@ int sec = 2; int backoff = 0; - switch (c->options.ce.proto) + switch (c->mode) { - case PROTO_TCP_SERVER: - sec = 1; + case CM_TOP: + if (has_udp_in_local_list(&c->options)) + { + sec = c->options.ce.connect_retry_seconds; + } + else + { + sec = 1; + } break; - case PROTO_UDP: - case PROTO_TCP_CLIENT: + case CM_CHILD_UDP: + case CM_CHILD_TCP: sec = c->options.ce.connect_retry_seconds; break; } @@ -2813,7 +2823,7 @@ } /* Slow down reconnection after 5 retries per remote -- for TCP client or UDP tls-client only */ - if (c->options.ce.proto == PROTO_TCP_CLIENT + if (c->mode == CM_CHILD_TCP || (c->options.ce.proto == PROTO_UDP && c->options.tls_client)) { backoff = (c->options.unsuccessful_attempts / c->options.connection_list->len) - 4; @@ -3293,7 +3303,21 @@ to.server = options->tls_server; to.replay_window = options->replay_window; to.replay_time = options->replay_time; - to.tcp_mode = link_socket_proto_connection_oriented(options->ce.proto); + + if (c->options.ce.local_list->len > 1) + { + for (int i = 0; i < c->options.ce.local_list->len; i++) + { + if (proto_is_dgram(c->options.ce.local_list->array[i]->proto)) + { + to.tcp_mode = false; + } + } + } + else + { + to.tcp_mode = link_socket_proto_connection_oriented(c->options.ce.local_list->array[0]->proto); + } to.config_ciphername = c->options.ciphername; to.config_ncp_ciphers = c->options.ncp_ciphers; to.transition_window = options->transition_window; @@ -3338,7 +3362,7 @@ /* should we not xmit any packets until we get an initial * response from client? */ - if (to.server && options->ce.proto == PROTO_TCP_SERVER) + if (to.server && c->mode == CM_CHILD_TCP) { to.xmit_hold = true; } @@ -4257,20 +4281,13 @@ #ifdef _WIN32 msg(M_INFO, "NOTE: --fast-io is disabled since we are running on Windows"); #else - if (!proto_is_udp(c->options.ce.proto)) + if (c->options.shaper) { - msg(M_INFO, "NOTE: --fast-io is disabled since we are not using UDP"); + msg(M_INFO, "NOTE: --fast-io is disabled since we are using --shaper"); } else { - if (c->options.shaper) - { - msg(M_INFO, "NOTE: --fast-io is disabled since we are using --shaper"); - } - else - { - c->c2.fast_io = true; - } + c->c2.fast_io = true; } #endif } @@ -4967,6 +4984,7 @@ /* options */ dest->options = src->options; + dest->options.ce.proto = ls->info.proto; options_detach(&dest->options); dest->c2.event_set = src->c2.event_set; @@ -5065,10 +5083,7 @@ dest->c2.es_owned = false; dest->c2.event_set = NULL; - if (proto_is_dgram(src->options.ce.proto)) - { - do_event_set_init(dest, false); - } + do_event_set_init(dest, false); #ifdef USE_COMP dest->c2.comp_context = NULL; diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index ba0905e..128a375 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -680,11 +680,11 @@ void multi_tcp_process_io(struct multi_context *m) { + struct multi_tcp *mtcp = m->mtcp; + const unsigned int udp_status = mtcp->udp_flags; const unsigned int mpp_flags = m->top.c2.fast_io ? (MPP_CONDITIONAL_PRE_SELECT | MPP_CLOSE_ON_SIGNAL) : (MPP_PRE_SELECT | MPP_CLOSE_ON_SIGNAL); - struct multi_tcp *mtcp = m->mtcp; - const unsigned int status = mtcp->event_set_status; int i; for (i = 0; i < mtcp->n_esr; ++i) @@ -725,9 +725,10 @@ msg(D_MULTI_ERRORS, "MULTI: mtcp_proc_io: null socket"); break; } - socket_reset_listen_persistent(ev_arg->u.ls); + if (!proto_is_dgram(ev_arg->u.ls->info.proto)) { + socket_reset_listen_persistent(ev_arg->u.ls); mi = multi_create_instance_tcp(m, ev_arg->u.ls); if (mi) { @@ -737,7 +738,23 @@ } else { - if (status & SOCKET_READ) + if (e->arg >= MULTI_N) + { + struct event_arg *ev_arg = (struct event_arg *)e->arg; + if (ev_arg->type != EVENT_ARG_LINK_SOCKET) + { + mtcp->udp_flags = ES_ERROR; + msg(D_LINK_ERRORS, + "io_work: non socket event delivered"); + break; + } + } + else + { + ev_arg->pending = true; + } + + if (udp_status & SOCKET_READ) { read_incoming_link(&m->top, ev_arg->u.ls); if (!IS_SIG(&m->top)) @@ -750,12 +767,12 @@ while (true) { multi_get_timeout(m, &m->top.c2.timeval); - io_wait_udp(&m->top, m->mtcp, p2mp_iow_flags(m)); + get_io_flags_udp(&m->top, m->mtcp, p2mp_iow_flags(m)); MULTI_CHECK_SIG(m); multi_process_per_second_timers(m); - if (m->mtcp->event_set_status == ES_TIMEOUT) + if (m->mtcp->udp_flags == ES_TIMEOUT) { multi_process_timeout(m, MPP_PRE_SELECT | MPP_CLOSE_ON_SIGNAL); } diff --git a/src/openvpn/mtcp.h b/src/openvpn/mtcp.h index b2fdb6e..d55bdfd 100644 --- a/src/openvpn/mtcp.h +++ b/src/openvpn/mtcp.h @@ -55,7 +55,7 @@ int n_esr; int maxevents; unsigned int tun_rwflags; - unsigned int event_set_status; + unsigned int udp_flags; #ifdef ENABLE_MANAGEMENT unsigned int management_persist_flags; #endif diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 4979751..8945a55 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -198,7 +198,6 @@ if (mroute_extract_openvpn_sockaddr(&real, &m->top.c2.from.dest, true) && m->top.c2.buf.len > 0) { - /*real.proto = ls->info.proto; */ struct hash_element *he; const uint32_t hv = hash_value(hash, &real); struct hash_bucket *bucket = hash_bucket(hash, hv); @@ -380,9 +379,7 @@ void multi_process_io_udp(struct multi_context *m) { - const unsigned int status = m->mtcp->event_set_status; - /*p2mp_iow_flags(m); */ - /*m->top.c2.event_set_status; */ + unsigned int status = m->mtcp->udp_flags; const unsigned int mpp_flags = m->top.c2.fast_io ? (MPP_CONDITIONAL_PRE_SELECT | MPP_CLOSE_ON_SIGNAL) : (MPP_PRE_SELECT | MPP_CLOSE_ON_SIGNAL); diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 5098581..108a5a8 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -607,6 +607,7 @@ ASSERT(!mi->halt); mi->halt = true; + bool is_dgram = proto_is_dgram(mi->context.c2.link_sockets[0]->info.proto); dmsg(D_MULTI_DEBUG, "MULTI: multi_close_instance called"); @@ -665,7 +666,7 @@ mi->did_iroutes = false; } - if (m->mtcp && !proto_is_dgram(m->top.options.ce.proto)) + if (!is_dgram) { multi_tcp_dereference_instance(m->mtcp, mi); } @@ -3406,6 +3407,7 @@ perf_push(PERF_PROC_IN_LINK); lsi = get_link_socket_info(c); + /*lsi = &ls->info; */ orig_buf = c->c2.buf.data; if (process_incoming_link_part1(c, lsi, floated)) { @@ -3856,7 +3858,7 @@ while ((he = hash_iterator_next(&hi))) { struct multi_instance *mi = (struct multi_instance *) he->value; - if (!mi->halt) + if (!mi->halt && proto_is_dgram(mi->context.options.ce.proto)) { send_control_channel_string(&mi->context, next_server ? "RESTART,[N]" : "RESTART", D_PUSH); multi_schedule_context_wakeup(m, mi); @@ -3894,13 +3896,15 @@ status_close(so); return false; } - else if (proto_is_dgram(m->top.options.ce.proto) - && is_exit_restart(m->top.sig->signal_received) - && (m->deferred_shutdown_signal.signal_received == 0) - && m->top.options.ce.explicit_exit_notification != 0) + else if (has_udp_in_local_list(&m->top.options)) { - multi_push_restart_schedule_exit(m, m->top.options.ce.explicit_exit_notification == 2); - return false; + if (is_exit_restart(m->top.sig->signal_received) + && (m->deferred_shutdown_signal.signal_received == 0) + && m->top.options.ce.explicit_exit_notification != 0) + { + multi_push_restart_schedule_exit(m, m->top.options.ce.explicit_exit_notification == 2); + return false; + } } return true; } @@ -4198,10 +4202,10 @@ multi_tcp_process_io(multi); MULTI_CHECK_SIG(multi); } - /*else if (status == 0) - * { - * multi_tcp_action(multi, NULL, TA_TIMEOUT, false); - * }*/ + else if (status == 0) + { + multi_tcp_action(multi, NULL, TA_TIMEOUT, false); + } perf_pop(); } diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 9e800bb..553bc26 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -987,10 +987,13 @@ const struct connection_entry *e, const int i) { - setenv_str_i(es, "proto", proto2ascii(e->proto, e->af, false), i); - /* expected to befor single socket contexts only */ - setenv_str_i(es, "local", e->local_list->array[0]->local, i); - setenv_str_i(es, "local_port", e->local_list->array[0]->port, i); + for (int j = 0; j < e->local_list->len; j++) + { + setenv_str_i(es, "proto", proto2ascii(e->local_list->array[j]->proto, e->af, false), i); + /* expected to befor single socket contexts only */ + setenv_str_i(es, "local", e->local_list->array[j]->local, i); + setenv_str_i(es, "local_port", e->local_list->array[j]->port, i); + } setenv_str_i(es, "remote", e->remote, i); setenv_str_i(es, "remote_port", e->remote_port, i); @@ -2455,7 +2458,7 @@ { struct local_entry *le = ce->local_list->array[i]; - if (proto_is_net(ce->proto) + if (proto_is_net(le->proto) && string_defined_equal(le->local, ce->remote) && string_defined_equal(le->port, ce->remote_port)) { @@ -3781,6 +3784,12 @@ options_postprocess_mutate_ce(o, o->connection_list->array[i]); } + if (!has_udp_in_local_list(o)) + { + o->fast_io = false; + msg(M_INFO, "NOTE: --fast-io is disabled while using multi-socket"); + } + if (o->ce.local_list) { for (i = 0; i < o->ce.local_list->len; i++) @@ -9629,3 +9638,19 @@ err: gc_free(&gc); } + +bool +has_udp_in_local_list(const struct options *options) +{ + if (options->ce.local_list) + { + for (int i = 0; i < options->ce.local_list->len; i++) + { + if (proto_is_dgram(options->ce.local_list->array[i]->proto)) + { + return true; + } + } + } + return false; +} diff --git a/src/openvpn/options.h b/src/openvpn/options.h index cba0333..59035f8 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -913,6 +913,8 @@ bool key_is_external(const struct options *options); +bool has_udp_in_local_list(const struct options *options); + /** * Returns whether the current configuration has dco enabled. */