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.

Reply via email to