const char *addr = strtok_r(source, "/", &saveptr);
const char *mask = strtok_r(NULL, "/", &saveptr);
- if (inet_pton(af, addr, &route->source) < 1) {
+ if (!addr || inet_pton(af, addr, &route->source) < 1) {
DPRINTF("Failed to parse route source: %s\n", addr);
goto error;
}
- route->sourcemask = atoi(mask);
+ route->sourcemask = (mask) ? atoi(mask) : ((af == AF_INET6) ? 128 : 32);
}
if (is_proto_route) {
if (a_new && a_old) {
keep = true;
- if (a_old->flags != a_new->flags)
+ if (a_old->flags != a_new->flags || a_old->failed)
keep = false;
if (a_old->valid_until != a_new->valid_until ||
if ((a_old->flags & DEVADDR_FAMILY) == DEVADDR_INET6)
v6 = true;
+ unsigned int table = (v6) ? iface->ip6table : iface->ip4table;
+
//This is needed for source routing to work correctly. If a device
//has two connections to a network using the same subnet, adding
//only the network-rule will cause packets to be routed through the
//first matching network (source IP matches both masks).
- set_ip_source_policy(false, v6, IPRULE_PRIORITY_ADDR, &a_old->addr,
- (v6) ? 128 : 32, (v6) ? iface->ip6table : iface->ip4table,
- NULL, NULL);
- set_ip_source_policy(false, v6, IPRULE_PRIORITY_NW, &a_old->addr,
- a_old->mask, (v6) ? iface->ip6table : iface->ip4table, NULL, NULL);
+ if (table) {
+ set_ip_source_policy(false, v6, IPRULE_PRIORITY_ADDR, &a_old->addr,
+ (v6) ? 128 : 32, table, NULL, NULL);
+ set_ip_source_policy(false, v6, IPRULE_PRIORITY_NW, &a_old->addr,
+ a_old->mask, table, NULL, NULL);
+ }
system_del_address(dev, a_old);
}
if (node_new) {
a_new->enabled = true;
if (!(a_new->flags & DEVADDR_EXTERNAL) && (!keep || replace)) {
- system_add_address(dev, a_new);
+ if (system_add_address(dev, a_new))
+ a_new->failed = true;
if (!keep) {
if ((a_new->flags & DEVADDR_FAMILY) == DEVADDR_INET6)
v6 = true;
- set_ip_source_policy(true, v6, IPRULE_PRIORITY_ADDR, &a_new->addr,
- (v6) ? 128 : 32, (v6) ? iface->ip6table : iface->ip4table,
- NULL, NULL);
- set_ip_source_policy(true, v6, IPRULE_PRIORITY_NW, &a_new->addr,
- a_new->mask, (v6) ? iface->ip6table : iface->ip4table,
- NULL, NULL);
+ unsigned int table = (v6) ? iface->ip6table : iface->ip4table;
+
+ if (table) {
+ set_ip_source_policy(true, v6, IPRULE_PRIORITY_ADDR, &a_new->addr,
+ (v6) ? 128 : 32, table, NULL, NULL);
+ set_ip_source_policy(true, v6, IPRULE_PRIORITY_NW, &a_new->addr,
+ a_new->mask, table, NULL, NULL);
+ }
}
if ((a_new->flags & DEVADDR_OFFLINK) || iface->metric)
if (node_old && node_new)
keep = !memcmp(&route_old->nexthop, &route_new->nexthop, sizeof(route_old->nexthop)) &&
- (route_old->table == route_new->table);
+ (route_old->table == route_new->table) && !route_old->failed;
if (node_old) {
if (!(route_old->flags & DEVADDR_EXTERNAL) && route_old->enabled && !keep)
route_new->metric = iface->metric;
if (!(route_new->flags & DEVADDR_EXTERNAL) && !keep && _enabled)
- system_add_route(dev, route_new);
+ if (system_add_route(dev, route_new))
+ route_new->failed = true;
route_new->iface = iface;
route_new->enabled = _enabled;
addr.preferred_until = now;
if (!addr.valid_until || addr.valid_until - now > 7200)
addr.valid_until = now + 7200;
+ system_del_address(l3_downlink, &addr); // Work around dangling prefix routes
system_add_address(l3_downlink, &addr);
if (prefix->iface) {
- set_ip_source_policy(false, true, IPRULE_PRIORITY_NW, &addr.addr,
- addr.mask, prefix->iface->ip6table, iface, NULL);
+ if (prefix->iface->ip6table)
+ set_ip_source_policy(false, true, IPRULE_PRIORITY_NW, &addr.addr,
+ addr.mask, prefix->iface->ip6table, iface, NULL);
set_ip_source_policy(false, true, IPRULE_PRIORITY_REJECT, &addr.addr,
addr.mask, 0, iface, "unreachable");
set_ip_source_policy(true, true, IPRULE_PRIORITY_REJECT, &addr.addr,
addr.mask, 0, iface, "unreachable");
- set_ip_source_policy(true, true, IPRULE_PRIORITY_NW, &addr.addr,
- addr.mask, prefix->iface->ip6table, iface, NULL);
+ if (prefix->iface->ip6table)
+ set_ip_source_policy(true, true, IPRULE_PRIORITY_NW, &addr.addr,
+ addr.mask, prefix->iface->ip6table, iface, NULL);
}
if (uplink && uplink->l3_dev.dev) {
int mtu = system_update_ipv6_mtu(