When an interface doesn't have a layer 2 address in6_get_soii_ifid() failes and then later on a in in6_get_ifid() a layer 2 address is "borrowed" from from another interface. Do the "borrowing" in in6_get_soii_ifid(), too so that semantically opaque interface identifiers work for these kind of interfaces, too.
diff --git in6_ifattach.c in6_ifattach.c index f40b1905fe4..adc54b1a4da 100644 --- in6_ifattach.c +++ in6_ifattach.c @@ -216,8 +216,9 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6) * in6 - upper 64bits are preserved */ int -in6_get_soii_ifid(struct ifnet *ifp, struct in6_addr *in6) +in6_get_soii_ifid(struct ifnet *ifp0, struct in6_addr *in6) { + struct ifnet *ifp; SHA2_CTX ctx; u_int8_t digest[SHA512_DIGEST_LENGTH]; struct in6_addr prefix; @@ -225,10 +226,25 @@ in6_get_soii_ifid(struct ifnet *ifp, struct in6_addr *in6) int dad_counter = 0; /* XXX not used */ char *addr; - if (ifp->if_xflags & IFXF_INET6_NOSOII) + if (ifp0->if_xflags & IFXF_INET6_NOSOII) return -1; - sdl = ifp->if_sadl; + sdl = ifp0->if_sadl; + + if (sdl == NULL || sdl->sdl_alen == 0) { + /* + * try to get it from some other hardware interface like + * in in6_get_ifid() + */ + TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp == ifp0) + continue; + sdl = ifp->if_sadl; + if (sdl != NULL && sdl->sdl_alen != 0) + break; + } + } + if (sdl == NULL || sdl->sdl_alen == 0) return -1; -- I'm not entirely sure you are real.