[M] Change in openvpn[master]: Add support for user defined L3 master devices

"its_Giaan (Code Review)" <[email protected]>
Newsgroups gmane.network.openvpn.devel
Message-ID <[email protected]>
Attention is currently required from: plaisthos.

Hello plaisthos,

I'd like you to do a code review.
Please visit

    http://gerrit.openvpn.net/c/openvpn/+/1703?usp=email

to review the following change.


Change subject: Add support for user defined L3 master devices
......................................................................

Add support for user defined L3 master devices

Introduce the --l3mdev option to allow associating OpenVPN
tun interfaces with a user-defined L3 master device (VRF).

When configured, the tun interface is automatically bound
to the specified l3mdev during interface initialization.

This allows VPN traffic to operate within a VRF domain,
enabling network isolation and policy-based routing at L3 level.

Note: This feature is Linux-only and relies on SITNL backend.

Change-Id: I115a17a2c61c65f48aea41d94150f34ea31f82da
Signed-off-by: Gianmarco De Gregori <[email protected]>
---
M doc/man-sections/vpn-network-options.rst
M src/openvpn/dco.c
M src/openvpn/networking.h
M src/openvpn/networking_sitnl.c
M src/openvpn/networking_sitnl.h
M src/openvpn/options.c
M src/openvpn/options.h
M src/openvpn/tun.c
8 files changed, 95 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/03/1703/1

diff --git a/doc/man-sections/vpn-network-options.rst b/doc/man-sections/vpn-network-options.rst
index 181c990..4cc11e9 100644
--- a/doc/man-sections/vpn-network-options.rst
+++ b/doc/man-sections/vpn-network-options.rst
@@ -304,6 +304,12 @@
   Specify the link layer address, more commonly known as the MAC address.
   Only applied to TAP devices.
 
+--l3mdev name
+   Specify the L3 master device (such as VRF) to which the tunnel 
+   interface will be bound. The specified device must already exist.
+
+  (Supported on Linux only, on other platforms this is a no-op).
+
 --netns name
   Specify the network namespace in which the tunnel interface will be created.
   The namespace must already exist.
diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c
index fbefcb6..40ef5b6 100644
--- a/src/openvpn/dco.c
+++ b/src/openvpn/dco.c
@@ -395,6 +395,7 @@
         msg(msglevel, "Note: --netns not supported by DCO, disabling data channel offload.");
         return false;
     }
+
 #endif /* if defined(_WIN32) */
 
 #if defined(HAVE_LIBCAPNG)
