summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2018-07-11 17:32:06 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2018-07-11 17:32:06 +0000
commit03febf9a0dc48ba08015ecbc2a204a5dd9f211e0 (patch)
treed8589070a93707297121e43ae3ae10032bb774ce
parent366c2cb28ec5ddf98890d94b4e617645bcd795b4 (diff)
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.
-rw-r--r--usr.sbin/rad/engine.c46
-rw-r--r--usr.sbin/rad/frontend.c48
-rw-r--r--usr.sbin/rad/rad.h3
3 files changed, 83 insertions, 14 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);
diff --git a/usr.sbin/rad/frontend.c b/usr.sbin/rad/frontend.c
index f6a7e7bee43..e3bc5376b7f 100644
--- a/usr.sbin/rad/frontend.c
+++ b/usr.sbin/rad/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.3 2018/07/11 14:03:13 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.4 2018/07/11 17:32:05 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -129,6 +129,7 @@ int in6_mask2prefixlen(struct in6_addr *);
void get_interface_prefixes(struct ra_iface *,
struct ra_prefix_conf *);
void build_package(struct ra_iface *);
+void build_leaving_package(struct ra_iface *);
void ra_output(struct ra_iface *, struct sockaddr_in6 *);
struct rad_conf *frontend_conf;
@@ -434,6 +435,7 @@ frontend_dispatch_engine(int fd, short event, void *bula)
struct imsg imsg;
struct imsg_send_ra send_ra;
struct ra_iface *ra_iface;
+ uint32_t if_index;
int n, shut = 0;
if (event & EV_READ) {
@@ -465,6 +467,17 @@ frontend_dispatch_engine(int fd, short event, void *bula)
if (ra_iface)
ra_output(ra_iface, &send_ra.to);
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));
+ ra_iface = find_ra_iface_by_id(if_index);
+ if (ra_iface) {
+ TAILQ_REMOVE(&ra_interfaces, ra_iface, entry);
+ free_ra_iface(ra_iface);
+ }
+ break;
default:
log_debug("%s: error handling imsg %d", __func__,
imsg.hdr.type);
@@ -631,7 +644,7 @@ merge_ra_interfaces(void)
{
struct ra_iface_conf *ra_iface_conf;
struct ra_prefix_conf *ra_prefix_conf;
- struct ra_iface *ra_iface, *tmp;
+ struct ra_iface *ra_iface;
uint32_t if_index;
TAILQ_FOREACH(ra_iface, &ra_interfaces, entry)
@@ -660,13 +673,6 @@ merge_ra_interfaces(void)
}
}
- TAILQ_FOREACH_SAFE(ra_iface, &ra_interfaces, entry, tmp) {
- if (ra_iface->removed) {
- TAILQ_REMOVE(&ra_interfaces, ra_iface, entry);
- free_ra_iface(ra_iface);
- }
- }
-
TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
while ((ra_prefix_conf = SIMPLEQ_FIRST(&ra_iface->prefixes))
!= NULL) {
@@ -676,6 +682,14 @@ merge_ra_interfaces(void)
}
ra_iface->prefix_count = 0;
+ if (ra_iface->removed) {
+ log_debug("iface removed: %s", ra_iface->name);
+ build_leaving_package(ra_iface);
+ frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0,
+ &ra_iface->if_index, sizeof(ra_iface->if_index));
+ continue;
+ }
+
ra_iface_conf = find_ra_iface_conf(
&frontend_conf->ra_iface_list, ra_iface->name);
@@ -898,6 +912,22 @@ build_package(struct ra_iface *ra_iface)
}
void
+build_leaving_package(struct ra_iface *ra_iface)
+{
+ struct nd_router_advert ra;
+ size_t len;
+
+ len = sizeof(ra);
+
+ memset(&ra, 0, sizeof(ra));
+
+ ra.nd_ra_type = ND_ROUTER_ADVERT;
+
+ memcpy(ra_iface->data, &ra, sizeof(ra));
+ ra_iface->datalen = sizeof(ra);
+}
+
+void
ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to)
{
diff --git a/usr.sbin/rad/rad.h b/usr.sbin/rad/rad.h
index 445bf9c6f8b..ee9b32dc86a 100644
--- a/usr.sbin/rad/rad.h
+++ b/usr.sbin/rad/rad.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rad.h,v 1.4 2018/07/11 14:03:13 florian Exp $ */
+/* $OpenBSD: rad.h,v 1.5 2018/07/11 17:32:05 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -62,6 +62,7 @@ enum imsg_type {
IMSG_RA_RS,
IMSG_SEND_RA,
IMSG_UPDATE_IF,
+ IMSG_REMOVE_IF,
IMSG_SOCKET_IPC
};