aboutsummaryrefslogtreecommitdiffstats
path: root/wg-dynamic-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'wg-dynamic-server.c')
-rw-r--r--wg-dynamic-server.c110
1 files changed, 63 insertions, 47 deletions
diff --git a/wg-dynamic-server.c b/wg-dynamic-server.c
index 0f16710..feb9656 100644
--- a/wg-dynamic-server.c
+++ b/wg-dynamic-server.c
@@ -9,7 +9,6 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <time.h>
#include <arpa/inet.h>
@@ -30,10 +29,11 @@
#include "netlink.h"
static const char *progname;
-static const char *wg_interface;
+static const char *wg_interface = NULL;
static struct in6_addr well_known;
static wg_device *device = NULL;
+static uint32_t leasetime = WG_DYNAMIC_DEFAULT_LEASETIME;
static int sockfd = -1;
static int epollfd = -1;
@@ -46,6 +46,7 @@ struct wg_dynamic_connection {
struct wg_dynamic_request req;
int fd;
wg_key pubkey;
+ struct in6_addr lladdr;
unsigned char *outbuf;
size_t buflen;
};
@@ -54,7 +55,7 @@ static struct wg_dynamic_connection connections[MAX_CONNECTIONS] = { 0 };
static void usage()
{
- die("usage: %s <wg-interface>\n", progname);
+ die("usage: %s [--leasetime <leasetime>] <wg-interface>\n", progname);
}
static bool valid_peer_found(wg_device *device)
@@ -128,7 +129,8 @@ static wg_key *addr_to_pubkey(struct sockaddr_storage *addr)
return NULL;
}
-static int accept_connection(wg_key *dest)
+static int accept_connection(wg_key *dest_pubkey,
+ struct in6_addr *dest_lladdr)
{
int fd;
wg_key *pubkey;
@@ -172,7 +174,10 @@ static int accept_connection(wg_key *dest)
return -ENOENT;
}
}
- memcpy(dest, pubkey, sizeof *dest);
+ memcpy(dest_pubkey, pubkey, sizeof *dest_pubkey);
+
+ memcpy(dest_lladdr, &((struct sockaddr_in6 *)&addr)->sin6_addr,
+ sizeof *dest_lladdr);
wg_key_b64_string key;
char out[INET6_ADDRSTRLEN];
@@ -216,7 +221,6 @@ static bool send_message(struct wg_dynamic_connection *con,
con->outbuf = malloc(con->buflen);
if (!con->outbuf)
fatal("malloc()");
-
memcpy(con->outbuf, buf + offset, con->buflen);
} else {
con->buflen = len - offset;
@@ -240,40 +244,6 @@ void close_connection(struct wg_dynamic_connection *con)
con->buflen = 0;
}
-static void add_allowed_ips(wg_key pubkey, struct in_addr *ipv4,
- struct in6_addr *ipv6)
-{
- wg_allowedip allowed_v4, allowed_v6;
- wg_peer peer = { 0 };
- wg_device dev = { .first_peer = &peer };
-
- strcpy(dev.name, wg_interface);
- memcpy(peer.public_key, pubkey, sizeof peer.public_key);
- wg_allowedip **cur = &peer.first_allowedip;
-
- if (ipv4) {
- allowed_v4 = (wg_allowedip){
- .family = AF_INET,
- .cidr = 32,
- .ip4 = *ipv4,
- };
- *cur = &allowed_v4;
- cur = &allowed_v4.next_allowedip;
- }
-
- if (ipv6) {
- allowed_v6 = (wg_allowedip){
- .family = AF_INET6,
- .cidr = 128,
- .ip6 = *ipv6,
- };
- *cur = &allowed_v6;
- }
-
- if (wg_set_device(&dev))
- fatal("wg_set_device()");
-}
-
static bool send_response(struct wg_dynamic_connection *con)
{
char buf[MAX_RESPONSE_SIZE];
@@ -282,19 +252,19 @@ static bool send_response(struct wg_dynamic_connection *con)
switch (con->req.cmd) {
case WGKEY_REQUEST_IP:;
struct wg_dynamic_request_ip *rip = con->req.result;
+ struct in6_addr *lladdr = &con->lladdr;
struct in_addr *ip4 = rip->has_ipv4 ? &rip->ipv4 : NULL;
struct in6_addr *ip6 = rip->has_ipv6 ? &rip->ipv6 : NULL;
struct wg_dynamic_lease *lease;
struct wg_dynamic_request_ip ans = { 0 };
- lease = new_lease(con->pubkey, WG_DYNAMIC_LEASETIME, ip4, ip6);
+ lease = set_lease(wg_interface, con->pubkey, leasetime, lladdr, ip4, ip6);
if (lease) {
memcpy(&ans.ipv4, &lease->ipv4, sizeof ans.ipv4);
memcpy(&ans.ipv6, &lease->ipv6, sizeof ans.ipv6);
ans.has_ipv4 = ans.has_ipv6 = true;
ans.start = lease->start_real;
ans.leasetime = lease->leasetime;
- add_allowed_ips(con->pubkey, &ans.ipv4, &ans.ipv6);
} else {
ans.wg_errno = E_IP_UNAVAIL;
}
@@ -402,6 +372,33 @@ static void cleanup()
}
}
+static void init_leaess_from_peers()
+{
+ wg_peer *peer;
+
+ wg_for_each_peer (device, peer) {
+ wg_allowedip *allowedip;
+ struct in6_addr *lladdr = NULL;
+ struct in_addr *ipv4 = NULL;
+ struct in6_addr *ipv6 = NULL;
+ wg_for_each_allowedip (peer, allowedip) {
+ if (allowedip->family == AF_INET6 &&
+ IN6_IS_ADDR_LINKLOCAL(&allowedip->ip6))
+ lladdr = &allowedip->ip6;
+ else if (allowedip->family == AF_INET && !ipv4)
+ ipv4 = &allowedip->ip4;
+ else if (allowedip->family == AF_INET6 && !ipv6)
+ ipv6 = &allowedip->ip6;
+ }
+
+ if (!ipv4 && !ipv6)
+ continue;
+
+ set_lease(wg_interface, peer->public_key, leasetime, lladdr,
+ ipv4, ipv6);
+ }
+}
+
static void setup()
{
struct wg_combined_ip ip;
@@ -442,7 +439,8 @@ static void setup()
wg_interface);
setup_sockets();
- leases_init("leases_file", nlsock);
+ leases_init(NULL, nlsock);
+ init_leaess_from_peers();
}
static int get_avail_request()
@@ -462,7 +460,7 @@ static void accept_incoming()
struct epoll_event ev;
while ((n = get_avail_request()) >= 0) {
- fd = accept_connection(&connections[n].pubkey);
+ fd = accept_connection(&connections[n].pubkey, &connections[n].lladdr);
if (fd < 0) {
if (fd == -ENOENT) {
debug("Failed to match IP to pubkey\n");
@@ -528,7 +526,7 @@ static void poll_loop()
fatal("epoll_ctl()");
while (1) {
- time_t next = leases_refresh() * 1000;
+ time_t next = leases_refresh(wg_interface) * 1000;
int nfds = epoll_wait(epollfd, events, MAX_CONNECTIONS, next);
if (nfds == -1) {
if (errno == EINTR)
@@ -544,11 +542,29 @@ static void poll_loop()
int main(int argc, char *argv[])
{
+ char *endptr = NULL;
+
progname = argv[0];
- if (argc != 2)
+ ++argv;
+ --argc;
+
+ while (argc > 0) {
+ if (!strcmp(argv[0], "--leasetime") && argc >= 2) {
+ leasetime = (uint32_t) strtoul(argv[1], &endptr, 10);
+ if (*endptr)
+ usage();
+ argv += 2;
+ argc -= 2;
+ } else {
+ wg_interface = argv[0];
+ argv += 1;
+ argc -= 1;
+ break;
+ }
+ }
+ if (!wg_interface || argc > 0)
usage();
- wg_interface = argv[1];
setup();
poll_loop();