diff options
Diffstat (limited to 'wg-dynamic-server.c')
-rw-r--r-- | wg-dynamic-server.c | 98 |
1 files changed, 65 insertions, 33 deletions
diff --git a/wg-dynamic-server.c b/wg-dynamic-server.c index b3cd417..25660db 100644 --- a/wg-dynamic-server.c +++ b/wg-dynamic-server.c @@ -189,50 +189,80 @@ static int get_avail_pollfds() } } -static void accept_connection(int fd, struct pollfd *pfd) +static int accept_connection(int sockfd) { - // struct sockaddr_storage; - + int fd; #ifdef __linux__ - pfd->fd = accept4(fd, NULL, NULL, SOCK_NONBLOCK); + fd = accept4(sockfd, NULL, NULL, SOCK_NONBLOCK); + if (fd < 0) + fatal("Failed to accept connection"); #else - pfd->fd = accept(fd, NULL, NULL); - int res = fcntl(pfd->fd, F_GETFL, 0); - if (res < 0 || fcntl(pfd->fd, F_SETFL, res | O_NONBLOCK) < 0) + 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; +} - if (pfd->fd < 0) - fatal("Failed to accept connection"); +static void close_connection(int *fd, struct wg_dynamic_request *req) +{ + if (close(*fd)) + debug("Failed to close socket"); + + *fd = -1; + free_wg_dynamic_request(req); } -static int handle_request(int fd) +static void response(struct wg_dynamic_request *req) { - ssize_t read; + 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; + } +} + +static bool handle_request(int fd, struct wg_dynamic_request *req) +{ + ssize_t bytes; + int ret; unsigned char buf[RECV_BUFSIZE + MAX_LINESIZE]; - struct wg_dynamic_request req = { - .cmd = WGKEY_UNKNOWN, - .version = 0, - .first = NULL, - .last = NULL, - }; while (1) { - read = recv(fd, buf, RECV_BUFSIZE, 0); - if (read >= 0) { - parse_request(&req, buf, read); - } else { + /* read = recv(fd, buf, RECV_BUFSIZE, 0); */ + bytes = read(fd, buf, RECV_BUFSIZE); + if (bytes < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) break; - fatal("recv()"); + // TODO: handle EINTR + + debug("Reading from socket failed: %s\n", + strerror(errno)); + return true; + } else if (bytes == 0) { + debug("Client disconnected unexpectedly\n"); + return true; } - } - if (close(fd)) - debug("failed to close accept() socket"); + ret = parse_request(req, buf, bytes); + if (ret < 0) { + // TODO: send error message back + debug("Error: %s\n", strerror(-ret)); + return true; + } else if (ret == 0) { + // TODO: complete message, validate? and answer + response(req); + return true; + } + } - return 1; + return false; } static void setup_socket(int *fd) @@ -274,8 +304,9 @@ 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; - int n; progname = argv[0]; inet_pton(AF_INET6, WG_DYNAMIC_ADDR, &well_known); @@ -304,17 +335,18 @@ 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) { - pollfds[0].revents = 0; n = get_avail_pollfds(); - if (n >= 0) - accept_connection(pollfds[0].fd, &pollfds[n]); + if (n >= 0) { + pollfds[0].revents = 0; + pollfds[n].fd = accept_connection(*sockfd); + } } for (int i = 1; i < MAX_CONNECTIONS + 1; ++i) { @@ -322,8 +354,8 @@ int main(int argc, char *argv[]) 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])) + close_connection(&pollfds[i].fd, &reqs[i - 1]); } } |