summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/configure.c294
-rw-r--r--src/fastd.c245
-rw-r--r--src/fastd.h4
-rw-r--r--src/method_ec25519_fhmqvc_xsalsa20_poly1305.c11
-rw-r--r--src/method_null.c5
6 files changed, 315 insertions, 246 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7315aa0..223c62a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -10,5 +10,5 @@ endif(WITH_METHOD_ECFXP)
include_directories(${FASTD_INCLUDES})
-add_executable(fastd fastd.c handshake.c peer.c printf.c queue.c task.c ${METHODS})
+add_executable(fastd fastd.c configure.c handshake.c peer.c printf.c queue.c task.c ${METHODS})
target_link_libraries(fastd rt ${FASTD_LIBS})
diff --git a/src/configure.c b/src/configure.c
new file mode 100644
index 0000000..7473696
--- /dev/null
+++ b/src/configure.c
@@ -0,0 +1,294 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "fastd.h"
+#include "peer.h"
+
+#include <config.h>
+
+#include <arpa/inet.h>
+#include <stdarg.h>
+
+
+extern fastd_method fastd_method_null;
+
+#ifdef WITH_METHOD_ECFXP
+extern fastd_method fastd_method_ec25519_fhmqvc_xsalsa20_poly1305;
+#endif
+
+
+static void default_config(fastd_config *conf) {
+ conf->loglevel = LOG_DEBUG;
+
+ conf->peer_stale_time = 300;
+ conf->peer_stale_time_temp = 30;
+ conf->eth_addr_stale_time = 300;
+
+ conf->ifname = NULL;
+
+ memset(&conf->bind_addr_in, 0, sizeof(struct sockaddr_in));
+ conf->bind_addr_in.sin_family = AF_UNSPEC;
+ conf->bind_addr_in.sin_port = htons(1337);
+ conf->bind_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ memset(&conf->bind_addr_in6, 0, sizeof(struct sockaddr_in6));
+ conf->bind_addr_in6.sin6_family = AF_UNSPEC;
+ conf->bind_addr_in6.sin6_port = htons(1337);
+ conf->bind_addr_in6.sin6_addr = in6addr_any;
+
+ conf->mtu = 1500;
+ conf->protocol = PROTOCOL_ETHERNET;
+ conf->method = &fastd_method_null;
+ conf->peers = NULL;
+}
+
+static bool config_match(const char *opt, ...) {
+ va_list ap;
+ bool match = false;
+ const char *str;
+
+ va_start(ap, opt);
+
+ while((str = va_arg(ap, const char*)) != NULL) {
+ if (strcmp(opt, str) == 0) {
+ match = true;
+ break;
+ }
+ }
+
+ va_end(ap);
+
+ return match;
+}
+
+#define IF_OPTION(args...) if(config_match(argv[i], args, NULL) && (++i))
+#define IF_OPTION_ARG(args...) if(config_match(argv[i], args, NULL) && ({ \
+ arg = argv[i+1]; \
+ i+=2; \
+ if (i > argc) \
+ exit_error(ctx, "config error: option `%s' needs an argument", argv[i-2]); \
+ true; \
+ }))
+#define IGNORE_OPTION (i++)
+
+void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *const argv[]) {
+ default_config(conf);
+
+ fastd_peer_config **current_peer = &conf->peers;
+
+ int i = 1;
+ const char *arg;
+ long l;
+ char *charptr;
+ char *endptr;
+ char *addrstr;
+
+ bool v4_peers = false, v6_peers = false;
+
+
+ conf->n_floating = 0;
+
+
+ while (i < argc) {
+ IF_OPTION_ARG("-i", "--interface") {
+ conf->ifname = arg;
+ continue;
+ }
+
+ IF_OPTION_ARG("-b", "--bind") {
+ if (arg[0] == '[') {
+ charptr = strchr(arg, ']');
+ if (!charptr || (charptr[1] != ':' && charptr[1] != '\0'))
+ exit_error(ctx, "invalid bind address `%s'", arg);
+
+ addrstr = strndup(arg+1, charptr-arg-1);
+
+ if (charptr[1] == ':')
+ charptr++;
+ else
+ charptr = NULL;
+ }
+ else {
+ charptr = strchr(arg, ':');
+ if (charptr) {
+ addrstr = strndup(arg, charptr-arg);
+ }
+ else {
+ addrstr = strdup(arg);
+ }
+ }
+
+ if (charptr) {
+ l = strtol(charptr+1, &endptr, 10);
+ if (*endptr || l > 65535)
+ exit_error(ctx, "invalid bind port `%s'", charptr+1);
+ }
+
+ if (strcmp(addrstr, "any") == 0) {
+ conf->bind_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ conf->bind_addr_in.sin_port = htons(l);
+
+ conf->bind_addr_in6.sin6_addr = in6addr_any;
+ conf->bind_addr_in6.sin6_port = htons(l);
+ }
+ else if (arg[0] == '[') {
+ conf->bind_addr_in6.sin6_family = AF_INET6;
+ if (inet_pton(AF_INET6, addrstr, &conf->bind_addr_in6.sin6_addr) != 1)
+ exit_error(ctx, "invalid bind address `%s'", addrstr);
+ conf->bind_addr_in6.sin6_port = htons(l);
+ }
+ else {
+ conf->bind_addr_in.sin_family = AF_INET;
+ if (inet_pton(AF_INET, addrstr, &conf->bind_addr_in.sin_addr) != 1)
+ exit_error(ctx, "invalid bind address `%s'", addrstr);
+ conf->bind_addr_in.sin_port = htons(l);
+ }
+
+ free(addrstr);
+
+ continue;
+ }
+
+ IF_OPTION_ARG("-M", "--mtu") {
+ conf->mtu = strtol(arg, &endptr, 10);
+ if (*endptr || conf->mtu < 576)
+ exit_error(ctx, "invalid mtu `%s'", arg);
+ continue;
+ }
+
+ IF_OPTION_ARG("-P", "--protocol") {
+ if (!strcmp(arg, "ethernet"))
+ conf->protocol = PROTOCOL_ETHERNET;
+ else if (!strcmp(arg, "ip"))
+ conf->protocol = PROTOCOL_IP;
+ else
+ exit_error(ctx, "invalid protocol `%s'", arg);
+ continue;
+ }
+
+
+ IF_OPTION_ARG("-m", "--method") {
+ if (!strcmp(arg, "null"))
+ conf->method = &fastd_method_null;
+#ifdef WITH_METHOD_ECFXP
+ if (!strcmp(arg, "ecfxp"))
+ conf->method = &fastd_method_ec25519_fhmqvc_xsalsa20_poly1305;
+#endif
+ else
+ exit_error(ctx, "invalid method `%s'", arg);
+ continue;
+ }
+
+ IF_OPTION_ARG("-p", "--peer") {
+ *current_peer = malloc(sizeof(fastd_peer_config));
+ (*current_peer)->next = NULL;
+
+ memset(&(*current_peer)->address, 0, sizeof(fastd_peer_address));
+ if (strcmp(arg, "float") == 0) {
+ (*current_peer)->address.sa.sa_family = AF_UNSPEC;
+ conf->n_floating++;
+ continue;
+ }
+
+ if (arg[0] == '[') {
+ charptr = strchr(arg, ']');
+ if (!charptr || (charptr[1] != ':' && charptr[1] != '\0'))
+ exit_error(ctx, "invalid peer address `%s'", arg);
+
+ addrstr = strndup(arg+1, charptr-arg-1);
+
+ if (charptr[1] == ':')
+ charptr++;
+ else
+ charptr = NULL;
+ }
+ else {
+ charptr = strchr(arg, ':');
+ if (charptr)
+ addrstr = strndup(arg, charptr-arg);
+ else
+ addrstr = strdup(arg);
+ }
+
+ if (charptr) {
+ l = strtol(charptr+1, &endptr, 10);
+ if (*endptr || l > 65535)
+ exit_error(ctx, "invalid peer port `%s'", charptr+1);
+ }
+ else {
+ l = 1337; /* default port */
+ }
+
+ if (arg[0] == '[') {
+ v6_peers = true;
+ (*current_peer)->address.in6.sin6_family = AF_INET6;
+ if (inet_pton(AF_INET6, addrstr, &(*current_peer)->address.in6.sin6_addr) != 1)
+ exit_error(ctx, "invalid peer address `%s'", addrstr);
+ (*current_peer)->address.in6.sin6_port = htons(l);
+ }
+ else {
+ v4_peers = true;
+ (*current_peer)->address.in.sin_family = AF_INET;
+ if (inet_pton(AF_INET, addrstr, &(*current_peer)->address.in.sin_addr) != 1)
+ exit_error(ctx, "invalid peer address `%s'", addrstr);
+ (*current_peer)->address.in.sin_port = htons(l);
+ }
+
+ free(addrstr);
+
+ current_peer = &(*current_peer)->next;
+
+ continue;
+ }
+
+ exit_error(ctx, "config error: unknown option `%s'", argv[i]);
+ }
+
+ if (conf->n_floating && conf->bind_addr_in.sin_family == AF_UNSPEC
+ && conf->bind_addr_in6.sin6_family == AF_UNSPEC) {
+ conf->bind_addr_in.sin_family = AF_INET;
+ conf->bind_addr_in6.sin6_family = AF_INET6;
+ }
+ else if (v4_peers) {
+ conf->bind_addr_in.sin_family = AF_INET;
+ }
+ else if (v6_peers) {
+ conf->bind_addr_in6.sin6_family = AF_INET6;
+ }
+
+ bool ok = true;
+ if (conf->protocol == PROTOCOL_IP && (!conf->peers || conf->peers->next)) {
+ pr_error(ctx, "for protocol `ip' exactly one peer must be configured");
+ ok = false;
+ }
+
+ if (ok)
+ ok = conf->method->check_config(ctx, conf);
+
+ if (!ok)
+ exit_error(ctx, "config error");
+}
diff --git a/src/fastd.c b/src/fastd.c
index 496df97..cae7c64 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -30,28 +30,16 @@
#include "peer.h"
#include "task.h"
-#include <config.h>
-
-#include <arpa/inet.h>
#include <fcntl.h>
-#include <getopt.h>
#include <linux/if_tun.h>
#include <net/if.h>
#include <poll.h>
-#include <stdarg.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
-extern fastd_method fastd_method_null;
-
-#ifdef WITH_METHOD_ECFXP
-extern fastd_method fastd_method_ec25519_fhmqvc_xsalsa20_poly1305;
-#endif
-
-
static void init_tuntap(fastd_context *ctx) {
struct ifreq ifr;
@@ -126,237 +114,6 @@ static void init_socket(fastd_context *ctx) {
}
}
-static void default_config(fastd_config *conf) {
- conf->loglevel = LOG_DEBUG;
-
- conf->peer_stale_time = 300;
- conf->peer_stale_time_temp = 30;
- conf->eth_addr_stale_time = 300;
-
- conf->ifname = NULL;
-
- memset(&conf->bind_addr_in, 0, sizeof(struct sockaddr_in));
- conf->bind_addr_in.sin_family = AF_UNSPEC;
- conf->bind_addr_in.sin_port = htons(1337);
- conf->bind_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
-
- memset(&conf->bind_addr_in6, 0, sizeof(struct sockaddr_in6));
- conf->bind_addr_in6.sin6_family = AF_UNSPEC;
- conf->bind_addr_in6.sin6_port = htons(1337);
- conf->bind_addr_in6.sin6_addr = in6addr_any;
-
- conf->mtu = 1500;
- conf->protocol = PROTOCOL_ETHERNET;
- conf->method = &fastd_method_null;
- conf->peers = NULL;
-}
-
-static void configure(fastd_context *ctx, fastd_config *conf, int argc, char *argv[]) {
- default_config(conf);
-
- fastd_peer_config **current_peer = &conf->peers;
-
- static const struct option long_options[] = {
- {"interface", required_argument, 0, 'i'},
- {"bind", required_argument, 0, 'b'},
- {"mtu", required_argument, 0, 'M'},
- {"protocol", required_argument, 0, 'P'},
- {"method", required_argument, 0, 'm'},
- {"peer", required_argument, 0, 'p'},
- {0, 0, 0, 0}
- };
-
- int c;
- int option_index = 0;
- long l;
- char *charptr;
- char *endptr;
- char *addrstr;
-
- bool v4_peers = false, v6_peers = false;
-
-
- conf->n_floating = 0;
-
- while ((c = getopt_long (argc, argv, "i:b:M:P:m:p:", long_options, &option_index)) != -1) {
- switch(c) {
- case 'i':
- conf->ifname = optarg;
- break;
-
- case 'b':
- if (optarg[0] == '[') {
- charptr = strchr(optarg, ']');
- if (!charptr || (charptr[1] != ':' && charptr[1] != '\0'))
- exit_error(ctx, "invalid bind address `%s'", optarg);
-
- addrstr = strndup(optarg+1, charptr-optarg-1);
-
- if (charptr[1] == ':')
- charptr++;
- else
- charptr = NULL;
- }
- else {
- charptr = strchr(optarg, ':');
- if (charptr) {
- addrstr = strndup(optarg, charptr-optarg);
- }
- else {
- addrstr = strdup(optarg);
- }
- }
-
- if (charptr) {
- l = strtol(charptr+1, &endptr, 10);
- if (*endptr || l > 65535)
- exit_error(ctx, "invalid bind port `%s'", charptr+1);
- }
-
- if (strcmp(addrstr, "any") == 0) {
- conf->bind_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
- conf->bind_addr_in.sin_port = htons(l);
-
- conf->bind_addr_in6.sin6_addr = in6addr_any;
- conf->bind_addr_in6.sin6_port = htons(l);
- }
- else if (optarg[0] == '[') {
- conf->bind_addr_in6.sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, addrstr, &conf->bind_addr_in6.sin6_addr) != 1)
- exit_error(ctx, "invalid bind address `%s'", addrstr);
- conf->bind_addr_in6.sin6_port = htons(l);
- }
- else {
- conf->bind_addr_in.sin_family = AF_INET;
- if (inet_pton(AF_INET, addrstr, &conf->bind_addr_in.sin_addr) != 1)
- exit_error(ctx, "invalid bind address `%s'", addrstr);
- conf->bind_addr_in.sin_port = htons(l);
- }
-
- free(addrstr);
-
- break;
-
- case 'M':
- conf->mtu = strtol(optarg, &endptr, 10);
- if (*endptr || conf->mtu < 576)
- exit_error(ctx, "invalid mtu `%s'", optarg);
- break;
-
- case 'P':
- if (!strcmp(optarg, "ethernet"))
- conf->protocol = PROTOCOL_ETHERNET;
- else if (!strcmp(optarg, "ip"))
- conf->protocol = PROTOCOL_IP;
- else
- exit_error(ctx, "invalid protocol `%s'", optarg);
- break;
-
- case 'm':
- if (!strcmp(optarg, "null"))
- conf->method = &fastd_method_null;
-#ifdef WITH_METHOD_ECFXP
- if (!strcmp(optarg, "ecfxp"))
- conf->method = &fastd_method_ec25519_fhmqvc_xsalsa20_poly1305;
-#endif
- else
- exit_error(ctx, "invalid method `%s'", optarg);
- break;
-
- case 'p':
- *current_peer = malloc(sizeof(fastd_peer_config));
- (*current_peer)->next = NULL;
-
- memset(&(*current_peer)->address, 0, sizeof(fastd_peer_address));
- if (strcmp(optarg, "float") == 0) {
- (*current_peer)->address.sa.sa_family = AF_UNSPEC;
- conf->n_floating++;
- continue;
- }
-
- if (optarg[0] == '[') {
- charptr = strchr(optarg, ']');
- if (!charptr || (charptr[1] != ':' && charptr[1] != '\0'))
- exit_error(ctx, "invalid peer address `%s'", optarg);
-
- addrstr = strndup(optarg+1, charptr-optarg-1);
-
- if (charptr[1] == ':')
- charptr++;
- else
- charptr = NULL;
- }
- else {
- charptr = strchr(optarg, ':');
- if (charptr)
- addrstr = strndup(optarg, charptr-optarg);
- else
- addrstr = strdup(optarg);
- }
-
- if (charptr) {
- l = strtol(charptr+1, &endptr, 10);
- if (*endptr || l > 65535)
- exit_error(ctx, "invalid peer port `%s'", charptr+1);
- }
- else {
- l = 1337; /* default port */
- }
-
- if (optarg[0] == '[') {
- v6_peers = true;
- (*current_peer)->address.in6.sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, addrstr, &(*current_peer)->address.in6.sin6_addr) != 1)
- exit_error(ctx, "invalid peer address `%s'", addrstr);
- (*current_peer)->address.in6.sin6_port = htons(l);
- }
- else {
- v4_peers = true;
- (*current_peer)->address.in.sin_family = AF_INET;
- if (inet_pton(AF_INET, addrstr, &(*current_peer)->address.in.sin_addr) != 1)
- exit_error(ctx, "invalid peer address `%s'", addrstr);
- (*current_peer)->address.in.sin_port = htons(l);
- }
-
- free(addrstr);
-
- current_peer = &(*current_peer)->next;
-
- break;
-
- case '?':
- exit(1);
-
- default:
- abort();
- }
- }
-
- if (conf->n_floating && conf->bind_addr_in.sin_family == AF_UNSPEC
- && conf->bind_addr_in6.sin6_family == AF_UNSPEC) {
- conf->bind_addr_in.sin_family = AF_INET;
- conf->bind_addr_in6.sin6_family = AF_INET6;
- }
- else if (v4_peers) {
- conf->bind_addr_in.sin_family = AF_INET;
- }
- else if (v6_peers) {
- conf->bind_addr_in6.sin6_family = AF_INET6;
- }
-
- bool ok = true;
- if (conf->protocol == PROTOCOL_IP && (!conf->peers || conf->peers->next)) {
- pr_error(ctx, "for protocol `ip' exactly one peer must be configured");
- ok = false;
- }
-
- if (ok)
- ok = conf->method->check_config(ctx, conf);
-
- if (!ok)
- exit_error(ctx, "config error");
-}
-
static void init_peers(fastd_context *ctx) {
fastd_peer_config *peer_conf;
for (peer_conf = ctx->conf->peers; peer_conf; peer_conf = peer_conf->next)
@@ -631,7 +388,7 @@ int main(int argc, char *argv[]) {
memset(&ctx, 0, sizeof(ctx));
fastd_config conf;
- configure(&ctx, &conf, argc, argv);
+ fastd_configure(&ctx, &conf, argc, argv);
ctx.conf = &conf;
update_time(&ctx);
diff --git a/src/fastd.h b/src/fastd.h
index 834fa39..c42baa3 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -59,6 +59,7 @@ struct _fastd_eth_addr {
struct _fastd_method {
const char *name;
+ bool (*handle_config)(fastd_context *ctx, const fastd_config *conf, const char *option);
bool (*check_config)(fastd_context *ctx, const fastd_config *conf);
size_t (*max_packet_size)(fastd_context *ctx);
@@ -80,7 +81,7 @@ struct _fastd_config {
unsigned peer_stale_time_temp;
unsigned eth_addr_stale_time;
- char *ifname;
+ const char *ifname;
struct sockaddr_in bind_addr_in;
struct sockaddr_in6 bind_addr_in6;
@@ -113,6 +114,7 @@ struct _fastd_context {
void fastd_printf(const fastd_context *ctx, const char *format, ...);
+void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *const argv[]);
#define pr_log(ctx, level, prefix, args...) if ((ctx)->conf == NULL || (level) <= (ctx)->conf->loglevel) \
do { fputs(prefix, stderr); fastd_printf(ctx, args); fputs("\n", stderr); } while(0)
diff --git a/src/method_ec25519_fhmqvc_xsalsa20_poly1305.c b/src/method_ec25519_fhmqvc_xsalsa20_poly1305.c
index 2a01ccd..b57531f 100644
--- a/src/method_ec25519_fhmqvc_xsalsa20_poly1305.c
+++ b/src/method_ec25519_fhmqvc_xsalsa20_poly1305.c
@@ -36,13 +36,23 @@
#include <crypto_secretbox_xsalsa20poly1305.h>
+typedef struct _method_config {
+ ecc_secret_key_256 secret_key;
+} method_config;
+
typedef struct _method_peer_config {
+ ecc_public_key_256 public_key;
} method_peer_config;
typedef struct _method_peer_state {
} method_peer_state;
+static bool method_handle_config(fastd_context *ctx, const fastd_config *conf, const char *option) {
+ printf("Unknown option: %s\n", option);
+ return false;
+}
+
static bool method_check_config(fastd_context *ctx, const fastd_config *conf) {
return true;
}
@@ -103,6 +113,7 @@ static void method_free_peer_private(fastd_context *ctx, fastd_peer *peer) {
const fastd_method fastd_method_ec25519_fhmqvc_xsalsa20_poly1305 = {
.name = "ec25519-fhmqvc-xsalsa20-poly1305",
+ .handle_config = method_handle_config,
.check_config = method_check_config,
.max_packet_size = method_max_packet_size,
diff --git a/src/method_null.c b/src/method_null.c
index f5a0d74..70c5a09 100644
--- a/src/method_null.c
+++ b/src/method_null.c
@@ -34,6 +34,10 @@
#include <arpa/inet.h>
+static bool method_handle_config(fastd_context *ctx, const fastd_config *conf, const char *option) {
+ return false;
+}
+
static bool method_check_config(fastd_context *ctx, const fastd_config *conf) {
if (conf->n_floating > 1) {
pr_error(ctx, "with method `null' use can't define more than one floating peer");
@@ -125,6 +129,7 @@ static void method_free_peer_private(fastd_context *ctx, fastd_peer *peer) {
const fastd_method fastd_method_null = {
.name = "null",
+ .handle_config = method_handle_config,
.check_config = method_check_config,
.max_packet_size = method_max_packet_size,