summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2022-05-19 17:21:23 +0200
committerFelix Fietkau <nbd@nbd.name>2022-05-19 17:21:24 +0200
commit507c0513d1766757d969530c51fe7d368354538d (patch)
tree21aa6169dacb0e913139a7409672f7342670078d
parent4b4849cf5e5a784aca40be55158744811b172e76 (diff)
downloadnetifd-507c0513d1766757d969530c51fe7d368354538d.tar.gz
interface-ip: add support for excluding interfaces in host route lookup
When adding host routes needed for an interface to communicate, it may be necessary to skip the interface itself, in case it provides a default route. This helps with avoiding accidental loops Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--interface-ip.c12
-rw-r--r--interface-ip.h3
-rw-r--r--proto-shell.c2
-rw-r--r--ubus.c9
4 files changed, 21 insertions, 5 deletions
diff --git a/interface-ip.c b/interface-ip.c
index 54d5fe0..585cb6f 100644
--- a/interface-ip.c
+++ b/interface-ip.c
@@ -257,12 +257,19 @@ interface_ip_find_route_target(struct interface *iface, union if_addr *a,
}
struct interface *
-interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface)
+interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface,
+ bool exclude)
{
struct device_route *route, *r_next = NULL;
bool defaultroute_target = false;
union if_addr addr_zero;
int addrsize = v6 ? sizeof(addr->in6) : sizeof(addr->in);
+ struct interface *exclude_iface = NULL;
+
+ if (exclude) {
+ exclude_iface = iface;
+ iface = NULL;
+ }
memset(&addr_zero, 0, sizeof(addr_zero));
if (memcmp(&addr_zero, addr, addrsize) == 0)
@@ -278,6 +285,9 @@ interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *if
interface_ip_find_route_target(iface, addr, v6, &r_next);
} else {
vlist_for_each_element(&interfaces, iface, node) {
+ if (iface == exclude_iface)
+ continue;
+
/* look for locally addressable target first */
if (interface_ip_find_addr_target(iface, addr, v6))
return iface;
diff --git a/interface-ip.h b/interface-ip.h
index b17ad94..8843349 100644
--- a/interface-ip.h
+++ b/interface-ip.h
@@ -184,7 +184,8 @@ void interface_ip_flush(struct interface_ip_settings *ip);
void interface_ip_set_enabled(struct interface_ip_settings *ip, bool enabled);
void interface_ip_update_metric(struct interface_ip_settings *ip, int metric);
-struct interface *interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface);
+struct interface *interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface,
+ bool exclude);
struct device_prefix* interface_ip_add_device_prefix(struct interface *iface,
struct in6_addr *addr, uint8_t length, time_t valid_until, time_t preferred_until,
diff --git a/proto-shell.c b/proto-shell.c
index e20d539..9cdbc7f 100644
--- a/proto-shell.c
+++ b/proto-shell.c
@@ -129,7 +129,7 @@ proto_shell_update_host_dep(struct proto_shell_dependency *dep)
}
if (!dep->any)
- iface = interface_ip_add_target_route(&dep->host, dep->v6, iface);
+ iface = interface_ip_add_target_route(&dep->host, dep->v6, iface, false);
if (!iface)
goto out;
diff --git a/ubus.c b/ubus.c
index a386179..2876e7d 100644
--- a/ubus.c
+++ b/ubus.c
@@ -54,6 +54,7 @@ enum {
HR_TARGET,
HR_V6,
HR_INTERFACE,
+ HR_EXCLUDE,
__HR_MAX
};
@@ -61,6 +62,7 @@ static const struct blobmsg_policy route_policy[__HR_MAX] = {
[HR_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
[HR_V6] = { .name = "v6", .type = BLOBMSG_TYPE_BOOL },
[HR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
+ [HR_EXCLUDE] = { .name = "exclude", .type = BLOBMSG_TYPE_BOOL },
};
static int
@@ -72,6 +74,7 @@ netifd_add_host_route(struct ubus_context *ctx, struct ubus_object *obj,
struct interface *iface = NULL;
union if_addr a;
bool v6 = false;
+ bool exclude = false;
blobmsg_parse(route_policy, __HR_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[HR_TARGET])
@@ -80,6 +83,9 @@ netifd_add_host_route(struct ubus_context *ctx, struct ubus_object *obj,
if (tb[HR_V6])
v6 = blobmsg_get_bool(tb[HR_V6]);
+ if (tb[HR_EXCLUDE])
+ exclude = blobmsg_get_bool(tb[HR_EXCLUDE]);
+
if (tb[HR_INTERFACE])
iface = vlist_find(&interfaces, blobmsg_data(tb[HR_INTERFACE]), iface, node);
@@ -87,8 +93,7 @@ netifd_add_host_route(struct ubus_context *ctx, struct ubus_object *obj,
if (!inet_pton(v6 ? AF_INET6 : AF_INET, blobmsg_data(tb[HR_TARGET]), &a))
return UBUS_STATUS_INVALID_ARGUMENT;
-
- iface = interface_ip_add_target_route(&a, v6, iface);
+ iface = interface_ip_add_target_route(&a, v6, iface, exclude);
if (!iface)
return UBUS_STATUS_NOT_FOUND;