interface-ip: allow configuring routes without explicit interface
authorJo-Philipp Wich <jo@mein.io>
Thu, 24 Aug 2023 12:43:31 +0000 (14:43 +0200)
committerJo-Philipp Wich <jo@mein.io>
Wed, 8 Nov 2023 08:49:57 +0000 (09:49 +0100)
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
interface-ip.h
system-linux.c

index fee29a99b299ab04f748e0da986bd05ae78a9d4f..d2fe385f8aa5409cfaa854028334bc6d5e136665 100644 (file)
@@ -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;
 
index 8843349b2de8227df6d2eabcfc99aa27b47fc04b..cc7efbdb84804f744f2b75d47631bff8982ef079 100644 (file)
@@ -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 {
index bb23404ed87c2c3bbff4d774ec5a51c24761101e..9097f6a56a1f2cb233de1ab74950d1653db01a0b 100644 (file)
@@ -3022,6 +3022,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;