aboutsummaryrefslogtreecommitdiffstats
path: root/wg-dynamic-server.c
diff options
context:
space:
mode:
authorThomas Gschwantner <tharre3@gmail.com>2019-02-09 23:13:31 +0100
committerThomas Gschwantner <tharre3@gmail.com>2019-02-09 23:13:31 +0100
commit5d6f048f59f1a5421e44f02bcc444ccd055d8779 (patch)
tree16f6e2fed1c61ba2f32f7148cdefe9f88b1443fd /wg-dynamic-server.c
parentFix licensing headers (diff)
downloadwg-dynamic-5d6f048f59f1a5421e44f02bcc444ccd055d8779.tar.xz
wg-dynamic-5d6f048f59f1a5421e44f02bcc444ccd055d8779.zip
Implement key=value parsing
Diffstat (limited to 'wg-dynamic-server.c')
-rw-r--r--wg-dynamic-server.c105
1 files changed, 64 insertions, 41 deletions
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 <arpa/inet.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <time.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/types.h>
@@ -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]);
}
}