|
From: Antonio Q. <a...@un...> - 2021-12-07 12:12:11
|
From: Arne Schwabe <ar...@rf...>
These two new methods can be used to create and delete a tun or an
ovpn-dco interface via RTNL API.
Signed-off-by: Arne Schwabe <ar...@rf...>
Signed-off-by: Antonio Quartulli <a...@un...>
---
src/openvpn/networking_sitnl.c | 94 ++++++++++++++++++++++
src/openvpn/networking_sitnl.h | 28 +++++++
tests/unit_tests/openvpn/test_networking.c | 22 ++++-
3 files changed, 143 insertions(+), 1 deletion(-)
diff --git a/src/openvpn/networking_sitnl.c b/src/openvpn/networking_sitnl.c
index e0003f5c..e6ffdb64 100644
--- a/src/openvpn/networking_sitnl.c
+++ b/src/openvpn/networking_sitnl.c
@@ -1312,6 +1312,100 @@ net_route_v6_del(openvpn_net_ctx_t *ctx, const struct in6_addr *dst,
table, metric);
}
+
+int
+net_iface_new(const char *iface, const char *type)
+{
+ struct sitnl_link_req req = { };
+ struct rtattr *tail = NULL;
+ int ret = -1;
+
+ 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;
+
+ if (iface)
+ {
+ SITNL_ADDATTR(&req.n, sizeof(req), IFLA_IFNAME, iface, strlen(iface) + 1);
+ }
+ tail = NLMSG_TAIL(&req.n);
+ SITNL_ADDATTR(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
+ SITNL_ADDATTR(&req.n, sizeof(req), IFLA_INFO_KIND, type,
+ strlen(type) + 1);
+ tail->rta_len = (uint8_t *)NLMSG_TAIL(&req.n) - (uint8_t *)tail;
+
+ req.i.ifi_family = AF_PACKET;
+ req.i.ifi_change = 0xFFFFFFFF;
+
+ msg(D_ROUTE, "%s: add %s type %s", __func__, np(iface), type);
+
+ if (iface)
+ {
+ /* if we have an interface name we can use that name to later
+ * lookup what interface index we created */
+ ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
+ if (!ret)
+ {
+ req.i.ifi_index = if_nametoindex(iface);
+ }
+
+ }
+ else
+ {
+ req.i.ifi_index = 1194;
+ do
+ {
+ /* for some reason RTM_NEWLINK does not have a reply */
+ /* Therefore we use try using different if indices untiles
+ * we get one that does not exist already */
+ req.i.ifi_index++;
+ ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
+ }
+ while (ret == -EEXIST);
+ }
+ if (!ret)
+ {
+ return req.i.ifi_index;
+ }
+
+err:
+ return ret;
+}
+
+int
+net_iface_del_name(const char *iface)
+{
+ int ifindex;
+
+ ifindex = if_nametoindex(iface);
+
+ msg(D_ROUTE,"%s: idel %s", __func__, iface);
+
+ if (ifindex == 0)
+ {
+ msg(D_ROUTE|M_ERRNO, "%s: rtnl: cannot get ifindex for %s:",
+ __func__, iface);
+ return -ENOENT;
+ }
+
+ return net_iface_del_index(ifindex);
+}
+
+int
+net_iface_del_index(int ifindex)
+{
+ struct sitnl_link_req req = { };
+
+ 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;
+
+ return sitnl_send(&req.n, 0, 0, NULL, NULL);
+}
+
#endif /* !ENABLE_SITNL */
#endif /* TARGET_LINUX */
diff --git a/src/openvpn/networking_sitnl.h b/src/openvpn/networking_sitnl.h
index f040020e..b88ffd4b 100644
--- a/src/openvpn/networking_sitnl.h
+++ b/src/openvpn/networking_sitnl.h
@@ -25,4 +25,32 @@
typedef char openvpn_net_iface_t;
typedef void *openvpn_net_ctx_t;
+/**
+ * @brief Add new interface (similar to ip link add)
+ *
+ * @param iface interface name
+ * @param type interface link type (for example "ovpn-dco")
+ * @return int 0 on success, negative error code on error
+ */
+int
+net_iface_new(const char *iface, const char *type);
+
+/**
+ * @brief Remove an interface (similar to ip link remove)
+ *
+ * @param iface interface name
+ * @return int 0 on success, negative error code on error
+ */
+int
+net_iface_del_name(const char *iface);
+
+/**
+ * @brief Remove an interface (similar to ip link remove)
+ *
+ * @param ifindex interface index
+ * @return int 0 on success, negative error code on error
+ */
+int
+net_iface_del_index(int ifindex);
+
#endif /* NETWORKING_SITNL_H_ */
diff --git a/tests/unit_tests/openvpn/test_networking.c b/tests/unit_tests/openvpn/test_networking.c
index 9e9744f4..37b97188 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, const char* type)
+{
+ printf("CMD: ip link add %s type %s\n", name, type);
+ return net_iface_new(name, type);
+}
+
+static int
+net__iface_del(const char *name)
+{
+ printf("CMD: ip link del %s\n", name);
+ return net_iface_del_name(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", "dummy");
+
+ case 9:
+ return net__iface_del("dummy0815");
+
default:
printf("invalid test: %d\n", test);
break;
--
2.32.0
|