summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2013-07-25 15:17:54 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2013-07-25 15:17:54 +0200
commit900ac61351cabc78b5126adbe9c9936d1c3b5ca6 (patch)
treeaf2c93deb9cdeec30aa5d7f79cc69519cb5b3217
parentc3dee51736841587b2f81adc54c1949276ab5de0 (diff)
downloadfastd-900ac61351cabc78b5126adbe9c9936d1c3b5ca6.tar
fastd-900ac61351cabc78b5126adbe9c9936d1c3b5ca6.zip
Move send functions out of fastd.c
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/config.c27
-rw-r--r--src/fastd.c196
-rw-r--r--src/fastd.h12
-rw-r--r--src/send.c132
5 files changed, 178 insertions, 190 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c2a0128..92ad954 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -26,6 +26,7 @@ add_executable(fastd
queue.c
random.c
resolve.c
+ send.c
shell.c
socket.c
task.c
diff --git a/src/config.c b/src/config.c
index ec04726..6296209 100644
--- a/src/config.c
+++ b/src/config.c
@@ -845,7 +845,31 @@ static void configure_user(fastd_context_t *ctx, fastd_config_t *conf) {
conf->n_groups = ngroups;
}
}
+}
+
+static void configure_method_parameters(fastd_context_t *ctx, fastd_config_t *conf) {
+ conf->max_packet_size = 0;
+ conf->min_encrypt_head_space = 0;
+ conf->min_decrypt_head_space = 0;
+ conf->min_encrypt_tail_space = 0;
+ conf->min_decrypt_tail_space = 0;
+
+ int i;
+ for (i = 0; i < MAX_METHODS; i++) {
+ if (!conf->methods[i])
+ break;
+
+ conf->max_packet_size = max_size_t(conf->max_packet_size, conf->methods[i]->max_packet_size(ctx));
+ conf->min_encrypt_head_space = max_size_t(conf->min_encrypt_head_space, conf->methods[i]->min_encrypt_head_space(ctx));
+ conf->min_decrypt_head_space = max_size_t(conf->min_decrypt_head_space, conf->methods[i]->min_decrypt_head_space(ctx));
+ conf->min_encrypt_tail_space = max_size_t(conf->min_encrypt_tail_space, conf->methods[i]->min_encrypt_tail_space(ctx));
+ conf->min_decrypt_tail_space = max_size_t(conf->min_decrypt_tail_space, conf->methods[i]->min_decrypt_tail_space(ctx));
+ }
+ conf->min_encrypt_head_space = alignto(conf->min_encrypt_head_space, 16);
+
+ /* ugly hack to get alignment right for aes128-gcm, which needs data aligned to 16 and has a 24 byte header */
+ conf->min_decrypt_head_space = alignto(conf->min_decrypt_head_space, 16) + 8;
}
void fastd_configure(fastd_context_t *ctx, fastd_config_t *conf, int argc, char *const argv[]) {
@@ -902,6 +926,9 @@ void fastd_configure(fastd_context_t *ctx, fastd_config_t *conf, int argc, char
exit_error(ctx, "config error: neither fixed peers nor peer dirs have been configured");
configure_user(ctx, conf);
+
+ ctx->conf = conf;
+ configure_method_parameters(ctx, conf);
}
static void peer_dirs_read_peer_group(fastd_context_t *ctx, fastd_config_t *new_conf) {
diff --git a/src/fastd.c b/src/fastd.c
index 10dbeec..9bd534d 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -276,189 +276,6 @@ static void close_sockets(fastd_context_t *ctx) {
free(ctx->socks);
}
-static size_t methods_max_packet_size(fastd_context_t *ctx) {
- size_t ret = ctx->conf->methods[0]->max_packet_size(ctx);
-
- int i;
- for (i = 0; i < MAX_METHODS; i++) {
- if (!ctx->conf->methods[i])
- break;
-
- size_t s = ctx->conf->methods[i]->max_packet_size(ctx);
- if (s > ret)
- ret = s;
- }
-
- return ret;
-}
-
-static size_t methods_min_encrypt_head_space(fastd_context_t *ctx) {
- size_t ret = 0;
-
- int i;
- for (i = 0; i < MAX_METHODS; i++) {
- if (!ctx->conf->methods[i])
- break;
-
- size_t s = ctx->conf->methods[i]->min_encrypt_head_space(ctx);
- if (s > ret)
- ret = s;
- }
-
- return alignto(ret, 16);
-}
-
-static size_t methods_min_decrypt_head_space(fastd_context_t *ctx) {
- size_t ret = 0;
-
- int i;
- for (i = 0; i < MAX_METHODS; i++) {
- if (!ctx->conf->methods[i])
- break;
-
- size_t s = ctx->conf->methods[i]->min_decrypt_head_space(ctx);
- if (s > ret)
- ret = s;
- }
-
- /* ugly hack to get alignment right for aes128-gcm, which needs data aligned to 16 and has a 24 byte header */
- return alignto(ret, 16) + 8;
-}
-
-static size_t methods_min_encrypt_tail_space(fastd_context_t *ctx) {
- size_t ret = 0;
-
- int i;
- for (i = 0; i < MAX_METHODS; i++) {
- if (!ctx->conf->methods[i])
- break;
-
- size_t s = ctx->conf->methods[i]->min_encrypt_tail_space(ctx);
- if (s > ret)
- ret = s;
- }
-
- return ret;
-}
-
-static size_t methods_min_decrypt_tail_space(fastd_context_t *ctx) {
- size_t ret = 0;
-
- int i;
- for (i = 0; i < MAX_METHODS; i++) {
- if (!ctx->conf->methods[i])
- break;
-
- size_t s = ctx->conf->methods[i]->min_decrypt_tail_space(ctx);
- if (s > ret)
- ret = s;
- }
-
- return ret;
-}
-
-static inline void add_pktinfo(struct msghdr *msg, const fastd_peer_address_t *local_addr) {
- if (!local_addr)
- return;
-
- struct cmsghdr *cmsg = (struct cmsghdr*)((char*)msg->msg_control + msg->msg_controllen);
-
- if (local_addr->sa.sa_family == AF_INET) {
- cmsg->cmsg_level = IPPROTO_IP;
- cmsg->cmsg_type = IP_PKTINFO;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
-
- msg->msg_controllen += cmsg->cmsg_len;
-
- struct in_pktinfo *pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
- pktinfo->ipi_addr = local_addr->in.sin_addr;
- }
- else if (local_addr->sa.sa_family == AF_INET6) {
- cmsg->cmsg_level = IPPROTO_IPV6;
- cmsg->cmsg_type = IPV6_PKTINFO;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
-
- msg->msg_controllen += cmsg->cmsg_len;
-
- struct in6_pktinfo *pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
- pktinfo->ipi6_addr = local_addr->in6.sin6_addr;
-
- if (IN6_IS_ADDR_LINKLOCAL(&local_addr->in6.sin6_addr))
- pktinfo->ipi6_ifindex = local_addr->in6.sin6_scope_id;
- }
-}
-
-static void fastd_send_type(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, uint8_t packet_type, fastd_buffer_t buffer) {
- if (!sock)
- exit_bug(ctx, "send: sock == NULL");
-
- struct msghdr msg = {};
- char cbuf[1024] = {};
-
- switch (remote_addr->sa.sa_family) {
- case AF_INET:
- msg.msg_name = (void*)&remote_addr->in;
- msg.msg_namelen = sizeof(struct sockaddr_in);
- break;
-
- case AF_INET6:
- msg.msg_name = (void*)&remote_addr->in6;
- msg.msg_namelen = sizeof(struct sockaddr_in6);
- break;
-
- default:
- exit_bug(ctx, "unsupported address family");
- }
-
- struct iovec iov[2] = {
- { .iov_base = &packet_type, .iov_len = 1 },
- { .iov_base = buffer.data, .iov_len = buffer.len }
- };
-
- msg.msg_iov = iov;
- msg.msg_iovlen = buffer.len ? 2 : 1;
- msg.msg_control = cbuf;
- msg.msg_controllen = 0;
-
- add_pktinfo(&msg, local_addr);
-
- int ret;
- do {
- ret = sendmsg(sock->fd, &msg, 0);
- } while (ret < 0 && errno == EINTR);
-
- if (ret < 0)
- pr_warn_errno(ctx, "sendmsg");
-
- fastd_buffer_free(buffer);
-}
-
-void fastd_send(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer) {
- fastd_send_type(ctx, sock, local_addr, remote_addr, PACKET_DATA, buffer);
-}
-
-void fastd_send_handshake(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer) {
- fastd_send_type(ctx, sock, local_addr, remote_addr, PACKET_HANDSHAKE, buffer);
-}
-
-static inline void send_all(fastd_context_t *ctx, fastd_peer_t *source_peer, fastd_buffer_t buffer) {
- fastd_peer_t *dest_peer;
- for (dest_peer = ctx->peers; dest_peer; dest_peer = dest_peer->next) {
- if (dest_peer == source_peer || !fastd_peer_is_established(dest_peer))
- continue;
-
- /* optimization, primarily for TUN mode: don't duplicate the buffer for the last (or only) peer */
- if (!dest_peer->next) {
- ctx->conf->protocol->send(ctx, dest_peer, buffer);
- return;
- }
-
- ctx->conf->protocol->send(ctx, dest_peer, fastd_buffer_dup(ctx, buffer, methods_min_encrypt_head_space(ctx), methods_min_encrypt_tail_space(ctx)));
- }
-
- fastd_buffer_free(buffer);
-}
-
static inline void handle_forward(fastd_context_t *ctx, fastd_peer_t *source_peer, fastd_buffer_t buffer) {
const fastd_eth_addr_t *dest_addr = fastd_get_dest_address(ctx, buffer);
@@ -473,7 +290,7 @@ static inline void handle_forward(fastd_context_t *ctx, fastd_peer_t *source_pee
ctx->conf->protocol->send(ctx, dest_peer, buffer);
}
else {
- send_all(ctx, source_peer, buffer);
+ fastd_send_all(ctx, source_peer, buffer);
}
}
@@ -685,7 +502,7 @@ static void handle_tasks(fastd_context_t *ctx) {
case TASK_KEEPALIVE:
pr_debug(ctx, "sending keepalive to %P", task->peer);
- ctx->conf->protocol->send(ctx, task->peer, fastd_buffer_alloc(ctx, 0, methods_min_encrypt_head_space(ctx), methods_min_encrypt_tail_space(ctx)));
+ ctx->conf->protocol->send(ctx, task->peer, fastd_buffer_alloc(ctx, 0, ctx->conf->min_encrypt_head_space, ctx->conf->min_encrypt_tail_space));
break;
default:
@@ -723,7 +540,7 @@ static inline bool handle_tun_tap(fastd_context_t *ctx, fastd_buffer_t buffer) {
static void handle_tun(fastd_context_t *ctx) {
size_t max_len = fastd_max_packet_size(ctx);
- fastd_buffer_t buffer = fastd_buffer_alloc(ctx, max_len, methods_min_encrypt_head_space(ctx), methods_min_encrypt_tail_space(ctx));
+ fastd_buffer_t buffer = fastd_buffer_alloc(ctx, max_len, ctx->conf->min_encrypt_head_space, ctx->conf->min_encrypt_tail_space);
ssize_t len = read(ctx->tunfd, buffer.data, max_len);
if (len < 0) {
@@ -741,7 +558,7 @@ static void handle_tun(fastd_context_t *ctx) {
return;
/* TUN mode or multicast packet */
- send_all(ctx, NULL, buffer);
+ fastd_send_all(ctx, NULL, buffer);
}
static inline void handle_socket_control(fastd_context_t *ctx, struct msghdr *message, const fastd_socket_t *sock, fastd_peer_address_t *local_addr) {
@@ -858,8 +675,8 @@ static inline void handle_socket_receive(fastd_context_t *ctx, fastd_socket_t *s
}
static void handle_socket(fastd_context_t *ctx, fastd_socket_t *sock) {
- size_t max_len = PACKET_TYPE_LEN + methods_max_packet_size(ctx);
- fastd_buffer_t buffer = fastd_buffer_alloc(ctx, max_len, methods_min_decrypt_head_space(ctx), methods_min_decrypt_tail_space(ctx));
+ size_t max_len = PACKET_TYPE_LEN + ctx->conf->max_packet_size;
+ fastd_buffer_t buffer = fastd_buffer_alloc(ctx, max_len, ctx->conf->min_decrypt_head_space, ctx->conf->min_decrypt_tail_space);
fastd_peer_address_t local_addr;
fastd_peer_address_t recvaddr;
struct iovec buffer_vec = { .iov_base = buffer.data, .iov_len = buffer.len };
@@ -1140,7 +957,6 @@ int main(int argc, char *argv[]) {
fastd_config_t conf;
fastd_configure(&ctx, &conf, argc, argv);
- ctx.conf = &conf;
init_log(&ctx);
diff --git a/src/fastd.h b/src/fastd.h
index 8668db6..1bbda28 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -208,6 +208,13 @@ struct fastd_config {
const fastd_protocol_t *protocol;
const fastd_method_t *methods[MAX_METHODS];
const fastd_method_t *method_default;
+
+ size_t max_packet_size;
+ size_t min_encrypt_head_space;
+ size_t min_decrypt_head_space;
+ size_t min_encrypt_tail_space;
+ size_t min_decrypt_tail_space;
+
char *secret;
unsigned key_valid;
unsigned key_refresh;
@@ -302,6 +309,7 @@ struct fastd_string_stack {
void fastd_send(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer);
+void fastd_send_all(fastd_context_t *ctx, fastd_peer_t *source_peer, fastd_buffer_t buffer);
void fastd_send_handshake(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer);
void fastd_handle_receive(fastd_context_t *ctx, fastd_peer_t *peer, fastd_buffer_t buffer);
@@ -483,4 +491,8 @@ static inline bool strequal(const char *str1, const char *str2) {
return (str1 == str2);
}
+static inline size_t max_size_t(size_t a, size_t b) {
+ return (a > b) ? a : b;
+}
+
#endif /* _FASTD_FASTD_H_ */
diff --git a/src/send.c b/src/send.c
new file mode 100644
index 0000000..4e0d77a
--- /dev/null
+++ b/src/send.c
@@ -0,0 +1,132 @@
+/*
+ Copyright (c) 2012-2013, Matthias Schiffer <mschiffer@universe-factory.net>
+ 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 "packet.h"
+#include "peer.h"
+
+
+static inline void add_pktinfo(struct msghdr *msg, const fastd_peer_address_t *local_addr) {
+ if (!local_addr)
+ return;
+
+ struct cmsghdr *cmsg = (struct cmsghdr*)((char*)msg->msg_control + msg->msg_controllen);
+
+ if (local_addr->sa.sa_family == AF_INET) {
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+
+ msg->msg_controllen += cmsg->cmsg_len;
+
+ struct in_pktinfo *pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ pktinfo->ipi_addr = local_addr->in.sin_addr;
+ }
+ else if (local_addr->sa.sa_family == AF_INET6) {
+ cmsg->cmsg_level = IPPROTO_IPV6;
+ cmsg->cmsg_type = IPV6_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+
+ msg->msg_controllen += cmsg->cmsg_len;
+
+ struct in6_pktinfo *pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ pktinfo->ipi6_addr = local_addr->in6.sin6_addr;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&local_addr->in6.sin6_addr))
+ pktinfo->ipi6_ifindex = local_addr->in6.sin6_scope_id;
+ }
+}
+
+static void send_type(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, uint8_t packet_type, fastd_buffer_t buffer) {
+ if (!sock)
+ exit_bug(ctx, "send: sock == NULL");
+
+ struct msghdr msg = {};
+ char cbuf[1024] = {};
+
+ switch (remote_addr->sa.sa_family) {
+ case AF_INET:
+ msg.msg_name = (void*)&remote_addr->in;
+ msg.msg_namelen = sizeof(struct sockaddr_in);
+ break;
+
+ case AF_INET6:
+ msg.msg_name = (void*)&remote_addr->in6;
+ msg.msg_namelen = sizeof(struct sockaddr_in6);
+ break;
+
+ default:
+ exit_bug(ctx, "unsupported address family");
+ }
+
+ struct iovec iov[2] = {
+ { .iov_base = &packet_type, .iov_len = 1 },
+ { .iov_base = buffer.data, .iov_len = buffer.len }
+ };
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = buffer.len ? 2 : 1;
+ msg.msg_control = cbuf;
+ msg.msg_controllen = 0;
+
+ add_pktinfo(&msg, local_addr);
+
+ int ret;
+ do {
+ ret = sendmsg(sock->fd, &msg, 0);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret < 0)
+ pr_warn_errno(ctx, "sendmsg");
+
+ fastd_buffer_free(buffer);
+}
+
+void fastd_send(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer) {
+ send_type(ctx, sock, local_addr, remote_addr, PACKET_DATA, buffer);
+}
+
+void fastd_send_handshake(fastd_context_t *ctx, const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer) {
+ send_type(ctx, sock, local_addr, remote_addr, PACKET_HANDSHAKE, buffer);
+}
+
+void fastd_send_all(fastd_context_t *ctx, fastd_peer_t *source_peer, fastd_buffer_t buffer) {
+ fastd_peer_t *dest_peer;
+ for (dest_peer = ctx->peers; dest_peer; dest_peer = dest_peer->next) {
+ if (dest_peer == source_peer || !fastd_peer_is_established(dest_peer))
+ continue;
+
+ /* optimization, primarily for TUN mode: don't duplicate the buffer for the last (or only) peer */
+ if (!dest_peer->next) {
+ ctx->conf->protocol->send(ctx, dest_peer, buffer);
+ return;
+ }
+
+ ctx->conf->protocol->send(ctx, dest_peer, fastd_buffer_dup(ctx, buffer, ctx->conf->min_encrypt_head_space, ctx->conf->min_encrypt_tail_space));
+ }
+
+ fastd_buffer_free(buffer);
+}