summaryrefslogtreecommitdiffstats
path: root/usr.sbin/rad/engine.c
diff options
context:
space:
mode:
authorflorian <florian@openbsd.org>2018-07-11 17:32:05 +0000
committerflorian <florian@openbsd.org>2018-07-11 17:32:05 +0000
commit4a78c7cf1da74945eaac89675bb548f92d5e06fe (patch)
treef09bb503b5dce40f98a535800daff14db6782dcd /usr.sbin/rad/engine.c
parentremove useless macro; (diff)
downloadwireguard-openbsd-4a78c7cf1da74945eaac89675bb548f92d5e06fe.tar.xz
wireguard-openbsd-4a78c7cf1da74945eaac89675bb548f92d5e06fe.zip
Send a RA with router lifetime of 0 when an interface is removed from
the config. RFC 4861, 6.2.5: [...] the router SHOULD transmit one or more (but not more than MAX_FINAL_RTR_ADVERTISEMENTS) final multicast Router Advertisements on the interface with a Router Lifetime field of zero.
Diffstat (limited to 'usr.sbin/rad/engine.c')
-rw-r--r--usr.sbin/rad/engine.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/usr.sbin/rad/engine.c b/usr.sbin/rad/engine.c
index 25df94b0ba3..4f568e37ee7 100644
--- a/usr.sbin/rad/engine.c
+++ b/usr.sbin/rad/engine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: engine.c,v 1.4 2018/07/11 14:03:13 florian Exp $ */
+/* $OpenBSD: engine.c,v 1.5 2018/07/11 17:32:05 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -43,8 +43,8 @@
#include "rad.h"
#include "engine.h"
-#define MAX_RTR_ADV_INTERVAL 600
-#define MIN_RTR_ADV_INTERVAL 200
+#define MAX_RTR_ADV_INTERVAL 600
+#define MIN_RTR_ADV_INTERVAL 200
struct engine_iface {
TAILQ_ENTRY(engine_iface) entry;
@@ -63,6 +63,7 @@ void parse_ra_rs(struct imsg_ra_rs *);
void parse_ra(struct imsg_ra_rs *);
void parse_rs(struct imsg_ra_rs *);
void update_iface(uint32_t);
+void remove_iface(uint32_t);
struct engine_iface *find_engine_iface_by_id(uint32_t);
void iface_timeout(int, short, void *);
@@ -147,6 +148,8 @@ engine(int debug, int verbose)
if (inet_pton(AF_INET6, "ff02::1", &all_nodes.sin6_addr) != 1)
fatal("inet_pton");
+ TAILQ_INIT(&engine_interfaces);
+
event_dispatch();
engine_shutdown();
@@ -224,6 +227,13 @@ engine_dispatch_frontend(int fd, short event, void *bula)
memcpy(&if_index, imsg.data, sizeof(if_index));
update_iface(if_index);
break;
+ case IMSG_REMOVE_IF:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(if_index))
+ fatal("%s: IMSG_REMOVE_IF wrong length: %d",
+ __func__, imsg.hdr.len);
+ memcpy(&if_index, imsg.data, sizeof(if_index));
+ remove_iface(if_index);
+ break;
case IMSG_CTL_LOG_VERBOSE:
/* Already checked by frontend. */
memcpy(&verbose, imsg.data, sizeof(verbose));
@@ -487,6 +497,7 @@ update_iface(uint32_t if_index)
engine_iface = calloc(1, sizeof(*engine_iface));
engine_iface->if_index = if_index;
evtimer_set(&engine_iface->timer, iface_timeout, engine_iface);
+ TAILQ_INSERT_TAIL(&engine_interfaces, engine_iface, entry);
}
tv.tv_sec = 0;
@@ -495,13 +506,40 @@ update_iface(uint32_t if_index)
}
void
+remove_iface(uint32_t if_index)
+{
+ struct engine_iface *engine_iface;
+ struct imsg_send_ra send_ra;
+ char if_name[IF_NAMESIZE];
+
+ if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) {
+ /* we don't know this interface, frontend can delete it */
+ engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0,
+ &if_index, sizeof(if_index));
+ return;
+ }
+
+ send_ra.if_index = engine_iface->if_index;
+ memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to));
+
+ TAILQ_REMOVE(&engine_interfaces, engine_iface, entry);
+ evtimer_del(&engine_iface->timer);
+
+ if (if_indextoname(if_index, if_name) != NULL)
+ engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra,
+ sizeof(send_ra));
+ engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0,
+ &engine_iface->if_index, sizeof(engine_iface->if_index));
+ free(engine_iface);
+}
+
+void
iface_timeout(int fd, short events, void *arg)
{
struct engine_iface *engine_iface = (struct engine_iface *)arg;
struct imsg_send_ra send_ra;
struct timeval tv;
-
tv.tv_sec = MIN_RTR_ADV_INTERVAL +
arc4random_uniform(MAX_RTR_ADV_INTERVAL - MIN_RTR_ADV_INTERVAL);
tv.tv_usec = arc4random_uniform(1000000);