X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Ftincd.c;h=7970bcc9f2b67d1854df8fd0dece1ec2277ae774;hb=3fba80174dbe29bcfe0d121a2a1d2e61be5ee57b;hp=1a9bad0d55cea46abe899685bd89ecfa80d1b2d6;hpb=108b238915c5f58b3d94ab433dc5d04e064c2b11;p=meshlink diff --git a/src/tincd.c b/src/tincd.c index 1a9bad0d..7970bcc9 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -1,9 +1,11 @@ /* tincd.c -- the main file for tincd Copyright (C) 1998-2005 Ivo Timmermans - 2000-2009 Guus Sliepen + 2000-2011 Guus Sliepen 2008 Max Rijevski 2009 Michael Tokarev + 2010 Julien Muchembled + 2010 Timothy Redaelli This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,7 +33,15 @@ #include #endif +#include +#include +#include +#include +#include + +#ifdef HAVE_LZO #include LZO1X_H +#endif #ifndef HAVE_MINGW #include @@ -57,16 +67,16 @@ char *program_name = NULL; /* If nonzero, display usage information and exit. */ -bool show_help = false; +static bool show_help = false; /* If nonzero, print the version on standard output and exit. */ -bool show_version = false; +static bool show_version = false; /* If nonzero, use null ciphers and skip all key exchanges. */ bool bypass_security = false; /* If nonzero, disable swapping for this process. */ -bool do_mlock = false; +static bool do_mlock = false; /* If nonzero, chroot to netdir after startup. */ static bool do_chroot = false; @@ -78,11 +88,11 @@ static const char *switchuser = NULL; bool use_logfile = false; char *identname = NULL; /* program name for syslog */ -char *controlsocketname = NULL; /* control socket location */ char *logfilename = NULL; /* log file location */ +char *pidfilename = NULL; char **g_argv; /* a copy of the cmdline arguments */ -static int status; +static int status = 1; static struct option const long_options[] = { {"config", required_argument, NULL, 'c'}, @@ -96,13 +106,15 @@ static struct option const long_options[] = { {"chroot", no_argument, NULL, 'R'}, {"user", required_argument, NULL, 'U'}, {"logfile", optional_argument, NULL, 4}, - {"controlsocket", required_argument, NULL, 5}, + {"pidfile", required_argument, NULL, 5}, + {"option", required_argument, NULL, 'o'}, {NULL, 0, NULL, 0} }; #ifdef HAVE_MINGW static struct WSAData wsa_state; CRITICAL_SECTION mutex; +int main2(int argc, char **argv); #endif static void usage(bool status) { @@ -117,8 +129,9 @@ static void usage(bool status) { " -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" - " --controlsocket=FILENAME Open control socket at FILENAME.\n" + " --pidfile=FILENAME Write PID and control socket cookie to FILENAME.\n" " --bypass-security Disables meta protocol security, for debugging.\n" + " -o, --option[HOST.]KEY=VALUE Set global/host configuration value.\n" " -R, --chroot chroot to NET dir at startup.\n" " -U, --user=USER setuid to given USER at startup.\n" " --help Display this help and exit.\n" " --version Output version information and exit.\n\n"); @@ -127,10 +140,14 @@ static void usage(bool status) { } static bool parse_options(int argc, char **argv) { + config_t *cfg; int r; int option_index = 0; + int lineno = 0; - while((r = getopt_long(argc, argv, "c:DLd::n:RU:", long_options, &option_index)) != EOF) { + cmdline_conf = list_alloc((list_action_t)free_config); + + while((r = getopt_long(argc, argv, "c:DLd::n:o:RU:", long_options, &option_index)) != EOF) { switch (r) { case 0: /* long option */ break; @@ -160,7 +177,16 @@ static bool parse_options(int argc, char **argv) { break; case 'n': /* net name given */ - netname = xstrdup(optarg); + /* netname "." is special: a "top-level name" */ + netname = strcmp(optarg, ".") != 0 ? + xstrdup(optarg) : NULL; + break; + + case 'o': /* option */ + cfg = parse_config_line(optarg, NULL, ++lineno); + if (!cfg) + return false; + list_insert_tail(cmdline_conf, cfg); break; case 'R': /* chroot to NETNAME dir */ @@ -190,7 +216,7 @@ static bool parse_options(int argc, char **argv) { break; case 5: /* open control socket here */ - controlsocketname = xstrdup(optarg); + pidfilename = xstrdup(optarg); break; case '?': @@ -231,6 +257,8 @@ static void make_names(void) { else xasprintf(&confbase, "%s", installdir); } + if(!pidfilename) + xasprintf(&pidfilename, "%s/pid", confbase); } RegCloseKey(key); if(*installdir) @@ -238,12 +266,12 @@ static void make_names(void) { } #endif - if(!controlsocketname) - xasprintf(&controlsocketname, "%s/run/%s.control/socket", LOCALSTATEDIR, identname); - if(!logfilename) xasprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname); + if(!pidfilename) + xasprintf(&pidfilename, LOCALSTATEDIR "/run/%s.pid", identname); + if(netname) { if(!confbase) xasprintf(&confbase, CONFDIR "/tinc/%s", netname); @@ -255,15 +283,15 @@ static void make_names(void) { } } -static void free_names() { +static void free_names(void) { if (identname) free(identname); if (netname) free(netname); - if (controlsocketname) free(controlsocketname); + if (pidfilename) free(pidfilename); if (logfilename) free(logfilename); if (confbase) free(confbase); } -static bool drop_privs() { +static bool drop_privs(void) { #ifdef HAVE_MINGW if (switchuser) { logger(LOG_ERR, "%s not supported on this platform", "-U"); @@ -312,12 +340,12 @@ static bool drop_privs() { } #ifdef HAVE_MINGW -# define setpriority(level) SetPriorityClass(GetCurrentProcess(), level) +# define setpriority(level) !SetPriorityClass(GetCurrentProcess(), (level)) #else # define NORMAL_PRIORITY_CLASS 0 # define BELOW_NORMAL_PRIORITY_CLASS 10 # define HIGH_PRIORITY_CLASS -10 -# define setpriority(level) nice(level) +# define setpriority(level) (setpriority(PRIO_PROCESS, 0, (level))) #endif int main(int argc, char **argv) { @@ -329,9 +357,9 @@ int main(int argc, char **argv) { make_names(); if(show_version) { - printf("%s version %s (built %s %s, protocol %d)\n", PACKAGE, - VERSION, __DATE__, __TIME__, PROT_CURRENT); - printf("Copyright (C) 1998-2009 Ivo Timmermans, Guus Sliepen and others.\n" + printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE, + VERSION, __DATE__, __TIME__, PROT_MAJOR, PROT_MINOR); + printf("Copyright (C) 1998-2011 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" @@ -345,6 +373,13 @@ int main(int argc, char **argv) { return 0; } +#ifdef HAVE_MINGW + if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) { + logger(LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError())); + return 1; + } +#endif + openlogger("tinc", use_logfile?LOGMODE_FILE:LOGMODE_STDERR); if(!event_init()) { @@ -352,9 +387,6 @@ int main(int argc, char **argv) { return 1; } - if(!init_control()) - return 1; - g_argv = argv; init_configuration(&config_tree); @@ -367,17 +399,14 @@ int main(int argc, char **argv) { if(!read_server_config()) return 1; +#ifdef HAVE_LZO if(lzo_init() != LZO_E_OK) { logger(LOG_ERR, "Error initializing LZO compressor!"); return 1; } +#endif #ifdef HAVE_MINGW - if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) { - logger(LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError())); - return 1; - } - if(!do_detach || !init_service()) return main2(argc, argv); else @@ -388,6 +417,7 @@ int main2(int argc, char **argv) { InitializeCriticalSection(&mutex); EnterCriticalSection(&mutex); #endif + char *priority = NULL; if(!detach()) return 1; @@ -406,7 +436,10 @@ int main2(int argc, char **argv) { /* Setup sockets and open device. */ if(!setup_network()) - goto end; + goto end_nonet; + + if(!init_control()) + goto end_nonet; /* Initiate all outgoing connections. */ @@ -414,16 +447,26 @@ int main2(int argc, char **argv) { /* Change process priority */ - char *priority = 0; - if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) { - if(!strcasecmp(priority, "Normal")) - setpriority(NORMAL_PRIORITY_CLASS); - else if(!strcasecmp(priority, "Low")) - setpriority(BELOW_NORMAL_PRIORITY_CLASS); - else if(!strcasecmp(priority, "High")) - setpriority(HIGH_PRIORITY_CLASS); - else { + if(!strcasecmp(priority, "Normal")) { + if (setpriority(NORMAL_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else if(!strcasecmp(priority, "Low")) { + if (setpriority(BELOW_NORMAL_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else if(!strcasecmp(priority, "High")) { + if (setpriority(HIGH_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else { logger(LOG_ERR, "Invalid priority `%s`!", priority); goto end; } @@ -440,20 +483,22 @@ int main2(int argc, char **argv) { /* Shutdown properly. */ ifdebug(CONNECTIONS) - dump_device_stats(); + devops.dump_stats(); close_network_connections(); end: + exit_control(); + +end_nonet: logger(LOG_NOTICE, "Terminating"); -#ifndef HAVE_MINGW - exit_control(); -#endif + free(priority); crypto_exit(); exit_configuration(&config_tree); + free(cmdline_conf); free_names(); return status;