diff options
author | 2018-05-17 13:39:00 +0000 | |
---|---|---|
committer | 2018-05-17 13:39:00 +0000 | |
commit | d3ff34773015779929eaf295ce6c950d49595894 (patch) | |
tree | 08b34eaf5937067b31656090337d00fc9724b4a7 | |
parent | Let hvn_iff handle promisc mode activation (diff) | |
download | wireguard-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.c | 46 | ||||
-rw-r--r-- | sbin/slaacd/frontend.c | 44 | ||||
-rw-r--r-- | sbin/slaacd/slaacd.c | 6 | ||||
-rw-r--r-- | sbin/slaacd/slaacd.h | 8 |
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; |