X-Git-Url: https://www.tinc-vpn.org/git/browse?a=blobdiff_plain;f=tincd.c;h=2e4015201ab61cc055772a208db2b4dd4d60a08d;hb=942ee816b88f9c35b456abab1864e5e2b811e5c8;hp=5f99cea883173bb10536e09574deb035d924a23e;hpb=7d12cbb6e6acebbe8f9bcab75f5ec878a3360eb9;p=tinc diff --git a/tincd.c b/tincd.c index 5f99cea8..2e401520 100644 --- a/tincd.c +++ b/tincd.c @@ -22,100 +22,321 @@ #include "system.h" +#include + +/* Darwin (MacOS/X) needs the following definition... */ +#ifndef _P1003_1B_VISIBLE +#define _P1003_1B_VISIBLE +#endif + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#include "tincd.h" #include "cfg/cfg.h" #include "fd/event.h" #include "fd/fd.h" #include "logger/logger.h" +#include "rt/rt.h" #include "support/avl.h" #include "support/sockaddr.h" #include "support/xalloc.h" #include "tnl/tnl.h" #include "vnd/vnd.h" -static bool vnd_recv(struct vnd *vnd, char *buf, int len) { - static int p = 0; - char b[4]; - logger(LOG_DEBUG, _("Read packet of %d bytes from vnd %p"), len, vnd); - memcpy(b, buf + 16, 4); - memcpy(buf + 16, buf + 20, 4); - memcpy(buf + 20, b, 4); - vnd->send(vnd, buf, len); - return true; +static bool show_help = false; +static bool show_version = false; +static int kill_tincd = 0; +static bool bypass_security = false; +static bool do_mlock = false; +static bool do_detach = true; +static int debug_level = 1; + +char *tinc_confbase = NULL; +char *tinc_netname = NULL; +char *tinc_identname = NULL; +char *tinc_pidfilename = NULL; +char *tinc_logfilename = NULL; +char *tinc_cfgfilename = NULL; + +bool tinc_use_logfile = false; + +int tinc_argc; +char **tinc_argv; +avl_tree_t *tinc_cfg; + +static struct option const long_options[] = { + {"config", required_argument, NULL, 'c'}, + {"kill", optional_argument, NULL, 'k'}, + {"net", required_argument, NULL, 'n'}, + {"help", no_argument, NULL, 1}, + {"version", no_argument, NULL, 2}, + {"no-detach", no_argument, NULL, 'D'}, + {"debug", optional_argument, NULL, 'd'}, + {"bypass-security", no_argument, NULL, 3}, + {"mlock", no_argument, NULL, 'L'}, + {"logfile", optional_argument, NULL, 4}, + {"pidfile", required_argument, NULL, 5}, + {NULL, 0, NULL, 0} +}; + +#ifdef HAVE_MINGW +static struct WSAData wsa_state; +#endif + +static void usage(bool status) { + if(status) + fprintf(stderr, _("Try `%s --help\' for more information.\n"), tinc_argv[0]); + else { + printf(_("Usage: %s [option]...\n\n"), tinc_argv[0]); + printf(_(" -c, --config=DIR Read configuration options from DIR.\n" + " -D, --no-detach Don't fork and detach.\n" + " -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n" + " -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n" + " -n, --net=NETNAME Connect to net NETNAME.\n" + " -L, --mlock Lock tinc into main memory.\n" + " --logfile[=FILENAME] Write log entries to a logfile.\n" + " --pidfile=FILENAME Write PID to FILENAME.\n" + " --help Display this help and exit.\n" + " --version Output version information and exit.\n\n")); + printf(_("Report bugs to tinc@tinc-vpn.org.\n")); + } } -static bool vnd_stop(event_t *event) { - static int i = 0; +static bool parse_options(int argc, char **argv) { + int result; + int option_index = 0; + + while((result = getopt_long(argc, argv, "c:DLd::k::n:", long_options, &option_index)) != EOF) { + switch (result) { + case 0: + break; + + case 'c': /* --config */ + tinc_confbase = xstrdup(optarg); + break; + + case 'D': /* --no-detach */ + do_detach = false; + break; + + case 'L': /* --mlock */ + do_mlock = true; + break; - logger(LOG_DEBUG, "i = %d", i++); + case 'd': /* --debug */ + if(optarg) + debug_level = atoi(optarg); + else + debug_level++; + break; - if(i > 5) { - fd_stop(); - return false; + case 'k': /* --kill */ +#ifndef HAVE_MINGW + if(optarg) { + if(!strcasecmp(optarg, "HUP")) + kill_tincd = SIGHUP; + else if(!strcasecmp(optarg, "TERM")) + kill_tincd = SIGTERM; + else if(!strcasecmp(optarg, "KILL")) + kill_tincd = SIGKILL; + else if(!strcasecmp(optarg, "USR1")) + kill_tincd = SIGUSR1; + else if(!strcasecmp(optarg, "USR2")) + kill_tincd = SIGUSR2; + else if(!strcasecmp(optarg, "WINCH")) + kill_tincd = SIGWINCH; + else if(!strcasecmp(optarg, "INT")) + kill_tincd = SIGINT; + else if(!strcasecmp(optarg, "ALRM")) + kill_tincd = SIGALRM; + else { + kill_tincd = atoi(optarg); + + if(!kill_tincd) { + fprintf(stderr, _("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"), + optarg); + usage(true); + return false; + } + } + } else + kill_tincd = SIGTERM; +#else + kill_tincd = 1; +#endif + break; + + case 'n': /* --net */ + tinc_netname = xstrdup(optarg); + break; + + case 1: /* --help */ + show_help = true; + break; + + case 2: /* --version */ + show_version = true; + break; + + case 3: /* --bypass-security */ + bypass_security = true; + break; + + case 4: /* --logfile */ + tinc_use_logfile = true; + if(optarg) + tinc_logfilename = xstrdup(optarg); + break; + + case 5: /* --pidfile */ + tinc_pidfilename = xstrdup(optarg); + break; + + case '?': + usage(true); + return false; + + default: + break; + } } - event_update(event, event->interval); return true; } -int test(int argc, char **argv) { - vnd_t *vnd; - event_t *stop; - tnl_listen_t *listener; - - //vnd_init(); - if(fd_init() && tnl_init()) { - vnd = vnd_new(); - vnd_set(vnd, "/dev/tun", "test", VND_MODE_TUN, vnd_recv); - - stop = event_new(); - event_set(stop, (struct timeval){5, 0}, vnd_stop, NULL); - event_add(stop); - - clear(new(listener)); - listener->type = SOCK_STREAM; - listener->protocol = IPPROTO_TCP; - sa(&listener->local.address)->sa_family = AF_INET; - - if(tnl_listen(listener) && vnd_open(vnd)) { - fd_run(); - vnd_close(vnd); - listener->close(listener); +static void make_names(void) +{ +#ifdef HAVE_MINGW + HKEY key; + char installdir[1024] = ""; + long len = sizeof(installdir); +#endif + + if(tinc_netname) + asprintf(&tinc_identname, "tinc.%s", tinc_netname); + else + tinc_identname = xstrdup("tinc"); + +#ifdef HAVE_MINGW + if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) { + if(!RegQueryValueEx(key, NULL, 0, 0, installdir, &len)) { + if(!tinc_logfilename) + asprintf(&tinc_logfilename, "%s/log/%s.log", tinc_identname); + if(!tinc_confbase) { + if(tinc_netname) + asprintf(&tinc_confbase, "%s/%s", installdir, tinc_netname); + else + asprintf(&tinc_confbase, "%s", installdir); + } } + RegCloseKey(key); + if(*installdir) + return; + } +#endif - vnd_free(vnd); + if(!tinc_pidfilename) + asprintf(&tinc_pidfilename, LOCALSTATEDIR "/run/%s.pid", tinc_identname); - tnl_exit(); - fd_exit(); + if(!tinc_logfilename) + asprintf(&tinc_logfilename, LOCALSTATEDIR "/log/%s.log", tinc_identname); + + if(!tinc_confbase) { + if(tinc_netname) + asprintf(&tinc_confbase, CONFDIR "/tinc/%s", tinc_netname); + else + asprintf(&tinc_confbase, CONFDIR "/tinc"); } - //vnd_exit(); -} -avl_tree_t *tinc_cfg = NULL; -char *tinc_netname = NULL; + asprintf(&tinc_cfgfilename, "%s/tinc.conf", tinc_confbase); +} int main(int argc, char **argv) { - tnl_listen_t *listener; + tinc_argc = argc; + tinc_argv = argv; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); - logger_init("tinc", LOGGER_MODE_STDERR); + if(!parse_options(argc, argv)) + return 1; + make_names(); + + if(show_version) { + printf(_("%s version %s (built %s %s, protocol %d/%d)\n"), PACKAGE, + VERSION, __DATE__, __TIME__, TNL_PROTOCOL, RT_PROTOCOL); + printf(_("Copyright (C) 1998-2004 Ivo Timmermans, Guus Sliepen and others.\n" + "See the AUTHORS file for a complete list.\n\n" + "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" + "and you are welcome to redistribute it under certain conditions;\n" + "see the file COPYING for details.\n")); + + return 0; + } + + if(show_help) { + usage(false); + return 0; + } + + if(kill_tincd) + return !kill_other(kill_tincd); + + logger_init("tinc", tinc_use_logfile ? LOGGER_MODE_FILE : LOGGER_MODE_STDERR); + + /* Lock all pages into memory if requested */ + + if(do_mlock) +#ifdef HAVE_MLOCKALL + if(mlockall(MCL_CURRENT | MCL_FUTURE)) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "mlockall", + strerror(errno)); +#else + { + logger(LOG_ERR, _("mlockall() not supported on this platform!")); +#endif + return -1; + } + tinc_cfg = cfg_tree_new(); + + asprintf(&tinc_cfgfilename, "%s/tinc.conf", tinc_confbase); - if(!cfg_read_file(tinc_cfg, "tinc.conf")) + if(!cfg_read_file(tinc_cfg, tinc_cfgfilename)) return 1; - if(fd_init() && tnl_init()) { - clear(new(listener)); - listener->type = SOCK_STREAM; - listener->protocol = IPPROTO_TCP; - sa(&listener->local.address)->sa_family = AF_INET; - ((struct sockaddr_in *) &listener->local.address)->sin_port = htons(655); - if(tnl_listen(listener)) { - fd_run(); - listener->close(listener); - } - tnl_exit() && fd_exit(); +#ifdef HAVE_MINGW + if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) { + logger(LOG_ERR, _("System call `%s' failed: %s"), "WSAStartup", winerror(GetLastError())); + return 1; } +#endif + + if(do_detach && !detach()) + return 1; + + logger(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"), + VERSION, __DATE__, __TIME__, logger_level); + if(!fd_init() || !rt_init()) + return 1; + + fd_run(); + + rt_exit(); + fd_exit(); +end: + logger(LOG_NOTICE, _("Terminating")); + +#ifndef HAVE_MINGW + remove_pid(tinc_pidfilename); +#endif + + logger_exit(); + return 0; } -