aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordberg.se>2019-09-29 22:08:29 +0200
committerLinus Nordberg <linus@nordberg.se>2019-09-29 22:36:19 +0200
commit6dcf16386f710304af2a00706f24f683305b8825 (patch)
tree78da952e9b26949d4078e7da40bb058281e6359c
parentAdd draft of protocol specification (diff)
downloadwg-dynamic-6dcf16386f710304af2a00706f24f683305b8825.tar.xz
wg-dynamic-6dcf16386f710304af2a00706f24f683305b8825.zip
Remove allowed-ips from peers as leases expire
-rw-r--r--lease.c20
-rw-r--r--lease.h4
-rw-r--r--wg-dynamic-server.c55
3 files changed, 76 insertions, 3 deletions
diff --git a/lease.c b/lease.c
index 8a48a27..5ea4f6f 100644
--- a/lease.c
+++ b/lease.c
@@ -203,8 +203,9 @@ bool extend_lease(struct wg_dynamic_lease *lease, uint32_t leasetime)
return false;
}
-int leases_refresh()
+int leases_refresh(void (*update_cb)(wg_key *, int))
{
+ wg_key updates[WG_DYNAMIC_LEASE_CHUNKSIZE] = { 0 };
time_t cur_time = get_monotonic_time();
if (cur_time < gexpires)
@@ -212,6 +213,7 @@ int leases_refresh()
gexpires = TIME_T_MAX;
+ int i = 0;
for (khint_t k = kh_begin(leases_ht); k != kh_end(leases_ht); ++k) {
if (!kh_exist(leases_ht, k))
continue;
@@ -228,6 +230,19 @@ int leases_refresh()
if (!IN6_IS_ADDR_UNSPECIFIED(ipv6))
ipp_del_v6(&pool, ipv6, 128);
+ memcpy(updates[i], kh_key(leases_ht, k), sizeof(wg_key));
+ {
+ wg_key_b64_string pubkey_asc;
+ wg_key_to_base64(pubkey_asc, updates[i]);
+ debug("Peer losing its lease: %s\n", pubkey_asc);
+ }
+ i++;
+ if (i == WG_DYNAMIC_LEASE_CHUNKSIZE) {
+ update_cb(updates, i);
+ i = 0;
+ memset(updates, 0, sizeof updates);
+ }
+
tmp = *pp;
*pp = (*pp)->next;
free(tmp);
@@ -239,6 +254,9 @@ int leases_refresh()
}
}
+ if (i)
+ update_cb(updates, i);
+
if (!kh_val(leases_ht, k)) {
free((char *)kh_key(leases_ht, k));
kh_del(leaseht, leases_ht, k);
diff --git a/lease.h b/lease.h
index 3e1402d..23852e6 100644
--- a/lease.h
+++ b/lease.h
@@ -13,6 +13,8 @@
#include "common.h"
#include "netlink.h"
+#define WG_DYNAMIC_LEASE_CHUNKSIZE 256
+
struct wg_dynamic_lease {
time_t start_real;
time_t start_mono;
@@ -54,7 +56,7 @@ bool extend_lease(struct wg_dynamic_lease *lease, uint32_t leasetime);
/* Refreshes all leases, meaning expired ones will be removed. Returns the
* amount of seconds until the next lease will expire, or at most INT_MAX/1000.
*/
-int leases_refresh();
+int leases_refresh(void (*update_cb)(wg_key *, int));
/*
* Updates all pools with information from the mnl socket nlsock.
diff --git a/wg-dynamic-server.c b/wg-dynamic-server.c
index fca1dfc..d1229cc 100644
--- a/wg-dynamic-server.c
+++ b/wg-dynamic-server.c
@@ -294,6 +294,59 @@ static void add_allowed_ips(wg_key pubkey, struct in_addr *ipv4,
fatal("wg_set_device()");
}
+/* TODO: have UPDATES contain {wg_key, ip4 and ip6} and remove only matching addrs */
+static void update_allowed_ips(wg_key *updates, int nupdates)
+{
+ wg_device newdev = { 0 };
+ wg_peer newpeers[WG_DYNAMIC_LEASE_CHUNKSIZE] = { 0 },
+ **nextpp = &newdev.first_peer;
+ wg_allowedip newallowedips[WG_DYNAMIC_LEASE_CHUNKSIZE] = { 0 };
+
+ int newpeers_idx = 0;
+ wg_peer *peer;
+ wg_for_each_peer (device, peer) {
+ for (int i = 0; i < nupdates; i++) {
+ if (!memcmp(peer->public_key, updates[i],
+ sizeof(wg_key))) {
+ wg_peer *pp = &newpeers[newpeers_idx];
+ pp->flags |= WGPEER_REPLACE_ALLOWEDIPS;
+ memcpy(pp->public_key, peer->public_key,
+ sizeof(wg_key));
+
+ /* Whacking all addrs except the first (!) link-local /128 . */
+ wg_allowedip *allowedip;
+ wg_for_each_allowedip (peer, allowedip) {
+ if (allowedip->family == AF_INET6 &&
+ allowedip->cidr == 128 &&
+ IN6_IS_ADDR_LINKLOCAL(
+ &allowedip->ip6)) {
+ wg_allowedip *aip =
+ &newallowedips
+ [newpeers_idx];
+ aip->family = AF_INET6;
+ memcpy(&aip->ip6,
+ &allowedip->ip6,
+ sizeof(struct in6_addr));
+ aip->cidr = 128;
+ pp->first_allowedip = aip;
+ break;
+ }
+ }
+ newpeers_idx++;
+ *nextpp = pp;
+ nextpp = &pp->next_peer;
+ break; /* Assuming no duplicated pubkeys in updates. */
+ }
+ }
+ }
+
+ if (newpeers_idx) {
+ strcpy(newdev.name, wg_interface);
+ if (wg_set_device(&newdev))
+ fatal("wg_set_device()");
+ }
+}
+
static int response_request_ip(struct wg_dynamic_attr *cur, wg_key pubkey,
struct wg_dynamic_lease **lease)
{
@@ -546,7 +599,7 @@ static void poll_loop()
fatal("epoll_ctl()");
while (1) {
- time_t next = leases_refresh() * 1000;
+ time_t next = leases_refresh(update_allowed_ips) * 1000;
int nfds = epoll_wait(epollfd, events, MAX_CONNECTIONS, next);
if (nfds == -1) {
if (errno == EINTR)