From ae429e372a412cec84c6f67477bd9d429c485ff7 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 31 May 2014 05:15:52 +0200 Subject: Split main function init() is still a bit long, but much better than before. --- src/config.c | 2 - src/fastd.c | 214 +++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 128 insertions(+), 88 deletions(-) diff --git a/src/config.c b/src/config.c index 6119669..21c30c4 100644 --- a/src/config.c +++ b/src/config.c @@ -58,8 +58,6 @@ extern const fastd_protocol_t fastd_protocol_ec25519_fhmqvc; /** Initializes the global configuration with default values */ static void default_config(void) { - memset(&conf, 0, sizeof(fastd_config_t)); - conf.log_syslog_ident = strdup("fastd"); conf.mtu = 1500; diff --git a/src/fastd.c b/src/fastd.c index 522d4b6..8b5e7de 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -63,7 +63,7 @@ /** The global context */ -fastd_context_t ctx; +fastd_context_t ctx = {}; static volatile bool sighup = false; /**< Is set to true when a SIGHUP is received */ @@ -277,38 +277,6 @@ static void dump_state(void) { pr_info("dump finished."); } -/** Performs periodic maintenance tasks */ -static inline void maintenance(void) { - if (!fastd_timed_out(&ctx.next_maintenance)) - return; - - fastd_socket_handle_binds(); - fastd_peer_maintenance(); - - ctx.next_maintenance.tv_sec += MAINTENANCE_INTERVAL; -} - -/** Reaps zombies of asynchronous shell commands. */ -static inline void reap_zombies(void) { - size_t i; - for (i = 0; i < VECTOR_LEN(ctx.async_pids);) { - pid_t pid = VECTOR_INDEX(ctx.async_pids, i); - if (waitpid(pid, NULL, WNOHANG) > 0) { - pr_debug("child process %u finished", (unsigned)pid); - } - else { - if (errno == ECHILD) { - i++; - continue; - } - else { - pr_error_errno("waitpid"); - } - } - - VECTOR_DELETE(ctx.async_pids, i); - } -} /** Closes all open FDs except stdin, stdout and stderr */ void fastd_close_all_fds(void) { @@ -333,8 +301,9 @@ void fastd_close_all_fds(void) { } } + /** Writes the PID file */ -static void write_pid(pid_t pid) { +static inline void write_pid(void) { if (!conf.pid_file) return; @@ -354,7 +323,7 @@ static void write_pid(pid_t pid) { goto end; } - if (dprintf(fd, "%i", pid) < 0) + if (dprintf(fd, "%u", (unsigned)getpid()) < 0) pr_error_errno("can't write PID file: dprintf"); if (close(fd) < 0) @@ -484,31 +453,23 @@ static void notify_systemd(const char *notify_socket) { } #endif -/** Main function */ -int main(int argc, char *argv[]) { - memset(&ctx, 0, sizeof(ctx)); - int status_fd = -1; - -#ifdef ENABLE_SYSTEMD - char *notify_socket = getenv("NOTIFY_SOCKET"); - - if (notify_socket) { - notify_socket = strdup(notify_socket); - - /* unset the socket to allow calling on_pre_up safely */ - unsetenv("NOTIFY_SOCKET"); - } -#endif +/** Early initialization before reading the config */ +static inline void init_early(void) { fastd_close_all_fds(); fastd_random_bytes(&ctx.randseed, sizeof(ctx.randseed), false); fastd_cipher_init(); fastd_mac_init(); +} - fastd_configure(argc, argv); +/** + Performs further initialization after the config has been loaded + This also handles special run modes like \em generate-key and \em verify-config. +*/ +static inline void init_config(int *status_fd) { if (conf.verify_config) { fastd_config_verify(); exit(0); @@ -529,13 +490,19 @@ int main(int argc, char *argv[]) { init_signals(); if (conf.daemon) - status_fd = daemonize(); + *status_fd = daemonize(); if (chdir("/")) pr_error("can't chdir to `/': %s", strerror(errno)); + /* + Initialize log here, as: + - we have already daemonized, so syslog will show the correct PID + - special run modes that should always log to stderr have been handled + */ init_log(); + /* Init crypto libs here as fastd_config_check() initializes the methods and might need them */ #ifdef HAVE_LIBSODIUM sodium_init(); #endif @@ -547,20 +514,35 @@ int main(int argc, char *argv[]) { #endif fastd_config_check(); +} - fastd_update_time(); +/** Initializes fastd */ +static inline void init(int argc, char *argv[]) { + int status_fd = -1; - ctx.next_maintenance = fastd_in_seconds(MAINTENANCE_INTERVAL); +#ifdef ENABLE_SYSTEMD + char *notify_socket = getenv("NOTIFY_SOCKET"); + + if (notify_socket) { + notify_socket = strdup(notify_socket); + /* unset the socket to allow calling on_pre_up safely */ + unsetenv("NOTIFY_SOCKET"); + } +#endif + + init_early(); + fastd_configure(argc, argv); + init_config(&status_fd); + + fastd_update_time(); + ctx.next_maintenance = fastd_in_seconds(MAINTENANCE_INTERVAL); ctx.unknown_handshakes[0].timeout = ctx.now; pr_info("fastd " FASTD_VERSION " starting"); fastd_cap_init(); - /* change groups early as the can be relevant for file access (for the PID file) */ - set_groups(); - init_sockets(); fastd_async_init(); fastd_poll_init(); @@ -572,7 +554,15 @@ int main(int argc, char *argv[]) { fastd_tuntap_open(); - write_pid(getpid()); + /* change groups before trying to write the PID file as they can be relevant for file access */ + set_groups(); + write_pid(); + + VECTOR_ALLOC(ctx.eth_addrs, 0); + VECTOR_ALLOC(ctx.peers, 0); + VECTOR_ALLOC(ctx.async_pids, 0); + + fastd_peer_hashtable_init(); #ifdef ENABLE_SYSTEMD if (notify_socket) { @@ -600,48 +590,89 @@ int main(int argc, char *argv[]) { set_user(); fastd_config_load_peer_dirs(); + init_peers(); +} - VECTOR_ALLOC(ctx.eth_addrs, 0); - VECTOR_ALLOC(ctx.peers, 0); - VECTOR_ALLOC(ctx.async_pids, 0); - - fastd_peer_hashtable_init(); - init_peers(); +/** Performs periodic maintenance tasks */ +static inline void maintenance(void) { + if (!fastd_timed_out(&ctx.next_maintenance)) + return; - while (!terminate) { - fastd_peer_handle_handshake_queue(); + fastd_socket_handle_binds(); + fastd_peer_maintenance(); - fastd_poll_handle(); + ctx.next_maintenance.tv_sec += MAINTENANCE_INTERVAL; +} - maintenance(); +/** Reaps zombies of asynchronous shell commands. */ +static inline void reap_zombies(void) { + size_t i; + for (i = 0; i < VECTOR_LEN(ctx.async_pids);) { + pid_t pid = VECTOR_INDEX(ctx.async_pids, i); + if (waitpid(pid, NULL, WNOHANG) > 0) { + pr_debug("child process %u finished", (unsigned)pid); + } + else { + if (errno == ECHILD) { + i++; + continue; + } + else { + pr_error_errno("waitpid"); + } + } - sigset_t set, oldset; - sigfillset(&set); - pthread_sigmask(SIG_SETMASK, &set, &oldset); + VECTOR_DELETE(ctx.async_pids, i); + } +} - if (sighup) { - sighup = false; +/** The \em real signal handlers */ +static inline void handle_signals(void) { + sigset_t set, oldset; + sigfillset(&set); + pthread_sigmask(SIG_SETMASK, &set, &oldset); - pr_info("reconfigure triggered"); + if (sighup) { + sighup = false; - fastd_config_load_peer_dirs(); - init_peers(); - } + pr_info("reconfigure triggered"); - if (dump) { - dump = false; - dump_state(); - } + fastd_config_load_peer_dirs(); + init_peers(); + } - if (sigchld) { - sigchld = false; - reap_zombies(); - } + if (dump) { + dump = false; + dump_state(); + } - pthread_sigmask(SIG_SETMASK, &oldset, NULL); + if (sigchld) { + sigchld = false; + reap_zombies(); } + pthread_sigmask(SIG_SETMASK, &oldset, NULL); +} + + +/** A single iteration of fastd's main loop */ +static inline void run(void) { + fastd_peer_handle_handshake_queue(); + fastd_poll_handle(); + + maintenance(); + handle_signals(); +} + +/** + Performs cleanup of resources used by fastd + + Besides running the on-down scripts and closing the TUN/TAP interface, this + also frees all memory allocatedby fastd to make debugging memory leaks with + valgrind as easy as possible. +*/ +static inline void cleanup(void) { on_down(); delete_peers(); @@ -669,6 +700,17 @@ int main(int argc, char *argv[]) { close_log(); fastd_config_release(); +} + + +/** Main function */ +int main(int argc, char *argv[]) { + init(argc, argv); + + while (!terminate) + run(); + + cleanup(); return 0; } -- cgit v1.2.3