-/* $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>
#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;
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 *);
if (inet_pton(AF_INET6, "ff02::1", &all_nodes.sin6_addr) != 1)
fatal("inet_pton");
+ TAILQ_INIT(&engine_interfaces);
+
event_dispatch();
engine_shutdown();
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));
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;
evtimer_add(&engine_iface->timer, &tv);
}
+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 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);
-/* $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>
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;
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) {
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);
{
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)
}
}
- 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) {
}
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);
}
}
+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)
{