summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2020-11-27 10:23:33 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2020-11-27 10:23:33 +0000
commit53a0d06bb23b7b4f11c03813436d7a65d44c2b51 (patch)
tree52c9bdbf02f3a9ee9a72e8a6538d51687a015245
parent755557c28adbd87dbb842d5feeb0838a151a9393 (diff)
Check if the interface has an IPv6 link-local address before using it.
Problem noted by & OK tb
-rw-r--r--usr.sbin/rad/frontend.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/usr.sbin/rad/frontend.c b/usr.sbin/rad/frontend.c
index c932c3dfca3..8947f616e73 100644
--- a/usr.sbin/rad/frontend.c
+++ b/usr.sbin/rad/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.31 2019/09/07 18:57:47 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.32 2020/11/27 10:23:32 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -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)