diff --git a/src/openvpn/networking.h b/src/openvpn/networking.h
index fab6bbf..3b4ac9f 100644
--- a/src/openvpn/networking.h
+++ b/src/openvpn/networking.h
@@ -125,6 +125,16 @@
 int net_iface_del(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface);
 
 /**
+ * Bind a network interface to an L3 master device.
+ *
+ * @param ctx       OpenVPN network context.
+ * @param iface     Interface to bind.
+ *
+ * @return 0 on success, -1 on error.
+ */
+int net_iface_l3mdev_bind(openvpn_net_ctx_t *ctx, const char *iface);
+
+/**
  * Bring interface up or down.
  *
  * @param ctx       the implementation specific context
diff --git a/src/openvpn/networking_sitnl.c b/src/openvpn/networking_sitnl.c
index b60131f..bb9e77a 100644
--- a/src/openvpn/networking_sitnl.c
+++ b/src/openvpn/networking_sitnl.c
@@ -187,6 +187,7 @@
     char path[PATH_MAX];
 
     ctx->netns = NULL;
+    ctx->l3mdev = NULL;
 
     if (c && c->options.netns)
     {
@@ -200,6 +201,16 @@
         ctx->netns = c->options.netns;
     }
 
+    if (c && c->options.l3mdev)
+    {
+        if (!if_nametoindex(c->options.l3mdev))
+        {
+            msg(M_ERR, "%s: L3 master device %s does not exist", __func__, c->options.l3mdev);
+        }
+
+        ctx->l3mdev = c->options.l3mdev;
+    }
+
     ctx->gc = gc_new();
     return 0;
 }
@@ -1046,6 +1057,44 @@
 #ifdef ENABLE_SITNL
 
 int
+net_iface_l3mdev_bind(openvpn_net_ctx_t *ctx, const char *iface)
+{
+    struct sitnl_link_req req;
+    int ifindex, l3mdev_index, ret = -1;
+
+    CLEAR(req);
+
+    ifindex = if_nametoindex(iface);
+    l3mdev_index = if_nametoindex(ctx->l3mdev);
+
+    if (ifindex == 0)
+    {
+        msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
+        return -1;
+    }
+    if (l3mdev_index == 0)
+    {
+        msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, ctx->l3mdev);
+        return -1;
+    }
+
+    req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
+    req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+    req.n.nlmsg_type = RTM_NEWLINK;
+
+    req.i.ifi_family = AF_PACKET;
+    req.i.ifi_index = ifindex;
+
+    SITNL_ADDATTR(&req.n, sizeof(req), IFLA_MASTER, &l3mdev_index, sizeof(int));
+
+    msg(M_INFO, "Binding %s to %s", iface, ctx->l3mdev);
+
+    ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
+err:
+    return ret;
+}
+
+int
 net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
 {
     struct sitnl_link_req req;
diff --git a/src/openvpn/networking_sitnl.h b/src/openvpn/networking_sitnl.h
index 7e723fe..6dff698 100644
--- a/src/openvpn/networking_sitnl.h
+++ b/src/openvpn/networking_sitnl.h
@@ -28,6 +28,7 @@
 struct openvpn_net_ctx
 {
     const char *netns;
+    const char *l3mdev;
     struct gc_arena gc;
 };
 
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index bde3680..5247c8e 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -6496,6 +6496,14 @@
         VERIFY_PERMISSION(OPT_P_GENERAL);
         options->netns = p[1];
     }
+    else if (streq(p[0], "l3mdev") && p[1] && !p[2])
+    {
+#ifndef ENABLE_SITNL
+        msg(M_WARN, "NOTE: --l3mdev is supported only on Linux when compiled with SITNL");
+#endif
+        VERIFY_PERMISSION(OPT_P_GENERAL);
+        options->l3mdev = p[1];
+    }
     else if (streq(p[0], "nice") && p[1] && !p[2])
     {
         VERIFY_PERMISSION(OPT_P_NICE);
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 88a6dfa..1afd41b 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -316,6 +316,7 @@
     struct dns_options dns_options;
 
     const char *netns;
+    const char *l3mdev;
     bool remote_random;
     const char *ipchange;
     const char *dev;
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index 51d9bed..250ce50 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -1059,6 +1059,15 @@
     {
         msg(M_FATAL, "Linux can't set mtu (%d) on %s", tun_mtu, ifname);
     }
+#if defined(ENABLE_SITNL)
+    if (ctx->l3mdev)
+    {
+        if (net_iface_l3mdev_bind(ctx, ifname) < 0)
+        {
+            msg(M_NONFATAL, "Linux can't bind %s to %s", ifname, ctx->l3mdev);
+        }
+    }
+#endif
 
     if (net_iface_up(ctx, ifname, true) < 0)
     {
@@ -1265,6 +1274,16 @@
         msg(M_FATAL, "Linux can't set mtu (%d) on %s", tun_mtu, ifname);
     }
 
+#if defined(ENABLE_SITNL)
+    if (ctx->l3mdev)
+    {
+        if (net_iface_l3mdev_bind(ctx, ifname) < 0)
+        {
+            msg(M_NONFATAL, "Linux can't bind %s to %s", ifname, ctx->l3mdev);
+        }
+    }
+#endif
+
     if (net_iface_up(ctx, ifname, true) < 0)
     {
         msg(M_FATAL, "Linux can't bring %s up", ifname);

-- 
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1703?usp=email
To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I115a17a2c61c65f48aea41d94150f34ea31f82da
Gerrit-Change-Number: 1703
Gerrit-PatchSet: 1
Gerrit-Owner: its_Giaan <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>

_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.