From patchwork Mon Sep 16 13:04:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "cron2 (Code Review)" X-Patchwork-Id: 3835 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:c41d:b0:5b9:581e:f939 with SMTP id jt29csp1191637mab; Mon, 16 Sep 2024 06:04:33 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVr6lsyP55UoogHyrhUd0SaFMwI58CHuVhGlwrnAxDuVK+SGbDw7ve/RwCIq5X84WUhWm09hwRsfXQ=@openvpn.net X-Google-Smtp-Source: AGHT+IHiRJ2+wnBPxOY2W9WzPpGm/GvHRuo3myNedGzqdq5aNwcz+Jg9nBSG89/RcigMdlmxK1UH X-Received: by 2002:a05:6870:568a:b0:259:88b4:976 with SMTP id 586e51a60fabf-27c68c34a0emr6416298fac.43.1726491873621; Mon, 16 Sep 2024 06:04:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1726491873; cv=none; d=google.com; s=arc-20240605; b=XUreJf29/ZtC489mEqqBNs2Nx/aF7We2GuYvm5lV/r2kAjkOA8uCdQ1cpB34FOuw2p 1dtf8Glf82sjOFZ5v417LsmQLS5IG2jeSwQqsFrg8cg3QuqzuqkY5zqz1SMS1SGezGb6 VwYWCCGRMA8VHYbcmVWnJd/aMCgUmNXavZ5KsGm3WTmLRt+atG2r0oExLWCL/11Cn9j8 Wg9XzUBRzN2UFmTNer7T7o6CCcRIWakqM3YtudPEKw0/lZbdBKRf3HyXLoGcRm97Rpsl C1MpMD1O5axZqk272Y/0V0XNwDX9fwVGRuiRwqxwD6QApBtiu6WM4xO1Erd14p4pu13P baag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; 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=lz6ThxkUJ7y/RNZVwjHZt7VVe2sAO4eYYtuE3X18cGs=; fh=lm0MLPW7DntlrDqRECIiC9JlE1uPxhepE0URYHIf+eE=; b=Zu+31pimV6GcL3dN0bfO9jgOFUi3k9OCQ5pQugXjNDk8LN/yLzDDVdmWunnD5Js0tf ELw1Wkq9B3aVdUy+iGDFA0+s4x7Jd0gC6BRgd1daJEjpvqY8IDYvDPBTLJ2Ybny+5/bp U8xbcZ71p3xwhHK1e0Bz08psdnP6cPneEg9sEO9uDr/nNC2phkBbjEapPtp7ey4s8IQj Pv8WcehlClQF1xrupKk+m/HSg5JASi+lGu/YyS4HqE41YuaWA6CH4JOjXVIMdWNPtFgF z7+ofmMWUOOpjPDw7oq7EPJvFvr/wqo/GmFmh2LGDNQjH1RIEei3Lwltz+94gThHoTGK QWdg==; 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=SjuY4Auy; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=VJP7MeAN; dkim=neutral (body hash did not verify) header.i=@openvpn.net header.s=google header.b=VS2ZELwf; 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; dara=fail header.i=@openvpn.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-27c95b54decsi2142134fac.330.2024.09.16.06.04.33 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Sep 2024 06:04:33 -0700 (PDT) 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=SjuY4Auy; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=VJP7MeAN; dkim=neutral (body hash did not verify) header.i=@openvpn.net header.s=google header.b=VS2ZELwf; 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; dara=fail header.i=@openvpn.net 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 1sqBOv-0007OK-MA; Mon, 16 Sep 2024 13:04:21 +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 1sqBOu-0007O9-J8 for openvpn-devel@lists.sourceforge.net; Mon, 16 Sep 2024 13:04:20 +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=LLnta/+HjC9CHJUo+8jW2KkRWKsR8NUujATIn7OAW8c=; b=SjuY4AuyBwolaBBbrrXZzmYA1x UqEk8nORv7DMAClilYVT9THWRu7eQ1+G3QOOiXNamjiNZjphbi9BbpAOOKooONiAnDC1QfACxpl3Y tz+vxTZugGTGIZbXp2WBjElXltI9IFtkBJdSW8C5jlbNnbc7cfKnkbAoFCbnzg6wb+XM=; 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=LLnta/+HjC9CHJUo+8jW2KkRWKsR8NUujATIn7OAW8c=; b=V JP7MeAN+qg8NLUQylr3j81GyFPH8wkzqJoSqbp5DLvebEZ4ZqIdBofw15oQQMXVuRSRkobdWib5BQ ToDdNGgkF0NlxT4km/S7k/PtfFLoCZt11HuUgDjxWA/ZdHyR45v5kdAzW6btRbtk5ERcytrL+zsVr L3KtoBdjGsSLeJWQ=; Received: from mail-wm1-f52.google.com ([209.85.128.52]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.95) id 1sqBOr-0000xI-Gs for openvpn-devel@lists.sourceforge.net; Mon, 16 Sep 2024 13:04:20 +0000 Received: by mail-wm1-f52.google.com with SMTP id 5b1f17b1804b1-42bb7298bdeso43019705e9.1 for ; Mon, 16 Sep 2024 06:04:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvpn.net; s=google; t=1726491846; x=1727096646; 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=LLnta/+HjC9CHJUo+8jW2KkRWKsR8NUujATIn7OAW8c=; b=VS2ZELwfNJWEMQGFii8cxrsjnBPcW8c8Ie2onmHIxFuatgh1w415Ab+YVLFFDqLxi4 zXNYvGGi/SJ4gZx5iozDPfb6YWZuiOJ2U05yO1M6j+HhmV6uPtcJCo7lZVSkWxPh2c4K FdR3yDAz8zY4pDGvnjcKS21BC2INNTJj6e+aur0YuCSgyA0xVH5t4yxLj5Z124uC4ske MkVTBY/TYc1kJN+CpfqYvrq2IJxGkEGiZzmrD4RWz4ZjT/RB40SIJ3Vk0IsLheFGK5ch Isj4weSY8CQ1FzGCV+T6SAtbhHfm5vDAXiWMeIMbrM4gVaOV6g7iLv4SJouImFkczqkZ 3Bng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726491846; x=1727096646; 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=LLnta/+HjC9CHJUo+8jW2KkRWKsR8NUujATIn7OAW8c=; b=jjSPeXRlbAbgFImC4AFTpOTgSIeYEemk4qVFtMNxZUa+nFrwofFk7ejTaOGOIOLbTm hfxRoPv60LcqS4rKmY0PWnONM0oll8NbNPupNakoAfRM8l3ryNqgurhwHGd19ida4jCs KJitkM9zd2XfptXporQEDq7+3ezAATGHU2tVNt/xwCizCxpZh8yiMpL2CEtk2cn5vu47 AuvfDFSSwoxNhQuFvRPN0VvDTDzPLMuMpoN+XMrw0EKsyUk14BdJYmLvpA2PIB1A7J/C FPh5jG99GGkau4MyF7GE3tCACZuTyZm1JoUj6NKH8q6IDeLt2SHH+56umeu472vp9cyo 2x/w== X-Gm-Message-State: AOJu0Yy1N1ijC4hW5ey197rDodhQWCkof2ALMaSoDB8GvlvMZCX3HZLm jlw5vmS8Pkj63hzrdw7JTdRXSgHHLwGuFSi4WI5t5DH1ZHJkjzVObA0sS/RwNhz2CJUus+aQvi+ t X-Received: by 2002:a05:600c:350a:b0:426:59fe:ac27 with SMTP id 5b1f17b1804b1-42d964d76ffmr114712645e9.26.1726491844924; Mon, 16 Sep 2024 06:04:04 -0700 (PDT) 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 5b1f17b1804b1-42d9b189a12sm110443055e9.32.2024.09.16.06.04.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Sep 2024 06:04:04 -0700 (PDT) From: "plaisthos (Code Review)" X-Google-Original-From: "plaisthos (Code Review)" X-Gerrit-PatchSet: 1 Date: Mon, 16 Sep 2024 13:04:03 +0000 To: flichtenheld Auto-Submitted: auto-generated X-Gerrit-MessageType: newchange X-Gerrit-Change-Id: I65099ef00822d08fd3f5480c80892f3bf86c56e7 X-Gerrit-Change-Number: 747 X-Gerrit-Project: openvpn X-Gerrit-ChangeURL: X-Gerrit-Commit: 889c11f14592f9f13ce7ff1b96ced946a359cd74 References: Message-ID: MIME-Version: 1.0 User-Agent: Gerrit/3.8.2 X-Spam-Score: -1.2 (-) 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: Attention is currently required from: flichtenheld. Hello flichtenheld, I'd like you to do a code review. Please visit Content analysis details: (-1.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -1.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.128.52 listed in wl.mailspike.net] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.128.52 listed in list.dnswl.org] 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 Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 0.0 T_KAM_HTML_FONT_INVALID Test for Invalidly Named or Formatted Colors in HTML X-Headers-End: 1sqBOr-0000xI-Gs Subject: [Openvpn-devel] [L] Change in openvpn[master]: Introduce DRIVER_AFUNIX backend for use with lwipovpn 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: 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?1810357942539597928?= X-GMAIL-MSGID: =?utf-8?q?1810357942539597928?= X-getmail-filter-classifier: gerrit message type newchange Attention is currently required from: flichtenheld. Hello flichtenheld, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/747?usp=email to review the following change. Change subject: Introduce DRIVER_AFUNIX backend for use with lwipovpn ...................................................................... Introduce DRIVER_AFUNIX backend for use with lwipovpn lwipovpn is a using lwip TCP/IP implementation with an AF_UNIX implementation to emulate a tun/tap device without messing with the TCP/IP stack of the host. For more information about lwipovpn see https://github.com/OpenVPN/lwipovpn Change-Id: I65099ef00822d08fd3f5480c80892f3bf86c56e7 Signed-off-by: Arne Schwabe --- M CMakeLists.txt M Changes.rst M doc/man-sections/vpn-network-options.rst M src/openvpn/Makefile.am M src/openvpn/forward.c M src/openvpn/init.c M src/openvpn/run_command.c M src/openvpn/run_command.h M src/openvpn/ssl.h M src/openvpn/tun.c M src/openvpn/tun.h A src/openvpn/tun_afunix.c A src/openvpn/tun_afunix.h 13 files changed, 383 insertions(+), 16 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/47/747/1 diff --git a/CMakeLists.txt b/CMakeLists.txt index ad620fa..6271574 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -536,6 +536,8 @@ src/openvpn/tls_crypt.c src/openvpn/tun.c src/openvpn/tun.h + src/openvpn/tun_afunix.c + src/openvpn/tun_afunix.h src/openvpn/networking_sitnl.c src/openvpn/networking_freebsd.c src/openvpn/auth_token.c diff --git a/Changes.rst b/Changes.rst index 439352a..f01f8bc 100644 --- a/Changes.rst +++ b/Changes.rst @@ -9,6 +9,19 @@ the user experience as the client shows an error instead of running into a timeout when the server just stops responding completely. +Support for tun/tap via unix domain socket and lwipovpn support + To allow better testing and emulating a full client with a full + network stack OpenVPN now allows a program executed to provide + a tun/tap device instead of opening a device. + + The co-developed lwipovpn program based on lwIP stack allows to + simulate full IP stack and an OpenVPN client using + ``dev-node:/path/to/lwipovpn`` can emulate a full client that + can be pinged, can server a website and more without requiring any + elevated permission. This can make testing OpenVPN much easier. + + For more details see [lwipovpn on Gihtub](https://github.com/OpenVPN/lwipovpn). + Deprecated features ------------------- ``secret`` support has been removed by default. diff --git a/doc/man-sections/vpn-network-options.rst b/doc/man-sections/vpn-network-options.rst index 84d4273..9ad79a0 100644 --- a/doc/man-sections/vpn-network-options.rst +++ b/doc/man-sections/vpn-network-options.rst @@ -117,6 +117,16 @@ figure out whether ``node`` is a TUN or TAP device based on the name, you should also specify ``--dev-type tun`` or ``--dev-type tap``. + If ``node`` starts with the string ``unix:`` openvpn will treat the rest + of the argument as a program. + OpenVPN will create a temporary unix domain socket and start the program + will pass the tun configuration as environment variables. + The temporary unix will be be passed in the environment variable + :code:`TUN_UNIXAF_PATH`. + + This ``unix:`` mode is designed mainly to use with the lwipovpn network + emulator (https://github.com/OpenVPN/lwipovpn). + --dev-type device-type Which device type are we using? ``device-type`` should be :code:`tun` (OSI Layer 3) or :code:`tap` (OSI Layer 2). Use this option only if diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index 56cce9d..26b9018 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -138,6 +138,7 @@ syshead.h \ tls_crypt.c tls_crypt.h \ tun.c tun.h \ + tun_afunix.c tun_afunix.h \ vlan.c vlan.h \ xkey_provider.c xkey_common.h \ xkey_helper.c \ diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 7b23131..9c78adf 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -41,6 +41,7 @@ #include "ssl_verify.h" #include "dco.h" #include "auth_token.h" +#include "tun_afunix.h" #include "memdbg.h" @@ -1319,7 +1320,14 @@ #else /* ifdef _WIN32 */ ASSERT(buf_init(&c->c2.buf, c->c2.frame.buf.headroom)); ASSERT(buf_safe(&c->c2.buf, c->c2.frame.buf.payload_size)); - c->c2.buf.len = read_tun(c->c1.tuntap, BPTR(&c->c2.buf), c->c2.frame.buf.payload_size); + if (c->c1.tuntap->backend_driver == DRIVER_AFUNIX) + { + c->c2.buf.len = tun_afunix_read(c->c1.tuntap, BPTR(&c->c2.buf), c->c2.frame.buf.payload_size); + } + else + { + c->c2.buf.len = read_tun(c->c1.tuntap, BPTR(&c->c2.buf), c->c2.frame.buf.payload_size); + } #endif /* ifdef _WIN32 */ #ifdef PACKET_TRUNCATION_CHECK @@ -1926,7 +1934,14 @@ #ifdef _WIN32 size = write_tun_buffered(c->c1.tuntap, &c->c2.to_tun); #else - size = write_tun(c->c1.tuntap, BPTR(&c->c2.to_tun), BLEN(&c->c2.to_tun)); + if (c->c1.tuntap->backend_driver == DRIVER_AFUNIX) + { + size = tun_afunix_write(c->c1.tuntap, BPTR(&c->c2.to_tun), BLEN(&c->c2.to_tun)); + } + else + { + size = write_tun(c->c1.tuntap, BPTR(&c->c2.to_tun), BLEN(&c->c2.to_tun)); + } #endif if (size > 0) diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 83cc670..35ee0fc 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -54,6 +54,7 @@ #include "mss.h" #include "mudp.h" #include "dco.h" +#include "tun_afunix.h" #include "memdbg.h" @@ -1758,10 +1759,18 @@ &c->net_ctx, c->c1.tuntap); + if (is_tun_afunix(c->options.dev_node)) + { + /* Using AF_UNIX trumps using DCO */ + c->c1.tuntap->backend_driver = DRIVER_AFUNIX; + } #ifdef _WIN32 - c->c1.tuntap->backend_driver = c->options.windows_driver; + else + { + c->c1.tuntap->backend_driver = c->options.windows_driver; + } #else - if (dco_enabled(&c->options)) + else if (dco_enabled(&c->options)) { c->c1.tuntap->backend_driver = DRIVER_DCO; } @@ -1786,6 +1795,10 @@ static bool can_preserve_tun(struct tuntap *tt) { + if (tt && tt->backend_driver == DRIVER_AFUNIX) + { + return false; + } #ifdef TARGET_ANDROID return false; #else @@ -1841,6 +1854,22 @@ #endif } +static void +open_tun_backend(struct context *c) +{ + struct tuntap *tt = c->c1.tuntap; + if (tt->backend_driver == DRIVER_AFUNIX) + { + open_tun_afunix(&c->options, c->c2.frame.tun_mtu, tt, c->c2.es); + } + else + { + open_tun(c->options.dev, c->options.dev_type, c->options.dev_node, + tt, &c->net_ctx); + } +} + + static bool do_open_tun(struct context *c, int *error_flags) { @@ -1863,7 +1892,8 @@ } #endif - /* initialize (but do not open) tun/tap object */ + /* initialize (but do not open) tun/tap object, this also sets + * the backend driver type */ do_init_tun(c); /* inherit the dco context from the tuntap object */ @@ -1898,7 +1928,7 @@ /* do ifconfig */ if (!c->options.ifconfig_noexec - && ifconfig_order() == IFCONFIG_BEFORE_TUN_OPEN) + && ifconfig_order(c->c1.tuntap) == IFCONFIG_BEFORE_TUN_OPEN) { /* guess actual tun/tap unit number that will be returned * by open_tun */ @@ -1911,7 +1941,7 @@ } /* possibly add routes */ - if (route_order() == ROUTE_BEFORE_TUN) + if (route_order(c->c1.tuntap) == ROUTE_BEFORE_TUN) { /* Ignore route_delay, would cause ROUTE_BEFORE_TUN to be ignored */ bool status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list, @@ -1928,8 +1958,7 @@ } /* open the tun device */ - open_tun(c->options.dev, c->options.dev_type, c->options.dev_node, - c->c1.tuntap, &c->net_ctx); + open_tun_backend(c); /* set the hardware address */ if (c->options.lladdr) @@ -1940,7 +1969,7 @@ /* do ifconfig */ if (!c->options.ifconfig_noexec - && ifconfig_order() == IFCONFIG_AFTER_TUN_OPEN) + && ifconfig_order(c->c1.tuntap) == IFCONFIG_AFTER_TUN_OPEN) { do_ifconfig(c->c1.tuntap, c->c1.tuntap->actual_name, c->c2.frame.tun_mtu, c->c2.es, &c->net_ctx); @@ -1966,7 +1995,7 @@ add_wfp_block(c); /* possibly add routes */ - if ((route_order() == ROUTE_AFTER_TUN) && (!c->options.route_delay_defined)) + if ((route_order(c->c1.tuntap) == ROUTE_AFTER_TUN) && (!c->options.route_delay_defined)) { int status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list, c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx); @@ -2026,6 +2055,10 @@ { undo_ifconfig(c->c1.tuntap, &c->net_ctx); } + if (c->c1.tuntap->backend_driver == DRIVER_AFUNIX) + { + tun_afunix_close(c->c1.tuntap); + } close_tun(c->c1.tuntap, &c->net_ctx); c->c1.tuntap = NULL; } @@ -2466,7 +2499,7 @@ c->c1.pulled_options_digest_save = c->c2.pulled_options_digest; /* if --route-delay was specified, start timer */ - if ((route_order() == ROUTE_AFTER_TUN) && c->options.route_delay_defined) + if ((route_order(c->c1.tuntap) == ROUTE_AFTER_TUN) && c->options.route_delay_defined) { event_timeout_init(&c->c2.route_wakeup, c->options.route_delay, now); event_timeout_init(&c->c2.route_wakeup_expire, c->options.route_delay + c->options.route_delay_window, now); diff --git a/src/openvpn/run_command.c b/src/openvpn/run_command.c index 292e81f..b355abf 100644 --- a/src/openvpn/run_command.c +++ b/src/openvpn/run_command.c @@ -204,6 +204,11 @@ goto done; } } + else if (flags & S_NOWAITPID && (stat > 0)) + { + ret = stat; + goto done; + } else if (platform_system_ok(stat)) { ret = true; diff --git a/src/openvpn/run_command.h b/src/openvpn/run_command.h index ccad307..1ad5560 100644 --- a/src/openvpn/run_command.h +++ b/src/openvpn/run_command.h @@ -47,6 +47,9 @@ /** Instead of returning 1/0 for success/fail, * return exit code when between 0 and 255 and -1 otherwise */ #define S_EXITCODE (1<<2) +/** instead of waiting for child process exist status return the + * pid of the child process */ +#define S_NOWAITPID (1<<3) /* wrapper around the execve() call */ int openvpn_popen(const struct argv *a, const struct env_set *es); diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index eea1323..0eacec8 100644 --- a/src/openvpn/ssl.h +++ b/src/openvpn/ssl.h @@ -219,7 +219,7 @@ void tls_multi_free(struct tls_multi *multi, bool clear); /** @} name Functions for initialization and cleanup of tls_multi structures */ - +\ /** @} addtogroup control_processor */ #define TLSMP_INACTIVE 0 diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 0832375..3f5f450 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -75,6 +75,9 @@ case DRIVER_DCO: return "ovpn-dco"; + case DRIVER_AFUNIX: + return "unix"; + #ifdef HAVE_NET_IF_UTUN_H case DRIVER_UTUN: return "utun"; diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index e41b616..75a4218 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -50,6 +50,10 @@ #else DRIVER_GENERIC_TUNTAP, #endif + /** using an AF_UNIX socket to pass packet from/to an external program + * this is always defined. We error out if a user tries to open this type + * on unsupported platforms*/ + DRIVER_AFUNIX, DRIVER_DCO, #ifdef HAVE_NET_IF_UTUN_H DRIVER_UTUN @@ -165,6 +169,15 @@ /* * Define a TUN/TAP dev. */ +#ifdef AF_UNIX +typedef struct afunix_context +{ + pid_t childprocess; +} afunix_context_t; + +#else /* ifdef AF_UNIX */ +typedef struct {} afunix_context_t; +#endif struct tuntap { @@ -179,7 +192,12 @@ */ enum tun_driver_type backend_driver; + /** if the internal variables related to ifconfig of this struct have + * been set up. This does NOT mean ifconfig has been called */ bool did_ifconfig_setup; + + /** if the internal variables related to ifconfig-ipv6 of this struct have + * been set up. This does NOT mean ifconfig has been called */ bool did_ifconfig_ipv6_setup; bool persistent_if; /* if existed before, keep on program end */ @@ -231,6 +249,7 @@ unsigned int rwflags_debug; dco_context_t dco; + afunix_context_t afunix; }; static inline bool @@ -354,8 +373,14 @@ #define IFCONFIG_DEFAULT IFCONFIG_AFTER_TUN_OPEN static inline int -ifconfig_order(void) +ifconfig_order(struct tuntap *tt) { +#if defined AF_UNIX + if (tt->backend_driver == DRIVER_AFUNIX) + { + return IFCONFIG_BEFORE_TUN_OPEN; + } +#endif #if defined(TARGET_LINUX) return IFCONFIG_AFTER_TUN_OPEN; #elif defined(TARGET_SOLARIS) @@ -380,8 +405,14 @@ #define ROUTE_ORDER_DEFAULT ROUTE_AFTER_TUN static inline int -route_order(void) +route_order(struct tuntap *tt) { +#if defined AF_UNIX + if (tt->backend_driver == DRIVER_AFUNIX) + { + return ROUTE_BEFORE_TUN; + } +#endif #if defined(TARGET_ANDROID) return ROUTE_BEFORE_TUN; #else @@ -759,5 +790,4 @@ { return tt && tt->type != DEV_TYPE_UNDEF; } - #endif /* TUN_H */ diff --git a/src/openvpn/tun_afunix.c b/src/openvpn/tun_afunix.c new file mode 100644 index 0000000..c599699 --- /dev/null +++ b/src/openvpn/tun_afunix.c @@ -0,0 +1,180 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2024 OpenVPN Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "syshead.h" + +#include "tun.h" +#include "fdmisc.h" +#include "run_command.h" +#include "manage.h" +#include "win32.h" +#include "wfp_block.h" +#include "argv.h" +#include "options.h" + +#include "memdbg.h" +#include "openssl_compat.h" + +#if defined(AF_UNIX) && !defined(WIN32) +/* Windows does implement some AF_UNIX functionality but key features + * like socketpair() and SOCK_DGRAM are missing */ + +#include +#include +#include +#include +#include + +static void +tun_afunix_exec_child(const char *dev_node, struct tuntap *tt, struct env_set *env) +{ + struct argv argv = argv_new(); + + /* since we know that dev-node starts with unix: we can just skip that + * to get the program name */ + const char *program = dev_node + strlen("unix:"); + + argv_printf(&argv, "%s", program); + + argv_msg(M_INFO, &argv); + tt->afunix.childprocess = openvpn_execve_check(&argv, env, S_NOWAITPID, + "ERROR: failure executing " + "process for tun"); + argv_free(&argv); +} + +void +open_tun_afunix(struct options *o, + int mtu, + struct tuntap *tt, + struct env_set *orig_env) +{ + struct gc_arena gc = gc_new(); + + int fds[2]; + if (!(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == 0)) + { + msg(M_ERR, "Cannot create socket pair for AF_UNIX socket to external " + "program"); + return; + } + + /* Use the first file descriptor for our side and avoid passing it + * to the child */ + tt->fd = fds[1]; + set_cloexec(tt->fd); + + /* Make a copy of the env, so we do not need to delete our custom + * environment variables later */ + struct env_set *env = env_set_create(&gc); + env_set_inherit(env, orig_env); + + setenv_int(env, "TUNTAP_SOCKET_FD", fds[0]); + setenv_str(env, "TUNTAP_DEV_TYPE", dev_type_string(o->dev, o->dev_type)); + setenv_int(env, "TUNTAP_MTU", mtu); + if (o->route_default_gateway) + { + setenv_str(env, "ifconfig_gateway", o->route_default_gateway); + } + if (o->lladdr) + { + setenv_str(env, "TUNTAP_LLADDR", o->lladdr); + } + + tun_afunix_exec_child(o->dev_node, tt, env); + + close(fds[0]); + + /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */ + tt->actual_name = string_alloc("internal:af_unix", NULL); + + gc_free(&gc); +} + +void +tun_afunix_close(struct tuntap *tt) +{ + ASSERT(tt); + if (tt->fd >= 0) + { + close(tt->fd); + tt->fd = 0; + } + kill(tt->afunix.childprocess, SIGINT); + + free(tt->actual_name); + free(tt); +} + +ssize_t +tun_afunix_write(struct tuntap *tt, uint8_t *buf, int len) +{ + int ret; + waitpid(tt->afunix.childprocess, &ret, WNOHANG); + if (ret != 0) + { + msg(M_INFO, "Child process for afunix dead"); + return EIO; + } + return write(tt->fd, buf, len); +} + +ssize_t +tun_afunix_read(struct tuntap *tt, uint8_t *buf, int len) +{ + return read(tt->fd, buf, len); +} +#else /* ifdef AF_UNIX */ +void +open_tun_afunix(const char *dev, const char *dev_type, int mtu, + struct tuntap *tt, struct env_set env) +{ + msg(M_ERR, "AF_UNIX socket support not available on this platform"); +} + +void +tun_afunix_close(struct tuntap *tt) +{ + /* should never be called as open_tun_afunix always fails */ + ASSERT(0); +} + +ssize_t +tun_afunix_write(struct tuntap *tt, uint8_t *buf, int len) +{ + /* should never be called as open_tun_afunix always fails */ + ASSERT(0); +} + +ssize_t +tun_afunix_read(struct tuntap *tt, uint8_t *buf, int len) +{ + /* should never be called as open_tun_afunix always fails */ + ASSERT(0); +} + +#endif /* ifdef AF_UNIX */ diff --git a/src/openvpn/tun_afunix.h b/src/openvpn/tun_afunix.h new file mode 100644 index 0000000..58fc1a5 --- /dev/null +++ b/src/openvpn/tun_afunix.h @@ -0,0 +1,72 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2024 OpenVPN Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef AFUNIX_TUN_H +#define AFUNIX_TUN_H +#include + +#include "tun.h" + +/** + * Opens an AF_UNIX based tun device. This also executes the command that + * the user provided to that will take care of implementing the actual tun + * device + */ +void +open_tun_afunix(struct options *o, + int mtu, + struct tuntap *tt, + struct env_set *env); + + +/** + * Closes the socket used for the AF_UNIX based device. Also sends a + * SIGINT to the child process that was spawned to handle the tun device + */ +void +tun_afunix_close(struct tuntap *tt); + +/** + * Writes a packet to a AF_UNIX based tun device + */ +ssize_t +tun_afunix_write(struct tuntap *tt, uint8_t *buf, int len); + +/** + * Reads a packet from a AF_UNIX based tun devices + */ +ssize_t +tun_afunix_read(struct tuntap *tt, uint8_t *buf, int len); + +#endif /* AFUNIX_TUN_H */ + +/** + * Checks whether a --dev-node parameter specifies a AF_UNIX device + * @param devnode the string to check + * @return true if the string starts with unix: + */ +static inline bool +is_tun_afunix(const char *devnode) +{ + return devnode && strprefix(devnode, "unix:"); +}