summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2013-05-13 10:55:01 +0200
committerSteven Barth <steven@midlink.org>2013-05-13 10:55:01 +0200
commit570302d28d18d47f095f864be161045e169b5941 (patch)
tree186fc425d49a6fcc25075d4d517df43f466248ab
parent3b8673edadc8ce6d1d90c12e6b8e57eeb291c521 (diff)
Add support for IPv6 and interface target-routes & dependencies
Signed-off-by: Steven Barth <steven@midlink.org>
-rwxr-xr-xdummy/netifd-proto.sh2
-rw-r--r--interface-ip.c15
-rw-r--r--interface-ip.h2
-rw-r--r--proto-shell.c28
-rw-r--r--ubus.c9
5 files changed, 44 insertions, 12 deletions
diff --git a/dummy/netifd-proto.sh b/dummy/netifd-proto.sh
index ae5a346..d8b540d 100755
--- a/dummy/netifd-proto.sh
+++ b/dummy/netifd-proto.sh
@@ -334,6 +334,7 @@ proto_set_available() {
proto_add_host_dependency() {
local interface="$1"
local host="$2"
+ local ifname="$3"
# execute in subshell to not taint callers env
# see tickets #11046, #11545, #11570
@@ -341,6 +342,7 @@ proto_add_host_dependency() {
json_init
json_add_int action 6
json_add_string host "$host"
+ [ -n "$ifname" ] && json_add_string ifname "$ifname"
_proto_notify "$interface" -S
)
}
diff --git a/interface-ip.c b/interface-ip.c
index e0bcdc0..31842c4 100644
--- a/interface-ip.c
+++ b/interface-ip.c
@@ -170,9 +170,8 @@ 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)
+interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface)
{
- struct interface *iface;
struct device_route *route, *r_next = NULL;
bool defaultroute_target = false;
int addrsize = v6 ? sizeof(addr->in6) : sizeof(addr->in);
@@ -188,7 +187,7 @@ interface_ip_add_target_route(union if_addr *addr, bool v6)
else
memcpy(&route->addr, addr, addrsize);
- vlist_for_each_element(&interfaces, iface, node) {
+ if (iface) {
/* look for locally addressable target first */
if (interface_ip_find_addr_target(iface, addr, v6))
goto done;
@@ -196,6 +195,16 @@ interface_ip_add_target_route(union if_addr *addr, bool v6)
/* do not stop at the first route, let the lookup compare
* masks to find the best match */
interface_ip_find_route_target(iface, addr, v6, &r_next);
+ } else {
+ vlist_for_each_element(&interfaces, iface, node) {
+ /* look for locally addressable target first */
+ if (interface_ip_find_addr_target(iface, addr, v6))
+ goto done;
+
+ /* do not stop at the first route, let the lookup compare
+ * masks to find the best match */
+ interface_ip_find_route_target(iface, addr, v6, &r_next);
+ }
}
if (!r_next) {
diff --git a/interface-ip.h b/interface-ip.h
index cd6ec84..c2213fd 100644
--- a/interface-ip.h
+++ b/interface-ip.h
@@ -137,7 +137,7 @@ 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 *interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *iface);
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 02f1836..8bbc36e 100644
--- a/proto-shell.c
+++ b/proto-shell.c
@@ -58,6 +58,8 @@ struct proto_shell_dependency {
union if_addr host;
bool v6;
+
+ char interface[];
};
struct proto_shell_state {
@@ -105,12 +107,15 @@ proto_shell_if_down_cb(struct interface_user *dep, struct interface *iface,
static void
proto_shell_update_host_dep(struct proto_shell_dependency *dep)
{
- struct interface *iface;
+ struct interface *iface = NULL;
if (dep->dep.iface)
goto out;
- iface = interface_ip_add_target_route(&dep->host, dep->v6);
+ if (dep->interface[0])
+ iface = vlist_find(&interfaces, dep->interface, iface, node);
+
+ iface = interface_ip_add_target_route(&dep->host, dep->v6, iface);
if (!iface)
goto out;
@@ -616,17 +621,28 @@ proto_shell_add_host_dependency(struct proto_shell_state *state, struct blob_att
{
struct proto_shell_dependency *dep;
struct blob_attr *host = tb[NOTIFY_HOST];
+ struct blob_attr *ifname = tb[NOTIFY_IFNAME];
+ size_t ifnamelen = (ifname) ? blobmsg_data_len(ifname) : 1;
if (!host)
return UBUS_STATUS_INVALID_ARGUMENT;
- dep = calloc(1, sizeof(*dep));
- if (!inet_pton(AF_INET, blobmsg_data(host), &dep->host)) {
- free(dep);
- return UBUS_STATUS_INVALID_ARGUMENT;
+ dep = calloc(1, sizeof(*dep) + ifnamelen);
+ if (inet_pton(AF_INET, blobmsg_data(host), &dep->host) < 1) {
+ if (inet_pton(AF_INET6, blobmsg_data(host), &dep->host) < 1) {
+ free(dep);
+ return UBUS_STATUS_INVALID_ARGUMENT;
+ } else {
+ dep->v6 = true;
+ }
}
dep->proto = state;
+ if (ifname)
+ memcpy(dep->interface, blobmsg_data(ifname), ifnamelen);
+ else
+ dep->interface[0] = 0;
+
dep->dep.cb = proto_shell_if_up_cb;
interface_add_user(&dep->dep, NULL);
list_add(&dep->list, &state->deps);
diff --git a/ubus.c b/ubus.c
index 0592399..774f9d1 100644
--- a/ubus.c
+++ b/ubus.c
@@ -50,12 +50,14 @@ netifd_handle_reload(struct ubus_context *ctx, struct ubus_object *obj,
enum {
HR_TARGET,
HR_V6,
+ HR_INTERFACE,
__HR_MAX
};
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 },
};
static int
@@ -64,7 +66,7 @@ netifd_add_host_route(struct ubus_context *ctx, struct ubus_object *obj,
struct blob_attr *msg)
{
struct blob_attr *tb[__HR_MAX];
- struct interface *iface;
+ struct interface *iface = NULL;
union if_addr a;
bool v6 = false;
@@ -75,12 +77,15 @@ 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_INTERFACE])
+ iface = vlist_find(&interfaces, blobmsg_data(tb[HR_INTERFACE]), iface, node);
+
memset(&a, 0, sizeof(a));
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 = interface_ip_add_target_route(&a, v6, iface);
if (!iface)
return UBUS_STATUS_NOT_FOUND;