#include "common.h" #include "buffer.h" #include "ip.h" #include "str.h" #include "option.h" #include "tun.h" #include "db.h" #include "state.h" #include #include #include #include #include #include #include #include #include #include #include #include "mud.h" #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif static struct { int timeout; volatile sig_atomic_t quit; volatile sig_atomic_t info; uint8_t key[crypto_generichash_KEYBYTES]; } gt; static void fd_set_nonblock (int fd) { int ret; do { ret = fcntl(fd, F_GETFL, 0); } while (ret==-1 && errno==EINTR); int flags = (ret==-1)?0:ret; do { ret = fcntl(fd, F_SETFL, flags|O_NONBLOCK); } while (ret==-1 && errno==EINTR); if (ret==-1) perror("fcntl O_NONBLOCK"); } static void gt_sa_handler (int sig) { switch (sig) { case SIGINT: case SIGQUIT: case SIGTERM: gt.quit = 1; break; case SIGUSR1: gt.info = 1; break; } } static void gt_set_signal (void) { struct sigaction sa = { .sa_flags = 0, }; sigemptyset(&sa.sa_mask); sa.sa_handler = gt_sa_handler; sigaction(SIGINT, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGUSR1, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction(SIGHUP, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); } static ssize_t fd_read (int fd, void *data, size_t size) { if ((fd==-1) || !size) return -1; ssize_t ret = read(fd, data, size); if (ret==-1) { if (errno==EAGAIN || errno==EINTR) return -1; if (errno) perror("read"); return 0; } return ret; } static ssize_t fd_write (int fd, const void *data, size_t size) { if ((fd==-1) || !size) return -1; ssize_t ret = write(fd, data, size); if (ret==-1) { if (errno==EAGAIN || errno==EINTR) return -1; if (errno==EPIPE || errno==ECONNRESET) return 0; if (errno) perror("write"); return 0; } return ret; } static size_t fd_read_all (int fd, void *data, size_t size) { size_t done = 0; while (doneINT_MAX) { gt_log("bad timeout\n"); return 1; } if (sodium_init()==-1) { gt_log("libsodium initialization has failed\n"); return 1; } if (state_init(statefile)) return 1; char *tun_name = NULL; int tun_fd = tun_create(dev, &tun_name, option_is_set(opts, "multiqueue")); if (tun_fd==-1) { gt_log("couldn't create tun device\n"); return 1; } fd_set_nonblock(tun_fd); if (gt_setup_secretkey(keyfile)) return 1; struct mud *mud = mud_create(bind_port); if (!mud) { gt_log("couldn't create mud\n"); return 1; } mud_set_key(mud, gt.key, sizeof(gt.key)); mud_set_send_timeout_msec(mud, gt.timeout); if (time_tolerance > 0) mud_set_time_tolerance_sec(mud, time_tolerance); if (bind_list) { char tmp[1024]; char *name = &tmp[0]; size_t size = str_cpy(tmp, bind_list, sizeof(tmp)-1); for (size_t i=0; i