X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Ftincctl.c;h=a882a6689c07ae06f91b3e95024ad8af589aa235;hb=48dd371b2ec69f02870aa5e2a67fc8adb4617ff1;hp=5ae76d31524baadef5781ff21388caaf3c81769e;hpb=b9a7444b9fa216d16d91f34d2e12f51fc4d60e46;p=tinc diff --git a/src/tincctl.c b/src/tincctl.c index 5ae76d31..a882a668 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -40,6 +40,9 @@ #include "version.h" #include "subnet.h" #include "keys.h" +#include "random.h" +#include "pidfile.h" +#include "console.h" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 @@ -610,8 +613,9 @@ static void pcap(int fd, FILE *out, uint32_t snaplen) { } } -static void logcontrol(int fd, FILE *out, int level) { - sendline(fd, "%d %d %d", CONTROL, REQ_LOG, level); +static void log_control(int fd, FILE *out, int level, bool use_color) { + sendline(fd, "%d %d %d %d", CONTROL, REQ_LOG, level, use_color); + char data[1024]; char line[32]; @@ -724,9 +728,9 @@ bool connect_tincd(bool verbose) { } } - FILE *f = fopen(pidfilename, "r"); + pidfile_t *pidfile = read_pidfile(); - if(!f) { + if(!pidfile) { if(verbose) { fprintf(stderr, "Could not open pid file %s: %s\n", pidfilename, strerror(errno)); } @@ -734,21 +738,11 @@ bool connect_tincd(bool verbose) { return false; } - char host[129]; - char port[129]; - - if(fscanf(f, "%20d %1024s %128s port %128s", &pid, controlcookie, host, port) != 4) { - if(verbose) { - fprintf(stderr, "Could not parse pid file %s\n", pidfilename); - } - - fclose(f); - return false; - } - - fclose(f); + pid = pidfile->pid; + strcpy(controlcookie, pidfile->cookie); #ifndef HAVE_WINDOWS + free(pidfile); if((pid == 0) || (kill(pid, 0) && (errno == ESRCH))) { fprintf(stderr, "Could not find tincd running at pid %d\n", pid); @@ -799,11 +793,12 @@ bool connect_tincd(bool verbose) { struct addrinfo *res = NULL; - if(getaddrinfo(host, port, &hints, &res) || !res) { + if(getaddrinfo(pidfile->host, pidfile->port, &hints, &res) || !res) { if(verbose) { - fprintf(stderr, "Cannot resolve %s port %s: %s\n", host, port, sockstrerror(sockerrno)); + fprintf(stderr, "Cannot resolve %s port %s: %s\n", pidfile->host, pidfile->port, sockstrerror(sockerrno)); } + free(pidfile); return false; } @@ -814,6 +809,7 @@ bool connect_tincd(bool verbose) { fprintf(stderr, "Cannot create TCP socket: %s\n", sockstrerror(sockerrno)); } + free(pidfile); return false; } @@ -827,14 +823,16 @@ bool connect_tincd(bool verbose) { if(connect(fd, res->ai_addr, res->ai_addrlen) < 0) { if(verbose) { - fprintf(stderr, "Cannot connect to %s port %s: %s\n", host, port, sockstrerror(sockerrno)); + fprintf(stderr, "Cannot connect to %s port %s: %s\n", pidfile->host, pidfile->port, sockstrerror(sockerrno)); } + free(pidfile); closesocket(fd); fd = -1; return false; } + free(pidfile); freeaddrinfo(res); #endif @@ -959,7 +957,7 @@ static int cmd_start(int argc, char *argv[]) { if(!pid) { close(pfd[0]); char buf[100]; - snprintf(buf, sizeof(buf), "%d", pfd[1]); + snprintf(buf, sizeof(buf), "%d %d", pfd[1], use_ansi_escapes(stderr)); setenv("TINC_UMBILICAL", buf, true); exit(execvp(c, nargv)); } else { @@ -1522,7 +1520,8 @@ static int cmd_log(int argc, char *argv[]) { signal(SIGINT, sigint_handler); #endif - logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1); + bool use_color = use_ansi_escapes(stdout); + log_control(fd, stdout, argc > 1 ? atoi(argv[1]) : DEBUG_UNSET, use_color); #ifdef SIGINT signal(SIGINT, SIG_DFL); @@ -1719,6 +1718,20 @@ const var_t variables[] = { {NULL, 0} }; +// Request actual port from tincd +static bool read_actual_port(void) { + pidfile_t *pidfile = read_pidfile(); + + if(pidfile) { + printf("%s\n", pidfile->port); + free(pidfile); + return true; + } else { + fprintf(stderr, "Could not get port from the pidfile.\n"); + return false; + } +} + static int cmd_config(int argc, char *argv[]) { if(argc < 2) { fprintf(stderr, "Invalid number of arguments.\n"); @@ -1729,16 +1742,17 @@ static int cmd_config(int argc, char *argv[]) { argv--, argc++; } - int action = -2; + typedef enum { GET, DEL, SET, ADD } action_t; + action_t action = GET; if(!strcasecmp(argv[1], "get")) { argv++, argc--; } else if(!strcasecmp(argv[1], "add")) { - argv++, argc--, action = 1; + argv++, argc--, action = ADD; } else if(!strcasecmp(argv[1], "del")) { - argv++, argc--, action = -1; + argv++, argc--, action = DEL; } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) { - argv++, argc--, action = 0; + argv++, argc--, action = SET; } if(argc < 2) { @@ -1784,13 +1798,18 @@ static int cmd_config(int argc, char *argv[]) { return 1; } - if(action >= 0 && !*value) { + if((action == SET || action == ADD) && !*value) { fprintf(stderr, "No value for variable given.\n"); return 1; } - if(action < -1 && *value) { - action = 0; + if(action == GET && *value) { + action = SET; + } + + // If port is requested, try reading it from the pidfile and fall back to configs if that fails + if(action == GET && !strcasecmp(variable, "Port") && read_actual_port()) { + return 0; } /* Some simple checks. */ @@ -1821,7 +1840,7 @@ static int cmd_config(int argc, char *argv[]) { /* Discourage use of obsolete variables. */ - if(variables[i].type & VAR_OBSOLETE && action >= 0) { + if(variables[i].type & VAR_OBSOLETE && (action == SET || action == ADD)) { if(force) { fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable); } else { @@ -1832,7 +1851,7 @@ static int cmd_config(int argc, char *argv[]) { /* Don't put server variables in host config files */ - if(node && !(variables[i].type & VAR_HOST) && action >= 0) { + if(node && !(variables[i].type & VAR_HOST) && (action == SET || action == ADD)) { if(force) { fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable); } else { @@ -1854,10 +1873,10 @@ static int cmd_config(int argc, char *argv[]) { /* Change "add" into "set" for variables that do not allow multiple occurrences. Turn on warnings when it seems variables might be removed unintentionally. */ - if(action == 1 && !(variables[i].type & VAR_MULTIPLE)) { + if(action == ADD && !(variables[i].type & VAR_MULTIPLE)) { warnonremove = true; - action = 0; - } else if(action == 0 && (variables[i].type & VAR_MULTIPLE)) { + action = SET; + } else if(action == SET && (variables[i].type & VAR_MULTIPLE)) { warnonremove = true; } @@ -1875,7 +1894,7 @@ static int cmd_config(int argc, char *argv[]) { } if(!found) { - if(force || action < 0) { + if(force || action == GET || action == DEL) { fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable); } else { fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable); @@ -1916,7 +1935,7 @@ static int cmd_config(int argc, char *argv[]) { char tmpfile[PATH_MAX]; FILE *tf = NULL; - if(action >= -1) { + if(action != GET) { if((size_t)snprintf(tmpfile, sizeof(tmpfile), "%s.config.tmp", filename) >= sizeof(tmpfile)) { fprintf(stderr, "Filename too long: %s.config.tmp\n", filename); return 1; @@ -1959,19 +1978,15 @@ static int cmd_config(int argc, char *argv[]) { // Did it match? if(!strcasecmp(buf2, variable)) { - // Get - if(action < -1) { + if(action == GET) { found = true; printf("%s\n", bvalue); - // Del - } else if(action == -1) { + } else if(action == DEL) { if(!*value || !strcasecmp(bvalue, value)) { removed = true; continue; } - - // Set - } else if(action == 0) { + } else if(action == SET) { // Warn if "set" was used for variables that can occur multiple times if(warnonremove && strcasecmp(bvalue, value)) { fprintf(stderr, "Warning: removing %s = %s\n", variable, bvalue); @@ -1990,8 +2005,7 @@ static int cmd_config(int argc, char *argv[]) { set = true; continue; - // Add - } else if(action > 0) { + } else if(action == ADD) { // Check if we've already seen this variable with the same value if(!strcasecmp(bvalue, value)) { found = true; @@ -1999,7 +2013,7 @@ static int cmd_config(int argc, char *argv[]) { } } - if(action >= -1) { + if(action != GET) { // Copy original line... if(fputs(buf1, tf) < 0) { fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno)); @@ -2028,14 +2042,14 @@ static int cmd_config(int argc, char *argv[]) { } // Add new variable if necessary. - if((action > 0 && !found) || (action == 0 && !set)) { + if((action == ADD && !found) || (action == SET && !set)) { if(fprintf(tf, "%s = %s\n", variable, value) < 0) { fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno)); return 1; } } - if(action < -1) { + if(action == GET) { if(found) { return 0; } else { @@ -2051,7 +2065,7 @@ static int cmd_config(int argc, char *argv[]) { } // Could we find what we had to remove? - if(action < 0 && !removed) { + if((action == GET || action == DEL) && !removed) { remove(tmpfile); fprintf(stderr, "No configuration variables deleted.\n"); return 1; @@ -3266,6 +3280,22 @@ static void cleanup(void) { free_names(); } +static int run_command(int argc, char *argv[]) { + if(optind >= argc) { + return cmd_shell(argc, argv); + } + + for(int i = 0; commands[i].command; i++) { + if(!strcasecmp(argv[optind], commands[i].command)) { + return commands[i].function(argc - optind, argv + optind); + } + } + + fprintf(stderr, "Unknown command `%s'.\n", argv[optind]); + usage(true); + return 1; +} + int main(int argc, char *argv[]) { program_name = argv[0]; orig_argv = argv; @@ -3301,20 +3331,13 @@ int main(int argc, char *argv[]) { #endif gettimeofday(&now, NULL); + random_init(); crypto_init(); prng_init(); - if(optind >= argc) { - return cmd_shell(argc, argv); - } + int result = run_command(argc, argv); - for(int i = 0; commands[i].command; i++) { - if(!strcasecmp(argv[optind], commands[i].command)) { - return commands[i].function(argc - optind, argv + optind); - } - } + random_exit(); - fprintf(stderr, "Unknown command `%s'.\n", argv[optind]); - usage(true); - return 1; + return result; }