diff mbox series

[RFC,netifd,2/2] interface-ip: allow configuring routes without explicit interface

Message ID 20230824125355.2762457-2-jo@mein.io
State Under Review
Delegated to: Jo-Philipp Wich
Headers show
Series [RFC,netifd,1/2] interface-ip: mask out host bits in IPv4 route targets | expand

Commit Message

Jo-Philipp Wich Aug. 24, 2023, 12:53 p.m. UTC
Support the configuration of network routes not bound to any specific
interface. In case such a route is configured, it will be internally
owned by the loopback interface and have a new DEVROUTE_NODEV flag
set to inhibit the RTA_OIF attribute when installing the kernel route.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
---
 interface-ip.c | 16 ++++++++++++----
 interface-ip.h |  3 +++
 system-linux.c |  3 +++
 3 files changed, 18 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/interface-ip.c b/interface-ip.c
index fee29a9..d2fe385 100644
--- a/interface-ip.c
+++ b/interface-ip.c
@@ -405,6 +405,7 @@  interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6)
 	struct blob_attr *tb[__ROUTE_MAX], *cur;
 	struct device_route *route;
 	int af = v6 ? AF_INET6 : AF_INET;
+	bool no_device = false;
 
 	blobmsg_parse(route_attr, __ROUTE_MAX, tb, blobmsg_data(attr), blobmsg_data_len(attr));
 
@@ -412,10 +413,13 @@  interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6)
 		return;
 
 	if (!iface) {
-		if ((cur = tb[ROUTE_INTERFACE]) == NULL)
-			return;
+		if ((cur = tb[ROUTE_INTERFACE]) == NULL) {
+			iface = vlist_find(&interfaces, "loopback", iface, node);
+			no_device = true;
+		} else {
+			iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
+		}
 
-		iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
 		if (!iface)
 			return;
 
@@ -520,7 +524,11 @@  interface_ip_add_route(struct interface *iface, struct blob_attr *attr, bool v6)
 		route->flags |= DEVROUTE_PROTO;
 	}
 
-	interface_set_route_info(iface, route);
+	if (no_device)
+		route->flags |= DEVROUTE_NODEV;
+	else
+		interface_set_route_info(iface, route);
+
 	vlist_add(&ip->route, &route->node, route);
 	return;
 
diff --git a/interface-ip.h b/interface-ip.h
index 8843349..cc7efbd 100644
--- a/interface-ip.h
+++ b/interface-ip.h
@@ -51,6 +51,9 @@  enum device_addr_flags {
 
 	/* neighbor mac address */
 	DEVNEIGH_MAC		= (1 << 11),
+
+	/* route specifies no device */
+	DEVROUTE_NODEV		= (1 << 12),
 };
 
 union if_addr {
diff --git a/system-linux.c b/system-linux.c
index 0760e73..a8add1e 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -2789,6 +2789,9 @@  static int system_rt(struct device *dev, struct device_route *route, int cmd)
 		}
 	}
 
+	if (route->flags & DEVROUTE_NODEV)
+		dev = NULL;
+
 	msg = nlmsg_alloc_simple(cmd, flags);
 	if (!msg)
 		return -1;