From: Felix Fietkau Date: Thu, 19 May 2022 15:21:23 +0000 (+0200) Subject: interface-ip: add support for excluding interfaces in host route lookup X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=507c0513d1766757d969530c51fe7d368354538d;p=project%2Fnetifd.git 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 --- 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;