diff options
author | 2019-08-30 17:25:37 +0000 | |
---|---|---|
committer | 2019-08-30 17:25:37 +0000 | |
commit | b64c4682bb880132c8db3fe68f3cc1f3caec8fe0 (patch) | |
tree | 206455ae703e81d3648d553c0a17b849bdb9bfaf | |
parent | revert r1.175 which added unveil to relayd; "check script" needs access to the (diff) | |
download | wireguard-openbsd-b64c4682bb880132c8db3fe68f3cc1f3caec8fe0.tar.xz wireguard-openbsd-b64c4682bb880132c8db3fe68f3cc1f3caec8fe0.zip |
Remove configured IPv6 addresses remaining when slaacd(8) detects a
link-state change and no new router advertisement is obtained (in accordance
with RFC 6059).
This should improve IPv6 -> legacy-IP-only transitions, preventing
applications from believing IPv6 connectivity is available when it is
not, potentially resulting in long timeouts.
suggestion, input and OK florian@ phessler@
-rw-r--r-- | sbin/slaacd/engine.c | 57 | ||||
-rw-r--r-- | sbin/slaacd/slaacd.c | 37 | ||||
-rw-r--r-- | sbin/slaacd/slaacd.h | 3 |
3 files changed, 89 insertions, 8 deletions
diff --git a/sbin/slaacd/engine.c b/sbin/slaacd/engine.c index f4d08df9c9b..aac8f7e1b8d 100644 --- a/sbin/slaacd/engine.c +++ b/sbin/slaacd/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.38 2019/08/26 18:50:04 pamela Exp $ */ +/* $OpenBSD: engine.c,v 1.39 2019/08/30 17:25:37 pamela Exp $ */ /* * Copyright (c) 2017 Florian Obser <florian@openbsd.org> @@ -91,6 +91,7 @@ enum if_state { IF_DELAY, IF_PROBE, IF_IDLE, + IF_DEAD, }; const char* if_state_name[] = { @@ -98,6 +99,7 @@ const char* if_state_name[] = { "IF_DELAY", "IF_PROBE", "IF_IDLE", + "IF_DEAD", }; enum proposal_state { @@ -107,6 +109,7 @@ enum proposal_state { PROPOSAL_NEARLY_EXPIRED, PROPOSAL_WITHDRAWN, PROPOSAL_DUPLICATED, + PROPOSAL_STALE, }; const char* proposal_state_name[] = { @@ -116,6 +119,7 @@ const char* proposal_state_name[] = { "NEARLY_EXPIRED", "WITHDRAWN", "DUPLICATED", + "STALE", }; const char* rpref_name[] = { @@ -245,6 +249,7 @@ void gen_addr(struct slaacd_iface *, struct radv_prefix *, void gen_address_proposal(struct slaacd_iface *, struct radv *, struct radv_prefix *, int); void free_address_proposal(struct address_proposal *); +void withdraw_addr(struct address_proposal *); void timeout_from_lifetime(struct address_proposal *); void configure_address(struct address_proposal *); void in6_prefixlen2mask(struct in6_addr *, int len); @@ -1996,10 +2001,31 @@ free_address_proposal(struct address_proposal *addr_proposal) LIST_REMOVE(addr_proposal, entries); evtimer_del(&addr_proposal->timer); + switch (addr_proposal->state) { + case PROPOSAL_STALE: + withdraw_addr(addr_proposal); + break; + default: + break; + } free(addr_proposal); } void +withdraw_addr(struct address_proposal *addr_proposal) +{ + struct imsg_configure_address address; + + log_debug("%s: %d", __func__, addr_proposal->if_index); + memset(&address, 0, sizeof(address)); + address.if_index = addr_proposal->if_index; + memcpy(&address.addr, &addr_proposal->addr, sizeof(address.addr)); + + engine_imsg_compose_main(IMSG_WITHDRAW_ADDRESS, 0, &address, + sizeof(address)); +} + +void gen_dfr_proposal(struct slaacd_iface *iface, struct radv *ra) { struct dfr_proposal *dfr_proposal; @@ -2095,6 +2121,7 @@ free_dfr_proposal(struct dfr_proposal *dfr_proposal) switch (dfr_proposal->state) { case PROPOSAL_CONFIGURED: case PROPOSAL_NEARLY_EXPIRED: + case PROPOSAL_STALE: withdraw_dfr(dfr_proposal); break; default: @@ -2235,6 +2262,8 @@ address_proposal_timeout(int fd, short events, void *arg) log_debug("%s: address duplicated", __func__); break; + case PROPOSAL_STALE: + break; default: log_debug("%s: unhandled state: %s", __func__, proposal_state_name[addr_proposal->state]); @@ -2327,6 +2356,8 @@ iface_timeout(int fd, short events, void *arg) { struct slaacd_iface *iface = (struct slaacd_iface *)arg; struct timeval tv; + struct address_proposal *addr_proposal; + struct dfr_proposal *dfr_proposal; log_debug("%s[%d]: %s", __func__, iface->if_index, if_state_name[iface->state]); @@ -2338,12 +2369,26 @@ iface_timeout(int fd, short events, void *arg) engine_imsg_compose_frontend( IMSG_CTL_SEND_SOLICITATION, 0, &iface->if_index, sizeof(iface->if_index)); - if (++iface->probes >= MAX_RTR_SOLICITATIONS) - iface->state = IF_IDLE; - else { + if (++iface->probes >= MAX_RTR_SOLICITATIONS) { + iface->state = IF_DEAD; + tv.tv_sec = 0; + } else tv.tv_sec = RTR_SOLICITATION_INTERVAL; - tv.tv_usec = arc4random_uniform(1000000); - evtimer_add(&iface->timer, &tv); + tv.tv_usec = arc4random_uniform(1000000); + evtimer_add(&iface->timer, &tv); + break; + case IF_DEAD: + while(!LIST_EMPTY(&iface->addr_proposals)) { + addr_proposal = + LIST_FIRST(&iface->addr_proposals); + addr_proposal->state = PROPOSAL_STALE; + free_address_proposal(addr_proposal); + } + while(!LIST_EMPTY(&iface->dfr_proposals)) { + dfr_proposal = + LIST_FIRST(&iface->dfr_proposals); + dfr_proposal->state = PROPOSAL_STALE; + free_dfr_proposal(dfr_proposal); } break; case IF_DOWN: diff --git a/sbin/slaacd/slaacd.c b/sbin/slaacd/slaacd.c index 5d4eda9421f..26a2e33493c 100644 --- a/sbin/slaacd/slaacd.c +++ b/sbin/slaacd/slaacd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: slaacd.c,v 1.38 2019/06/28 13:32:46 deraadt Exp $ */ +/* $OpenBSD: slaacd.c,v 1.39 2019/08/30 17:25:37 pamela Exp $ */ /* * Copyright (c) 2017 Florian Obser <florian@openbsd.org> @@ -65,6 +65,7 @@ void main_dispatch_frontend(int, short, void *); void main_dispatch_engine(int, short, void *); void handle_proposal(struct imsg_proposal *); void configure_interface(struct imsg_configure_address *); +void delete_address(struct imsg_configure_address *); void configure_gateway(struct imsg_configure_dfr *, uint8_t); void add_gateway(struct imsg_configure_dfr *); void delete_gateway(struct imsg_configure_dfr *); @@ -519,6 +520,14 @@ main_dispatch_engine(int fd, short event, void *bula) memcpy(&address, imsg.data, sizeof(address)); configure_interface(&address); break; + case IMSG_WITHDRAW_ADDRESS: + if (IMSG_DATA_SIZE(imsg) != sizeof(address)) + fatalx("%s: IMSG_WITHDRAW_ADDRESS wrong " + "length: %lu", __func__, + IMSG_DATA_SIZE(imsg)); + memcpy(&address, imsg.data, sizeof(address)); + delete_address(&address); + break; case IMSG_CONFIGURE_DFR: if (IMSG_DATA_SIZE(imsg) != sizeof(dfr)) fatalx("%s: IMSG_CONFIGURE_DFR wrong " @@ -771,6 +780,32 @@ configure_interface(struct imsg_configure_address *address) } void +delete_address(struct imsg_configure_address *address) +{ + + struct in6_ifreq in6_ridreq; + char *if_name; + + memset(&in6_ridreq, 0, sizeof(in6_ridreq)); + + if_name = if_indextoname(address->if_index, in6_ridreq.ifr_name); + if (if_name == NULL) { + log_warnx("%s: cannot find interface %d", __func__, + address->if_index); + return; + } + + memcpy(&in6_ridreq.ifr_ifru, &address->addr, + sizeof(in6_ridreq.ifr_ifru)); + + log_debug("%s: %s", __func__, if_name); + + if (ioctl(ioctl_sock, SIOCDIFADDR_IN6, &in6_ridreq) == -1) + log_warn("%s: cannot remove address", __func__); + +} + +void configure_gateway(struct imsg_configure_dfr *dfr, uint8_t rtm_type) { struct rt_msghdr rtm; diff --git a/sbin/slaacd/slaacd.h b/sbin/slaacd/slaacd.h index eea0d906516..c82b35d92e8 100644 --- a/sbin/slaacd/slaacd.h +++ b/sbin/slaacd/slaacd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: slaacd.h,v 1.21 2019/03/02 05:34:59 pamela Exp $ */ +/* $OpenBSD: slaacd.h,v 1.22 2019/08/30 17:25:37 pamela Exp $ */ /* * Copyright (c) 2017 Florian Obser <florian@openbsd.org> @@ -72,6 +72,7 @@ enum imsg_type { IMSG_PROPOSAL, IMSG_PROPOSAL_ACK, IMSG_CONFIGURE_ADDRESS, + IMSG_WITHDRAW_ADDRESS, IMSG_DEL_ADDRESS, IMSG_DEL_ROUTE, IMSG_FAKE_ACK, |