diff options
author | Linus Nordberg <linus@nordberg.se> | 2019-03-11 15:48:19 +0100 |
---|---|---|
committer | Linus Nordberg <linus@nordberg.se> | 2019-03-11 15:48:19 +0100 |
commit | 25e086b36cf6cd07ec8bff7119b5dc3c6b0e750e (patch) | |
tree | 2c13470069d1f7ff536256b0f745875c281302f2 /wg-dynamic-server.c | |
parent | Fix debug printout. (diff) | |
download | wg-dynamic-25e086b36cf6cd07ec8bff7119b5dc3c6b0e750e.tar.xz wg-dynamic-25e086b36cf6cd07ec8bff7119b5dc3c6b0e750e.zip |
WIP respond request_ip with whatever client asks for
Diffstat (limited to 'wg-dynamic-server.c')
-rw-r--r-- | wg-dynamic-server.c | 149 |
1 files changed, 127 insertions, 22 deletions
diff --git a/wg-dynamic-server.c b/wg-dynamic-server.c index 0a771a4..89a2d86 100644 --- a/wg-dynamic-server.c +++ b/wg-dynamic-server.c @@ -24,6 +24,8 @@ #include "dbg.h" #include "netlink.h" +#define MAX_RESPONSE_SIZE 8192 + static const char *progname; static struct in6_addr well_known; @@ -215,12 +217,108 @@ static void close_connection(int *fd, struct wg_dynamic_request *req) free_wg_dynamic_request(req); } +static int allocate_from_pool(struct wg_dynamic_request * const req, + struct wg_combined_ip addrs[2], uint32_t *expires) +{ + struct wg_dynamic_attr *attr; + int i; + + /* NOTE: "allocating" whatever client asks for */ + /* TODO: choose an ip address from pool of available + * addresses, together with an appropriate lease time */ + /* NOTE: the pool is to be drawn from what routes are pointing + * to the wg interface, and kept up to date as the routing + * table changes */ + + *expires = time(NULL) + WG_DYNAMIC_LEASETIME; + + i = 0; + attr = req->first; + while (attr) { + switch (attr->key) { + case WGKEY_IPV4: + /* fall through */ + case WGKEY_IPV6: + if (i > 1) + break; + memcpy(&addrs[i++], attr->value, sizeof *addrs); + break; + case WGKEY_LEASETIME: + memcpy(expires, attr->value, sizeof(uint32_t)); + *expires += time(NULL); + break; + default: + debug("Ignoring invalid attribute for request_ip: %d\n", + attr->key); + } + + attr = attr->next; + } + + return 0; +} + +static bool send_error(int fd, int ret) +{ + debug("Error: %s\n", strerror(ret)); + return true; +} + +static void send_later(struct wg_dynamic_request *req, + unsigned char * const buf, size_t msglen) +{ + unsigned char *newbuf = malloc(msglen); + if (!newbuf) + fatal("Failed malloc()"); + memcpy(newbuf, buf, msglen); + + free(req->buf); + req->buf = newbuf; + req->buflen = msglen; +} + +static size_t serialise_lease(char *buf, size_t bufsize, size_t offset, + struct wg_combined_ip addrs[2], uint32_t expires) +{ + char addrbuf[INET6_ADDRSTRLEN]; + char *fmt; + size_t w; + + w = 0; + for (int i = 0; i < 2; i++) { + switch (addrs[i].family) { + case AF_INET: + fmt = "ipv4=%s\n"; + break; + case AF_INET6: + fmt = "ipv6=%s\n"; + break; + default: + fatal("Invalid family: %d", addrs[i].family); + } + + if (!inet_ntop(addrs[i].family, &addrs[i].ip.ip4, addrbuf, + sizeof addrbuf)) + fatal("Failed inet_ntop"); + w += printf_to_buf(buf, bufsize, offset, fmt, addrbuf); + offset += w; + } + + if (w) + offset += printf_to_buf(buf, bufsize, offset, "leasetime=%u\n", + expires); + + return offset; +} + static bool send_response(int fd, struct wg_dynamic_request *req) { - unsigned char buf[8192]; /* FIXME */ - ssize_t len; - unsigned char *newbuf; - size_t to_write; + int ret; + unsigned char buf[MAX_RESPONSE_SIZE+1]; + size_t msglen; + size_t written; + struct wg_combined_ip addrs[2] = { 0 }; + uint32_t expires; printf("Recieved request of type %s.\n", WG_DYNAMIC_KEY[req->cmd]); struct wg_dynamic_attr *cur = req->first; @@ -229,30 +327,37 @@ static bool send_response(int fd, struct wg_dynamic_request *req) cur = cur->next; } -#define REPLY "reply=fake\n\n" - len = sizeof REPLY - 1; - memcpy(buf, REPLY, len); + ret = EINVAL; + msglen = 0; + switch (req->cmd) { + case WGKEY_REQUEST_IP: + msglen = printf_to_buf((char *) buf, sizeof buf, 0, "%s=%d\n", + WG_DYNAMIC_KEY[req->cmd], + WG_DYNAMIC_PROTOCOL_VERSION); + ret = allocate_from_pool(req, addrs, &expires); + if (ret) + break; + msglen += serialise_lease((char *) buf, sizeof buf, msglen, + addrs, expires); + + /* TODO: inform wg about the new address (or maybe if (send_rather wait until after we've closed this tcp if (send_connection?) */ + + break; + default: + debug("Unknown command: %d\n", req->cmd); + return true; + } - to_write = len; - if (send_message(fd, buf, &to_write)) + msglen += printf_to_buf((char *) buf, sizeof buf, msglen, + "errno=%d\n\n", ret); + written = send_message(fd, buf, &msglen); + if (!msglen) return true; - newbuf = malloc(to_write); - if (!newbuf) - fatal("Failed malloc()"); - memcpy(newbuf, buf + len - to_write, to_write); - free(req->buf); - req->buf = newbuf; - req->buflen = to_write; + send_later(req, buf + written, msglen); return false; } -static bool send_error(int fd, int ret) -{ - debug("Error: %s\n", strerror(ret)); - return true; -} - static void setup_socket(int *fd) { int val = 1; |