netifd: return the interface for locally addressable host dependencies (FS#1452)
[project/netifd.git] / interface-ip.c
index 716a093..1c84d4f 100644 (file)
@@ -204,7 +204,7 @@ __find_ip_route_target(struct interface_ip_settings *ip, union if_addr *a,
                if (route->flags & DEVROUTE_TABLE)
                        continue;
 
-               if (!*res || route->mask < (*res)->mask)
+               if (!*res || route->mask > (*res)->mask)
                        *res = route;
        }
 }
@@ -245,7 +245,7 @@ interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *if
        if (iface) {
                /* look for locally addressable target first */
                if (interface_ip_find_addr_target(iface, addr, v6))
-                       goto done;
+                       return iface;
 
                /* do not stop at the first route, let the lookup compare
                 * masks to find the best match */
@@ -254,7 +254,7 @@ interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *if
                vlist_for_each_element(&interfaces, iface, node) {
                        /* look for locally addressable target first */
                        if (interface_ip_find_addr_target(iface, addr, v6))
-                               goto done;
+                               return iface;
 
                        /* do not stop at the first route, let the lookup compare
                         * masks to find the best match */
@@ -272,8 +272,6 @@ interface_ip_add_target_route(union if_addr *addr, bool v6, struct interface *if
        route->mtu = r_next->mtu;
        route->metric = r_next->metric;
        route->table = r_next->table;
-
-done:
        route->iface = iface;
        if (defaultroute_target)
                free(route);
@@ -712,9 +710,16 @@ random_ifaceid(struct in6_addr *addr)
        addr->s6_addr32[3] = (uint32_t)mrand48();
 }
 
-static void
+static bool
 eui64_ifaceid(struct interface *iface, struct in6_addr *addr)
 {
+       struct device_settings st;
+
+       device_merge_settings(iface->l3_dev.dev, &st);
+
+       if (!(st.flags & DEV_OPT_MACADDR))
+               return false;
+
        /* get mac address */
        uint8_t *macaddr = iface->l3_dev.dev->settings.macaddr;
        uint8_t *ifaceid = addr->s6_addr + 8;
@@ -723,11 +728,15 @@ eui64_ifaceid(struct interface *iface, struct in6_addr *addr)
        ifaceid[3] = 0xff;
        ifaceid[4] = 0xfe;
        ifaceid[0] ^= 0x02;
+
+       return true;
 }
 
-static void
+static bool
 generate_ifaceid(struct interface *iface, struct in6_addr *addr)
 {
+       bool ret = true;
+
        /* generate new iface id */
        switch (iface->assignment_iface_id_selection) {
        case IFID_FIXED:
@@ -741,9 +750,13 @@ generate_ifaceid(struct interface *iface, struct in6_addr *addr)
                break;
        case IFID_EUI64:
                /* eui64 */
-               eui64_ifaceid(iface, addr);
+               ret = eui64_ifaceid(iface, addr);
+               break;
+       default:
+               ret = false;
                break;
        }
+       return ret;
 }
 
 static void
@@ -797,12 +810,15 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment,
                system_del_route(l3_downlink, &route);
                system_add_address(l3_downlink, &addr);
 
+               assignment->addr = in6addr_any;
                assignment->enabled = false;
        } else if (add && (iface->state == IFS_UP || iface->state == IFS_SETUP)) {
                if (IN6_IS_ADDR_UNSPECIFIED(&addr.addr.in6)) {
                        addr.addr.in6 = prefix->addr;
                        addr.addr.in6.s6_addr32[1] |= htonl(assignment->assigned);
-                       generate_ifaceid(iface, &addr.addr.in6);
+                       if (!generate_ifaceid(iface, &addr.addr.in6))
+                               return;
+
                        assignment->addr = addr.addr.in6;
                        route.addr = addr.addr;
                }