summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorflorian <florian@openbsd.org>2017-05-27 10:55:50 +0000
committerflorian <florian@openbsd.org>2017-05-27 10:55:50 +0000
commit231782b74be04a1ecee3e056b5d35f72e1b09eb2 (patch)
tree6bfb60457bf563b06f4b55a02d186ffb3e591d62
parentthis expects 2byte ASN, so use that, instead of an asn that may or may not fit (diff)
downloadwireguard-openbsd-231782b74be04a1ecee3e056b5d35f72e1b09eb2.tar.xz
wireguard-openbsd-231782b74be04a1ecee3e056b5d35f72e1b09eb2.zip
handle expiration / renewal of non-privacy addresses
-rw-r--r--usr.sbin/slaacd/engine.c132
1 files changed, 107 insertions, 25 deletions
diff --git a/usr.sbin/slaacd/engine.c b/usr.sbin/slaacd/engine.c
index d2f6c65e456..113231974b0 100644
--- a/usr.sbin/slaacd/engine.c
+++ b/usr.sbin/slaacd/engine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: engine.c,v 1.15 2017/05/27 10:54:44 florian Exp $ */
+/* $OpenBSD: engine.c,v 1.16 2017/05/27 10:55:50 florian Exp $ */
/*
* Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -221,7 +221,11 @@ struct address_proposal *find_address_proposal_by_id(struct slaacd_iface *,
int64_t);
struct address_proposal *find_address_proposal_by_addr(struct slaacd_iface *,
struct sockaddr_in6 *);
+void find_prefix(struct slaacd_iface *, struct
+ address_proposal *, struct radv **, struct
+ radv_prefix **);
int engine_imsg_compose_main(int, pid_t, void *, uint16_t);
+uint32_t real_lifetime(struct timespec *, uint32_t);
struct imsgev *iev_frontend;
struct imsgev *iev_main;
@@ -1384,7 +1388,6 @@ void update_iface_ra(struct slaacd_iface *iface, struct radv *ra)
struct radv *old_ra;
struct radv_prefix *prefix;
struct address_proposal *addr_proposal;
- struct timeval tv;
int found, found_privacy;
char hbuf[NI_MAXHOST];
@@ -1416,35 +1419,42 @@ void update_iface_ra(struct slaacd_iface *iface, struct radv *ra)
found = 1;
+ if (real_lifetime(&addr_proposal->uptime,
+ addr_proposal->vltime) >= prefix->vltime) {
+ log_warn("ignoring router advertisement"
+ " that lowers vltime");
+ continue;
+ }
+
addr_proposal->when = ra->when;
addr_proposal->uptime = ra->uptime;
addr_proposal->vltime = prefix->vltime;
addr_proposal->pltime = prefix->pltime;
- if (addr_proposal->state ==
- PROPOSAL_CONFIGURED) {
- log_debug("updating timeout");
- addr_proposal->next_timeout =
- addr_proposal->pltime -
- MAX_RTR_SOLICITATIONS *
- (RTR_SOLICITATION_INTERVAL + 1);
- tv.tv_sec = addr_proposal->next_timeout;
- tv.tv_usec =
- arc4random_uniform(1000000);
-
- evtimer_add(&addr_proposal->timer, &tv);
+ log_debug("%s, state: %s", __func__,
+ proposal_state_name[addr_proposal->state]);
+
+ switch (addr_proposal->state) {
+ case PROPOSAL_CONFIGURED:
+ case PROPOSAL_NEARLY_EXPIRED:
+ log_debug("updating address");
+ configure_address(iface, addr_proposal);
+ break;
+ default:
+ if (getnameinfo((struct sockaddr *)
+ &addr_proposal->addr,
+ addr_proposal->addr.sin6_len, hbuf,
+ sizeof(hbuf), NULL, 0,
+ NI_NUMERICHOST | NI_NUMERICSERV)) {
+ log_warn("cannot get proposal "
+ "IP");
+ strlcpy(hbuf, "uknown",
+ sizeof(hbuf));
+ }
+ log_debug("%s: iface %d: %s", __func__,
+ iface->if_index, hbuf);
+ break;
}
-
- if (getnameinfo((struct sockaddr *)
- &addr_proposal->addr,
- addr_proposal->addr.sin6_len, hbuf,
- sizeof(hbuf), NULL, 0, NI_NUMERICHOST |
- NI_NUMERICSERV)) {
- log_warn("cannot get router IP");
- strlcpy(hbuf, "uknown", sizeof(hbuf));
- }
- log_debug("%s: iface %d: %s: %lld s", __func__,
- iface->if_index, hbuf, tv.tv_sec);
}
if (!found)
@@ -1720,6 +1730,30 @@ address_proposal_timeout(int fd, short events, void *arg)
free(addr_proposal);
}
break;
+ case PROPOSAL_CONFIGURED:
+ log_debug("PROPOSAL_CONFIGURED timeout: id: %lld, privacy: %s",
+ addr_proposal->id, addr_proposal->privacy ? "y" : "n");
+
+ addr_proposal->next_timeout = 1;
+ addr_proposal->timeout_count = 0;
+ addr_proposal->state = PROPOSAL_NEARLY_EXPIRED;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ evtimer_add(&addr_proposal->timer, &tv);
+
+ break;
+ case PROPOSAL_NEARLY_EXPIRED:
+ engine_imsg_compose_frontend(IMSG_CTL_SEND_SOLICITATION,
+ 0, &addr_proposal->if_index,
+ sizeof(addr_proposal->if_index));
+ tv.tv_sec = addr_proposal->next_timeout;
+ tv.tv_usec = arc4random_uniform(1000000);
+ addr_proposal->next_timeout *= 2;
+ evtimer_add(&addr_proposal->timer, &tv);
+ log_debug("%s: scheduling new timeout in %llds.%06ld",
+ __func__, tv.tv_sec, tv.tv_usec);
+ break;
default:
log_debug("%s: unhandled state: %s", __func__,
proposal_state_name[addr_proposal->state]);
@@ -1806,3 +1840,51 @@ find_address_proposal_by_addr(struct slaacd_iface *iface, struct sockaddr_in6
return (NULL);
}
+
+/* XXX currently unused */
+void
+find_prefix(struct slaacd_iface *iface, struct address_proposal *addr_proposal,
+ struct radv **result_ra, struct radv_prefix **result_prefix)
+{
+ struct radv *ra;
+ struct radv_prefix *prefix;
+ uint32_t lifetime, max_lifetime = 0;
+
+ *result_ra = NULL;
+ *result_prefix = NULL;
+
+ LIST_FOREACH(ra, &iface->radvs, entries) {
+ LIST_FOREACH(prefix, &ra->prefixes, entries) {
+ if (memcmp(&prefix->prefix, &addr_proposal->prefix,
+ sizeof(addr_proposal->prefix)) != 0)
+ continue;
+ lifetime = real_lifetime(&ra->uptime,
+ prefix->vltime);
+ if (lifetime > max_lifetime) {
+ max_lifetime = lifetime;
+ *result_ra = ra;
+ *result_prefix = prefix;
+ }
+
+ }
+ }
+}
+
+uint32_t
+real_lifetime(struct timespec *received_uptime, uint32_t ltime)
+{
+ struct timespec now, diff;
+ int64_t remaining;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &now))
+ fatal("clock_gettime");
+
+ timespecsub(&now, received_uptime, &diff);
+
+ remaining = ((int64_t)ltime) - diff.tv_sec;
+
+ if (remaining < 0)
+ remaining = 0;
+
+ return (remaining);
+}