From patchwork Tue Sep 22 08:24:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Baffo X-Patchwork-Id: 5395 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:6446:b0:8a0:ea1f:253a with SMTP id n6csp12954844mag; Tue, 22 Sep 2026 01:24:29 -0700 (PDT) X-Forwarded-Encrypted: i=2; AKwUvByXdnlgYan8C1WrRey+KQ5RK82TDvI2hDkKfADMz5tzGeRo4rHnsVqP/0E0kHO5XiOYrhZOu1yF9ng=@openvpn.net X-Received: by 2002:a05:6808:4f2b:b0:4cb:f21b:6f93 with SMTP id 5614622812f47-4ccf977f7damr16030317b6e.38.1790065469442; Tue, 22 Sep 2026 01:24:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1790065469; cv=none; d=google.com; s=arc-20260327; b=RwZ9QDYgCvOOKcRdE5WMPv3ch92MSw/tajBT3d09QtuE6GhaV/H2R9MrXhsFHNAw0t 0s4neH+w6O8GjPd6z00K1BJZby9pKe7+NCXOXhOybechoNy8Zt3vwGvfxwoSSzEyW5NM bcQtyFNLvEe0LgpncT0j2mEHdljOLH5YzHbwilg10ZQndUAdnXyi8FOA0ZVVhcFHpk3v dUTNVn2qDUUNfkJJxpMuwQADlhPM7WgBgAhmfLqvkFPNYTlmCSf3F4X6IaF4OvZLy4H1 CGznz82KINuRzSsz1q9dQhOvhZ/R5IqEn33VFf3XP5dMvjwZhpWeDOV2Yi4Ea9roRHaX JHOQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=errors-to:content-transfer-encoding:cc:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:message-id:date:to:from:dkim-signature:dkim-signature :dkim-signature:dkim-signature; bh=ZtE6BpOkBt2wOTWsMdGU3Gp03ZspuNsJK8IabkQsy/8=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=j+mOPTmozGzZMB1n70Z201psp7bZQc7O4ObQ8xcGKF12rr0U6Zb6A+pbD82NdscnuD hjMV/Xq5qx27MOq7fwfKrQPUeY6Y9oPqgQtLy6mfwQSerJk0OMVNqhqNZr47gVd4wGZX tK9UyLQu/fduED/agNTZGQf8i2JCDXoOmdW6Hx6PbBeqa9HkG0qdINentShPyuD93sVH 0rXCSOEQTKDk8fblSf4mXFT6MqsAbCX0SKhV6ZQegFXFCdgokGvUZ+v9HWyd8wivJs79 Mo1f5uE+cr4HV9TKbt0LNiOabCbQgRatJMGGl+QCQ42giAyGShPWDiX2Lp2LtqAQsjTf Zvrw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=CsLehd8x; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Rx5rEkLO; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=ZgYClEDg; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=jBleMtg8; 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 Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 5614622812f47-4d4bf071eb7si1297902b6e.16.2026.09.22.01.24.28 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Sep 2026 01:24:29 -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=pass header.i=@lists.sourceforge.net header.s=beta header.b=CsLehd8x; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Rx5rEkLO; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=ZgYClEDg; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=jBleMtg8; 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 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:Cc: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:Message-ID:Date:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Owner; bh=ZtE6BpOkBt2wOTWsMdGU3Gp03ZspuNsJK8IabkQsy/8=; b=CsLehd8x8BxdpgYqBP+Jqu4BcK Roo0ysWtjd19u15PJfYZi3DUc2kYHR9UP6scyIsiNrOePp/m7clmlwiUxZhvjL5GWJ4XcaUM6Emim TOqiT8fQo+ubM+CSd/TAp2qjHLgMEEce1EmirtqbsHhSTLFRvxe02yty6iEsKZccDFHY=; 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 1x8vnd-0003QZ-Ry; Tue, 22 Sep 2026 08:24:25 +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 1x8vna-0003QF-Ll for openvpn-devel@lists.sourceforge.net; Tue, 22 Sep 2026 08:24:23 +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:Message-ID: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=cD08sRUDIcgyy8v/O6jOsNYYnC+CX1WbvOBjLYg+9xo=; b=Rx5rEkLOo2jLpZs2E5Nf6mvCMF 5GfmpSE51+J5XfB3mPPNsQHTCkEkQiw9uc1en642mKglFT6+l9cRkOsL/xfr3dsSRkpDpWo7LfSXc TcvMhu0wKy7riv13HJveZNG0I83b8bhQAHAsd0t2q3d0JKm/W5REZ/SsBAOMIzwN5i+Q=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:Message-ID:Date:Subject:Cc:To:From :Sender:Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=cD08sRUDIcgyy8v/O6jOsNYYnC+CX1WbvOBjLYg+9xo=; b=Z gYClEDgxVgEgMHEu+6NWMSWR1OBb4rNXi9WVrK9yB3i9eWOx16D+3+aMp6qc1RiPbcFW2l7Feup44 gf2Er5WOC0gFTrWotl22q17tAji+4Vu86L0Jvme9OkXBOQocSJiXMficIVRQeTJW3pejBeorMdOnA 2enBhHuTuwS+Rajk=; Received: from mout-b-106.mailbox.org ([195.10.208.46]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1x8vnY-0005Se-Fq for openvpn-devel@lists.sourceforge.net; Tue, 22 Sep 2026 08:24:22 +0000 Received: from smtp102.mailbox.org (smtp102.mailbox.org [10.196.197.102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-b-106.mailbox.org (Postfix) with ESMTPS id 4hptRc4rffzNlZq; Tue, 22 Sep 2026 10:24:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1790065452; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=cD08sRUDIcgyy8v/O6jOsNYYnC+CX1WbvOBjLYg+9xo=; b=jBleMtg8hr8qwwH/prQY5igYUADfB3fu/9FxeRmB9g1f9kcrYzJxIDqefMQzEIq0KSoHJy 5QDaAZb/XIr5xT0JX5+z/08hwOfHGDzVcTs8Jwh/skfh5DNwDwku/XaPVEnZmPlxHppFK6 Hgx/CEhEtdy2jhIh+KSJDo1+0KsXyk8kbHnIqJrc3syA/3T/UsyZ/n8ymaKlV7eokwwEKa YnyQx8C/OAXPIqTBtVQU8fLv60CWpKWnlWQOGtJJmeU7HEVbMGznJ3uMhf3P8mdk54cvna 87ArOqlrjHA/RLlH/9jQ0Fs3zRKeSgBZ5TbZaWk4fNQnUJxQvKrAt4/h0d059g== From: Marco Baffo To: openvpn-devel@lists.sourceforge.net Date: Tue, 22 Sep 2026 10:24:06 +0200 Message-ID: <20260922082408.2930734-1-marco@mandelbit.com> MIME-Version: 1.0 X-Spam-Score: -0.2 (/) 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: ovpn currently looks up the target interface in the network namespace associated with the netlink socket. This prevents a userspace process from controlling an ovpn interface located in another namesp [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -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 X-Headers-End: 1x8vnY-0005Se-Fq Subject: [Openvpn-devel] [RFC ovpn net-next v5 1/3] ovpn: support operations on interfaces in foreign netns 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: , Cc: Antonio Quartulli Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: 1877019689398896090 X-GMAIL-MSGID: 1877019689398896090 ovpn currently looks up the target interface in the network namespace associated with the netlink socket. This prevents a userspace process from controlling an ovpn interface located in another namespace. Add the optional OVPN_A_TARGET_NETNSID attribute. When present, it identifies the namespace containing the target interface relative to the namespace of the requesting Netlink socket. Resolve the ID and perform the interface lookup there. When absent, preserve the existing lookup behavior. Allow the attribute in all peer and key request policies, including peer dump requests. Signed-off-by: Marco Baffo --- Changes in v5: - Fix RCT and line too long in netlink.c Changes in v4: - None. Changes in v3: - None. Changes in v2: - Improved Doc. Documentation/netlink/specs/ovpn.yaml | 27 ++++++++++++++++ drivers/net/ovpn/netlink-gen.c | 45 ++++++++++++++++----------- drivers/net/ovpn/netlink.c | 20 +++++++++++- include/uapi/linux/ovpn.h | 1 + 4 files changed, 74 insertions(+), 19 deletions(-) diff --git a/Documentation/netlink/specs/ovpn.yaml b/Documentation/netlink/specs/ovpn.yaml index ac50d1d7c00a6..3d8055282ebe5 100644 --- a/Documentation/netlink/specs/ovpn.yaml +++ b/Documentation/netlink/specs/ovpn.yaml @@ -341,12 +341,20 @@ attribute-sets: type: nest doc: Peer specific cipher configuration nested-attributes: keyconf + - + name: target-netnsid + type: s32 + doc: >- + ID of the network namespace containing the ovpn interface, relative to + the network namespace of the requesting Netlink socket - name: ovpn-peer-new-input subset-of: ovpn attributes: - name: ifindex + - + name: target-netnsid - name: peer nested-attributes: peer-new-input @@ -356,6 +364,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: peer nested-attributes: peer-set-input @@ -365,6 +375,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: peer nested-attributes: peer-del-input @@ -374,6 +386,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: keyconf nested-attributes: keyconf-get @@ -383,6 +397,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: keyconf nested-attributes: keyconf-swap-input @@ -392,6 +408,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: keyconf nested-attributes: keyconf-del-input @@ -409,6 +427,7 @@ operations: request: attributes: - ifindex + - target-netnsid - peer - name: peer-set @@ -421,6 +440,7 @@ operations: request: attributes: - ifindex + - target-netnsid - peer - name: peer-get @@ -433,6 +453,7 @@ operations: request: attributes: - ifindex + - target-netnsid - peer reply: attributes: @@ -441,6 +462,7 @@ operations: request: attributes: - ifindex + - target-netnsid reply: attributes: - peer @@ -455,6 +477,7 @@ operations: request: attributes: - ifindex + - target-netnsid - peer - name: peer-del-ntf @@ -473,6 +496,7 @@ operations: request: attributes: - ifindex + - target-netnsid - keyconf - name: key-get @@ -485,6 +509,7 @@ operations: request: attributes: - ifindex + - target-netnsid - keyconf reply: attributes: @@ -500,6 +525,7 @@ operations: request: attributes: - ifindex + - target-netnsid - keyconf - name: key-swap-ntf @@ -519,6 +545,7 @@ operations: request: attributes: - ifindex + - target-netnsid - keyconf - diff --git a/drivers/net/ovpn/netlink-gen.c b/drivers/net/ovpn/netlink-gen.c index 92d2fdc17c2e8..7ac9de00e0206 100644 --- a/drivers/net/ovpn/netlink-gen.c +++ b/drivers/net/ovpn/netlink-gen.c @@ -126,55 +126,64 @@ const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_TX_ID + 1] = { }; /* OVPN_CMD_PEER_NEW - do */ -static const struct nla_policy ovpn_peer_new_nl_policy[OVPN_A_PEER + 1] = { +static const struct nla_policy ovpn_peer_new_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_new_input_nl_policy), }; /* OVPN_CMD_PEER_SET - do */ -static const struct nla_policy ovpn_peer_set_nl_policy[OVPN_A_PEER + 1] = { +static const struct nla_policy ovpn_peer_set_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_set_input_nl_policy), }; /* OVPN_CMD_PEER_GET - do */ -static const struct nla_policy ovpn_peer_get_do_nl_policy[OVPN_A_PEER + 1] = { +static const struct nla_policy ovpn_peer_get_do_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy), }; /* OVPN_CMD_PEER_GET - dump */ -static const struct nla_policy ovpn_peer_get_dump_nl_policy[OVPN_A_IFINDEX + 1] = { +static const struct nla_policy ovpn_peer_get_dump_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, }; /* OVPN_CMD_PEER_DEL - do */ -static const struct nla_policy ovpn_peer_del_nl_policy[OVPN_A_PEER + 1] = { +static const struct nla_policy ovpn_peer_del_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_del_input_nl_policy), }; /* OVPN_CMD_KEY_NEW - do */ -static const struct nla_policy ovpn_key_new_nl_policy[OVPN_A_KEYCONF + 1] = { +static const struct nla_policy ovpn_key_new_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy), }; /* OVPN_CMD_KEY_GET - do */ -static const struct nla_policy ovpn_key_get_nl_policy[OVPN_A_KEYCONF + 1] = { +static const struct nla_policy ovpn_key_get_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_get_nl_policy), }; /* OVPN_CMD_KEY_SWAP - do */ -static const struct nla_policy ovpn_key_swap_nl_policy[OVPN_A_KEYCONF + 1] = { +static const struct nla_policy ovpn_key_swap_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_swap_input_nl_policy), }; /* OVPN_CMD_KEY_DEL - do */ -static const struct nla_policy ovpn_key_del_nl_policy[OVPN_A_KEYCONF + 1] = { +static const struct nla_policy ovpn_key_del_nl_policy[OVPN_A_TARGET_NETNSID + 1] = { [OVPN_A_IFINDEX] = { .type = NLA_U32, }, + [OVPN_A_TARGET_NETNSID] = { .type = NLA_S32, }, [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_del_input_nl_policy), }; @@ -186,7 +195,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = { .doit = ovpn_nl_peer_new_doit, .post_doit = ovpn_nl_post_doit, .policy = ovpn_peer_new_nl_policy, - .maxattr = OVPN_A_PEER, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { @@ -195,7 +204,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = { .doit = ovpn_nl_peer_set_doit, .post_doit = ovpn_nl_post_doit, .policy = ovpn_peer_set_nl_policy, - .maxattr = OVPN_A_PEER, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { @@ -204,14 +213,14 @@ static const struct genl_split_ops ovpn_nl_ops[] = { .doit = ovpn_nl_peer_get_doit, .post_doit = ovpn_nl_post_doit, .policy = ovpn_peer_get_do_nl_policy, - .maxattr = OVPN_A_PEER, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { .cmd = OVPN_CMD_PEER_GET, .dumpit = ovpn_nl_peer_get_dumpit, .policy = ovpn_peer_get_dump_nl_policy, - .maxattr = OVPN_A_IFINDEX, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, { @@ -220,7 +229,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = { .doit = ovpn_nl_peer_del_doit, .post_doit = ovpn_nl_post_doit, .policy = ovpn_peer_del_nl_policy, - .maxattr = OVPN_A_PEER, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { @@ -229,7 +238,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = { .doit = ovpn_nl_key_new_doit, .post_doit = ovpn_nl_post_doit, .policy = ovpn_key_new_nl_policy, - .maxattr = OVPN_A_KEYCONF, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { @@ -238,7 +247,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = { .doit = ovpn_nl_key_get_doit, .post_doit = ovpn_nl_post_doit, .policy = ovpn_key_get_nl_policy, - .maxattr = OVPN_A_KEYCONF, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { @@ -247,7 +256,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = { .doit = ovpn_nl_key_swap_doit, .post_doit = ovpn_nl_post_doit, .policy = ovpn_key_swap_nl_policy, - .maxattr = OVPN_A_KEYCONF, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { @@ -256,7 +265,7 @@ static const struct genl_split_ops ovpn_nl_ops[] = { .doit = ovpn_nl_key_del_doit, .post_doit = ovpn_nl_post_doit, .policy = ovpn_key_del_nl_policy, - .maxattr = OVPN_A_KEYCONF, + .maxattr = OVPN_A_TARGET_NETNSID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, }; diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c index 4dad852941982..7a13c056131de 100644 --- a/drivers/net/ovpn/netlink.c +++ b/drivers/net/ovpn/netlink.c @@ -36,21 +36,37 @@ static struct ovpn_priv * ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info, netdevice_tracker *tracker) { + struct net *target_net = NULL; struct ovpn_priv *ovpn; struct net_device *dev; - int ifindex; + int ifindex, target_id; if (GENL_REQ_ATTR_CHECK(info, OVPN_A_IFINDEX)) return ERR_PTR(-EINVAL); ifindex = nla_get_u32(info->attrs[OVPN_A_IFINDEX]); + if (info->attrs[OVPN_A_TARGET_NETNSID]) { + /* Target netns IDs are relative to the requesting Netlink socket */ + target_id = nla_get_s32(info->attrs[OVPN_A_TARGET_NETNSID]); + target_net = get_net_ns_by_id(net, target_id); + if (!target_net) { + NL_SET_ERR_MSG_MOD(info->extack, + "invalid target network namespace ID"); + NL_SET_BAD_ATTR(info->extack, + info->attrs[OVPN_A_TARGET_NETNSID]); + return ERR_PTR(-EINVAL); + } + net = target_net; + } + rcu_read_lock(); dev = dev_get_by_index_rcu(net, ifindex); if (!dev) { rcu_read_unlock(); NL_SET_ERR_MSG_MOD(info->extack, "ifindex does not match any interface"); + put_net(target_net); return ERR_PTR(-ENODEV); } @@ -59,12 +75,14 @@ ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info, NL_SET_ERR_MSG_MOD(info->extack, "specified interface is not ovpn"); NL_SET_BAD_ATTR(info->extack, info->attrs[OVPN_A_IFINDEX]); + put_net(target_net); return ERR_PTR(-EINVAL); } ovpn = netdev_priv(dev); netdev_hold(dev, tracker, GFP_ATOMIC); rcu_read_unlock(); + put_net(target_net); return ovpn; } diff --git a/include/uapi/linux/ovpn.h b/include/uapi/linux/ovpn.h index 06690090a1a95..3fdf24182df43 100644 --- a/include/uapi/linux/ovpn.h +++ b/include/uapi/linux/ovpn.h @@ -85,6 +85,7 @@ enum { OVPN_A_IFINDEX = 1, OVPN_A_PEER, OVPN_A_KEYCONF, + OVPN_A_TARGET_NETNSID, __OVPN_A_MAX, OVPN_A_MAX = (__OVPN_A_MAX - 1) From patchwork Tue Sep 22 08:24:07 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Baffo X-Patchwork-Id: 5396 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:6446:b0:8a0:ea1f:253a with SMTP id n6csp12954872mag; Tue, 22 Sep 2026 01:24:33 -0700 (PDT) X-Forwarded-Encrypted: i=2; AKwUvBx2YCaHCo4sX9S8M3RxKq89P2M5CaKD5HBmLgb8z/V+1p/GaKalUug9hwiw7ChxCU6nvO8rZDyjeKY=@openvpn.net X-Received: by 2002:a4a:edcd:0:b0:6b1:404f:6eb4 with SMTP id 006d021491bc7-6ca9a0270f0mr11223483eaf.9.1790065473682; Tue, 22 Sep 2026 01:24:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1790065473; cv=none; d=google.com; s=arc-20260327; b=KWbAlM2iZhHHV4UWIsVOx65ybB4MN77AArMtqW9TeIGIZ5PmRlNKPwesS78zLHPQ/f 41A1387OQzGiplcRoZQQB97GdFftjyyMUDsuKdVWvh5/U4Dd5yPK2lnn35AIg0MvlUx7 DisHKUCIELb+lE/y/u2Py5pX5Pq6W0rOrvx8b1hxvetanJEpYDt5m2hpzdk5YD4go4b8 r1cXhq3jBm+8wxgdONriJeOxCIvbAit0vUHq4HdZWpEgNqjl+MsKDcdIidMQhtT4EhIx Kp5UuTBsYzRtxQ8tHHuEL5boXMBHMA2Xx/OhxNXTuHwSyYJCzIMbstKTgfZ2wXfxfH1a N4Jw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=errors-to:content-transfer-encoding:cc: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:dkim-signature; bh=yGqUSdPLH/TNO9CRzAxW+VsKsNSUQdRRqd4i4FFP5Og=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=eaHcpsu0+OPpcgN6zKJ1pYk2n+fC5jA0sZs3PtjskEblcoA+tC8BYsFxDCke90tMD3 n7CE9bfeS8W1jZZDPUFlfSFNpsZCtfq0DMKVg8qwdtWf6LDNrzgUPAWtTaDgogbzt+Z3 2HcLwHqLmFSaNQ46zhW1unLFYiHXNh6jT8ziiKGNwWCAbLXTMKhgpgZxv48j9y6zdthm qKKP3AxXbJjN+QPNtC5eybHfOYabQhZ7RUSQyN3S4T9ms5y29W7wy+mC9+7t3tyHWiqv pBsLEkZlZpB+3ciD3IJt/F4MFawggNAkap08onyOTND2g9oavpHm1us08OE83VH//mVa 80kw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=aCS7QwUj; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=lTFbbbC9; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="hE11g/L6"; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b="M/97voqQ"; 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 Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-48fbf4b289dsi944321fac.194.2026.09.22.01.24.33 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Sep 2026 01:24: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=pass header.i=@lists.sourceforge.net header.s=beta header.b=aCS7QwUj; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=lTFbbbC9; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="hE11g/L6"; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b="M/97voqQ"; 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 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:Cc: 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:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=yGqUSdPLH/TNO9CRzAxW+VsKsNSUQdRRqd4i4FFP5Og=; b=aCS7QwUjlui1482McBR9hkmN3i xmMVuo9EmsN6WoAzElxQplKxOpFzsMpTt2ZELjNrFuWqJZgKEivEgvDEaQoIAABB3mu3Y3WuW3krl MSD5LSrBECpy0v1oQo0qUXXonRxvKUQqDg6Cpbij2mPQcpuK+KEMCd9IOKgo4tuVwFjo=; Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1x8vnl-0002Ul-Cn; Tue, 22 Sep 2026 08:24:30 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1x8vne-0002T2-53 for openvpn-devel@lists.sourceforge.net; Tue, 22 Sep 2026 08:24:23 +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:Cc:To:From:Sender:Reply-To: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=QBpPCXVbZfbngu0Y7PsZ0werro+77CozEA8OSF+q+Yw=; b=lTFbbbC9X8OpxPeYoPAEolMZUi mr+sDDe/NbWKlGw4kSpbbXn18soebqsUDkZYp6uNtGLhdzcNNN8VZIsKI7xmmV/TwsEQ11EEH04nW 30cO7LsFJhfooJasG5EPYi3N/Xrn9syZ+4PJxlFcTjmnK+PcjiNhPxu26FXhGZDNaZjg=; 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:Cc:To:From:Sender:Reply-To: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=QBpPCXVbZfbngu0Y7PsZ0werro+77CozEA8OSF+q+Yw=; b=hE11g/L6knMZNckE9BMmqfe0di E+bUsCDBfrU0ApH+ttA03v8u91b/dnqbZxxocWp0q7r3aDix38jfKpywd9huvA4eFN5mpSPp+WJzp nARuDSY5VbWrBW3xxUB/7sPvJXB16DBMDQ+uIJvj5Iv77xGaFq3qIA0kyUEmTSPvduz0=; Received: from mout-b-203.mailbox.org ([195.10.208.52]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1x8vnb-0005Sp-0k for openvpn-devel@lists.sourceforge.net; Tue, 22 Sep 2026 08:24:23 +0000 Received: from smtp102.mailbox.org (smtp102.mailbox.org [IPv6:2001:67c:2050:b231:465::102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-b-203.mailbox.org (Postfix) with ESMTPS id 4hptRg4wrJzLmJm; Tue, 22 Sep 2026 10:24:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1790065455; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QBpPCXVbZfbngu0Y7PsZ0werro+77CozEA8OSF+q+Yw=; b=M/97voqQmC0llxPLTl7k5Wvzw1lLWDBukHLZSqLFFyFB6VJummWKuvdPwAArhhmUMsrLAN vKact8P7ui2XXzK3uvCZDuQurIr2r+CQL2DfbC4gFGgo8gSEda0SmwM0vjkSnfFGTPulBd CaGg5FHCjMinfg9Ee1/Nmgt80h5wLQtjNWALFceuBsvHuqXYVj+u/aqO/Fo8X20gEGvwBb 0uUjYykQ9d8XrzBbmZWEgNE7iHcb4v38i5uvuKDYArxNWy8Qm2qZ7wzBcVWU+P4l2YHOQH hzeHIPiQzZ98c05rYnj8jicS+7S6SlcTA8qjTuie3U2Fmp7WH3cf62fJ8gW7qg== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of marco@mandelbit.com designates 2001:67c:2050:b231:465::102 as permitted sender) smtp.mailfrom=marco@mandelbit.com From: Marco Baffo To: openvpn-devel@lists.sourceforge.net Date: Tue, 22 Sep 2026 10:24:07 +0200 Message-ID: <20260922082408.2930734-2-marco@mandelbit.com> In-Reply-To: <20260922082408.2930734-1-marco@mandelbit.com> References: <20260922082408.2930734-1-marco@mandelbit.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4hptRg4wrJzLmJm X-Spam-Score: -0.2 (/) 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: vpn notifications are multicast in the network namespace of the peer transport socket, but carry an ifindex that is only meaningful in the ovpn device namespace. If the two namespaces differ, listener [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -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 X-Headers-End: 1x8vnb-0005Sp-0k Subject: [Openvpn-devel] [RFC ovpn net-next v5 2/3] ovpn: send notifications in the device netns 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: , Cc: Antonio Quartulli Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: 1877019694062351523 X-GMAIL-MSGID: 1877019694062351523 vpn notifications are multicast in the network namespace of the peer transport socket, but carry an ifindex that is only meaningful in the ovpn device namespace. If the two namespaces differ, listeners resolve it to an unrelated interface, as ifindexes are numbered per netns. Multicast notifications in the device namespace instead. This also avoids depending on the transport socket when sending a notification. Fixes: 89d3c0e4612a ("ovpn: kill key and notify userspace in case of IV exhaustion") Fixes: a215d253c17a ("ovpn: notify userspace when a peer is deleted") Fixes: c841b676da98 ("ovpn: notify userspace on client float event") Signed-off-by: Marco Baffo --- Changes in v5: - None Changes in v4: - Instead of adding the netns id in the noify message we just send the message in the ovpn netns. Changes in v3: - Removed changes in the ovpn.yaml . - Changed peernet2id_alloc() to peernet2id() to avoid potential deadlock when the notication is send from softirq context (peer-float, key-swap). Changes in v2: - This is a new patch. drivers/net/ovpn/netlink.c | 44 +++++--------------------------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c index 7a13c056131de..f6758b16b26ae 100644 --- a/drivers/net/ovpn/netlink.c +++ b/drivers/net/ovpn/netlink.c @@ -1182,7 +1182,6 @@ int ovpn_nl_key_del_doit(struct sk_buff *skb, struct genl_info *info) */ int ovpn_nl_peer_del_notify(struct ovpn_peer *peer) { - struct ovpn_socket *sock; struct sk_buff *msg; struct nlattr *attr; int ret = -EMSGSIZE; @@ -1215,23 +1214,12 @@ int ovpn_nl_peer_del_notify(struct ovpn_peer *peer) goto err_cancel_msg; nla_nest_end(msg, attr); - genlmsg_end(msg, hdr); - - rcu_read_lock(); - sock = rcu_dereference(peer->sock); - if (!sock) { - ret = -EINVAL; - goto err_unlock; - } - genlmsg_multicast_netns(&ovpn_nl_family, sock_net(sock->sk), msg, 0, - OVPN_NLGRP_PEERS, GFP_ATOMIC); - rcu_read_unlock(); + genlmsg_multicast_netns(&ovpn_nl_family, dev_net(peer->ovpn->dev), msg, + 0, OVPN_NLGRP_PEERS, GFP_ATOMIC); return 0; -err_unlock: - rcu_read_unlock(); err_cancel_msg: genlmsg_cancel(msg, hdr); err_free_msg: @@ -1249,7 +1237,6 @@ int ovpn_nl_peer_del_notify(struct ovpn_peer *peer) int ovpn_nl_peer_float_notify(struct ovpn_peer *peer, const struct sockaddr_storage *ss) { - struct ovpn_socket *sock; struct sockaddr_in6 *sa6; struct sockaddr_in *sa; struct sk_buff *msg; @@ -1299,21 +1286,11 @@ int ovpn_nl_peer_float_notify(struct ovpn_peer *peer, nla_nest_end(msg, attr); genlmsg_end(msg, hdr); - - rcu_read_lock(); - sock = rcu_dereference(peer->sock); - if (!sock) { - ret = -EINVAL; - goto err_unlock; - } - genlmsg_multicast_netns(&ovpn_nl_family, sock_net(sock->sk), msg, + genlmsg_multicast_netns(&ovpn_nl_family, dev_net(peer->ovpn->dev), msg, 0, OVPN_NLGRP_PEERS, GFP_ATOMIC); - rcu_read_unlock(); return 0; -err_unlock: - rcu_read_unlock(); err_cancel_msg: genlmsg_cancel(msg, hdr); err_free_msg: @@ -1330,7 +1307,6 @@ int ovpn_nl_peer_float_notify(struct ovpn_peer *peer, */ int ovpn_nl_key_swap_notify(struct ovpn_peer *peer, u8 key_id) { - struct ovpn_socket *sock; struct nlattr *k_attr; struct sk_buff *msg; int ret = -EMSGSIZE; @@ -1364,20 +1340,10 @@ int ovpn_nl_key_swap_notify(struct ovpn_peer *peer, u8 key_id) nla_nest_end(msg, k_attr); genlmsg_end(msg, hdr); - - rcu_read_lock(); - sock = rcu_dereference(peer->sock); - if (!sock) { - ret = -EINVAL; - goto err_unlock; - } - genlmsg_multicast_netns(&ovpn_nl_family, sock_net(sock->sk), msg, 0, - OVPN_NLGRP_PEERS, GFP_ATOMIC); - rcu_read_unlock(); + genlmsg_multicast_netns(&ovpn_nl_family, dev_net(peer->ovpn->dev), msg, + 0, OVPN_NLGRP_PEERS, GFP_ATOMIC); return 0; -err_unlock: - rcu_read_unlock(); err_cancel_msg: genlmsg_cancel(msg, hdr); err_free_msg: From patchwork Tue Sep 22 08:24:08 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Baffo X-Patchwork-Id: 5397 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:6446:b0:8a0:ea1f:253a with SMTP id n6csp12955124mag; Tue, 22 Sep 2026 01:24:57 -0700 (PDT) X-Forwarded-Encrypted: i=2; AKwUvBxo4n3tB4PrOwjZcARKCVPU33xRk4qVhaqf2aa3zubkaHnMPf/vMX1xE2kp9y1o6NLAK6YTZfzSTUY=@openvpn.net X-Received: by 2002:a05:6808:1709:b0:4b9:e65b:8c29 with SMTP id 5614622812f47-4ccf79cbaf5mr11723817b6e.23.1790065497583; Tue, 22 Sep 2026 01:24:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1790065497; cv=none; d=google.com; s=arc-20260327; b=cF7A+h9p6Fk1QCayaZsguHsHVSfEi41MyvzvOSzXcs1FOWe6N2jdY7i24RJ37Ge1ba pvlgWVXDe7HfvhOn8zPM0J09Oz0elqHXGYpsyY38JG7mXwRHe/m2DKXVC9rlcMqAEXmB ozzGcKejqaNkE1TffvdvNHF1O4dU3SMPrlQU+v3tlr3jNS9NBHnaoyhXzTLltg0VQ9wG Yxaa/W+TRy5W5pp2I0Rbw4YKjOClPXHQu8WmAY7+uSHiAY29f8Gq52VYNDUKtRWWSR9A eOVpHJcFnPR+vqfw5z/7ngxZC1fzecDWw748jTLcuYIF14QcpgZ7dKlhcfX1tPKPRMSb H/5g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=errors-to:content-transfer-encoding:cc: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:dkim-signature; bh=y7wbpeDecjL2TyzNqond51bP9ROr4S4QigKvojQAmW8=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=ANInekbHRSh6pWZNH5iQ2oYgzSLcwW0xw/on+zsLav9DJKKV8qgWPTBs5TlYme4xbF vPDc1hJA7mUDmxftzocXSQjH2WtUQh19x3oUp079pWWQDB28ag2Jy9z4RkV/llHhsc3j Zthoz0mtz3EPS4Bb8x4EIXBixcCD3oZA7CMEW3x3rI/7sYYMn29iygV1ajFXpvlSBpk9 A6bhaxZhfOfo7Tog6vi6Yss+4ihfBzL0FQCMtTGCzcSKrZIsV7AvZJjGaWw3+yZwQcbb CX0sSjK7rHDqY82g4dlfjfpA+btfTJn/Mx7rgGygb3dsylDYtM6D8pWxYtw9m0jeyTmP tQng==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=jwUQYear; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=WcOq3Kxg; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=N173TgMo; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=kZLB9PPl; 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 Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 5614622812f47-4d4c2f06459si1281508b6e.93.2026.09.22.01.24.57 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Sep 2026 01:24:57 -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=pass header.i=@lists.sourceforge.net header.s=beta header.b=jwUQYear; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=WcOq3Kxg; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=N173TgMo; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=kZLB9PPl; 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 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:Cc: 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:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=y7wbpeDecjL2TyzNqond51bP9ROr4S4QigKvojQAmW8=; b=jwUQYearx5Khq3UFcwpL7zYAr4 A1pMTxAbtnsqJrZhoeFOaDw60zQKs694aYPaxEjIPQZT7UKwAQkpX4FuZ2ODmS37Cj6Bm0M/RSqs+ Mx1Ql3NpktiSs3plsSTiBWF6oUqkZjwJWVHnWPYYX8ca6b9MrREMjZylBkltI6vH1sZY=; 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 1x8vo6-0003gc-6V; Tue, 22 Sep 2026 08:24:54 +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 1x8vns-0003gI-3C for openvpn-devel@lists.sourceforge.net; Tue, 22 Sep 2026 08:24:40 +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:Cc:To:From:Sender:Reply-To: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=VQpbY7TSDOqrRVDiHbP7BZy+WGL1XVvigUo1LgDBb0g=; b=WcOq3Kxg4Ofo8h9AqycZLRmqk8 5vu6tj2WobmdglQfBFH4HV00mqwhVm5HeFe29jLtzQgSfki2QHAjQONyEBAIYUojsF6mgbv/kU+BS /uvDtuRBL4xKHXUaX2xgB6F+xs1dUo5lJbzLRI/EQuHE/n5mKifV5Nyf48WqmgCkt1IM=; 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:Cc:To:From:Sender:Reply-To: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=VQpbY7TSDOqrRVDiHbP7BZy+WGL1XVvigUo1LgDBb0g=; b=N173TgMoyuIyzmGlLbaU1F157K VOCsMH2qBhtUJ3L9MxeEk3i5Kk4R7VUS+va4gelBoRWA6Augrd7ZLG5dgMHBM+/Xfz53N4OLY++Bg ECfv6Je+O+jz+th5MqVaqIe609QIgRTcAKYwExkZ6kUThzvMKrpdhLW+VmCyn167yV4s=; Received: from mout-b-106.mailbox.org ([195.10.208.46]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1x8vne-0001iw-TH for openvpn-devel@lists.sourceforge.net; Tue, 22 Sep 2026 08:24:31 +0000 Received: from smtp102.mailbox.org (smtp102.mailbox.org [IPv6:2001:67c:2050:b231:465::102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-b-106.mailbox.org (Postfix) with ESMTPS id 4hptRl0CGzzNlqt; Tue, 22 Sep 2026 10:24:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1790065459; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VQpbY7TSDOqrRVDiHbP7BZy+WGL1XVvigUo1LgDBb0g=; b=kZLB9PPlveFecT/MKOWa7CETNRaNmJ7uzoAZ2wdzQrEpFfBvccAtfSHrlT00mXff3qerWj BUTlMdFF6jTByoesK0Dc6oPm8YOmU12NpnUpk0B07pnuyyPuqdMOpbPYA7hzJ4JIAY0PdQ 42YDmu3D2/OjRx7z6rZkO5JLDFHWjduTf16R+abLH/RvleRmhinopncX7YyzTM5Coz7isp Zo4USq9xUTVpOo2xksc8wP/ZNeu2ULG19DPxUJq0IJZzEqMspJrVBRrtgX9vEmLNXh2NCv e1trjWlORc6vVwS6vy+YZx4LiGRJ5n3Pvy9gPWwAD+DOzMtSlCUAin/KUYyCiA== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of marco@mandelbit.com designates 2001:67c:2050:b231:465::102 as permitted sender) smtp.mailfrom=marco@mandelbit.com From: Marco Baffo To: openvpn-devel@lists.sourceforge.net Date: Tue, 22 Sep 2026 10:24:08 +0200 Message-ID: <20260922082408.2930734-3-marco@mandelbit.com> In-Reply-To: <20260922082408.2930734-1-marco@mandelbit.com> References: <20260922082408.2930734-1-marco@mandelbit.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4hptRl0CGzzNlqt X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-1.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: Extend ovpn-cli with -n to resolve an interface in a named network namespace and include OVPN_A_TARGET_NETNSID in peer and key requests. Use -n for existing peer and key operations that do not create transport sockets, exercising foreign-netns requests throughout the test suite. Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -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 X-Headers-End: 1x8vne-0001iw-TH Subject: [Openvpn-devel] [RFC ovpn net-next v5 3/3] selftests: ovpn: test operations in a foreign netns 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: , Cc: Antonio Quartulli Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: 1877019718694939120 X-GMAIL-MSGID: 1877019718694939120 Extend ovpn-cli with -n to resolve an interface in a named network namespace and include OVPN_A_TARGET_NETNSID in peer and key requests. Use -n for existing peer and key operations that do not create transport sockets, exercising foreign-netns requests throughout the test suite. Signed-off-by: Marco Baffo --- Changes in v5: - Fix RCT in ovpn-cli.c Changese in v4: - None. Changes in v3: - None. Changes in v2: - Used "ovpn-cli -n" instead of "ip netns exec ovpn-cli" where possible. - Removed additional tests since we modified the existing ones to exercise the new code path. tools/testing/selftests/net/ovpn/common.sh | 8 +- tools/testing/selftests/net/ovpn/ovpn-cli.c | 265 +++++++++++++++++- .../selftests/net/ovpn/test-close-socket.sh | 4 +- tools/testing/selftests/net/ovpn/test-mark.sh | 6 +- tools/testing/selftests/net/ovpn/test.sh | 50 ++-- 5 files changed, 288 insertions(+), 45 deletions(-) diff --git a/tools/testing/selftests/net/ovpn/common.sh b/tools/testing/selftests/net/ovpn/common.sh index 2d844eb3aa6e3..4f2510fb6d7f7 100644 --- a/tools/testing/selftests/net/ovpn/common.sh +++ b/tools/testing/selftests/net/ovpn/common.sh @@ -221,7 +221,7 @@ ovpn_add_peer() { ${OVPN_UDP_PEERS_FILE} for p in $(seq 1 ${OVPN_NUM_PEERS}); do - ip netns exec "${server_ns}" ${OVPN_CLI} \ + "${OVPN_CLI}" -n "${server_ns}" \ new_key tun0 ${p} 1 0 ${OVPN_ALG} 0 \ data64.key done @@ -244,7 +244,7 @@ ovpn_add_peer() { ip netns exec "${peer_ns}" ${OVPN_CLI} new_peer \ tun${1} ${PEER_ID} ${TX_ID} ${LPORT} ${RADDR} \ ${RPORT} - ip netns exec "${peer_ns}" ${OVPN_CLI} new_key tun${1} \ + "${OVPN_CLI}" -n "${peer_ns}" new_key tun${1} \ ${PEER_ID} 1 0 ${OVPN_ALG} 1 data64.key fi else @@ -252,8 +252,8 @@ ovpn_add_peer() { (ip netns exec "${server_ns}" ${OVPN_CLI} listen tun0 \ 1 ${M_ID} ${OVPN_TCP_PEERS_FILE} && { for p in $(seq 1 ${OVPN_NUM_PEERS}); do - ip netns exec "${server_ns}" \ - ${OVPN_CLI} new_key tun0 ${p} \ + "${OVPN_CLI}" -n "${server_ns}" \ + new_key tun0 ${p} \ 1 0 ${OVPN_ALG} 0 data64.key done }) & diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c b/tools/testing/selftests/net/ovpn/ovpn-cli.c index f4effa7580c0f..a0e4f2f581b59 100644 --- a/tools/testing/selftests/net/ovpn/ovpn-cli.c +++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c @@ -6,6 +6,7 @@ * Author: Antonio Quartulli */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include @@ -121,6 +123,8 @@ struct ovpn_ctx { unsigned int ifindex; char ifname[IFNAMSIZ]; + const char *target_netns_name; + int target_netnsid; enum ovpn_mode mode; bool mode_set; @@ -224,6 +228,10 @@ static struct nl_ctx *nl_ctx_alloc_flags(struct ovpn_ctx *ovpn, int cmd, if (ovpn->ifindex > 0) NLA_PUT_U32(ctx->nl_msg, OVPN_A_IFINDEX, ovpn->ifindex); + if (ovpn->target_netnsid >= 0) + NLA_PUT_S32(ctx->nl_msg, OVPN_A_TARGET_NETNSID, + ovpn->target_netnsid); + return ctx; nla_put_failure: err_msg: @@ -1365,12 +1373,195 @@ static int ovpn_rt_send(struct nlmsghdr *payload, pid_t peer, return ret; } +static int ovpn_parse_netnsid(struct nlmsghdr *msg, void *arg) +{ + struct rtgenmsg *gen; + struct rtattr *attr; + int len; + + if (msg->nlmsg_type != RTM_NEWNSID || + msg->nlmsg_len < NLMSG_LENGTH(sizeof(*gen))) + return -EINVAL; + + gen = NLMSG_DATA(msg); + len = NLMSG_PAYLOAD(msg, sizeof(*gen)); + attr = (struct rtattr *)((char *)gen + NLMSG_ALIGN(sizeof(*gen))); + + for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) { + if (attr->rta_type != NETNSA_NSID) + continue; + + if (RTA_PAYLOAD(attr) < sizeof(int32_t)) + return -EINVAL; + + memcpy(arg, RTA_DATA(attr), sizeof(int32_t)); + return 0; + } + + return -ENOENT; +} + +struct ovpn_netns_req { + struct nlmsghdr n; + struct rtgenmsg g; + char buf[64]; +}; + +static int ovpn_get_netnsid(int netns_fd, int *netnsid) +{ + struct ovpn_netns_req req = { 0 }; + uint32_t fd = netns_fd; + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.g)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_GETNSID; + req.g.rtgen_family = AF_UNSPEC; + + if (ovpn_addattr(&req.n, sizeof(req), NETNSA_FD, &fd, + sizeof(fd)) < 0) + return -EMSGSIZE; + + *netnsid = NETNSA_NSID_NOT_ASSIGNED; + return ovpn_rt_send(&req.n, 0, 0, ovpn_parse_netnsid, netnsid); +} + +static int ovpn_assign_netnsid(int netns_fd) +{ + /* NETNSA_NSID_NOT_ASSIGNED asks the kernel to allocate an NSID. */ + int32_t netnsid = NETNSA_NSID_NOT_ASSIGNED; + struct ovpn_netns_req req = { 0 }; + uint32_t fd = netns_fd; + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.g)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_NEWNSID; + req.g.rtgen_family = AF_UNSPEC; + + if (ovpn_addattr(&req.n, sizeof(req), NETNSA_NSID, &netnsid, + sizeof(netnsid)) < 0 || + ovpn_addattr(&req.n, sizeof(req), NETNSA_FD, &fd, + sizeof(fd)) < 0) + return -EMSGSIZE; + + return ovpn_rt_send(&req.n, 0, 0, NULL, NULL); +} + +/* Get the target NSID relative to the current netns, assigning one if necessary. */ +static int ovpn_get_or_assign_netnsid(int netns_fd) +{ + int netnsid, ret; + + ret = ovpn_get_netnsid(netns_fd, &netnsid); + if (ret < 0) + return ret; + + if (netnsid >= 0) + return netnsid; + + ret = ovpn_assign_netnsid(netns_fd); + if (ret < 0 && ret != -EEXIST) + return ret; + + ret = ovpn_get_netnsid(netns_fd, &netnsid); + if (ret < 0) + return ret; + + if (netnsid < 0) + return -ENOENT; + + return netnsid; +} + +static int ovpn_parse_ifindex(struct nlmsghdr *msg, void *arg) +{ + struct ifinfomsg *ifinfo; + + if (msg->nlmsg_type != RTM_NEWLINK || + msg->nlmsg_len < NLMSG_LENGTH(sizeof(*ifinfo))) + return -EINVAL; + + ifinfo = NLMSG_DATA(msg); + if (ifinfo->ifi_index <= 0) + return -EINVAL; + + *(unsigned int *)arg = ifinfo->ifi_index; + + return 0; +} + struct ovpn_link_req { struct nlmsghdr n; struct ifinfomsg i; char buf[256]; }; +static int ovpn_get_ifindex(int netnsid, const char *ifname, + unsigned int *ifindex) +{ + struct ovpn_link_req req = { 0 }; + int32_t id = netnsid; + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_GETLINK; + req.i.ifi_family = AF_UNSPEC; + + if (ovpn_addattr(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &id, + sizeof(id)) < 0 || + ovpn_addattr(&req.n, sizeof(req), IFLA_IFNAME, ifname, + strlen(ifname) + 1) < 0) + return -EMSGSIZE; + + return ovpn_rt_send(&req.n, 0, 0, ovpn_parse_ifindex, ifindex); +} + +#define NETNS_RUN_DIR "/var/run/netns" + +static int ovpn_resolve_netns(struct ovpn_ctx *ovpn) +{ + int len, target_fd, ret; + char path[PATH_MAX]; + + if (!ovpn->target_netns_name[0] || + strchr(ovpn->target_netns_name, '/')) { + fprintf(stderr, "invalid network namespace name: %s\n", + ovpn->target_netns_name); + return -EINVAL; + } + + len = snprintf(path, sizeof(path), "%s/%s", NETNS_RUN_DIR, + ovpn->target_netns_name); + if (len < 0 || len >= (int)sizeof(path)) + return -ENAMETOOLONG; + + target_fd = open(path, O_RDONLY); + if (target_fd < 0) { + ret = errno; + fprintf(stderr, "cannot open network namespace %s: %s\n", + ovpn->target_netns_name, strerror(ret)); + return -ret; + } + + ovpn->target_netnsid = ovpn_get_or_assign_netnsid(target_fd); + if (ovpn->target_netnsid < 0) { + ret = ovpn->target_netnsid; + fprintf(stderr, "cannot resolve network namespace ID for %s\n", + ovpn->target_netns_name); + goto out; + } + + ret = ovpn_get_ifindex(ovpn->target_netnsid, ovpn->ifname, + &ovpn->ifindex); + if (ret < 0) { + fprintf(stderr, "cannot find interface %s in namespace %s\n", + ovpn->ifname, ovpn->target_netns_name); + } +out: + close(target_fd); + + return ret; +} + static int ovpn_new_iface(struct ovpn_ctx *ovpn) { struct rtattr *linkinfo, *data; @@ -1662,8 +1853,10 @@ static int ovpn_listen_mcast(void) static void usage(const char *cmd) { fprintf(stderr, - "Usage %s [arguments..]\n", + "Usage %s [-n ] [arguments..]\n", cmd); + fprintf(stderr, + "\t-n netns: run peer/key operations on an interface in the named network namespace\n"); fprintf(stderr, "where can be one of the following\n\n"); fprintf(stderr, "* new_iface [mode]: create new ovpn interface\n"); @@ -1968,6 +2161,26 @@ static enum ovpn_cmd ovpn_parse_cmd(const char *cmd) return CMD_INVALID; } +static bool ovpn_cmd_supports_target_netns(enum ovpn_cmd cmd) +{ + switch (cmd) { + case CMD_LISTEN: + case CMD_CONNECT: + case CMD_NEW_PEER: + case CMD_NEW_MULTI_PEER: + case CMD_SET_PEER: + case CMD_DEL_PEER: + case CMD_GET_PEER: + case CMD_NEW_KEY: + case CMD_DEL_KEY: + case CMD_GET_KEY: + case CMD_SWAP_KEYS: + return true; + default: + return false; + } +} + /* Send process to background and waits for signal. * * This helper is called at the end of commands @@ -2023,6 +2236,7 @@ static int ovpn_run_cmd(struct ovpn_ctx *ovpn) } peer_ctx.ifindex = ovpn->ifindex; + peer_ctx.target_netnsid = ovpn->target_netnsid; peer_ctx.sa_family = ovpn->sa_family; peer_ctx.asymm_id = ovpn->asymm_id; @@ -2109,6 +2323,7 @@ static int ovpn_run_cmd(struct ovpn_ctx *ovpn) struct ovpn_ctx peer_ctx = { 0 }; peer_ctx.ifindex = ovpn->ifindex; + peer_ctx.target_netnsid = ovpn->target_netnsid; peer_ctx.socket = ovpn->socket; peer_ctx.sa_family = AF_UNSPEC; peer_ctx.asymm_id = ovpn->asymm_id; @@ -2181,13 +2396,19 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[]) strscpy(ovpn->ifname, argv[2], IFNAMSIZ - 1); ovpn->ifname[IFNAMSIZ - 1] = '\0'; - /* all commands, except NEW_IFNAME, needs an ifindex */ + /* all commands, except NEW_IFACE, need an ifindex */ if (ovpn->cmd != CMD_NEW_IFACE) { - ovpn->ifindex = if_nametoindex(ovpn->ifname); - if (!ovpn->ifindex) { - fprintf(stderr, "cannot find interface: %s\n", - strerror(errno)); - return -1; + if (ovpn->target_netns_name) { + ret = ovpn_resolve_netns(ovpn); + if (ret < 0) + return ret; + } else { + ovpn->ifindex = if_nametoindex(ovpn->ifname); + if (!ovpn->ifindex) { + fprintf(stderr, "cannot find interface: %s\n", + strerror(errno)); + return -1; + } } } @@ -2433,30 +2654,52 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[]) int main(int argc, char *argv[]) { + const char *program = argv[0]; struct ovpn_ctx ovpn; int ret; + memset(&ovpn, 0, sizeof(ovpn)); + if (argc > 1 && !strcmp(argv[1], "-n")) { + if (argc < 4) { + fprintf(stderr, + "Error: -n requires a namespace and a command.\n\n"); + usage(program); + return -EINVAL; + } + + ovpn.target_netns_name = argv[2]; + argc -= 2; + argv += 2; + } + if (argc < 2) { - usage(argv[0]); + usage(program); return -1; } - memset(&ovpn, 0, sizeof(ovpn)); + ovpn.target_netnsid = NETNSA_NSID_NOT_ASSIGNED; ovpn.sa_family = AF_UNSPEC; ovpn.cipher = OVPN_CIPHER_ALG_NONE; ovpn.cmd = ovpn_parse_cmd(argv[1]); if (ovpn.cmd == CMD_INVALID) { fprintf(stderr, "Error: unknown command.\n\n"); - usage(argv[0]); + usage(program); return -1; } + if (ovpn.target_netns_name && + !ovpn_cmd_supports_target_netns(ovpn.cmd)) { + fprintf(stderr, "Error: -n is not supported for command %s.\n", + argv[1]); + return -EOPNOTSUPP; + } + ret = ovpn_parse_cmd_args(&ovpn, argc, argv); if (ret < 0) { fprintf(stderr, "Error: invalid arguments.\n\n"); if (ret == -EINVAL) - usage(argv[0]); + usage(program); return ret; } diff --git a/tools/testing/selftests/net/ovpn/test-close-socket.sh b/tools/testing/selftests/net/ovpn/test-close-socket.sh index ec9a51bbf3c92..0e4e33b2973fd 100755 --- a/tools/testing/selftests/net/ovpn/test-close-socket.sh +++ b/tools/testing/selftests/net/ovpn/test-close-socket.sh @@ -40,10 +40,10 @@ ovpn_prepare_network() { for p in $(seq 1 ${OVPN_NUM_PEERS}); do peer_ns="ovpn_peer${p}" ovpn_cmd_ok "set peer0 timeout for peer ${p}" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 \ + "${OVPN_CLI}" -n ovpn_peer0 set_peer tun0 \ ${p} 60 120 ovpn_cmd_ok "set peer${p} timeout for peer ${p}" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \ + "${OVPN_CLI}" -n "${peer_ns}" set_peer \ tun${p} $((p + OVPN_ID_OFFSET)) 60 120 done } diff --git a/tools/testing/selftests/net/ovpn/test-mark.sh b/tools/testing/selftests/net/ovpn/test-mark.sh index 7c1d56e9c525d..8a9ca52f86be1 100755 --- a/tools/testing/selftests/net/ovpn/test-mark.sh +++ b/tools/testing/selftests/net/ovpn/test-mark.sh @@ -42,7 +42,7 @@ ovpn_mark_prepare_network() { ASYMM "${OVPN_UDP_PEERS_FILE}" "${MARK}" for p in $(seq 1 3); do ovpn_cmd_ok "install server key for peer ${p}" \ - ip netns exec ovpn_peer0 "${OVPN_CLI}" new_key tun0 \ + "${OVPN_CLI}" -n ovpn_peer0 new_key tun0 \ "${p}" 1 0 "${OVPN_ALG}" 0 data64.key done @@ -53,10 +53,10 @@ ovpn_mark_prepare_network() { for p in $(seq 1 3); do peer_ns="ovpn_peer${p}" ovpn_cmd_ok "set peer0 timeout for peer ${p}" \ - ip netns exec ovpn_peer0 "${OVPN_CLI}" set_peer tun0 \ + "${OVPN_CLI}" -n ovpn_peer0 set_peer tun0 \ "${p}" 60 120 ovpn_cmd_ok "set peer${p} timeout for peer ${p}" \ - ip netns exec "${peer_ns}" "${OVPN_CLI}" set_peer \ + "${OVPN_CLI}" -n "${peer_ns}" set_peer \ tun"${p}" $((p + OVPN_ID_OFFSET)) 60 120 done } diff --git a/tools/testing/selftests/net/ovpn/test.sh b/tools/testing/selftests/net/ovpn/test.sh index 9b5610837032f..468dd7985c8f2 100755 --- a/tools/testing/selftests/net/ovpn/test.sh +++ b/tools/testing/selftests/net/ovpn/test.sh @@ -48,10 +48,10 @@ ovpn_prepare_network() { for p in $(seq 1 ${OVPN_NUM_PEERS}); do peer_ns="ovpn_peer${p}" ovpn_cmd_ok "set peer0 timeout for peer ${p}" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 \ + "${OVPN_CLI}" -n ovpn_peer0 set_peer tun0 \ ${p} 60 120 ovpn_cmd_ok "set peer${p} timeout for peer ${p}" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \ + "${OVPN_CLI}" -n "${peer_ns}" set_peer \ tun${p} $((p + OVPN_ID_OFFSET)) 60 120 done } @@ -151,14 +151,14 @@ ovpn_run_key_rollover() { for p in $(seq 1 ${OVPN_NUM_PEERS}); do peer_ns="ovpn_peer${p}" ovpn_cmd_ok "add secondary key on peer0 for peer ${p}" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} new_key tun0 \ + "${OVPN_CLI}" -n ovpn_peer0 new_key tun0 \ ${p} 2 1 ${OVPN_ALG} 0 data64.key ovpn_cmd_ok "add secondary key on peer${p} for peer ${p}" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} new_key tun${p} \ + "${OVPN_CLI}" -n "${peer_ns}" new_key tun${p} \ $((p + OVPN_ID_OFFSET)) 2 1 ${OVPN_ALG} 1 \ data64.key ovpn_cmd_ok "swap keys on peer${p}" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} swap_keys \ + "${OVPN_CLI}" -n "${peer_ns}" swap_keys \ tun${p} $((p + OVPN_ID_OFFSET)) done } @@ -166,22 +166,22 @@ ovpn_run_key_rollover() { ovpn_run_queries() { ovpn_log "Querying all peers:" - ovpn_cmd_ok "query all peers from peer0" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} get_peer tun0 - ovpn_cmd_ok "query all peers from peer1" \ - ip netns exec ovpn_peer1 ${OVPN_CLI} get_peer tun1 + ovpn_cmd_ok "query all peers on peer0" \ + "${OVPN_CLI}" -n ovpn_peer0 get_peer tun0 + ovpn_cmd_ok "query all peers on peer1" \ + "${OVPN_CLI}" -n ovpn_peer1 get_peer tun1 ovpn_log "Querying peer 1:" - ovpn_cmd_ok "query peer 1 from peer0" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} get_peer tun0 1 + ovpn_cmd_ok "query peer 1 on peer0" \ + "${OVPN_CLI}" -n ovpn_peer0 get_peer tun0 1 } ovpn_query_peer_missing() { ovpn_log "Querying non-existent peer 20:" ovpn_cmd_fail "query missing peer 20 on peer0" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} get_peer tun0 20 + "${OVPN_CLI}" -n ovpn_peer0 get_peer tun0 20 } ovpn_run_peer_cleanup() { @@ -191,9 +191,9 @@ ovpn_run_peer_cleanup() { ovpn_log "Deleting peer 1:" ovpn_cmd_ok "delete peer1 on peer0" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} del_peer tun0 1 + "${OVPN_CLI}" -n ovpn_peer0 del_peer tun0 1 ovpn_cmd_ok "delete peer1 on peer1" \ - ip netns exec ovpn_peer1 ${OVPN_CLI} del_peer tun1 \ + "${OVPN_CLI}" -n ovpn_peer1 del_peer tun1 \ $((1 + OVPN_ID_OFFSET)) ovpn_log "Querying keys:" @@ -201,10 +201,10 @@ ovpn_run_peer_cleanup() { for p in $(seq 2 ${OVPN_NUM_PEERS}); do peer_ns="ovpn_peer${p}" ovpn_cmd_ok "query peer${p} key 1" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} get_key tun${p} \ + "${OVPN_CLI}" -n "${peer_ns}" get_key tun${p} \ $((p + OVPN_ID_OFFSET)) 1 ovpn_cmd_ok "query peer${p} key 2" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} get_key tun${p} \ + "${OVPN_CLI}" -n "${peer_ns}" get_key tun${p} \ $((p + OVPN_ID_OFFSET)) 2 done } @@ -217,16 +217,16 @@ ovpn_run_traffic_delete_peer() { ovpn_run_bg ping_pid ip netns exec ovpn_peer2 ping -qf -w 4 5.5.5.1 sleep 2 ovpn_cmd_ok "delete peer0 peer 2" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} del_peer tun0 2 + "${OVPN_CLI}" -n ovpn_peer0 del_peer tun0 2 if [ "${OVPN_PROTO}" == "TCP" ]; then # In TCP mode this command is expected to fail for both peers. ovpn_cmd_mayfail "delete peer2 peer 2 (TCP non-fatal)" \ - ip netns exec ovpn_peer2 ${OVPN_CLI} del_peer tun2 \ + "${OVPN_CLI}" -n ovpn_peer2 del_peer tun2 \ $((2 + OVPN_ID_OFFSET)) else - ovpn_cmd_ok "delete peer2 peer 2" ip netns exec ovpn_peer2 \ - ${OVPN_CLI} del_peer tun2 $((2 + OVPN_ID_OFFSET)) + ovpn_cmd_ok "delete peer2 peer 2" "${OVPN_CLI}" -n ovpn_peer2 \ + del_peer tun2 $((2 + OVPN_ID_OFFSET)) fi wait "${ping_pid}" || true @@ -241,10 +241,10 @@ ovpn_run_key_cleanup() { for p in $(seq 3 ${OVPN_NUM_PEERS}); do peer_ns="ovpn_peer${p}" ovpn_cmd_ok "delete key 1 for peer${p}" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} del_key tun${p} \ + "${OVPN_CLI}" -n "${peer_ns}" del_key tun${p} \ $((p + OVPN_ID_OFFSET)) 1 ovpn_cmd_ok "delete key 2 for peer${p}" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} del_key tun${p} \ + "${OVPN_CLI}" -n "${peer_ns}" del_key tun${p} \ $((p + OVPN_ID_OFFSET)) 2 done } @@ -258,11 +258,11 @@ ovpn_run_timeouts() { for p in $(seq 3 ${OVPN_NUM_PEERS}); do # Non-fatal: this may fail in some protocol modes. ovpn_cmd_mayfail "set peer0 timeout for peer ${p} (non-fatal)" \ - ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 \ + "${OVPN_CLI}" -n ovpn_peer0 set_peer tun0 \ ${p} 3 3 peer_ns="ovpn_peer${p}" ovpn_cmd_ok "disable timeout on peer${p} while peer0 adjusts \ - state" ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \ + state" "${OVPN_CLI}" -n "${peer_ns}" set_peer \ tun${p} $((p + OVPN_ID_OFFSET)) 0 0 done # wait for peers to timeout @@ -273,7 +273,7 @@ ovpn_run_timeouts() { for p in $(seq 3 ${OVPN_NUM_PEERS}); do peer_ns="ovpn_peer${p}" ovpn_cmd_ok "set peer${p} P2P timeout" \ - ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \ + "${OVPN_CLI}" -n "${peer_ns}" set_peer \ tun${p} $((p + OVPN_ID_OFFSET)) 3 3 done sleep 5