{
struct interface *iface;
struct device_route *route, *r_next = NULL;
+ bool defaultroute_target = false;
+ int addrsize = v6 ? sizeof(addr->in6) : sizeof(addr->in);
route = calloc(1, sizeof(*route));
if (!route)
- return false;
+ return NULL;
route->flags = v6 ? DEVADDR_INET6 : DEVADDR_INET4;
route->mask = v6 ? 128 : 32;
- memcpy(&route->addr, addr, v6 ? sizeof(addr->in6) : sizeof(addr->in));
+ if (memcmp(&route->addr, addr, addrsize) == 0)
+ defaultroute_target = true;
+ else
+ memcpy(&route->addr, addr, addrsize);
vlist_for_each_element(&interfaces, iface, node) {
/* look for locally addressable target first */
interface_ip_find_route_target(iface, addr, v6, &r_next);
}
- if (!r_next)
+ if (!r_next) {
+ free(route);
return NULL;
+ }
iface = r_next->iface;
memcpy(&route->nexthop, &r_next->nexthop, sizeof(route->nexthop));
done:
route->iface = iface;
- vlist_add(&iface->host_routes, &route->node, &route->flags);
+ if (defaultroute_target)
+ free(route);
+ else
+ vlist_add(&iface->host_routes, &route->node, &route->flags);
return iface;
}
}
if ((cur = tb[ROUTE_TARGET]) != NULL) {
- if (!inet_pton(af, blobmsg_data(cur), &route->addr)) {
+ if (!parse_ip_and_netmask(af, blobmsg_data(cur), &route->addr, &route->mask)) {
DPRINTF("Failed to parse route target: %s\n", (char *) blobmsg_data(cur));
goto error;
}
route->flags |= DEVROUTE_METRIC;
}
- if ((cur = tb[ROUTE_MTU]) != NULL)
+ if ((cur = tb[ROUTE_MTU]) != NULL) {
route->mtu = blobmsg_get_u32(cur);
+ route->flags |= DEVROUTE_MTU;
+ }
vlist_add(&ip->route, &route->node, &route->flags);
return;
}
static void
+interface_handle_subnet_route(struct interface *iface, struct device_addr *addr, bool add)
+{
+ struct device *dev = iface->l3_dev.dev;
+ struct device_route route;
+
+ memset(&route, 0, sizeof(route));
+ route.iface = iface;
+ route.flags = addr->flags;
+ route.mask = addr->mask;
+ memcpy(&route.addr, &addr->addr, sizeof(route.addr));
+ clear_if_addr(&route.addr, route.mask);
+
+ if (add) {
+ route.flags |= DEVADDR_KERNEL;
+ system_del_route(dev, &route);
+
+ route.flags &= ~DEVADDR_KERNEL;
+ route.metric = iface->metric;
+ system_add_route(dev, &route);
+ } else {
+ system_del_route(dev, &route);
+ }
+}
+
+static void
interface_update_proto_addr(struct vlist_tree *tree,
struct vlist_node *node_new,
struct vlist_node *node_old)
struct device *dev;
struct device_addr *a_new = NULL, *a_old = NULL;
bool keep = false;
- struct device_route *route;
ip = container_of(tree, struct interface_ip_settings, addr);
iface = ip->iface;
uint32_t *a = (uint32_t *) &a_new->addr;
mask >>= a_new->mask;
- a_new->broadcast = *a | mask;
+ a_new->broadcast = *a | htonl(mask);
}
}
}
if (node_old) {
- if (!(a_old->flags & DEVADDR_EXTERNAL) && a_old->enabled && !keep)
+ if (!(a_old->flags & DEVADDR_EXTERNAL) && a_old->enabled && !keep) {
+ interface_handle_subnet_route(iface, a_old, false);
system_del_address(dev, a_old);
+ }
free(a_old);
}
if (!(a_new->flags & DEVADDR_EXTERNAL) && !keep) {
system_add_address(dev, a_new);
if (iface->metric)
- goto replace_route;
+ interface_handle_subnet_route(iface, a_new, true);
}
}
- return;
-
-replace_route:
- route = calloc(1, sizeof(*route));
- route->iface = iface;
- route->flags = a_new->flags | DEVADDR_KERNEL;
- route->mask = a_new->mask;
- memcpy(&route->addr, &a_new->addr, sizeof(route->addr));
- clear_if_addr(&route->addr, route->mask);
-
- system_del_route(dev, route);
-
- route->flags &= ~DEVADDR_KERNEL;
- route->metric = iface->metric;
- vlist_add(&ip->route, &route->node, &route->flags);
}
static bool
struct dns_server *s;
s = calloc(1, sizeof(*s));
+ if (!s)
+ return;
+
s->af = AF_INET;
if (inet_pton(s->af, str, &s->addr.in))
goto add;
vlist_simple_flush(&ip->dns_search);
vlist_flush(&ip->route);
vlist_flush(&ip->addr);
+ interface_write_resolv_conf();
}
void