/*
tincctl.c -- Controlling a running tincd
- Copyright (C) 2007-2016 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2007-2017 Guus Sliepen <guus@tinc-vpn.org>
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 *scriptinterpreter = NULL;
char *scriptextension = "";
static char *prompt;
+char *device = NULL;
+char *iface = NULL;
+int debug_level = -1;
static struct option const long_options[] = {
{"batch", no_argument, NULL, 'b'},
static void version(void) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
- printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
+ printf("Copyright (C) 1998-2017 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"
// Make sure the key size is a multiple of 8 bits.
bits &= ~0x7;
- // Force them to be between 1024 and 8192 bits long.
- if(bits < 1024)
- bits = 1024;
- if(bits > 8192)
- bits = 8192;
+ // Make sure that a valid key size is used.
+ if(bits < 1024 || bits > 8192) {
+ fprintf(stderr, "Invalid key size %d specified! It should be between 1024 and 8192 bits.\n", bits);
+ return false;
+ } else if(bits < 2048) {
+ fprintf(stderr, "WARNING: generating a weak %d bits RSA key! 2048 or more bits are recommended.\n", bits);
+ }
fprintf(stderr, "Generating %d bits keys:\n", bits);
char *newline = NULL;
if(!fd)
- abort();
+ return false;
while(!(newline = memchr(buffer, '\n', blen))) {
int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
va_start(ap, format);
blen = vsnprintf(buffer, sizeof buffer, format, ap);
+ buffer[sizeof buffer - 1] = 0;
va_end(ap);
if(blen < 1 || blen >= sizeof buffer)
}
fclose(f);
+
+#ifndef HAVE_MINGW
if ((pid == 0) || (kill(pid, 0) && (errno == ESRCH))) {
fprintf(stderr, "Could not find tincd running at pid %d\n", pid);
/* clean up the stale socket and pid file */
return false;
}
-#ifndef HAVE_MINGW
struct sockaddr_un sa;
sa.sun_family = AF_UNIX;
strncpy(sa.sun_path, unixsocketname, sizeof sa.sun_path);
char data[4096];
int version;
- if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %s %d", &code, data, &version) != 3 || code != 0) {
+ if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %4095s %d", &code, data, &version) != 3 || code != 0) {
if(verbose)
fprintf(stderr, "Cannot read greeting from control socket: %s\n", sockstrerror(sockerrno));
close(fd);
if(!pid) {
close(pfd[0]);
- char buf[100] = "";
+ char buf[100];
snprintf(buf, sizeof buf, "%d", pfd[1]);
setenv("TINC_UMBILICAL", buf, true);
exit(execvp(c, nargv));
if(!connect_tincd(true)) {
if(pid) {
if(kill(pid, SIGTERM)) {
- fprintf(stderr, "Could not send TERM signal to process with PID %u: %s\n", pid, strerror(errno));
+ fprintf(stderr, "Could not send TERM signal to process with PID %d: %s\n", pid, strerror(errno));
return 1;
}
- fprintf(stderr, "Sent TERM signal to process with PID %u.\n", pid);
+ fprintf(stderr, "Sent TERM signal to process with PID %d.\n", pid);
waitpid(pid, NULL, 0);
return 0;
}
FILE *f = fopen(fname, "r");
if(!f) {
fprintf(stderr, "Cannot open %s: %s\n", fname, strerror(errno));
- fclose(f);
continue;
}
while(recvline(fd, line, sizeof line)) {
char node1[4096], node2[4096];
- int n = sscanf(line, "%d %d %s %s", &code, &req, node1, node2);
+ int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, node1, node2);
if(n == 2) {
if(do_graph && req == REQ_DUMP_NODES)
continue;
switch(req) {
case REQ_DUMP_NODES: {
- int n = sscanf(line, "%*d %*d %s %s %s port %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
+ int n = sscanf(line, "%*d %*d %4095s %4095s %4095s port %4095s %d %d %d %d %x %x %4095s %4095s %d %hd %hd %hd %ld", node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
if(n != 17) {
fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
return 1;
} break;
case REQ_DUMP_EDGES: {
- int n = sscanf(line, "%*d %*d %s %s %s port %s %s port %s %x %d", from, to, host, port, local_host, local_port, &options, &weight);
+ int n = sscanf(line, "%*d %*d %4095s %4095s %4095s port %4095s %4095s port %4095s %x %d", from, to, host, port, local_host, local_port, &options, &weight);
if(n != 8) {
fprintf(stderr, "Unable to parse edge dump from tincd.\n");
return 1;
} break;
case REQ_DUMP_SUBNETS: {
- int n = sscanf(line, "%*d %*d %s %s", subnet, node);
+ int n = sscanf(line, "%*d %*d %4095s %4095s", subnet, node);
if(n != 2) {
fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
return 1;
} break;
case REQ_DUMP_CONNECTIONS: {
- int n = sscanf(line, "%*d %*d %s %s port %s %x %d %x", node, host, port, &options, &socket, &status_int);
+ int n = sscanf(line, "%*d %*d %4095s %4095s port %4095s %x %d %x", node, host, port, &options, &socket, &status_int);
if(n != 6) {
fprintf(stderr, "Unable to parse connection dump from tincd.\n");
return 1;
{"Hostnames", VAR_SERVER},
{"IffOneQueue", VAR_SERVER},
{"Interface", VAR_SERVER},
+ {"InvitationExpire", VAR_SERVER},
{"KeyExpire", VAR_SERVER},
{"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
{"LocalDiscovery", VAR_SERVER},
+ {"LogLevel", VAR_SERVER},
{"MACExpire", VAR_SERVER},
{"MaxConnectionBurst", VAR_SERVER},
{"MaxOutputBufferSize", VAR_SERVER},
bool firstline = true;
while(fgets(buf, sizeof buf, in)) {
- if(sscanf(buf, "Name = %s", name) == 1) {
+ if(sscanf(buf, "Name = %4095s", name) == 1) {
firstline = false;
if(!check_id(name)) {
char *newline = memchr(data, '\n', len);
if(!newline || (newline - data > MAX_STRING_SIZE - 1)) {
fprintf(stderr, "Invalid input\n");
+ free(data);
return 1;
}
if(sscanf(data, "Signature = %s %ld %s", signer, &t, sig) != 3 || strlen(sig) != 86 || !t || !check_id(signer)) {
fprintf(stderr, "Invalid input\n");
+ free(data);
return 1;
}
if(node && strcmp(node, signer)) {
fprintf(stderr, "Signature is not made by %s\n", node);
+ free(data);
return 1;
}
while(recvline(fd, line, sizeof line)) {
char item[4096];
- int n = sscanf(line, "%d %d %s", &code, &req, item);
+ int n = sscanf(line, "%d %d %4095s", &code, &req, item);
if(n == 2) {
i++;
if(i >= 2)
while(p && *p) {
if(nargc >= maxargs) {
- fprintf(stderr, "next %p '%s', p %p '%s'\n", next, next, p, p);
- abort();
maxargs *= 2;
nargv = xrealloc(nargv, maxargs * sizeof *nargv);
}
if(nargc == argc)
continue;
- if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit"))
+ if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit")) {
+ free(nargv);
return result;
+ }
bool found = false;