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.