aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gschwantner <tharre3@gmail.com>2019-09-14 19:43:33 +0200
committerThomas Gschwantner <tharre3@gmail.com>2019-12-11 06:22:17 +0100
commitd69ddbec4d9e5ebed0e7de4a9c7fa04ffcddefce (patch)
treed0a1e1852b78b2fe03698c7fb6d1a38c06f67a7e
parentExtract all RTNETLINK code into ipm.{c,h} (diff)
downloadwg-dynamic-d69ddbec4d9e5ebed0e7de4a9c7fa04ffcddefce.tar.xz
wg-dynamic-d69ddbec4d9e5ebed0e7de4a9c7fa04ffcddefce.zip
Fixup client, including a lot of refactoring
-rw-r--r--Makefile2
-rw-r--r--common.c8
-rw-r--r--common.h1
-rw-r--r--wg-dynamic-client.c550
4 files changed, 197 insertions, 364 deletions
diff --git a/Makefile b/Makefile
index 720acb8..dc381c3 100644
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ COMPILE.c = @echo " CC $@";
COMPILE.c += $(BUILT_IN_COMPILE.c)
endif
-all: wg-dynamic-server
+all: wg-dynamic-server wg-dynamic-client
wg-dynamic-client: wg-dynamic-client.o netlink.o common.o ipm.o
wg-dynamic-server: wg-dynamic-server.o netlink.o radix-trie.o common.o random.o lease.o ipm.o
diff --git a/common.c b/common.c
index da9226e..fae76f7 100644
--- a/common.c
+++ b/common.c
@@ -371,14 +371,6 @@ void print_to_buf(char *buf, size_t bufsize, size_t *offset, char *fmt, ...)
*offset += n;
}
-uint32_t current_time()
-{
- struct timespec tp;
- if (clock_gettime(CLOCK_REALTIME, &tp))
- fatal("clock_gettime(CLOCK_REALTIME)");
- return tp.tv_sec;
-}
-
bool is_link_local(unsigned char *addr)
{
/* TODO: check if the remaining 54 bits are 0 */
diff --git a/common.h b/common.h
index 0bb0741..779477f 100644
--- a/common.h
+++ b/common.h
@@ -93,6 +93,5 @@ void free_wg_dynamic_request(struct wg_dynamic_request *req);
size_t serialize_request_ip(bool include_header, char *buf, size_t len,
struct wg_dynamic_request_ip *rip);
void print_to_buf(char *buf, size_t bufsize, size_t *offset, char *fmt, ...);
-uint32_t current_time();
bool is_link_local(unsigned char *addr);
#endif
diff --git a/wg-dynamic-client.c b/wg-dynamic-client.c
index f3e3274..e425a27 100644
--- a/wg-dynamic-client.c
+++ b/wg-dynamic-client.c
@@ -2,446 +2,288 @@
*
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
*/
+#define _POSIX_C_SOURCE 200112L
-#include <fcntl.h>
-#include <poll.h>
+#include <arpa/inet.h>
#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
#include <unistd.h>
-#include <arpa/inet.h>
-#include <libmnl/libmnl.h>
-#include <linux/rtnetlink.h>
-
#include "common.h"
#include "dbg.h"
+#include "ipm.h"
#include "netlink.h"
-struct wg_dynamic_lease {
- struct wg_combined_ip ip4;
- struct wg_combined_ip ip6;
- uint32_t start;
- uint32_t leasetime;
- struct wg_dynamic_lease *next;
-};
-
static const char *progname;
static const char *wg_interface;
+static struct in6_addr well_known;
+static struct in6_addr lladdr;
+
+static struct in_addr ipv4;
+static struct in6_addr ipv6;
+static bool ipv4_assigned = false, ipv6_assigned = false;
+
static wg_device *device = NULL;
-static int our_fd = -1;
-static struct in6_addr our_lladdr = { 0 };
-static struct wg_combined_ip our_gaddr4 = { 0 };
-static struct wg_combined_ip our_gaddr6 = { 0 };
-static struct wg_dynamic_lease our_lease = { 0 };
-
-struct mnl_cb_data {
- uint32_t ifindex;
- struct in6_addr *lladdr;
- struct wg_combined_ip *gaddr4;
- struct wg_combined_ip *gaddr6;
-};
+static int sockfd = -1;
+
+static volatile sig_atomic_t should_exit = 0;
static void usage()
{
die("usage: %s <wg-interface>\n", progname);
}
-int data_cb(const struct nlmsghdr *nlh, void *data)
-{
- struct nlattr *tb[IFA_MAX + 1] = {};
- struct ifaddrmsg *ifa = mnl_nlmsg_get_payload(nlh);
- struct mnl_cb_data *cb_data = (struct mnl_cb_data *)data;
- unsigned char *addr;
-
- if (ifa->ifa_index != cb_data->ifindex)
- return MNL_CB_OK;
-
- mnl_attr_parse(nlh, sizeof(*ifa), data_attr_cb, tb);
-
- if (!tb[IFA_ADDRESS])
- return MNL_CB_OK;
-
- addr = mnl_attr_get_payload(tb[IFA_ADDRESS]);
- char out[INET6_ADDRSTRLEN];
- inet_ntop(ifa->ifa_family, addr, out, sizeof(out));
- debug("index=%d, family=%d, addr=%s\n", ifa->ifa_index, ifa->ifa_family,
- out);
-
- if (ifa->ifa_scope == RT_SCOPE_LINK) {
- if (ifa->ifa_prefixlen != 128)
- return MNL_CB_OK;
- memcpy(cb_data->lladdr, addr, 16);
- } else if (ifa->ifa_scope == RT_SCOPE_UNIVERSE) {
- switch (ifa->ifa_family) {
- case AF_INET:
- cb_data->gaddr4->family = ifa->ifa_family;
- memcpy(&cb_data->gaddr4->ip4, addr, 4);
- cb_data->gaddr4->cidr = ifa->ifa_prefixlen;
- break;
- case AF_INET6:
- cb_data->gaddr6->family = ifa->ifa_family;
- memcpy(&cb_data->gaddr6->ip6, addr, 16);
- cb_data->gaddr6->cidr = ifa->ifa_prefixlen;
- break;
- default:
- die("Unknown address family: %u\n", ifa->ifa_family);
- }
- }
-
- return MNL_CB_OK;
-}
-
-static void iface_update(uint16_t cmd, uint16_t flags, uint32_t ifindex,
- const struct wg_combined_ip *addr)
+/* NOTE: do NOT call exit() in here */
+static void cleanup()
{
- struct mnl_socket *nl;
- char buf[MNL_SOCKET_BUFFER_SIZE];
- struct nlmsghdr *nlh;
- unsigned int seq, portid;
- struct ifaddrmsg *ifaddr; /* linux/if_addr.h */
- int ret;
-
- nl = mnl_socket_open(NETLINK_ROUTE);
- if (nl == NULL)
- fatal("mnl_socket_open");
-
- if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
- fatal("mnl_socket_bind");
-
- portid = mnl_socket_get_portid(nl);
- seq = time(NULL);
- nlh = mnl_nlmsg_put_header(buf);
- nlh->nlmsg_seq = seq;
- nlh->nlmsg_type = cmd;
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
- ifaddr = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifaddrmsg));
- ifaddr->ifa_family = addr->family;
- ifaddr->ifa_prefixlen = addr->cidr;
- ifaddr->ifa_scope = RT_SCOPE_UNIVERSE; /* linux/rtnetlink.h */
- ifaddr->ifa_index = ifindex;
- mnl_attr_put(nlh, IFA_LOCAL, addr->family == AF_INET ? 4 : 16, &addr);
-
- if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
- fatal("mnl_socket_sendto");
-
- do {
- ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
- if (ret <= MNL_CB_STOP)
- break;
- ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
- } while (ret > 0);
-
- if (ret == -1)
- fatal("mnl_cb_run/mnl_socket_recvfrom");
+ if (ipv4_assigned && ipm_deladdr_v4(device->ifindex, &ipv4))
+ debug("Failed to cleanup ipv4 address");
+ if (ipv6_assigned && ipm_deladdr_v6(device->ifindex, &ipv6))
+ debug("Failed to cleanup ipv6 address");
- mnl_socket_close(nl);
-}
+ if (sockfd >= 0)
+ close(sockfd);
-static void iface_remove_addr(uint32_t ifindex,
- const struct wg_combined_ip *addr)
-{
- char ipstr[INET6_ADDRSTRLEN];
- debug("removing %s/%u from interface %u\n",
- inet_ntop(addr->family, &addr, ipstr, sizeof ipstr), addr->cidr,
- ifindex);
- iface_update(RTM_DELADDR, 0, ifindex, addr);
+ ipm_free();
+ wg_free_device(device);
}
-static void iface_add_addr(uint32_t ifindex, const struct wg_combined_ip *addr)
+static void handler(int signum)
{
- char ipstr[INET6_ADDRSTRLEN];
- debug("adding %s/%u to interface %u\n",
- inet_ntop(addr->family, &addr, ipstr, sizeof ipstr), addr->cidr,
- ifindex);
- iface_update(RTM_NEWADDR, NLM_F_REPLACE | NLM_F_CREATE, ifindex, addr);
+ UNUSED(signum);
+ should_exit = 1;
}
-static bool get_and_validate_local_addrs(uint32_t ifindex,
- struct in6_addr *lladdr,
- struct wg_combined_ip *gaddr4,
- struct wg_combined_ip *gaddr6)
+static void check_signal()
{
- struct mnl_cb_data cb_data = {
- .ifindex = ifindex,
- .lladdr = lladdr,
- .gaddr4 = gaddr4,
- .gaddr6 = gaddr6,
- };
-
- iface_get_all_addrs(AF_INET, data_cb, &cb_data);
- iface_get_all_addrs(AF_INET6, data_cb, &cb_data);
-
- return !IN6_IS_ADDR_UNSPECIFIED(cb_data.lladdr);
+ if (should_exit)
+ exit(EXIT_FAILURE);
}
-static int try_connect(int *fd)
+static int request_ip(struct wg_dynamic_request_ip *rip)
{
- struct timeval tval = { .tv_sec = 1, .tv_usec = 0 };
- struct sockaddr_in6 our_addr = {
+ unsigned char buf[RECV_BUFSIZE + MAX_LINESIZE];
+ size_t msglen, remaining, off = 0;
+ struct sockaddr_in6 dstaddr = {
.sin6_family = AF_INET6,
- .sin6_addr = our_lladdr,
+ .sin6_addr = well_known,
.sin6_port = htons(WG_DYNAMIC_PORT),
.sin6_scope_id = device->ifindex,
};
- struct sockaddr_in6 their_addr = {
+ struct sockaddr_in6 srcaddr = {
.sin6_family = AF_INET6,
+ .sin6_addr = lladdr,
.sin6_port = htons(WG_DYNAMIC_PORT),
.sin6_scope_id = device->ifindex,
};
+ struct wg_dynamic_request req = {
+ .cmd = WGKEY_REQUEST_IP,
+ .version = 1,
+ .result = rip,
+ };
+ struct timeval timeout = { .tv_sec = 30 };
+ ssize_t ret;
+ int val = 1;
- *fd = socket(AF_INET6, SOCK_STREAM, 0);
- if (*fd < 0)
+ sockfd = socket(AF_INET6, SOCK_STREAM, 0);
+ if (sockfd < 0)
fatal("Creating a socket failed");
- if (setsockopt(*fd, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof tval) == -1)
- fatal("Setting socket option failed");
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val))
+ fatal("setsockopt(SO_REUSEADDR)");
+
+ if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
+ sizeof timeout))
+ fatal("setsockopt(SO_RCVTIMEO)");
+
+ if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,
+ sizeof timeout))
+ fatal("setsockopt(SO_SNDTIMEO)");
- if (bind(*fd, (struct sockaddr *)&our_addr, sizeof(our_addr)))
+ if (bind(sockfd, (struct sockaddr *)&srcaddr, sizeof(srcaddr)))
fatal("Binding socket failed");
- if (inet_pton(AF_INET6, WG_DYNAMIC_ADDR, &their_addr.sin6_addr) != 1)
- fatal("inet_pton()");
+ if (connect(sockfd, (struct sockaddr *)&dstaddr, sizeof(dstaddr)))
+ fatal("connect()");
+
+ if (ipv4_assigned) {
+ memcpy(&rip->ipv4, &ipv4, sizeof rip->ipv4);
+ rip->has_ipv4 = true;
+ }
+ if (ipv6_assigned) {
+ memcpy(&rip->ipv6, &ipv6, sizeof rip->ipv6);
+ rip->has_ipv6 = true;
+ }
+
+ msglen = serialize_request_ip(true, (char *)buf, RECV_BUFSIZE, rip);
+ do {
+ ssize_t written = write(sockfd, buf + off, msglen - off);
+ if (written == -1) {
+ if (errno == EINTR) {
+ check_signal();
+ continue;
+ }
+
+ fatal("write()");
+ }
- if (connect(*fd, (struct sockaddr *)&their_addr,
- sizeof(struct sockaddr_in6))) {
- char out[INET6_ADDRSTRLEN];
+ off += written;
+ } while (off < msglen);
- if (!inet_ntop(their_addr.sin6_family, &their_addr.sin6_addr,
- out, sizeof out))
- fatal("inet_ntop()");
- debug("Connecting to [%s]:%u failed: %s\n", out,
- ntohs(their_addr.sin6_port), strerror(errno));
+ memset(rip, 0, sizeof *rip);
+
+ while ((ret = handle_request(sockfd, &req, buf, &remaining)) <= 0) {
+ if (ret == 0) {
+ check_signal();
+ continue;
+ }
+
+ if (close(sockfd))
+ debug("Failed to close socket: %s\n", strerror(errno));
- if (close(*fd))
- debug("Closing socket failed: %s\n", strerror(errno));
- *fd = -1;
return -1;
}
- return 0;
-}
+ if (remaining > 0)
+ log_err("Warning: discarding %zu extra bytes sent by the server\n",
+ remaining);
-static void request_ip(int fd, const struct wg_dynamic_lease *lease)
-{
- unsigned char buf[MAX_RESPONSE_SIZE + 1];
- char addrstr[INET6_ADDRSTRLEN];
- size_t msglen;
-
- msglen = 0;
- msglen += print_to_buf((char *)buf, sizeof buf, msglen, "%s=%d\n",
- WG_DYNAMIC_KEY[WGKEY_REQUEST_IP], 1);
-
- if (lease && lease->ip4.ip4.s_addr) {
- if (!inet_ntop(AF_INET, &lease->ip4.ip4, addrstr,
- sizeof addrstr))
- fatal("inet_ntop()");
- msglen += print_to_buf((char *)buf, sizeof buf, msglen,
- "ipv4=%s/32\n", addrstr);
+ if (rip->wg_errno)
+ return -1;
+
+ if (!ipv4_assigned || memcmp(&ipv4, &rip->ipv4, sizeof ipv4)) {
+ if (ipv4_assigned && ipm_deladdr_v4(device->ifindex, &ipv4))
+ fatal("ipm_deladdr_v4()");
+
+ memcpy(&ipv4, &rip->ipv4, sizeof ipv4);
+ if (ipm_newaddr_v4(device->ifindex, &ipv4))
+ fatal("ipm_newaddr_v4()");
+ ipv4_assigned = true;
}
- if (lease && !IN6_IS_ADDR_UNSPECIFIED(&lease->ip6.ip6)) {
- if (!inet_ntop(AF_INET6, &lease->ip6.ip6, addrstr,
- sizeof addrstr))
- fatal("inet_ntop()");
- msglen += print_to_buf((char *)buf, sizeof buf, msglen,
- "ipv6=%s/128\n", addrstr);
+
+ if (!ipv6_assigned || memcmp(&ipv6, &rip->ipv6, sizeof ipv6)) {
+ if (ipv6_assigned && ipm_deladdr_v6(device->ifindex, &ipv6))
+ fatal("ipm_deladdr_v6()");
+
+ memcpy(&ipv6, &rip->ipv6, sizeof ipv6);
+ if (ipm_newaddr_v6(device->ifindex, &ipv6))
+ fatal("ipm_newaddr_v6()");
+ ipv6_assigned = true;
}
- /* nmsglen += print_to_buf((char *)buf, sizeof buf, msglen,
- "leasetime=%u\n", fixme); */
- msglen += print_to_buf((char *)buf, sizeof buf, msglen, "\n");
+ if (close(sockfd))
+ debug("Failed to close socket: %s\n", strerror(errno));
- send_message(fd, buf, &msglen);
+ return 0;
}
-static uint32_t time_until_refresh(uint32_t now, struct wg_dynamic_lease *lease)
+static void setup()
{
- uint32_t refresh_at;
+ struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 };
+ struct wg_combined_ip ip;
+ int ret;
- if (lease->leasetime == 0)
- return 0;
- refresh_at = lease->start + (lease->leasetime * 8) / 10;
+ if (atexit(cleanup))
+ die("Failed to set exit function\n");
- if (refresh_at < now)
- return 0;
- return refresh_at - now;
-}
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGINT, &sa, NULL) == -1)
+ fatal("sigaction()");
-static int handle_received_lease(const struct wg_dynamic_request *req)
-{
- uint32_t ret;
- struct wg_dynamic_attr *attr;
- struct wg_dynamic_lease *lease = &our_lease;
- uint32_t now = current_time();
- uint32_t lease_start = 0;
- uint32_t curleasetime = lease->start + lease->leasetime;
-
- attr = req->first;
- while (attr) {
- switch (attr->key) {
- case WGKEY_IPV4:
- memcpy(&lease->ip4, attr->value,
- sizeof(struct wg_combined_ip));
- break;
- case WGKEY_IPV6:
- memcpy(&lease->ip6, attr->value,
- sizeof(struct wg_combined_ip));
- break;
- case WGKEY_LEASESTART:
- memcpy(&lease_start, attr->value, sizeof(uint32_t));
- break;
- case WGKEY_LEASETIME:
- memcpy(&lease->leasetime, attr->value,
- sizeof(uint32_t));
- break;
- case WGKEY_ERRNO:
- memcpy(&ret, attr->value, sizeof(uint32_t));
- if (ret) {
- debug("Request IP failed with %ud from server\n",
- ret);
- return -ret;
- }
- break;
- case WGKEY_ERRMSG:
- /* TODO: do something with the error message */
- break;
- default:
- debug("Ignoring invalid attribute for request_ip: %d\n",
- attr->key);
- }
- attr = attr->next;
- }
-
- if (lease->leasetime == 0 || (lease->ip4.ip4.s_addr == 0 &&
- IN6_IS_ADDR_UNSPECIFIED(&lease->ip6.ip6)))
- return -EINVAL;
+ if (wg_get_device(&device, wg_interface))
+ fatal("Unable to access interface %s", wg_interface);
- if (abs(now - lease_start) < 15)
- lease->start = lease_start;
- else
- lease->start = now;
+ if (inet_pton(AF_INET6, WG_DYNAMIC_ADDR, &well_known) != 1)
+ fatal("inet_pton()");
- debug("Replacing lease %u -> %u\n", curleasetime,
- lease->start + lease->leasetime);
+ ipm_init();
- return 0;
-}
+ ret = ipm_getlladdr(device->ifindex, &ip);
+ if (ret == -1)
+ fatal("ipm_getlladdr()");
-static void cleanup()
-{
- wg_free_device(device);
- if (our_fd != -1 && close(our_fd))
- debug("Failed to close fd %d\n", our_fd);
-}
+ if (ret == -2 || ip.family != AF_INET6)
+ die("%s needs to be assigned an IPv6 link local address\n",
+ wg_interface);
-static bool handle_error(int fd, int ret)
-{
- UNUSED(fd);
- UNUSED(ret);
+ if (ret == -3)
+ die("Interface must not have multiple link-local addresses assigned\n");
- debug("Unable to parse response: %s\n", strerror(ret));
+ if (ip.cidr != 128)
+ die("Link-local address must have a CIDR of 128\n");
- return true;
+ memcpy(&lladdr, &ip, 16);
}
-static void maybe_update_iface()
+static void xnanosleep(time_t duration)
{
- if (memcmp(&our_gaddr4, &our_lease.ip4, sizeof our_gaddr4) ||
- our_gaddr4.cidr != our_lease.ip4.cidr) {
- if (our_gaddr4.ip4.s_addr)
- iface_remove_addr(device->ifindex, &our_gaddr4);
- iface_add_addr(device->ifindex, &our_lease.ip4);
- memcpy(&our_gaddr4, &our_lease.ip4, sizeof our_gaddr4);
- }
- if (memcmp(&our_gaddr6, &our_lease.ip6, sizeof our_gaddr6) ||
- our_gaddr6.cidr != our_lease.ip6.cidr) {
- if (!IN6_IS_ADDR_UNSPECIFIED(&our_gaddr6.ip6))
- iface_remove_addr(device->ifindex, &our_gaddr6);
- iface_add_addr(device->ifindex, &our_lease.ip6);
- memcpy(&our_gaddr6, &our_lease.ip6, sizeof our_gaddr6);
+ struct timespec rem, timeout = { .tv_sec = duration };
+ int ret;
+
+ while ((ret = clock_nanosleep(CLOCK_BOOTTIME, 0, &timeout, &rem))) {
+ if (ret == EINTR) {
+ check_signal();
+ memcpy(&timeout, &rem, sizeof timeout);
+ continue;
+ }
+
+ die("clock_nanosleep(): %s\n", strerror(ret));
}
}
-static bool handle_response(int fd, struct wg_dynamic_request *req)
+static void loop()
{
- UNUSED(fd);
-
-#if 0
- printf("Recieved response of type %s.\n", WG_DYNAMIC_KEY[req->cmd]);
- struct wg_dynamic_attr *cur = req->first;
- while (cur) {
- printf(" with attr %s.\n", WG_DYNAMIC_KEY[cur->key]);
- cur = cur->next;
+ struct wg_dynamic_request_ip rip = { 0 };
+ struct timespec tsend, trecv;
+ time_t expires, timeout;
+
+ if (clock_gettime(CLOCK_REALTIME, &tsend))
+ fatal("clock_gettime(CLOCK_REALTIME)");
+
+ if (request_ip(&rip)) {
+ /* TODO: implement some sort of exponential backoff */
+ debug("Server communication error, trying again in 30s\n");
+ xnanosleep(30);
+ return;
}
-#endif
-
- switch (req->cmd) {
- case WGKEY_REQUEST_IP:
- if (handle_received_lease(req) == 0)
- maybe_update_iface();
- break;
- default:
- debug("Unknown command: %d\n", req->cmd);
- return true;
+
+ if (clock_gettime(CLOCK_REALTIME, &trecv))
+ fatal("clock_gettime(CLOCK_REALTIME)");
+
+ if (tsend.tv_sec < rip.start + 5 || rip.start > trecv.tv_sec + 5)
+ expires = tsend.tv_sec + rip.leasetime;
+ else
+ expires = MIN(rip.leasetime, trecv.tv_sec) + rip.leasetime;
+
+ if (expires <= trecv.tv_sec) {
+ log_err("Warning: lease we tried to aquire already expired\n");
+ return;
}
- return true;
+ /* TODO: implement random jitter */
+ timeout = (expires - trecv.tv_sec);
+ timeout -= MIN(30, timeout * 0.5);
+
+ debug("Sleeping for %zus\n", timeout);
+ xnanosleep(timeout);
}
-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
+int main(int argc, char *argv[])
{
- int *fd = &our_fd;
- struct wg_dynamic_request req = { 0 };
-
progname = argv[0];
if (argc != 2)
usage();
wg_interface = argv[1];
+ setup();
- if (wg_get_device(&device, wg_interface))
- fatal("Unable to access interface %s", wg_interface);
-
- if (atexit(cleanup))
- die("Failed to set exit function\n");
-
- if (!get_and_validate_local_addrs(device->ifindex, &our_lladdr,
- &our_gaddr4, &our_gaddr6))
- die("%s needs to have an IPv6 link local address with prefixlen 128 assigned\n",
- wg_interface);
- // TODO: verify that we have a peer with an allowed-ips including fe80::/128
-
- char lladr_str[INET6_ADDRSTRLEN];
- debug("%s: %s\n", wg_interface,
- inet_ntop(AF_INET6, &our_lladdr, lladr_str, sizeof lladr_str));
-
- /* If we have an address configured, let's assume it's from a
- * lease in order to get renewal done. */
- if (our_gaddr4.ip4.s_addr ||
- !IN6_IS_ADDR_UNSPECIFIED(&our_gaddr6.ip6)) {
- our_lease.start = current_time();
- our_lease.leasetime = 15;
- memcpy(&our_lease.ip4, &our_gaddr4,
- sizeof(struct wg_combined_ip));
- memcpy(&our_lease.ip6, &our_gaddr6,
- sizeof(struct wg_combined_ip));
- }
-
- while (1) {
- sleep(time_until_refresh(current_time(), &our_lease));
-
- if (*fd == -1 && try_connect(fd)) {
- sleep(1);
- continue;
- }
-
- request_ip(*fd, &our_lease);
-
- while (!handle_request(&req, handle_response, handle_error))
- ;
- close_connection(&req);
- }
+ while (1)
+ loop();
return 0;
}