From patchwork Thu Aug 6 15:49:46 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Baffo X-Patchwork-Id: 5210 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:77c3:b0:87d:ab56:3700 with SMTP id r3csp7872607mau; Thu, 6 Aug 2026 08:50:14 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+RrlZYXfunYVH/3WuE4asBi+Q6tYIrweFpX56m+URqLr38Hdmd8lM3yX8pSi8QDm+I8OVmHJlWiMiSA=@openvpn.net X-Received: by 2002:a05:6830:3699:b0:7e6:ef1d:4aeb with SMTP id 46e09a7af769-7f1e5f19e54mr10462095a34.15.1786031414405; Thu, 06 Aug 2026 08:50:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1786031414; cv=none; d=google.com; s=arc-20260327; b=CZD92U0V1o/mIu4IfiPCWntwsbTbXiqF6lcptmobyH7FvW0afea1JMekwKB/wyWXbQ 27+ma9RkMWc38ztp4fwkSHt1ACg6NHBxFPZshSsAg9e6BAMK52Vr81lbbl6Z83PFxb2S iosdkt1ASFsFUaHYjNS0gon/MCY85SpvGnyObNKUqaianEn77Og9DREwYW/beqFtGZl9 I/7MFTMSwFRBqoj58krq4MVhACJ7+5NY5o0eVhIAk0Tj3maF7bDgGiEbUzh2NUOmtHhV uFXPLuXcaJeocNDS6aHPZx9bDxAWJKBSe8tT/3t92+nN1TAtBc+bPoqr4ZvUppyUCj7l qG8Q== 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=tWIaJvSyV7Y2hC+53AOK7HPAsabFjylI0JVjkZ+ImYs=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=HAMRfNTCl5aiLG3eQkFHdc6sUNwK8syJdIogu+l9wi3qR3pyB3LKwRUphZcoww3VHs iAqjL/1U2RK71BsvabO+MCwi4+HeHGAY1zxC1YxvE3Fjv7FxjCKTfCePwqh0tioeZoBv maIrgAa7RdvA0U8WgZX/M22TmmEdmpYiw9d9ZSUlq3ssfPJNja7sDnkQKGzjmfW3Yb8t jysC2UvajKJhsgTCl/RNeFh2rZp4uAW24nwcB5nZ+1WOoGG/BcPU8gWxYVZCehoolwpU XsPipVqzavHFUupgmvhkuscwKi8ZC+/EEEkvTpPFWlFFatmuQf6ZVLavjy5AkEUxwlkz dNGA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=bE10DuLn; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=nNQSxUmw; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=IgZY0KAz; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=JYhqHfRZ; 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 46e09a7af769-7f1df61ee18si6751873a34.65.2026.08.06.08.50.14 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Aug 2026 08:50:14 -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=bE10DuLn; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=nNQSxUmw; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=IgZY0KAz; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=JYhqHfRZ; 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=tWIaJvSyV7Y2hC+53AOK7HPAsabFjylI0JVjkZ+ImYs=; b=bE10DuLn+GSNQbIJxw1hTmEuF0 ZosS6g7HGYtvduAIO4b0Zl3R4FuigPR8IN//I9723lvysAMQEnbe/VQiNV4wZN1KM6VFCkDAxyzB9 RDFzxswQOQvBBdGz5aZ10b1vVRUHK4LuGErgjnyjyzc9yJtVjXOE3wMFaUOyjbaKuhGA=; 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 1ws0MF-0002aH-Qe; Thu, 06 Aug 2026 15:50:09 +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 1ws0ME-0002a8-7D for openvpn-devel@lists.sourceforge.net; Thu, 06 Aug 2026 15:50:08 +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=ZyBW172czuNgR/f96Ry//N6ejpifvf3uq2YuXbV+yNg=; b=nNQSxUmwVEjq3ynEIPBXSEPXBl e1BDJLF+d2kip2pxNRjucuwlIeTaf8OGPpIFQ2/zcB/swjnCoE3eLJXrGPL6LHUcU+intmOonacfy iRskLA9zCNKZW6bibBrSGhIfma2gcf/q7Qcj9UlAFAX8G/4hBP31Yc56ewwxLVzohf5M=; 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=ZyBW172czuNgR/f96Ry//N6ejpifvf3uq2YuXbV+yNg=; b=I gZY0KAz8dk5IlH7Y5A4CBZz66JzdALeWFXYBrqDoNWtN+X8/f64/nxYf/gVQu6zJZdiBZUZsZBvrd JIinYKfXoaYiW0HTt47adWh9LasHr1zUXxdJaOo3c//5iQ3JQU4SvfTwbu4bYxtCbDpzoGv9y4mRz ay7u34DPuABXnisQ=; Received: from mout-b-107.mailbox.org ([195.10.208.47]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1ws0MD-00048O-7I for openvpn-devel@lists.sourceforge.net; Thu, 06 Aug 2026 15:50:07 +0000 Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:b231:465::202]) (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-107.mailbox.org (Postfix) with ESMTPS id 4hGBYf1hyHz3y9r; Thu, 06 Aug 2026 17:49:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1786031398; 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=ZyBW172czuNgR/f96Ry//N6ejpifvf3uq2YuXbV+yNg=; b=JYhqHfRZHKFfauShOKsOMrzXEV+e/jZg/gt5XJQCFxRMu1uMb2oK5xTRqtQCFVSXq7uiu4 xV6HNWywwwG4c96K5fWcug9wObL4fKBPtElpaY7/K7lmikeTUoPAUv19aYebb2p8MWzc7n sZ/nAd3N1k5QMDQvUTIew287UX5aJVgSn6nW9Y6xV9c+B6LFuVa5G5t1znQwYDLcphkHwz COLOf664FvSwQPGTL6XQLV4d9JKxT9g1qC1RXcqrSbTrfaenAbwfVKmewLYcndrxYEZAWf zNq4XkRCqXNgWnswIVqPUArAHXnNRMr5huKE2hVTXVVV20kRvU3ksrQ1diQQBw== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of marco@mandelbit.com designates 2001:67c:2050:b231:465::202 as permitted sender) smtp.mailfrom=marco@mandelbit.com From: Marco Baffo To: openvpn-devel@lists.sourceforge.net Date: Thu, 6 Aug 2026 17:49:46 +0200 Message-ID: <20260806154948.795039-1-marco@mandelbit.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4hGBYf1hyHz3y9r 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_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.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-Headers-End: 1ws0MD-00048O-7I Subject: [Openvpn-devel] [PATCH ovpn net-next v4 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: 1872789676679084074 X-GMAIL-MSGID: 1872789676679084074 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 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 | 17 ++++++++++ include/uapi/linux/ovpn.h | 1 + 4 files changed, 72 insertions(+), 18 deletions(-) diff --git a/Documentation/netlink/specs/ovpn.yaml b/Documentation/netlink/specs/ovpn.yaml index b0c782e59a32..1f0d4d6037c0 100644 --- a/Documentation/netlink/specs/ovpn.yaml +++ b/Documentation/netlink/specs/ovpn.yaml @@ -337,12 +337,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 @@ -352,6 +360,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: peer nested-attributes: peer-set-input @@ -361,6 +371,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: peer nested-attributes: peer-del-input @@ -370,6 +382,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: keyconf nested-attributes: keyconf-get @@ -379,6 +393,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: keyconf nested-attributes: keyconf-swap-input @@ -388,6 +404,8 @@ attribute-sets: attributes: - name: ifindex + - + name: target-netnsid - name: keyconf nested-attributes: keyconf-del-input @@ -405,6 +423,7 @@ operations: request: attributes: - ifindex + - target-netnsid - peer - name: peer-set @@ -417,6 +436,7 @@ operations: request: attributes: - ifindex + - target-netnsid - peer - name: peer-get @@ -429,6 +449,7 @@ operations: request: attributes: - ifindex + - target-netnsid - peer reply: attributes: @@ -437,6 +458,7 @@ operations: request: attributes: - ifindex + - target-netnsid reply: attributes: - peer @@ -451,6 +473,7 @@ operations: request: attributes: - ifindex + - target-netnsid - peer - name: peer-del-ntf @@ -469,6 +492,7 @@ operations: request: attributes: - ifindex + - target-netnsid - keyconf - name: key-get @@ -481,6 +505,7 @@ operations: request: attributes: - ifindex + - target-netnsid - keyconf reply: attributes: @@ -496,6 +521,7 @@ operations: request: attributes: - ifindex + - target-netnsid - keyconf - name: key-swap-ntf @@ -515,6 +541,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 2147cec7c2c5..3f513e3675a3 100644 --- a/drivers/net/ovpn/netlink-gen.c +++ b/drivers/net/ovpn/netlink-gen.c @@ -118,55 +118,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), }; @@ -178,7 +187,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, }, { @@ -187,7 +196,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, }, { @@ -196,14 +205,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, }, { @@ -212,7 +221,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, }, { @@ -221,7 +230,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, }, { @@ -230,7 +239,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, }, { @@ -239,7 +248,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, }, { @@ -248,7 +257,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 4c66c1ec497e..b70ecfaf46c8 100644 --- a/drivers/net/ovpn/netlink.c +++ b/drivers/net/ovpn/netlink.c @@ -38,6 +38,7 @@ ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info, { struct ovpn_priv *ovpn; struct net_device *dev; + struct net *target_net = NULL; int ifindex; if (GENL_REQ_ATTR_CHECK(info, OVPN_A_IFINDEX)) @@ -45,12 +46,26 @@ ovpn_get_dev_from_attrs(struct net *net, const struct genl_info *info, 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_net = get_net_ns_by_id(net, nla_get_s32(info->attrs[OVPN_A_TARGET_NETNSID])); + 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 +74,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 06690090a1a9..3fdf24182df4 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 Thu Aug 6 15:49:47 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Baffo X-Patchwork-Id: 5211 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:77c3:b0:87d:ab56:3700 with SMTP id r3csp7873172mau; Thu, 6 Aug 2026 08:50:36 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+Rr7k+r/Bv5kJtatweWXLSo3910OEv+txr1FyvkpE3+CdP8VGlcxRN728xcoWmNiuNPA6puHTub3BIM=@openvpn.net X-Received: by 2002:a05:6808:238d:b0:49b:33c8:4b75 with SMTP id 5614622812f47-4afadf41feemr7691790b6e.5.1786031436737; Thu, 06 Aug 2026 08:50:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1786031436; cv=none; d=google.com; s=arc-20260327; b=eHU7rr3FSPFK6GA+GZPiwUB/ckeHx1xKR98+Y+PseOk+veepj0t3XVrPecKK75dBZW Wsgbw5YgwmRucJnLuV5T7pd0UazZi3ji3f7IkTBFWhx7+9kWncgRhLjr778KG83zHaC2 Z7PnJvFji1fpYeFV7Ohvrer46xX1RJxsTf0vvpceOcnXlS+XrA7SUohbHytm15wPhY+J DbkHELmMAHBixqPie7HJXtyD70Bca7Zb7GFRYyf1NYYUcoAhTXb1diBh9wqmep2qyQP/ V7CrPbn86fVcX3xSODg07K5B0dyJSpBjQlshGIu7Vpaso/XhjyK2vDF7N+tuZM2xfMcB M8gA== 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=nvUqk2WFmsh00QJ8G7PkViEPoqoVQzomdSDhvxME+IY=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=hQiuITFTTTCr5Yo0wsNnakIqoxcF1NcXlKGQ7R+9+fZRonTjzIKAQjo8gmoqGrfFUR LBbmPMDttiH9oM9uj3wHw2S0Lqv6oKc94LbVHH6/EyFQWWtRzFMvwBUYKtBtVPwRyiXz xFrDlkzYYJAt9lAz5OotJGmyKeykkoRr9CTbY9WQ+H3MHnmhxpFywB/8uLvo+VACdw5y Zr2iuKK+Jffhc7nw1blAHRXYimPoBlY5sc+cW72TVH3vIRSq5EAMblhGRfy4KmJpxxvm lZtu4rLz0SaEbC6PICosyZY87svoUMAw4ccIBNbNs3GL8OV1PfKtWo5knSAh3Z9SblMc Jp6g==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=H5Ow7tdn; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="mErBmk8/"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=iP20y2K+; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=F9MVr0V6; 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-4afae5f6a50si5846989b6e.32.2026.08.06.08.50.36 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Aug 2026 08:50:36 -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=H5Ow7tdn; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="mErBmk8/"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=iP20y2K+; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=F9MVr0V6; 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=nvUqk2WFmsh00QJ8G7PkViEPoqoVQzomdSDhvxME+IY=; b=H5Ow7tdnikR7XfWRwZTAeRomwC RLF5EU2EVGeh9RCnbWcQKB1ICMTZLHSQtfeujIG3vob8jPuQnG5yfVNXJNXbAjGs1jHsy9BobgKZv 7UsoSEHKbDsYI/SJ3GcfKVEEAn80R3VoxyH1ncDca2m7XkdS4E8njGJWVz0HwDC1MNaQ=; Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1ws0Mb-0004wG-6A; Thu, 06 Aug 2026 15:50:33 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1ws0MY-0004uz-2V for openvpn-devel@lists.sourceforge.net; Thu, 06 Aug 2026 15:50:30 +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=tFzaBkC8jsDMnxzNL1N90evg2QdF9avvJ5VR2pRTbeU=; b=mErBmk8/KZoJc741E2ZHRwNJ1R bYY2lLYPY0o/n4BX77PkrZqBYM03zNIP5w7Wb6AKgQ3cjEx3GrYe1wk73aD1itRiSP+KcEws3rN7E i2LKyZQtLxgY49t0hV0vqW64LhD+HsNwnde2ISNm5N0dNjgmoFguS+ny0K5xfFW0Uit0=; 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=tFzaBkC8jsDMnxzNL1N90evg2QdF9avvJ5VR2pRTbeU=; b=iP20y2K+q0Nd/9PFlLEUUWUJpX 6EbDGvhZBBa401isqyYisn7PJOud7fVdIlYumUz1BceudECphMyiJCui7I7UO3l5aQYDrtZ35wMk1 wJqVMHrnGtTBtWHBCIA/p/f0vw+KRdR17qrpM2yajpcQEu3oYbSGloRgtuTSM10fhyAc=; 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 1ws0MP-000494-7n for openvpn-devel@lists.sourceforge.net; Thu, 06 Aug 2026 15:50:18 +0000 Received: from smtp202.mailbox.org (smtp202.mailbox.org [10.196.197.202]) (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 4hGBYs1Z4LzNkTf; Thu, 06 Aug 2026 17:50:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1786031409; 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=tFzaBkC8jsDMnxzNL1N90evg2QdF9avvJ5VR2pRTbeU=; b=F9MVr0V6JEmiqy3Rw4+MAzEd5KoAlYxCaO4eKycxrl+ZGh67v5gH9LqdbW4xV2EYnoOVMU us16N/EOBwe8/BCVjdgit7mSvvSgUb7ae3l751j36bY+D3zCXmIWsEKjnNXWbVat0Rfgzc zdT+VXUUihICU2tmSTM4VDIcqrETPtunkn/pQne5ex0gruK2S/ByhRHNkJba+DdQpBy2dX JzdPPjxKBmyTAjeCIeZBzxbplJbCyFPGav1IMqt2gdN1H76rmuv2t0+f4bB0OmSFF642+q N0Pt5C8gzqnRQbDQD5/dSo+XSh0KHApwI1wZGRn05+ut0zyW4Fd/t3AHLMY+pA== From: Marco Baffo To: openvpn-devel@lists.sourceforge.net Date: Thu, 6 Aug 2026 17:49:47 +0200 Message-ID: <20260806154948.795039-2-marco@mandelbit.com> In-Reply-To: <20260806154948.795039-1-marco@mandelbit.com> References: <20260806154948.795039-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-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: 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: 1ws0MP-000494-7n Subject: [Openvpn-devel] [PATCH ovpn net-next v4 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: 1872789699764142524 X-GMAIL-MSGID: 1872789699764142524 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 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 b70ecfaf46c8..97d25788a2a2 100644 --- a/drivers/net/ovpn/netlink.c +++ b/drivers/net/ovpn/netlink.c @@ -1175,7 +1175,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; @@ -1208,23 +1207,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: @@ -1242,7 +1230,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; @@ -1292,21 +1279,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: @@ -1323,7 +1300,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; @@ -1357,20 +1333,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 Thu Aug 6 15:49:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Baffo X-Patchwork-Id: 5212 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:77c3:b0:87d:ab56:3700 with SMTP id r3csp7873183mau; Thu, 6 Aug 2026 08:50:37 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+RpHcBzkeP8k50ZefJaGy3YvioVL1mQcf5fufRB4vL7DYMMP9TV5qeLemOJ5Zssy5GwgnUxJKLx0Y5c=@openvpn.net X-Received: by 2002:a05:6871:79a9:b0:455:d6a6:6fdf with SMTP id 586e51a60fabf-4599f0ef42dmr8372379fac.21.1786031437483; Thu, 06 Aug 2026 08:50:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1786031437; cv=none; d=google.com; s=arc-20260327; b=NMp1ndWZMv1HJJ3mmAgGqZcp1skbjHI+X+bGp/NZhes2tR/4yJUsgPyZ+euE1MFhT6 0H8nYoRhpC3FIUaFSc2DW+IOCqqrKvXSKKkp4iOvScEFj0dJbCBkHod6joL+mALz8Hl6 AV+d3QY036OmomdET1dUcYyA+bsE5XyvcDchvSMeLt6aNejghZnuLc4nVGDDYN7XcFvi OwnfppH8VegMfmOfMKhbPKqQPddTrehoaYC5z29NxiTx4ccbN1SojNLQ8BiQ1qEILSTK lCc4x0iC71q0r2/Li5xod0qgCPD98dX7FS2huCT6perGB36rHmj1JYyudRXpJSm59t3F +dmw== 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=La5RI3x01C6c2UZzxVQam/6uuylRrs9p9w6Q8YqoRKM=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=ofiINKtuN6R52yhXDWiaf3/IGKWHXWxgi2DMP65qFczlUn3mavJh4i5TLmJf500t+3 ylhbuvPRRqbDwO2MqKjASjJj/3GLuiyjH03UdhTMtpq970qmngQO4TteO+jy3+h52GxT MfcV9iTjS6LlxIxtQfIcRsvaNK+q25vEQcJunfRHw8DEKtnmbMbLiDdVfD15yqyBXqs8 Y+4k3ppfjHfKF85dZNHDEQAq8Qet0+ECRwiAgs9j0+TDLkfxa1kiU+Ui5kxibLYXM9jy mlr5QIDBi3FvoyqdXiqqUm6CILtzPmP2beguAhBcCHLvW6jEgpnbDY/673QAdaKjZ9Zc nJMQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=lZwbj4jz; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=lWXkIouY; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=jQIHV2wj; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b="OZb/KtrK"; 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-4599e247738si3390302fac.104.2026.08.06.08.50.37 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Aug 2026 08:50:37 -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=lZwbj4jz; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=lWXkIouY; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=jQIHV2wj; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b="OZb/KtrK"; 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=La5RI3x01C6c2UZzxVQam/6uuylRrs9p9w6Q8YqoRKM=; b=lZwbj4jzViGdfYk7LN1pJLa+/N t7KSFZ0UqEbqe2QvV/1JqTkMui+nUjZ+FXRzEluA8vZ3eJCxmN/eSbDjMpPPdxFZweByQT4NuEsLj tkPU29fYFI9KuwFr8icu/nwwVMvvPUMtv6lVkVuPNN7n+McAWAYXg3/An39AdzaKb2yw=; 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 1ws0Mc-0000uo-Bo; Thu, 06 Aug 2026 15:50:34 +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 1ws0MZ-0000ue-Q8 for openvpn-devel@lists.sourceforge.net; Thu, 06 Aug 2026 15:50:31 +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=0FxAuH52QKF1Vmw42IimAd+TcGSlVdTd9pGgZUat/XA=; b=lWXkIouYpeOiAiYnlYPAEKkbsl ru6OElMsIkLytutCvSpt9br6cKWmvlOtwD4oKmBhMB1JwjqzChutI2ZH61fs9UrRAQaIm61UwmV2d ouENmVNLLzZE9AP7ITO+eXct2P0M4FBwFwRbX9eA+JSfxH6lHlSDuQYLwwQ+d4SGLI2M=; 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=0FxAuH52QKF1Vmw42IimAd+TcGSlVdTd9pGgZUat/XA=; b=jQIHV2wjmyt6UV+qhHQy59tL/u MZXo2ycfOGf+yjIcCN43BtRysJXMSVHAeaRp2zHnb0Mk2jXsQ1DRbsEowbte82mImy17WVNfpzGnE 7tUE0lPvQYxfHyTdImU1VRK8TtqJlkwJa+qpFLmQx8cQXghgO4oYfF2CtxSCKIVFFI4o=; Received: from mout-b-210.mailbox.org ([195.10.208.40]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1ws0MW-0000Bl-Ld for openvpn-devel@lists.sourceforge.net; Thu, 06 Aug 2026 15:50:31 +0000 Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:b231:465::202]) (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-210.mailbox.org (Postfix) with ESMTPS id 4hGBZ44GVNzFqPk; Thu, 06 Aug 2026 17:50:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1786031420; 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=0FxAuH52QKF1Vmw42IimAd+TcGSlVdTd9pGgZUat/XA=; b=OZb/KtrK+QQZMLvweAuBX8VbagX7Nru6fGv3SEzRqbqMxH/eUNb59Ff6vRe4fsZHqZb//e HpZXwI7mZ/8WBxd3kY43sgW2o+QJMOhEObZvHFbiB+6b/X56XFPxNGSpX6fKkQAXPJrWj3 cWLj6lISvlhBfjrXYJs2YiHWaiNVycGjUTQbj8NyqcQarfVw4tST0n1+W7Z29rbYCi/XcZ nDwIbPsaAFZt9Kf+kLcm2guiYTeLX3oPhNKX29Rj/CooK2fXuRTz63nYe3ovE8VvFELeZr vA6xhvIjINlCRo9niCN7RYSJow2IGPn7C+RP7MoER5lIxwTqfY5zQ3l+fHYsPA== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of marco@mandelbit.com designates 2001:67c:2050:b231:465::202 as permitted sender) smtp.mailfrom=marco@mandelbit.com From: Marco Baffo To: openvpn-devel@lists.sourceforge.net Date: Thu, 6 Aug 2026 17:49:48 +0200 Message-ID: <20260806154948.795039-3-marco@mandelbit.com> In-Reply-To: <20260806154948.795039-1-marco@mandelbit.com> References: <20260806154948.795039-1-marco@mandelbit.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4hGBZ44GVNzFqPk 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 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: 1ws0MW-0000Bl-Ld Subject: [Openvpn-devel] [PATCH ovpn net-next v4 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: 1872789700826315242 X-GMAIL-MSGID: 1872789700826315242 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 --- 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 | 266 +++++++++++++++++- .../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, 289 insertions(+), 45 deletions(-) diff --git a/tools/testing/selftests/net/ovpn/common.sh b/tools/testing/selftests/net/ovpn/common.sh index 2d844eb3aa6e..4f2510fb6d7f 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 f4effa7580c0..4e1735fe1bb2 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,196 @@ 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 target_fd, ret; + char path[PATH_MAX]; + int len; + + 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 +1854,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 +2162,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 +2237,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 +2324,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 +2397,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; + } } } @@ -2434,29 +2656,51 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[]) int main(int argc, char *argv[]) { struct ovpn_ctx ovpn; + const char *program = argv[0]; 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 ec9a51bbf3c9..0e4e33b2973f 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 7c1d56e9c525..8a9ca52f86be 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 9b5610837032..468dd7985c8f 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