From patchwork Fri Apr 1 20:08:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 2365 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.27.255.53]) by backend41.mail.ord1d.rsapps.net with LMTP id 8DnyEKb2R2KVCQAAqwncew (envelope-from ) for ; Sat, 02 Apr 2022 03:09:26 -0400 Received: from proxy13.mail.iad3a.rsapps.net ([172.27.255.53]) by director8.mail.ord1d.rsapps.net with LMTP id wDeCHKb2R2LyXgAAfY0hYg (envelope-from ) for ; Sat, 02 Apr 2022 03:09:26 -0400 Received: from smtp52.gate.iad3a ([172.27.255.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy13.mail.iad3a.rsapps.net with LMTPS id qPktF6b2R2IfaAAAwhxzoA (envelope-from ) for ; Sat, 02 Apr 2022 03:09:26 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp52.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: d425067a-b253-11ec-8a26-525400a7d0a1-1-1 Received: from [216.105.38.7] ([216.105.38.7:33168] helo=lists.sourceforge.net) by smtp52.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 26/3C-02504-5A6F7426; Sat, 02 Apr 2022 03:09:26 -0400 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.94.2) (envelope-from ) id 1naXrr-0005HI-HU; Sat, 02 Apr 2022 07:08:14 +0000 Received: from [172.30.20.202] (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.94.2) (envelope-from ) id 1naXrq-0005HA-Pp for openvpn-devel@lists.sourceforge.net; Sat, 02 Apr 2022 07:08:13 +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=F/lao5GqfJQjfMh8eIGXmKrIkTIEpjQxyRoZQaixyZA=; b=b+X9qQ8wBHKUpIWiFUnufvBxRG 5iT+QdyIt2mlqCMI3/Gr6j3PrqnlXkozupLvWsn+7eCxdDvh5fnkv6h1TSA5OvnH+kH/IvsBjgcha p8ot8NIOXt7vlgiMjCnTTuhecUTAiV6bO6cixI+FRB3bw4As1DI1s+TSy8xLWiNJwYfQ=; 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=F/lao5GqfJQjfMh8eIGXmKrIkTIEpjQxyRoZQaixyZA=; b=RmDTQw/a7mpzCSLL34P9k6FQZT 9Wt1q75l60TOi8wUP8krb2uHl/bOph+qjZ+OsBKlZrnboq3OQXP4U9kbPqninHbvvBtCqF513KcC0 FXnTwH6IxOJtdbwFGFCtUmsTBUSveT65ru1rMk2BUoxKgN4nkxrXshyAuAmdO/OcodIQ=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.94.2) id 1naXro-0003Zo-Ah for openvpn-devel@lists.sourceforge.net; Sat, 02 Apr 2022 07:08:13 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Sat, 2 Apr 2022 09:08:58 +0200 Message-Id: <20220402070902.30282-4-a@unstable.cc> In-Reply-To: <20220402070902.30282-1-a@unstable.cc> References: <20220402070902.30282-1-a@unstable.cc> MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-2.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: These two new methods can be used to create and delete a tun or an ovpn-dco interface via networking API. Implementations for SITNL and iproute2 are provided Signed-off-by: Arne Schwabe Signed-off-by: Antonio Quartulli --- src/openvpn/networking.h | 27 ++++++++ src/openvpn/networking_iproute2.c | 35 +++++++++++ src/openvp [...] Content analysis details: (-0.0 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 T_SCC_BODY_TEXT_LINE No description available. X-Headers-End: 1naXro-0003Zo-Ah Subject: [Openvpn-devel] [PATCH 3/7] networking: implement net_iface_new and net_iface_del APIs 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 These two new methods can be used to create and delete a tun or an ovpn-dco interface via networking API. Implementations for SITNL and iproute2 are provided Signed-off-by: Arne Schwabe Signed-off-by: Antonio Quartulli --- src/openvpn/networking.h | 27 ++++++++ src/openvpn/networking_iproute2.c | 35 +++++++++++ src/openvpn/networking_sitnl.c | 71 ++++++++++++++++++++++ tests/unit_tests/openvpn/test_networking.c | 22 ++++++- 4 files changed, 154 insertions(+), 1 deletion(-) diff --git a/src/openvpn/networking.h b/src/openvpn/networking.h index 9335701e..02d498fd 100644 --- a/src/openvpn/networking.h +++ b/src/openvpn/networking.h @@ -35,6 +35,12 @@ typedef void *openvpn_net_ctx_t; typedef void *openvpn_net_iface_t; #endif /* ifdef ENABLE_SITNL */ +enum iface_type { + IFACE_DUMMY, + IFACE_TUN, + IFACE_OVPN_DCO, +}; + /* Only the iproute2 backend implements these functions, * the rest can rely on these stubs */ @@ -87,6 +93,27 @@ void net_ctx_reset(openvpn_net_ctx_t *ctx); */ void net_ctx_free(openvpn_net_ctx_t *ctx); +/** + * Add a new interface + * + * @param ctx the implementation specific context + * @param iface interface to create + * @param type interface type (see enum iface_type declaration) + * @param arg extra data required by the specific type + * @return int 0 on success, negative error code on error + */ +int net_iface_new(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface, + enum iface_type type, void *arg); + +/** + * Remove an interface + * + * @param ctx the implementation specific context + * @param iface interface to delete + * @return int 0 on success, negative error code on error + */ +int net_iface_del(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface); + /** * Bring interface up or down. * diff --git a/src/openvpn/networking_iproute2.c b/src/openvpn/networking_iproute2.c index 3ca2bb35..f61f2d14 100644 --- a/src/openvpn/networking_iproute2.c +++ b/src/openvpn/networking_iproute2.c @@ -38,6 +38,12 @@ #include #include +static const char *iface_type_str[] = { + [IFACE_DUMMY] = "dummy", + [IFACE_TUN] = "tun", + [IFACE_OVPN_DCO] = "ovpn-dco", +}; + int net_ctx_init(struct context *c, openvpn_net_ctx_t *ctx) { @@ -63,6 +69,35 @@ net_ctx_free(openvpn_net_ctx_t *ctx) gc_free(&ctx->gc); } +int +net_iface_new(openvpn_net_ctx_t *ctx, const char *iface, enum iface_type type, + void *arg) +{ + struct argv argv = argv_new(); + + argv_printf(&argv, "%s link add %s type %s", iproute_path, iface, + iface_type_str[type]); + argv_msg(M_INFO, &argv); + openvpn_execve_check(&argv, ctx->es, S_FATAL, "Linux ip link add failed"); + + argv_free(&argv); + + return 0; +} + +int +net_iface_del(openvpn_net_ctx_t *ctx, const char *iface) +{ + struct argv argv = argv_new(); + + argv_printf(&argv, "%s link del %s", iproute_path, iface); + openvpn_execve_check(&argv, ctx->es, S_FATAL, "Linux ip link del failed"); + + argv_free(&argv); + + return 0; +} + int net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up) { diff --git a/src/openvpn/networking_sitnl.c b/src/openvpn/networking_sitnl.c index 9b2f58d9..d321f55a 100644 --- a/src/openvpn/networking_sitnl.c +++ b/src/openvpn/networking_sitnl.c @@ -56,6 +56,18 @@ #define NLMSG_TAIL(nmsg) \ ((struct rtattr *)(((uint8_t *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) +#define SITNL_NEST(_msg, _max_size, _attr) \ + ({ \ + struct rtattr *_nest = NLMSG_TAIL(_msg); \ + SITNL_ADDATTR(_msg, _max_size, _attr, NULL, 0); \ + _nest; \ + }) + +#define SITNL_NEST_END(_msg, _nest) \ + { \ + _nest->rta_len = (void *)NLMSG_TAIL(_msg) - (void *)_nest; \ + } + /** * Generic address data structure used to pass addresses and prefixes as * argument to AF family agnostic functions @@ -596,6 +608,13 @@ net_route_v6_best_gw(openvpn_net_ctx_t *ctx, const struct in6_addr *dst, } #ifdef ENABLE_SITNL + +static const char *iface_type_str[] = { + [IFACE_DUMMY] = "dummy", + [IFACE_TUN] = "tun", + [IFACE_OVPN_DCO] = "ovpn-dco", +}; + int net_route_v4_best_gw(openvpn_net_ctx_t *ctx, const in_addr_t *dst, in_addr_t *best_gw, char *best_iface) @@ -1313,6 +1332,58 @@ net_route_v6_del(openvpn_net_ctx_t *ctx, const struct in6_addr *dst, table, metric); } + +int +net_iface_new(openvpn_net_ctx_t *ctx, const char *iface, enum iface_type type, + void *arg) +{ + struct sitnl_link_req req = { }; + int ret = -1; + + ASSERT(iface); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i)); + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + req.n.nlmsg_type = RTM_NEWLINK; + + SITNL_ADDATTR(&req.n, sizeof(req), IFLA_IFNAME, iface, strlen(iface) + 1); + + struct rtattr *linkinfo = SITNL_NEST(&req.n, sizeof(req), IFLA_LINKINFO); + SITNL_ADDATTR(&req.n, sizeof(req), IFLA_INFO_KIND, iface_type_str[type], + strlen(iface_type_str[type]) + 1); + SITNL_NEST_END(&req.n, linkinfo); + + req.i.ifi_family = AF_PACKET; + req.i.ifi_change = 0xFFFFFFFF; + + msg(D_ROUTE, "%s: add %s type %s", __func__, iface, iface_type_str[type]); + + ret = sitnl_send(&req.n, 0, 0, NULL, NULL); +err: + return ret; +} + +int +net_iface_del(openvpn_net_ctx_t *ctx, const char *iface) +{ + struct sitnl_link_req req = { }; + int ifindex = if_nametoindex(iface); + + if (!ifindex) + return errno; + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_DELLINK; + + req.i.ifi_family = AF_PACKET; + req.i.ifi_index = ifindex; + + msg(D_ROUTE, "%s: delete %s", __func__, iface); + + return sitnl_send(&req.n, 0, 0, NULL, NULL); +} + #endif /* !ENABLE_SITNL */ #endif /* TARGET_LINUX */ diff --git a/tests/unit_tests/openvpn/test_networking.c b/tests/unit_tests/openvpn/test_networking.c index 9e9744f4..f70157dc 100644 --- a/tests/unit_tests/openvpn/test_networking.c +++ b/tests/unit_tests/openvpn/test_networking.c @@ -13,6 +13,20 @@ net__iface_up(bool up) return net_iface_up(NULL, iface, up); } +static int +net__iface_new(const char *name, enum iface_type type, char *type_str) +{ + printf("CMD: ip link add %s type %s\n", name, type_str); + return net_iface_new(NULL, name, type, NULL); +} + +static int +net__iface_del(const char *name) +{ + printf("CMD: ip link del %s\n", name); + return net_iface_del(NULL, name); +} + static int net__iface_mtu_set(int mtu) { @@ -191,7 +205,7 @@ net__route_v6_add_gw(const char *dst_str, int prefixlen, const char *gw_str, static void usage(char *name) { - printf("Usage: %s <0-7>\n", name); + printf("Usage: %s <0-9>\n", name); } int @@ -243,6 +257,12 @@ main(int argc, char *argv[]) case 7: return net__route_v6_add_gw("2001:cafe:babe::", 48, "2001::2", 600); + case 8: + return net__iface_new("dummy0815", IFACE_DUMMY, "dummy"); + + case 9: + return net__iface_del("dummy0815"); + default: printf("invalid test: %d\n", test); break;