diff options
-rw-r--r-- | interface-ip.c | 12 | ||||
-rw-r--r-- | interface-ip.h | 3 | ||||
-rw-r--r-- | proto-shell.c | 2 | ||||
-rw-r--r-- | ubus.c | 9 |
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; @@ -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; |