diff options
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/dlist.h (renamed from src/task.h) | 41 | ||||
-rw-r--r-- | src/fastd.c | 59 | ||||
-rw-r--r-- | src/fastd.h | 5 | ||||
-rw-r--r-- | src/handshake.c | 1 | ||||
-rw-r--r-- | src/peer.c | 28 | ||||
-rw-r--r-- | src/peer.h | 13 | ||||
-rw-r--r-- | src/protocol_ec25519_fhmqvc.c | 7 | ||||
-rw-r--r-- | src/queue.c | 97 | ||||
-rw-r--r-- | src/queue.h | 54 | ||||
-rw-r--r-- | src/task.c | 68 |
11 files changed, 102 insertions, 273 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d5cba98..3e962f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,7 +24,6 @@ add_executable(fastd options.c peer.c printf.c - queue.c random.c receive.c resolve.c @@ -32,7 +31,6 @@ add_executable(fastd sha256.c shell.c socket.c - task.c tuntap.c protocol_ec25519_fhmqvc.c ${BISON_fastd_config_parse_OUTPUTS} @@ -24,31 +24,40 @@ */ -#ifndef _FASTD_TASK_H_ -#define _FASTD_TASK_H_ +#ifndef _FASTD_DLIST_H_ +#define _FASTD_DLIST_H_ -#include "fastd.h" -#include "packet.h" +#include "types.h" -#include <sys/uio.h> +#include <stdlib.h> -typedef struct fastd_task { - fastd_queue_entry_t entry; +typedef struct fastd_dlist_head fastd_dlist_head_t; - fastd_peer_t *peer; -} fastd_task_t; +struct fastd_dlist_head { + fastd_dlist_head_t *prev; + fastd_dlist_head_t *next; +}; -static inline int fastd_task_timeout(fastd_context_t *ctx) { - return fastd_queue_timeout(ctx, &ctx->task_queue); -} +static inline void fastd_dlist_insert(fastd_dlist_head_t *list, fastd_dlist_head_t *elem) { + elem->prev = list; + elem->next = list->next; + + list->next = elem; + if (elem->next) + elem->next->prev = elem; +} -fastd_task_t* fastd_task_get(fastd_context_t *ctx); +static inline void fastd_dlist_remove(fastd_dlist_head_t *elem) { + if (elem->prev) + elem->prev->next = elem->next; -void fastd_task_schedule_handshake(fastd_context_t *ctx, fastd_peer_t *peer, int timeout); + if (elem->next) + elem->next->prev = elem->prev; -void fastd_task_delete_peer(fastd_context_t *ctx, fastd_peer_t *peer); + elem->prev = elem->next = NULL; +} -#endif /* _FASTD_TASK_H_ */ +#endif /* _FASTD_DLIST_H_ */ diff --git a/src/fastd.c b/src/fastd.c index 786f158..7c702c1 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -28,7 +28,6 @@ #include "crypto.h" #include "handshake.h" #include "peer.h" -#include "task.h" #include <fcntl.h> #include <grp.h> @@ -422,33 +421,32 @@ static void send_handshake(fastd_context_t *ctx, fastd_peer_t *peer) { ctx->conf->protocol->handshake_init(ctx, peer->sock, &peer->local_address, &peer->address, peer); } -static void handle_tasks(fastd_context_t *ctx) { - fastd_task_t *task; - while ((task = fastd_task_get(ctx)) != NULL) { - fastd_peer_schedule_handshake(ctx, task->peer); +static void handle_handshake_queue(fastd_context_t *ctx) { + if (!ctx->handshake_queue.next) + return; - if(!fastd_peer_may_connect(ctx, task->peer)) { - task->peer->next_remote = task->peer->remotes; - free(task); - continue; - } + fastd_peer_t *peer = container_of(ctx->handshake_queue.next, fastd_peer_t, handshake_entry); + if (timespec_after(&peer->next_handshake, &ctx->now)) + return; - send_handshake(ctx, task->peer); + fastd_peer_schedule_handshake_default(ctx, peer); - if (fastd_peer_is_established(task->peer)) { - free(task); - continue; - } + if (!fastd_peer_may_connect(ctx, peer)) { + peer->next_remote = peer->remotes; + return; + } - task->peer->next_remote = task->peer->next_remote->next; - if (!task->peer->next_remote) - task->peer->next_remote = task->peer->remotes; + send_handshake(ctx, peer); - if (fastd_remote_is_dynamic(task->peer->next_remote)) - fastd_resolve_peer(ctx, task->peer, task->peer->next_remote); + if (fastd_peer_is_established(peer)) + return; - free(task); - } + peer->next_remote = peer->next_remote->next; + if (!peer->next_remote) + peer->next_remote = peer->remotes; + + if (fastd_remote_is_dynamic(peer->next_remote)) + fastd_resolve_peer(ctx, peer, peer->next_remote); } static inline bool handle_tun_tap(fastd_context_t *ctx, fastd_buffer_t buffer) { @@ -518,6 +516,19 @@ static void handle_resolve_returns(fastd_context_t *ctx) { fastd_remote_unref(resolve_return.remote); } +static inline int handshake_timeout(fastd_context_t *ctx) { + if (!ctx->handshake_queue.next) + return -1; + + fastd_peer_t *peer = container_of(ctx->handshake_queue.next, fastd_peer_t, handshake_entry); + + int diff_msec = timespec_diff(&peer->next_handshake, &ctx->now); + if (diff_msec < 0) + return 0; + else + return diff_msec; +} + static void handle_input(fastd_context_t *ctx) { const size_t n_fds = 2 + ctx->n_socks + ctx->n_peers; struct pollfd fds[n_fds]; @@ -552,7 +563,7 @@ static void handle_input(fastd_context_t *ctx) { if (keepalive_timeout < 0) keepalive_timeout = 0; - int timeout = fastd_task_timeout(ctx); + int timeout = handshake_timeout(ctx); if (timeout < 0 || timeout > keepalive_timeout) timeout = keepalive_timeout; @@ -811,7 +822,7 @@ int main(int argc, char *argv[]) { init_peers(&ctx); while (!terminate) { - handle_tasks(&ctx); + handle_handshake_queue(&ctx); handle_input(&ctx); diff --git a/src/fastd.h b/src/fastd.h index 133e2e0..848a5d3 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -29,7 +29,7 @@ #include "compat.h" #include "types.h" -#include "queue.h" +#include "dlist.h" #include <errno.h> #include <stdarg.h> @@ -277,7 +277,8 @@ struct fastd_context { fastd_peer_group_t *peer_group; fastd_peer_t *peers; fastd_peer_t *peers_temp; - fastd_queue_t task_queue; + + fastd_dlist_head_t handshake_queue; struct timespec next_keepalives; int resolverfd; diff --git a/src/handshake.c b/src/handshake.c index d74436f..10dafa0 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -27,7 +27,6 @@ #include "handshake.h" #include "packet.h" #include "peer.h" -#include "task.h" static const char *const RECORD_TYPES[RECORD_MAX] = { @@ -95,6 +95,30 @@ void fastd_peer_reset_socket(fastd_context_t *ctx, fastd_peer_t *peer) { } } +void fastd_peer_schedule_handshake(fastd_context_t *ctx, fastd_peer_t *peer, int delay) { + fastd_peer_unschedule_handshake(ctx, peer); + + peer->next_handshake = ctx->now; + + peer->next_handshake.tv_sec += delay/1000; + peer->next_handshake.tv_nsec += (delay%1000)*1e6; + + if (peer->next_handshake.tv_nsec > 1e9) { + peer->next_handshake.tv_sec++; + peer->next_handshake.tv_nsec -= 1e9; + } + + fastd_dlist_head_t *list; + for (list = &ctx->handshake_queue; list->next; list = list->next) { + fastd_peer_t *entry = container_of(list->next, fastd_peer_t, handshake_entry); + + if (timespec_after(&entry->next_handshake, &peer->next_handshake)) + break; + } + + fastd_dlist_insert(list, &peer->handshake_entry); +} + static inline fastd_peer_group_t* find_peer_group(fastd_peer_group_t *group, const fastd_peer_group_config_t *config) { if (group->conf == config) return group; @@ -147,7 +171,7 @@ static void reset_peer(fastd_context_t *ctx, fastd_peer_t *peer) { ctx->n_eth_addr -= deleted; - fastd_task_delete_peer(ctx, peer); + fastd_peer_unschedule_handshake(ctx, peer); } static void init_handshake(fastd_context_t *ctx, fastd_peer_t *peer) { @@ -158,7 +182,7 @@ static void init_handshake(fastd_context_t *ctx, fastd_peer_t *peer) { if (!fastd_peer_is_established(peer)) peer->state = STATE_HANDSHAKE; - fastd_task_schedule_handshake(ctx, peer, delay); + fastd_peer_schedule_handshake(ctx, peer, delay); } void fastd_peer_handle_resolve(fastd_context_t *ctx, fastd_peer_t *peer, fastd_remote_t *remote, const fastd_peer_address_t *address) { @@ -28,7 +28,6 @@ #define _FASTD_PEER_H_ #include "fastd.h" -#include "task.h" struct fastd_peer { @@ -48,6 +47,9 @@ struct fastd_peer { fastd_remote_t *remotes; fastd_remote_t *next_remote; + struct timespec next_handshake; + fastd_dlist_head_t handshake_entry; + struct timespec last_handshake; fastd_peer_address_t last_handshake_address; @@ -136,9 +138,14 @@ bool fastd_peer_owns_address(fastd_context_t *ctx, const fastd_peer_t *peer, con bool fastd_peer_matches_address(fastd_context_t *ctx, const fastd_peer_t *peer, const fastd_peer_address_t *addr); bool fastd_peer_claim_address(fastd_context_t *ctx, fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr); void fastd_peer_reset_socket(fastd_context_t *ctx, fastd_peer_t *peer); +void fastd_peer_schedule_handshake(fastd_context_t *ctx, fastd_peer_t *peer, int delay); + +static inline void fastd_peer_schedule_handshake_default(fastd_context_t *ctx, fastd_peer_t *peer) { + fastd_peer_schedule_handshake(ctx, peer, fastd_rand(ctx, 17500, 22500)); +} -static inline void fastd_peer_schedule_handshake(fastd_context_t *ctx, fastd_peer_t *peer) { - fastd_task_schedule_handshake(ctx, peer, fastd_rand(ctx, 17500, 22500)); +static inline void fastd_peer_unschedule_handshake(fastd_context_t *ctx UNUSED, fastd_peer_t *peer) { + fastd_dlist_remove(&peer->handshake_entry); } const fastd_eth_addr_t* fastd_get_source_address(const fastd_context_t *ctx, fastd_buffer_t buffer); diff --git a/src/protocol_ec25519_fhmqvc.c b/src/protocol_ec25519_fhmqvc.c index d1d4740..bb75404 100644 --- a/src/protocol_ec25519_fhmqvc.c +++ b/src/protocol_ec25519_fhmqvc.c @@ -28,7 +28,6 @@ #include "handshake.h" #include "peer.h" #include "sha256.h" -#include "task.h" #include <libuecc/ecc.h> @@ -149,7 +148,7 @@ static inline void check_session_refresh(fastd_context_t *ctx, fastd_peer_t *pee pr_verbose(ctx, "refreshing session with %P", peer); session->handshakes_cleaned = true; session->refreshing = true; - fastd_task_schedule_handshake(ctx, peer, 0); + fastd_peer_schedule_handshake(ctx, peer, 0); } } @@ -436,7 +435,7 @@ static bool establish(fastd_context_t *ctx, fastd_peer_t *peer, const fastd_meth pr_verbose(ctx, "new session with %P established using method `%s'.", peer, method->name); if (initiator) - fastd_peer_schedule_handshake(ctx, peer); + fastd_peer_schedule_handshake_default(ctx, peer); else send_empty(ctx, peer, &peer->protocol_state->session); @@ -793,7 +792,7 @@ static void protocol_handle_recv(fastd_context_t *ctx, fastd_peer_t *peer, fastd if (!peer->protocol_state->session.handshakes_cleaned) { pr_debug(ctx, "cleaning left handshakes with %P", peer); - fastd_task_delete_peer(ctx, peer); + fastd_peer_unschedule_handshake(ctx, peer); peer->protocol_state->session.handshakes_cleaned = true; if (peer->protocol_state->session.method->session_is_initiator(ctx, peer->protocol_state->session.method_state)) diff --git a/src/queue.c b/src/queue.c deleted file mode 100644 index 93dd92d..0000000 --- a/src/queue.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - 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 "queue.h" -#include "fastd.h" - -#include <stdint.h> - - -void fastd_queue_put(fastd_context_t *ctx, fastd_queue_t *queue, fastd_queue_entry_t *entry, int timeout) { - entry->timeout = ctx->now; - - if (timeout) { - entry->timeout.tv_sec += timeout/1000; - entry->timeout.tv_nsec += (timeout%1000)*1e6; - - if (entry->timeout.tv_nsec > 1e9) { - entry->timeout.tv_sec++; - entry->timeout.tv_nsec -= 1e9; - } - } - - fastd_queue_entry_t **current; - for (current = &queue->head;; current = &(*current)->next) { - if (!(*current) || timespec_after(&(*current)->timeout, &entry->timeout)) { - entry->next = *current; - *current = entry; - break; - } - } -} - -fastd_queue_entry_t* fastd_queue_get(fastd_context_t *ctx, fastd_queue_t *queue) { - if (!queue->head || fastd_queue_timeout(ctx, queue) > 0) - return NULL; - - fastd_queue_entry_t *entry = queue->head; - queue->head = entry->next; - - return entry; -} - -int fastd_queue_timeout(fastd_context_t *ctx, fastd_queue_t *queue) { - if (!queue->head) - return -1; - - int diff_msec = timespec_diff(&queue->head->timeout, &ctx->now); - if (diff_msec < 0) - return 0; - else - return diff_msec; -} - -void fastd_queue_filter(fastd_context_t *ctx UNUSED, fastd_queue_t *queue, bool (*pred)(fastd_queue_entry_t*, void*), void *extra) { - fastd_queue_entry_t **entry, *next; - for (entry = &queue->head; *entry;) { - next = (*entry)->next; - - if (!pred(*entry, extra)) - *entry = next; - else - entry = &(*entry)->next; - } -} - -bool fastd_queue_has_entry(fastd_context_t *ctx UNUSED, fastd_queue_t *queue, bool (*pred)(fastd_queue_entry_t*, void*), void *extra) { - fastd_queue_entry_t *entry; - for (entry = queue->head; entry; entry = entry->next) { - if (pred(entry, extra)) - return true; - } - - return false; -} diff --git a/src/queue.h b/src/queue.h deleted file mode 100644 index c74fd55..0000000 --- a/src/queue.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - 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. -*/ - - -#ifndef _FASTD_QUEUE_H_ -#define _FASTD_QUEUE_H_ - -#include "types.h" - -#include <stdlib.h> -#include <time.h> - - -typedef struct fastd_queue_entry fastd_queue_entry_t; - -struct fastd_queue_entry { - fastd_queue_entry_t *next; - struct timespec timeout; -}; - -typedef struct fastd_queue { - fastd_queue_entry_t *head; -} fastd_queue_t; - - -void fastd_queue_put(fastd_context_t *ctx, fastd_queue_t *queue, fastd_queue_entry_t *entry, int timeout); -fastd_queue_entry_t* fastd_queue_get(fastd_context_t *ctx, fastd_queue_t *queue); -int fastd_queue_timeout(fastd_context_t *ctx, fastd_queue_t *queue); -void fastd_queue_filter(fastd_context_t *ctx, fastd_queue_t *queue, bool (*pred)(fastd_queue_entry_t*, void*), void *extra); -bool fastd_queue_has_entry(fastd_context_t *ctx, fastd_queue_t *queue, bool (*pred)(fastd_queue_entry_t*, void*), void *extra); - -#endif /* _FASTD_QUEUE_T_H_ */ diff --git a/src/task.c b/src/task.c deleted file mode 100644 index 768c9c3..0000000 --- a/src/task.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - 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 "task.h" - - -fastd_task_t* fastd_task_get(fastd_context_t *ctx) { - return container_of(fastd_queue_get(ctx, &ctx->task_queue), fastd_task_t, entry); -} - -static bool is_peer(fastd_queue_entry_t *data, void *extra) { - fastd_task_t *task = container_of(data, fastd_task_t, entry); - fastd_peer_t *peer = extra; - - return (task->peer == peer); -} - -void fastd_task_schedule_handshake(fastd_context_t *ctx, fastd_peer_t *peer, int timeout) { - if (fastd_queue_has_entry(ctx, &ctx->task_queue, is_peer, peer)) { - pr_debug(ctx, "not sending a handshake to %P, there still is one queued", peer); - return; - } - - fastd_task_t *task = malloc(sizeof(fastd_task_t)); - - task->peer = peer; - - fastd_queue_put(ctx, &ctx->task_queue, &task->entry, timeout); -} - -static bool delete_peer_task(fastd_queue_entry_t *data, void *extra) { - fastd_task_t *task = container_of(data, fastd_task_t, entry); - fastd_peer_t *peer = extra; - - if (task->peer != peer) - return true; - - free(task); - - return false; -} - -void fastd_task_delete_peer(fastd_context_t *ctx, fastd_peer_t *peer) { - fastd_queue_filter(ctx, &ctx->task_queue, delete_peer_task, peer); -} |