On Fri, Sep 06, 2019 at 09:15:16PM +0200, Sebastian Benoit wrote:
> Florian Obser(flor...@openbsd.org) on 2019.09.06 16:51:35 +0200:
> > On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote:
> > > Hi,
> > > 
> > > I've a pair of redundant routers, which need to run rad(8) on the
> > > internal interfaces.
> > > 
> > > But using carp, on the inactive router, rad complains every
> > > time it tries to send a RA:
> > > 
> > >  rad[65590]: sendmsg on carp2: Can't assign requested address
> > > 
> > > Which I can understand since it currently doesnt "own" the shared IPv6
> > > address of the carp interface.
> > > 
> > > Is there a way to configure rad to avoid these errors?
> > > How do other people handle the situation?
> > > 
> > > Thanks in advance,
> > > -- 
> > > Matthieu Herrb
> > > 
> > 
> > This should keep the noise down.
> > 
> > OK?
> 
> comment inline
> 
> >     if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
> > -           log_debug("keeping interface %s", name);
> > -           ra_iface->removed = 0;
> > +           ra_iface->link_state = link_state;
> > +           if (link_state == LINK_STATE_DOWN) {
> 
> note that there are some (physical) interfaces that do not report a link
> state and thus are unknown even when they can send packets.

I know, observe how I don't care about UP but rather DOWN.

> Use the LINK_STATE_IS_UP() macro here.

Probably best to use !LINK_STATE_IS_UP() :P

> 
> Do we need to consider the case of an interface being administratively down
> here (!(ifap->flags & IFF_UP))?.

I checked, no. sendmsg doesn't error out, the packet is just not going
out. I would leave it at that.

diff --git frontend.c frontend.c
index 8178b058629..3cf52fb4127 100644
--- frontend.c
+++ frontend.c
@@ -104,6 +104,7 @@ struct ra_iface {
        char                            conf_name[IF_NAMESIZE];
        uint32_t                        if_index;
        int                             removed;
+       int                             link_state;
        int                             prefix_count;
        size_t                          datalen;
        uint8_t                         data[RA_MAX_SIZE];
@@ -117,6 +118,7 @@ void                         frontend_startup(void);
 void                    icmp6_receive(int, short, void *);
 void                    join_all_routers_mcast_group(struct ra_iface *);
 void                    leave_all_routers_mcast_group(struct ra_iface *);
+int                     get_link_state(char *);
 void                    merge_ra_interface(char *, char *);
 void                    merge_ra_interfaces(void);
 struct ra_iface                *find_ra_iface_by_id(uint32_t);
@@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, char 
*if_name)
        return (NULL);
 }
 
+int
+get_link_state(char *if_name)
+{
+       struct ifaddrs  *ifap, *ifa;
+       int              ls = LINK_STATE_UNKNOWN;
+
+       if (getifaddrs(&ifap) != 0) {
+               log_warn("getifaddrs");
+               return LINK_STATE_UNKNOWN;
+       }
+       for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+               if (ifa->ifa_addr->sa_family != AF_LINK)
+                       continue;
+               if (strcmp(if_name, ifa->ifa_name) != 0)
+                       continue;
+
+               ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state;
+               break;
+       }
+       freeifaddrs(ifap);
+       return ls;
+}
+
 void
 merge_ra_interface(char *name, char *conf_name)
 {
        struct ra_iface         *ra_iface;
        uint32_t                 if_index;
+       int                      link_state;
+
+       link_state = get_link_state(name);
 
        if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
-               log_debug("keeping interface %s", name);
-               ra_iface->removed = 0;
+               ra_iface->link_state = link_state;
+               if (!LINK_STATE_IS_UP(link_state)) {
+                       log_debug("%s down, ignoring", name);
+                       ra_iface->removed = 1;
+               } else {
+                       log_debug("keeping interface %s", name);
+                       ra_iface->removed = 0;
+               }
+               return;
+       }
+
+       if (!LINK_STATE_IS_UP(link_state)) {
+               log_debug("%s down, ignoring", name);
                return;
        }
 
        log_debug("new interface %s", name);
        if ((if_index = if_nametoindex(name)) == 0)
                return;
+
        log_debug("adding interface %s", name);
        if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL)
                fatal("%s", __func__);
@@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 
*to)
        ssize_t                  len;
        int                      hoplimit = 255;
 
+       if (!LINK_STATE_IS_UP(ra_iface->link_state))
+               return;
+
        sndmhdr.msg_name = to;
        sndmhdr.msg_iov[0].iov_base = ra_iface->data;
        sndmhdr.msg_iov[0].iov_len = ra_iface->datalen;


-- 
I'm not entirely sure you are real.

Reply via email to