summaryrefslogtreecommitdiff
path: root/usr.sbin/rad
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2019-09-07 18:57:48 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2019-09-07 18:57:48 +0000
commit01f46a00fd62d17e1359273f122cddcd08755275 (patch)
treea783984230d5cb97480808ba79ec4d9e8dccad44 /usr.sbin/rad
parentd90e540d455af87be8bc13428936470df0495489 (diff)
Do not try to send router advertisements on interfaces that have no link.
Keeps log noise down on carp backup interfaces. Reported by matthieu Previous version OK deraadt Input & OK benno
Diffstat (limited to 'usr.sbin/rad')
-rw-r--r--usr.sbin/rad/frontend.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/usr.sbin/rad/frontend.c b/usr.sbin/rad/frontend.c
index 8178b058629..c932c3dfca3 100644
--- a/usr.sbin/rad/frontend.c
+++ b/usr.sbin/rad/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.30 2019/06/28 13:32:49 deraadt Exp $ */
+/* $OpenBSD: frontend.c,v 1.31 2019/09/07 18:57:47 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -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;