From 5d6f048f59f1a5421e44f02bcc444ccd055d8779 Mon Sep 17 00:00:00 2001 From: Thomas Gschwantner Date: Sat, 9 Feb 2019 23:13:31 +0100 Subject: Implement key=value parsing --- wg-dynamic-server.c | 105 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 41 deletions(-) (limited to 'wg-dynamic-server.c') diff --git a/wg-dynamic-server.c b/wg-dynamic-server.c index 8f27acf..81e53f6 100644 --- a/wg-dynamic-server.c +++ b/wg-dynamic-server.c @@ -3,15 +3,16 @@ * Copyright (C) 2015-2019 WireGuard LLC. All Rights Reserved. */ +#define _GNU_SOURCE #define _POSIX_C_SOURCE 200112L -#include #include #include #include -#include #include +#include +#include #include #include #include @@ -175,46 +176,63 @@ static bool valid_peer_found(wg_device *device) return false; } -static void accept_connection(struct pollfd pollfds[]) +static int get_avail_pollfds() { - int nfds; - - pollfds[0].revents = 0; - for (nfds = 1;; ++nfds) { + for (int nfds = 1;; ++nfds) { if (nfds >= MAX_CONNECTIONS + 1) - return; + return -1; if (pollfds[nfds].fd < 0) - break; + return nfds; } - - pollfds[nfds].fd = accept(pollfds[0].fd, NULL, NULL); - if (pollfds[nfds].fd < 0) - fatal("failed to accept connection"); } -static int handle_request(int fd) +static int accept_connection(int sockfd) { - ssize_t read; - uint8_t buf[8192]; + int fd; +#ifdef __linux__ + fd = accept4(sockfd, NULL, NULL, SOCK_NONBLOCK); + if (fd < 0) + fatal("Failed to accept connection"); +#else + fd = accept(sockfd, NULL, NULL); + if (fd < 0) + fatal("Failed to accept connection"); + + int res = fcntl(fd, F_GETFL, 0); + if (res < 0 || fcntl(fd, F_SETFL, res | O_NONBLOCK) < 0) + fatal("Setting socket to nonblocking failed"); +#endif + return fd; +} - read = recv(fd, buf, sizeof buf, 0); - if (read == -1) - fatal("recv()"); +static void close_connection(int *fd, struct wg_dynamic_request *req) +{ + if (close(*fd)) + debug("Failed to close socket"); - buf[read] = '\0'; - debug("%s", buf); - // TODO: do some actual parsing + *fd = -1; + free_wg_dynamic_request(req); +} - if (close(fd)) - debug("failed to close accept() socket"); +static void send_response(int fd, struct wg_dynamic_request *req) +{ + printf("Recieved request 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; + } +} - return 1; +static void send_error(int fd, int ret) +{ + debug("Error: %s\n", strerror(ret)); } static void setup_socket(int *fd) { - int res, val = 1; + int val = 1; struct sockaddr_in6 addr = { .sin6_family = AF_INET6, .sin6_port = htons(WG_DYNAMIC_PORT), @@ -224,19 +242,16 @@ static void setup_socket(int *fd) *fd = socket(AF_INET6, SOCK_STREAM, 0); if (*fd < 0) - fatal("creating a socket failed"); + fatal("Creating a socket failed"); - res = setsockopt(*fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val); - if (res == -1) - fatal("setting socket option failed"); + if (setsockopt(*fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val) == -1) + fatal("Setting socket option failed"); - res = bind(*fd, (struct sockaddr *)&addr, sizeof(addr)); - if (res == -1) - fatal("binding socket failed"); + if (bind(*fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) + fatal("Binding socket failed"); - res = listen(*fd, SOMAXCONN); - if (res == -1) - fatal("listening to socket failed"); + if (listen(*fd, SOMAXCONN) == -1) + fatal("Listening to socket failed"); } static void cleanup() @@ -254,6 +269,8 @@ static void cleanup() int main(int argc, char *argv[]) { + struct wg_dynamic_request reqs[MAX_CONNECTIONS] = { 0 }; + int *sockfd = &pollfds[0].fd, n; const char *iface; progname = argv[0]; @@ -283,22 +300,28 @@ int main(int argc, char *argv[]) if (!valid_peer_found(device)) die("%s has no peers with link-local allowedips\n", iface); - setup_socket(&pollfds[0].fd); + setup_socket(sockfd); while (1) { if (poll(pollfds, MAX_CONNECTIONS + 1, -1) == -1) fatal("Failed to poll() fds"); - if (pollfds[0].revents & POLLIN) - accept_connection(pollfds); + if (pollfds[0].revents & POLLIN) { + n = get_avail_pollfds(); + if (n >= 0) { + pollfds[0].revents = 0; + pollfds[n].fd = accept_connection(*sockfd); + } + } for (int i = 1; i < MAX_CONNECTIONS + 1; ++i) { if (!(pollfds[i].revents & POLLIN)) continue; pollfds[i].revents = 0; - if (handle_request(pollfds[i].fd) > 0) - pollfds[i].fd = -1; + if (handle_request(pollfds[i].fd, &reqs[i - 1], + send_response, send_error)) + close_connection(&pollfds[i].fd, &reqs[i - 1]); } } -- cgit v1.2.3-59-g8ed1b