/*
tincctl.c -- Controlling a running tincd
- Copyright (C) 2007-2017 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2007-2018 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
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-2017 Ivo Timmermans, Guus Sliepen and others.\n"
+ printf("Copyright (C) 1998-2018 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"
char buf[PATH_MAX];
char buf2[PATH_MAX];
+ask_filename:
+
/* Check stdin and stdout */
if(ask && tty) {
/* Ask for a file and/or directory name. */
#endif
/* The directory is a relative path or a filename. */
getcwd(directory, sizeof(directory));
- snprintf(buf2, sizeof(buf2), "%s" SLASH "%s", directory, filename);
+
+ if(snprintf(buf2, sizeof(buf2), "%s" SLASH "%s", directory, filename) >= sizeof(buf2)) {
+ fprintf(stderr, "Filename too long: %s" SLASH "%s\n", directory, filename);
+
+ if(ask && tty) {
+ goto ask_filename;
+ } else {
+ return NULL;
+ }
+ }
+
filename = buf2;
}
strncpy(sa.sun_path, unixsocketname, sizeof(sa.sun_path));
+ sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
+
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(fd < 0) {
setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof(one));
#endif
+ sendline(fd, "%d ^%s %d", ID, controlcookie, TINC_CTL_VERSION_CURRENT);
+
char data[4096];
int version;
return false;
}
- sendline(fd, "%d ^%s %d", ID, controlcookie, TINC_CTL_VERSION_CURRENT);
-
if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &version, &pid) != 3 || code != 4 || version != TINC_CTL_VERSION_CURRENT) {
if(verbose) {
fprintf(stderr, "Could not fully establish control socket connection\n");
}
char fname[PATH_MAX];
- snprintf(fname, sizeof(fname), "%s" SLASH "%s", dname, ent->d_name);
+
+ if(snprintf(fname, sizeof(fname), "%s" SLASH "%s", dname, ent->d_name) >= sizeof(fname)) {
+ fprintf(stderr, "Filename too long: %s" SLASH "%s\n", dname, ent->d_name);
+ continue;
+ }
+
FILE *f = fopen(fname, "r");
if(!f) {
unsigned int options, status_int;
node_status_t status;
long int last_state_change;
+ int udp_ping_rtt;
+ uint64_t in_packets, in_bytes, out_packets, out_bytes;
switch(req) {
case REQ_DUMP_NODES: {
- 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);
+ int n = sscanf(line, "%*d %*d %4095s %4095s %4095s port %4095s %d %d %d %d %x %x %4095s %4095s %d %hd %hd %hd %ld %d %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change, &udp_ping_rtt, &in_packets, &in_bytes, &out_packets, &out_bytes);
- if(n != 17) {
+ if(n != 22) {
fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
return 1;
}
continue;
}
- printf("%s id %s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %d (min %d max %d)\n",
- node, id, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu);
+ printf("%s id %s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %d (min %d max %d) rx %"PRIu64" %"PRIu64" tx %"PRIu64" %"PRIu64,
+ node, id, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu, in_packets, in_bytes, out_packets, out_bytes);
+
+ if(udp_ping_rtt != -1) {
+ printf(" rtt %d.%03d", udp_ping_rtt / 1000, udp_ping_rtt % 1000);
+ }
+
+ printf("\n");
}
}
break;
FILE *tf = NULL;
if(action >= -1) {
- snprintf(tmpfile, sizeof(tmpfile), "%s.config.tmp", filename);
+ if(snprintf(tmpfile, sizeof(tmpfile), "%s.config.tmp", filename) >= sizeof(tmpfile)) {
+ fprintf(stderr, "Filename too long: %s.config.tmp\n", filename);
+ return 1;
+ }
+
tf = fopen(tmpfile, "w");
if(!tf) {
fclose(out);
}
- snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name);
+ if(snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name) >= sizeof(filename)) {
+ fprintf(stderr, "Filename too long: %s" SLASH "%s\n", hosts_dir, name);
+ return 1;
+ }
if(!force && !access(filename, F_OK)) {
fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
static struct WSAData wsa_state;
if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
- fprintf(stderr, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError()));
+ fprintf(stderr, "System call `%s' failed: %s\n", "WSAStartup", winerror(GetLastError()));
return false;
}