summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorflorian <florian@openbsd.org>2018-05-17 13:39:00 +0000
committerflorian <florian@openbsd.org>2018-05-17 13:39:00 +0000
commitd3ff34773015779929eaf295ce6c950d49595894 (patch)
tree08b34eaf5937067b31656090337d00fc9724b4a7
parentLet hvn_iff handle promisc mode activation (diff)
downloadwireguard-openbsd-d3ff34773015779929eaf295ce6c950d49595894.tar.xz
wireguard-openbsd-d3ff34773015779929eaf295ce6c950d49595894.zip
Handle RTM_DELETE of slaacd managed default route by re-inserting it.
Problem pointed out & OK phessler
-rw-r--r--sbin/slaacd/engine.c46
-rw-r--r--sbin/slaacd/frontend.c44
-rw-r--r--sbin/slaacd/slaacd.c6
-rw-r--r--sbin/slaacd/slaacd.h8
4 files changed, 95 insertions, 9 deletions
diff --git a/sbin/slaacd/engine.c b/sbin/slaacd/engine.c
index 184b349f650..86dc07f06d0 100644
--- a/sbin/slaacd/engine.c
+++ b/sbin/slaacd/engine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: engine.c,v 1.24 2018/04/23 13:49:04 florian Exp $ */
+/* $OpenBSD: engine.c,v 1.25 2018/05/17 13:39:00 florian Exp $ */
/*
* Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -259,6 +259,8 @@ struct address_proposal *find_address_proposal_by_addr(struct slaacd_iface *,
struct sockaddr_in6 *);
struct dfr_proposal *find_dfr_proposal_by_id(struct slaacd_iface *,
int64_t);
+struct dfr_proposal *find_dfr_proposal_by_gw(struct slaacd_iface *,
+ struct sockaddr_in6 *);
void find_prefix(struct slaacd_iface *, struct
address_proposal *, struct radv **, struct
radv_prefix **);
@@ -389,6 +391,7 @@ engine_dispatch_frontend(int fd, short event, void *bula)
struct address_proposal *addr_proposal = NULL;
struct dfr_proposal *dfr_proposal = NULL;
struct imsg_del_addr del_addr;
+ struct imsg_del_route del_route;
ssize_t n;
int shut = 0;
#ifndef SMALL
@@ -521,6 +524,28 @@ engine_dispatch_frontend(int fd, short event, void *bula)
}
break;
+ case IMSG_DEL_ROUTE:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(del_route))
+ fatal("%s: IMSG_DEL_ROUTE wrong length: %d",
+ __func__, imsg.hdr.len);
+ memcpy(&del_route, imsg.data, sizeof(del_route));
+ iface = get_slaacd_iface_by_id(del_addr.if_index);
+ if (iface == NULL) {
+ log_debug("IMSG_DEL_ROUTE: unknown interface"
+ ", ignoring");
+ break;
+ }
+
+ dfr_proposal = find_dfr_proposal_by_gw(iface,
+ &del_route.gw);
+
+ if (dfr_proposal) {
+ dfr_proposal->state = PROPOSAL_WITHDRAWN;
+ free_dfr_proposal(dfr_proposal);
+ start_probe(iface);
+ }
+ break;
default:
log_debug("%s: unexpected imsg %d", __func__,
imsg.hdr.type);
@@ -1932,10 +1957,7 @@ configure_dfr(struct dfr_proposal *dfr_proposal)
if (prev_state == PROPOSAL_CONFIGURED || prev_state ==
PROPOSAL_NEARLY_EXPIRED) {
- /*
- * nothing to do here, routes do not expire in the kernel
- * XXX check if the route got deleted and re-add it?
- */
+ /* nothing to do here, routes do not expire in the kernel */
return;
}
@@ -2276,6 +2298,20 @@ find_dfr_proposal_by_id(struct slaacd_iface *iface, int64_t id)
return (NULL);
}
+struct dfr_proposal*
+find_dfr_proposal_by_gw(struct slaacd_iface *iface, struct sockaddr_in6
+ *addr)
+{
+ struct dfr_proposal *dfr_proposal;
+
+ LIST_FOREACH (dfr_proposal, &iface->dfr_proposals, entries) {
+ if (memcmp(&dfr_proposal->addr, addr, sizeof(*addr)) == 0)
+ return (dfr_proposal);
+ }
+
+ return (NULL);
+}
+
/* XXX currently unused */
void
diff --git a/sbin/slaacd/frontend.c b/sbin/slaacd/frontend.c
index c57e122ee33..d8ca40d6a80 100644
--- a/sbin/slaacd/frontend.c
+++ b/sbin/slaacd/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.16 2018/05/17 11:51:27 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.17 2018/05/17 13:39:00 florian Exp $ */
/*
* Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -674,7 +674,9 @@ handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info)
struct if_msghdr *ifm;
struct imsg_proposal_ack proposal_ack;
struct imsg_del_addr del_addr;
+ struct imsg_del_route del_route;
struct sockaddr_rtlabel *rl;
+ struct in6_addr *in6;
int64_t id, pid;
int flags, xflags, if_index;
char ifnamebuf[IFNAMSIZ];
@@ -729,6 +731,46 @@ handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info)
ifm->ifm_index);
}
break;
+ case RTM_DELETE:
+ ifm = (struct if_msghdr *)rtm;
+ if ((rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY | RTA_LABEL)) !=
+ (RTA_DST | RTA_GATEWAY | RTA_LABEL))
+ break;
+ if (rti_info[RTAX_DST]->sa_family != AF_INET6)
+ break;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)
+ rti_info[RTAX_DST])->sin6_addr))
+ break;
+ if (rti_info[RTAX_GATEWAY]->sa_family != AF_INET6)
+ break;
+ if (rti_info[RTAX_LABEL]->sa_len !=
+ sizeof(struct sockaddr_rtlabel))
+ break;
+
+ rl = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL];
+ if (strcmp(rl->sr_label, SLAACD_RTA_LABEL) != 0)
+ break;
+
+ if_name = if_indextoname(ifm->ifm_index, ifnamebuf);
+
+ del_route.if_index = ifm->ifm_index;
+ memcpy(&del_route.gw, rti_info[RTAX_GATEWAY],
+ sizeof(del_route.gw));
+ in6 = &del_route.gw.sin6_addr;
+ /* XXX from route(8) p_sockaddr() */
+ if (IN6_IS_ADDR_LINKLOCAL(in6) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(in6) ||
+ IN6_IS_ADDR_MC_INTFACELOCAL(in6)) {
+ del_route.gw.sin6_scope_id =
+ (u_int32_t)ntohs(*(u_short *) &in6->s6_addr[2]);
+ *(u_short *)&in6->s6_addr[2] = 0;
+ }
+ frontend_imsg_compose_engine(IMSG_DEL_ROUTE,
+ 0, 0, &del_route, sizeof(del_route));
+ log_debug("RTM_DELETE: %s[%u]", if_name,
+ ifm->ifm_index);
+
+ break;
case RTM_PROPOSAL:
ifm = (struct if_msghdr *)rtm;
if_name = if_indextoname(ifm->ifm_index, ifnamebuf);
diff --git a/sbin/slaacd/slaacd.c b/sbin/slaacd/slaacd.c
index 8b5499f97af..8a405b5ca94 100644
--- a/sbin/slaacd/slaacd.c
+++ b/sbin/slaacd/slaacd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: slaacd.c,v 1.21 2018/05/17 11:52:04 florian Exp $ */
+/* $OpenBSD: slaacd.c,v 1.22 2018/05/17 13:39:00 florian Exp $ */
/*
* Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -82,6 +82,7 @@ const char* imsg_type_name[] = {
"IMSG_PROPOSAL_ACK",
"IMSG_CONFIGURE_ADDRESS",
"IMSG_DEL_ADDRESS",
+ "IMSG_DEL_ROUTE",
"IMSG_FAKE_ACK",
"IMSG_CONFIGURE_DFR",
"IMSG_WITHDRAW_DFR",
@@ -308,7 +309,8 @@ main(int argc, char *argv[])
fatal("route socket");
rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) |
- ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_PROPOSAL);
+ ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_PROPOSAL) |
+ ROUTE_FILTER(RTM_DELETE);
if (setsockopt(frontend_routesock, PF_ROUTE, ROUTE_MSGFILTER,
&rtfilter, sizeof(rtfilter)) < 0)
fatal("setsockopt(ROUTE_MSGFILTER)");
diff --git a/sbin/slaacd/slaacd.h b/sbin/slaacd/slaacd.h
index 0efbe0cb1fb..923b5ec9f40 100644
--- a/sbin/slaacd/slaacd.h
+++ b/sbin/slaacd/slaacd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: slaacd.h,v 1.15 2018/05/17 11:51:27 florian Exp $ */
+/* $OpenBSD: slaacd.h,v 1.16 2018/05/17 13:39:00 florian Exp $ */
/*
* Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -70,6 +70,7 @@ enum imsg_type {
IMSG_PROPOSAL_ACK,
IMSG_CONFIGURE_ADDRESS,
IMSG_DEL_ADDRESS,
+ IMSG_DEL_ROUTE,
IMSG_FAKE_ACK,
IMSG_CONFIGURE_DFR,
IMSG_WITHDRAW_DFR,
@@ -185,6 +186,11 @@ struct imsg_del_addr {
struct sockaddr_in6 addr;
};
+struct imsg_del_route {
+ uint32_t if_index;
+ struct sockaddr_in6 gw;
+};
+
struct imsg_proposal_ack {
int64_t id;
pid_t pid;