The way rad(8) is normaly used is netstart(8) setup a bunch of interfaces with IPv6 prefixes and one or more are listed in rad.conf. Everything just works.
But rad can also be configured to work on interfaces that are dynamically added (tap, pair, vether...) It would then spam the log with: sendmsg on vether1: Can't assign requested address as noted by tb. It's also not sensible to use such an interface, it can't possibly work. So we are going to ignore interfaces without link local address. OK? diff --git frontend.c frontend.c index c932c3dfca3..77bbedb2a3e 100644 --- frontend.c +++ frontend.c @@ -133,6 +133,7 @@ void free_ra_iface(struct ra_iface *); int in6_mask2prefixlen(struct in6_addr *); void get_interface_prefixes(struct ra_iface *, struct ra_prefix_conf *); +int interface_has_linklocal_address(char *); void build_packet(struct ra_iface *); void build_leaving_packet(struct ra_iface *); void ra_output(struct ra_iface *, struct sockaddr_in6 *); @@ -750,14 +751,19 @@ merge_ra_interface(char *name, char *conf_name) { struct ra_iface *ra_iface; uint32_t if_index; - int link_state; + int link_state, has_linklocal; link_state = get_link_state(name); + has_linklocal = interface_has_linklocal_address(name); if ((ra_iface = find_ra_iface_by_name(name)) != NULL) { ra_iface->link_state = link_state; if (!LINK_STATE_IS_UP(link_state)) { - log_debug("%s down, ignoring", name); + log_debug("%s down, removing", name); + ra_iface->removed = 1; + } else if (!has_linklocal) { + log_debug("%s has no IPv6 link-local address, " + "removing", name); ra_iface->removed = 1; } else { log_debug("keeping interface %s", name); @@ -771,6 +777,11 @@ merge_ra_interface(char *name, char *conf_name) return; } + if (!has_linklocal) { + log_debug("%s has no IPv6 link-local address, ignoring", name); + return; + } + log_debug("new interface %s", name); if ((if_index = if_nametoindex(name)) == 0) return; @@ -918,6 +929,32 @@ in6_mask2prefixlen(struct in6_addr *in6) return (plen); } +int +interface_has_linklocal_address(char *name) +{ + struct ifaddrs *ifap, *ifa; + struct sockaddr_in6 *sin6; + int ret = 0; + + if (getifaddrs(&ifap) != 0) + fatal("getifaddrs"); + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (strcmp(name, ifa->ifa_name) != 0) + continue; + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + + sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; + + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + ret = 1; + break; + } + } + freeifaddrs(ifap); + return (ret); +} void get_interface_prefixes(struct ra_iface *ra_iface, struct ra_prefix_conf *autoprefix) -- I'm not entirely sure you are real.