]> git.meshlink.io Git - meshlink/blobdiff - src/tincd.c
Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1
[meshlink] / src / tincd.c
index 21623647fb1eb0be7876a74c49fa16d19263494b..7970bcc9f2b67d1854df8fd0dece1ec2277ae774 100644 (file)
@@ -1,9 +1,11 @@
 /*
     tincd.c -- the main file for tincd
     Copyright (C) 1998-2005 Ivo Timmermans
-                  2000-2010 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2011 Guus Sliepen <guus@tinc-vpn.org>
                   2008      Max Rijevski <maksuf@gmail.com>
                   2009      Michael Tokarev <mjt@tls.msk.ru>
+                  2010      Julien Muchembled <jm@jmuchemb.eu>
+                  2010      Timothy Redaelli <timothy@redaelli.eu>
 
     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
 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;
@@ -87,10 +89,10 @@ bool use_logfile = false;
 
 char *identname = NULL;                                /* program name for syslog */
 char *logfilename = NULL;                      /* log file location */
-char *controlcookiename = NULL;
+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'},
@@ -104,13 +106,15 @@ static struct option const long_options[] = {
        {"chroot", no_argument, NULL, 'R'},
        {"user", required_argument, NULL, 'U'},
        {"logfile", optional_argument, NULL, 4},
-       {"controlcookie", 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) {
@@ -125,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"
-                               "      --controlcookie=FILENAME  Write control socket cookie to 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");
@@ -135,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;
@@ -168,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 */
@@ -198,7 +216,7 @@ static bool parse_options(int argc, char **argv) {
                                break;
 
                        case 5:                                 /* open control socket here */
-                               controlcookiename = xstrdup(optarg);
+                               pidfilename = xstrdup(optarg);
                                break;
 
                        case '?':
@@ -239,8 +257,8 @@ static void make_names(void) {
                                else
                                        xasprintf(&confbase, "%s", installdir);
                        }
-                       if(!controlcookiename)
-                               xasprintf(&controlcookiename, "%s/cookie", confbase);
+                       if(!pidfilename)
+                               xasprintf(&pidfilename, "%s/pid", confbase);
                }
                RegCloseKey(key);
                if(*installdir)
@@ -251,8 +269,8 @@ static void make_names(void) {
        if(!logfilename)
                xasprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname);
 
-       if(!controlcookiename)
-               xasprintf(&controlcookiename, LOCALSTATEDIR "/run/%s.cookie", identname);
+       if(!pidfilename)
+               xasprintf(&pidfilename, LOCALSTATEDIR "/run/%s.pid", identname);
 
        if(netname) {
                if(!confbase)
@@ -265,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 (controlcookiename) free(controlcookiename);
+       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");
@@ -322,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) {
@@ -339,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-2010 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"
@@ -399,6 +417,7 @@ int main2(int argc, char **argv) {
        InitializeCriticalSection(&mutex);
        EnterCriticalSection(&mutex);
 #endif
+        char *priority = NULL;
 
        if(!detach())
                return 1;
@@ -417,10 +436,10 @@ int main2(int argc, char **argv) {
        /* Setup sockets and open device. */
 
        if(!setup_network())
-               goto end;
+               goto end_nonet;
 
        if(!init_control())
-               return 1;
+               goto end_nonet;
 
        /* Initiate all outgoing connections. */
 
@@ -428,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;
                 }
@@ -454,18 +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");
 
-       exit_control();
+       free(priority);
 
        crypto_exit();
 
        exit_configuration(&config_tree);
+       free(cmdline_conf);
        free_names();
 
        return status;