From: Steven Barth Date: Tue, 26 May 2015 11:51:52 +0000 (+0200) Subject: linux: more IPv6 onlink-route handling fixes / improvements X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=commitdiff_plain;h=3204adab41de155959575eb4d3a415ea947b861f linux: more IPv6 onlink-route handling fixes / improvements Signed-off-by: Steven Barth --- diff --git a/interface-ip.c b/interface-ip.c index 18dd2fa..aec3892 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -710,7 +710,9 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment, struct device *l3_downlink = iface->l3_dev.dev; struct device_addr addr; + struct device_route route; memset(&addr, 0, sizeof(addr)); + memset(&route, 0, sizeof(route)); if (IN6_IS_ADDR_UNSPECIFIED(&assignment->addr)) { addr.addr.in6 = prefix->addr; @@ -722,15 +724,14 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment, addr.addr.in6 = assignment->addr; addr.mask = assignment->length; - addr.flags = DEVADDR_INET6; + addr.flags = DEVADDR_INET6 | DEVADDR_OFFLINK; addr.preferred_until = prefix->preferred_until; addr.valid_until = prefix->valid_until; - if (addr.mask < 64) { - addr.mask = 64; - system_del_address(l3_downlink, &addr); - addr.mask = assignment->length; - } + route.flags = DEVADDR_INET6; + route.mask = addr.mask < 64 ? 64 : addr.mask; + route.addr = addr.addr; + clear_if_addr(&route.addr, route.mask); if (!add && assignment->enabled) { time_t now = system_get_rtime(); @@ -738,8 +739,6 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment, 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 - if (prefix->iface) { if (prefix->iface->ip6table) set_ip_source_policy(false, true, IPRULE_PRIORITY_NW, &addr.addr, @@ -749,16 +748,12 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment, addr.mask, 0, iface, "unreachable"); } - if (addr.mask < 64) - addr.mask = 64; - - interface_handle_subnet_route(iface, &addr, false); + system_del_route(l3_downlink, &route); system_add_address(l3_downlink, &addr); assignment->enabled = false; } else if (add && (iface->state == IFS_UP || iface->state == IFS_SETUP) && !system_add_address(l3_downlink, &addr)) { - interface_handle_subnet_route(iface, &addr, false); if (prefix->iface && !assignment->enabled) { set_ip_source_policy(true, true, IPRULE_PRIORITY_REJECT, &addr.addr, @@ -769,10 +764,8 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment, addr.mask, prefix->iface->ip6table, iface, NULL); } - if (addr.mask < 64) - addr.mask = 64; - - interface_handle_subnet_route(iface, &addr, true); + route.metric = iface->metric; + system_add_route(l3_downlink, &route); if (uplink && uplink->l3_dev.dev) { int mtu = system_update_ipv6_mtu( diff --git a/system-linux.c b/system-linux.c index 08b6757..a6dde59 100644 --- a/system-linux.c +++ b/system-linux.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -47,10 +48,6 @@ #define RT_TABLE_PRELOCAL 128 #endif -#ifndef IFA_F_NOPREFIXROUTE -#define IFA_F_NOPREFIXROUTE 0x200 -#endif - #include #include #include @@ -1431,7 +1428,6 @@ static int system_addr(struct device *dev, struct device_addr *addr, int cmd) .ifa_family = (alen == 4) ? AF_INET : AF_INET6, .ifa_prefixlen = addr->mask, .ifa_index = dev->ifindex, - .ifa_flags = (addr->flags & DEVADDR_OFFLINK) ? IFA_F_NOPREFIXROUTE : 0, }; struct nl_msg *msg; @@ -1474,6 +1470,9 @@ static int system_addr(struct device *dev, struct device_addr *addr, int cmd) } nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo); + + if (cmd == RTM_NEWADDR && (addr->flags & DEVADDR_OFFLINK)) + nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE); } return system_rtnl_call(msg);