1 /*
2     tincctl.c -- Controlling a running tincd
3     Copyright (C) 2007-2021 Guus Sliepen <guus@tinc-vpn.org>
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include "system.h"
21 
22 #include <getopt.h>
23 
24 #ifdef HAVE_READLINE
25 #include "readline/readline.h"
26 #include "readline/history.h"
27 #endif
28 
29 #include "xalloc.h"
30 #include "protocol.h"
31 #include "control_common.h"
32 #include "crypto.h"
33 #include "ecdsagen.h"
34 #include "fsck.h"
35 #include "info.h"
36 #include "invitation.h"
37 #include "names.h"
38 #include "rsagen.h"
39 #include "utils.h"
40 #include "tincctl.h"
41 #include "top.h"
42 #include "version.h"
43 #include "subnet.h"
44 
45 #ifndef MSG_NOSIGNAL
46 #define MSG_NOSIGNAL 0
47 #endif
48 
49 static char **orig_argv;
50 static int orig_argc;
51 
52 /* If nonzero, display usage information and exit. */
53 static bool show_help = false;
54 
55 /* If nonzero, print the version on standard output and exit.  */
56 static bool show_version = false;
57 
58 static char *name = NULL;
59 static char controlcookie[1025];
60 char *tinc_conf = NULL;
61 char *hosts_dir = NULL;
62 struct timeval now;
63 
64 // Horrible global variables...
65 static int pid = 0;
66 int fd = -1;
67 char line[4096];
68 static int code;
69 static int req;
70 static int result;
71 bool force = false;
72 bool tty = true;
73 bool confbasegiven = false;
74 bool netnamegiven = false;
75 char *scriptinterpreter = NULL;
76 char *scriptextension = "";
77 static char *prompt;
78 char *device = NULL;
79 char *iface = NULL;
80 int debug_level = -1;
81 
82 static struct option const long_options[] = {
83 	{"batch", no_argument, NULL, 'b'},
84 	{"config", required_argument, NULL, 'c'},
85 	{"net", required_argument, NULL, 'n'},
86 	{"help", no_argument, NULL, 1},
87 	{"version", no_argument, NULL, 2},
88 	{"pidfile", required_argument, NULL, 3},
89 	{"force", no_argument, NULL, 4},
90 	{NULL, 0, NULL, 0}
91 };
92 
version(void)93 static void version(void) {
94 	printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
95 	       BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
96 	printf("Copyright (C) 1998-2018 Ivo Timmermans, Guus Sliepen and others.\n"
97 	       "See the AUTHORS file for a complete list.\n\n"
98 	       "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
99 	       "and you are welcome to redistribute it under certain conditions;\n"
100 	       "see the file COPYING for details.\n");
101 }
102 
usage(bool status)103 static void usage(bool status) {
104 	if(status) {
105 		fprintf(stderr, "Try `%s --help\' for more information.\n", program_name);
106 	} else {
107 		printf("Usage: %s [options] command\n\n", program_name);
108 		printf("Valid options are:\n"
109 		       "  -b, --batch             Don't ask for anything (non-interactive mode).\n"
110 		       "  -c, --config=DIR        Read configuration options from DIR.\n"
111 		       "  -n, --net=NETNAME       Connect to net NETNAME.\n"
112 		       "      --pidfile=FILENAME  Read control cookie from FILENAME.\n"
113 		       "      --force             Force some commands to work despite warnings.\n"
114 		       "      --help              Display this help and exit.\n"
115 		       "      --version           Output version information and exit.\n"
116 		       "\n"
117 		       "Valid commands are:\n"
118 		       "  init [name]                Create initial configuration files.\n"
119 		       "  get VARIABLE               Print current value of VARIABLE\n"
120 		       "  set VARIABLE VALUE         Set VARIABLE to VALUE\n"
121 		       "  add VARIABLE VALUE         Add VARIABLE with the given VALUE\n"
122 		       "  del VARIABLE [VALUE]       Remove VARIABLE [only ones with watching VALUE]\n"
123 		       "  start [tincd options]      Start tincd.\n"
124 		       "  stop                       Stop tincd.\n"
125 		       "  restart [tincd options]    Restart tincd.\n"
126 		       "  reload                     Partially reload configuration of running tincd.\n"
127 		       "  pid                        Show PID of currently running tincd.\n"
128 #ifdef DISABLE_LEGACY
129 		       "  generate-keys              Generate a new Ed25519 public/private key pair.\n"
130 #else
131 		       "  generate-keys [bits]       Generate new RSA and Ed25519 public/private key pairs.\n"
132 		       "  generate-rsa-keys [bits]   Generate a new RSA public/private key pair.\n"
133 #endif
134 		       "  generate-ed25519-keys      Generate a new Ed25519 public/private key pair.\n"
135 		       "  dump                       Dump a list of one of the following things:\n"
136 		       "    [reachable] nodes        - all known nodes in the VPN\n"
137 		       "    edges                    - all known connections in the VPN\n"
138 		       "    subnets                  - all known subnets in the VPN\n"
139 		       "    connections              - all meta connections with ourself\n"
140 		       "    [di]graph                - graph of the VPN in dotty format\n"
141 		       "    invitations              - outstanding invitations\n"
142 		       "  info NODE|SUBNET|ADDRESS   Give information about a particular NODE, SUBNET or ADDRESS.\n"
143 		       "  purge                      Purge unreachable nodes\n"
144 		       "  debug N                    Set debug level\n"
145 		       "  retry                      Retry all outgoing connections\n"
146 		       "  disconnect NODE            Close meta connection with NODE\n"
147 #ifdef HAVE_CURSES
148 		       "  top                        Show real-time statistics\n"
149 #endif
150 		       "  pcap [snaplen]             Dump traffic in pcap format [up to snaplen bytes per packet]\n"
151 		       "  log [level]                Dump log output [up to the specified level]\n"
152 		       "  export                     Export host configuration of local node to standard output\n"
153 		       "  export-all                 Export all host configuration files to standard output\n"
154 		       "  import                     Import host configuration file(s) from standard input\n"
155 		       "  exchange                   Same as export followed by import\n"
156 		       "  exchange-all               Same as export-all followed by import\n"
157 		       "  invite NODE [...]          Generate an invitation for NODE\n"
158 		       "  join INVITATION            Join a VPN using an INVITATION\n"
159 		       "  network [NETNAME]          List all known networks, or switch to the one named NETNAME.\n"
160 		       "  fsck                       Check the configuration files for problems.\n"
161 		       "  sign [FILE]                Generate a signed version of a file.\n"
162 		       "  verify NODE [FILE]         Verify that a file was signed by the given NODE.\n"
163 		       "\n");
164 		printf("Report bugs to tinc@tinc-vpn.org.\n");
165 	}
166 }
167 
parse_options(int argc,char ** argv)168 static bool parse_options(int argc, char **argv) {
169 	int r;
170 	int option_index = 0;
171 
172 	while((r = getopt_long(argc, argv, "+bc:n:", long_options, &option_index)) != EOF) {
173 		switch(r) {
174 		case 0:   /* long option */
175 			break;
176 
177 		case 'b':
178 			tty = false;
179 			break;
180 
181 		case 'c': /* config file */
182 			confbase = xstrdup(optarg);
183 			confbasegiven = true;
184 			break;
185 
186 		case 'n': /* net name given */
187 			netname = xstrdup(optarg);
188 			break;
189 
190 		case 1:   /* show help */
191 			show_help = true;
192 			break;
193 
194 		case 2:   /* show version */
195 			show_version = true;
196 			break;
197 
198 		case 3:   /* open control socket here */
199 			pidfilename = xstrdup(optarg);
200 			break;
201 
202 		case 4:   /* force */
203 			force = true;
204 			break;
205 
206 		case '?': /* wrong options */
207 			usage(true);
208 			return false;
209 
210 		default:
211 			break;
212 		}
213 	}
214 
215 	if(!netname && (netname = getenv("NETNAME"))) {
216 		netname = xstrdup(netname);
217 	}
218 
219 	/* netname "." is special: a "top-level name" */
220 
221 	if(netname && (!*netname || !strcmp(netname, "."))) {
222 		free(netname);
223 		netname = NULL;
224 	}
225 
226 	if(netname && (strpbrk(netname, "\\/") || *netname == '.')) {
227 		fprintf(stderr, "Invalid character in netname!\n");
228 		return false;
229 	}
230 
231 	return true;
232 }
233 
234 /* Open a file with the desired permissions, minus the umask.
235    Also, if we want to create an executable file, we call fchmod()
236    to set the executable bits. */
237 
fopenmask(const char * filename,const char * mode,mode_t perms)238 FILE *fopenmask(const char *filename, const char *mode, mode_t perms) {
239 	mode_t mask = umask(0);
240 	perms &= ~mask;
241 	umask(~perms & 0777);
242 	FILE *f = fopen(filename, mode);
243 
244 	if(!f) {
245 		fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
246 		return NULL;
247 	}
248 
249 #ifdef HAVE_FCHMOD
250 
251 	if((perms & 0444) && f) {
252 		fchmod(fileno(f), perms);
253 	}
254 
255 #endif
256 	umask(mask);
257 	return f;
258 }
259 
disable_old_keys(const char * filename,const char * what)260 static void disable_old_keys(const char *filename, const char *what) {
261 	char tmpfile[PATH_MAX] = "";
262 	char buf[1024];
263 	bool disabled = false;
264 	bool block = false;
265 	bool error = false;
266 
267 	FILE *r = fopen(filename, "r");
268 	FILE *w = NULL;
269 
270 	if(!r) {
271 		return;
272 	}
273 
274 	int result = snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename);
275 
276 	if(result < sizeof(tmpfile)) {
277 		struct stat st = {.st_mode = 0600};
278 		fstat(fileno(r), &st);
279 		w = fopenmask(tmpfile, "w", st.st_mode);
280 	}
281 
282 	while(fgets(buf, sizeof(buf), r)) {
283 		if(!block && !strncmp(buf, "-----BEGIN ", 11)) {
284 			if((strstr(buf, " ED25519 ") && strstr(what, "Ed25519")) || (strstr(buf, " RSA ") && strstr(what, "RSA"))) {
285 				disabled = true;
286 				block = true;
287 			}
288 		}
289 
290 		bool ed25519pubkey = !strncasecmp(buf, "Ed25519PublicKey", 16) && strchr(" \t=", buf[16]) && strstr(what, "Ed25519");
291 
292 		if(ed25519pubkey) {
293 			disabled = true;
294 		}
295 
296 		if(w) {
297 			if(block || ed25519pubkey) {
298 				fputc('#', w);
299 			}
300 
301 			if(fputs(buf, w) < 0) {
302 				error = true;
303 				break;
304 			}
305 		}
306 
307 		if(block && !strncmp(buf, "-----END ", 9)) {
308 			block = false;
309 		}
310 	}
311 
312 	if(w)
313 		if(fclose(w) < 0) {
314 			error = true;
315 		}
316 
317 	if(ferror(r) || fclose(r) < 0) {
318 		error = true;
319 	}
320 
321 	if(disabled) {
322 		if(!w || error) {
323 			fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
324 
325 			if(w) {
326 				unlink(tmpfile);
327 			}
328 
329 			return;
330 		}
331 
332 #ifdef HAVE_MINGW
333 		// We cannot atomically replace files on Windows.
334 		char bakfile[PATH_MAX] = "";
335 		snprintf(bakfile, sizeof(bakfile), "%s.bak", filename);
336 
337 		if(rename(filename, bakfile) || rename(tmpfile, filename)) {
338 			rename(bakfile, filename);
339 #else
340 
341 		if(rename(tmpfile, filename)) {
342 #endif
343 			fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
344 		} else  {
345 #ifdef HAVE_MINGW
346 			unlink(bakfile);
347 #endif
348 			fprintf(stderr, "Warning: old key(s) found and disabled.\n");
349 		}
350 	}
351 
352 	unlink(tmpfile);
353 }
354 
355 static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) {
356 	FILE *r;
357 	char directory[PATH_MAX] = ".";
358 	char buf[PATH_MAX];
359 	char buf2[PATH_MAX];
360 
361 ask_filename:
362 
363 	/* Check stdin and stdout */
364 	if(ask && tty) {
365 		/* Ask for a file and/or directory name. */
366 		fprintf(stderr, "Please enter a file to save %s to [%s]: ", what, filename);
367 
368 		if(fgets(buf, sizeof(buf), stdin) == NULL) {
369 			fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
370 			return NULL;
371 		}
372 
373 		size_t len = strlen(buf);
374 
375 		if(len) {
376 			buf[--len] = 0;
377 		}
378 
379 		if(len) {
380 			filename = buf;
381 		}
382 	}
383 
384 #ifdef HAVE_MINGW
385 
386 	if(filename[0] != '\\' && filename[0] != '/' && !strchr(filename, ':')) {
387 #else
388 
389 	if(filename[0] != '/') {
390 #endif
391 		/* The directory is a relative path or a filename. */
392 		getcwd(directory, sizeof(directory));
393 
394 		if((size_t)snprintf(buf2, sizeof(buf2), "%s" SLASH "%s", directory, filename) >= sizeof(buf2)) {
395 			fprintf(stderr, "Filename too long: %s" SLASH "%s\n", directory, filename);
396 
397 			if(ask && tty) {
398 				goto ask_filename;
399 			} else {
400 				return NULL;
401 			}
402 		}
403 
404 		filename = buf2;
405 	}
406 
407 	disable_old_keys(filename, what);
408 
409 	/* Open it first to keep the inode busy */
410 
411 	r = fopenmask(filename, mode, perms);
412 
413 	if(!r) {
414 		fprintf(stderr, "Error opening file `%s': %s\n", filename, strerror(errno));
415 		return NULL;
416 	}
417 
418 	return r;
419 }
420 
421 /*
422   Generate a public/private Ed25519 key pair, and ask for a file to store
423   them in.
424 */
425 static bool ed25519_keygen(bool ask) {
426 	ecdsa_t *key;
427 	FILE *f;
428 	char fname[PATH_MAX];
429 
430 	fprintf(stderr, "Generating Ed25519 key pair:\n");
431 
432 	if(!(key = ecdsa_generate())) {
433 		fprintf(stderr, "Error during key generation!\n");
434 		return false;
435 	} else {
436 		fprintf(stderr, "Done.\n");
437 	}
438 
439 	snprintf(fname, sizeof(fname), "%s" SLASH "ed25519_key.priv", confbase);
440 	f = ask_and_open(fname, "private Ed25519 key", "a", ask, 0600);
441 
442 	if(!f) {
443 		goto error;
444 	}
445 
446 	if(!ecdsa_write_pem_private_key(key, f)) {
447 		fprintf(stderr, "Error writing private key!\n");
448 		goto error;
449 	}
450 
451 	fclose(f);
452 
453 	if(name) {
454 		snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, name);
455 	} else {
456 		snprintf(fname, sizeof(fname), "%s" SLASH "ed25519_key.pub", confbase);
457 	}
458 
459 	f = ask_and_open(fname, "public Ed25519 key", "a", ask, 0666);
460 
461 	if(!f) {
462 		return false;
463 	}
464 
465 	char *pubkey = ecdsa_get_base64_public_key(key);
466 	fprintf(f, "Ed25519PublicKey = %s\n", pubkey);
467 	free(pubkey);
468 
469 	fclose(f);
470 	ecdsa_free(key);
471 
472 	return true;
473 
474 error:
475 
476 	if(f) {
477 		fclose(f);
478 	}
479 
480 	ecdsa_free(key);
481 	return false;
482 }
483 
484 #ifndef DISABLE_LEGACY
485 /*
486   Generate a public/private RSA key pair, and ask for a file to store
487   them in.
488 */
489 static bool rsa_keygen(int bits, bool ask) {
490 	rsa_t *key;
491 	FILE *f;
492 	char fname[PATH_MAX];
493 
494 	// Make sure the key size is a multiple of 8 bits.
495 	bits &= ~0x7;
496 
497 	// Make sure that a valid key size is used.
498 	if(bits < 1024 || bits > 8192) {
499 		fprintf(stderr, "Invalid key size %d specified! It should be between 1024 and 8192 bits.\n", bits);
500 		return false;
501 	} else if(bits < 2048) {
502 		fprintf(stderr, "WARNING: generating a weak %d bits RSA key! 2048 or more bits are recommended.\n", bits);
503 	}
504 
505 	fprintf(stderr, "Generating %d bits keys:\n", bits);
506 
507 	if(!(key = rsa_generate(bits, 0x10001))) {
508 		fprintf(stderr, "Error during key generation!\n");
509 		return false;
510 	} else {
511 		fprintf(stderr, "Done.\n");
512 	}
513 
514 	snprintf(fname, sizeof(fname), "%s" SLASH "rsa_key.priv", confbase);
515 	f = ask_and_open(fname, "private RSA key", "a", ask, 0600);
516 
517 	if(!f) {
518 		goto error;
519 	}
520 
521 	if(!rsa_write_pem_private_key(key, f)) {
522 		fprintf(stderr, "Error writing private key!\n");
523 		goto error;
524 	}
525 
526 	fclose(f);
527 
528 	if(name) {
529 		snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, name);
530 	} else {
531 		snprintf(fname, sizeof(fname), "%s" SLASH "rsa_key.pub", confbase);
532 	}
533 
534 	f = ask_and_open(fname, "public RSA key", "a", ask, 0666);
535 
536 	if(!f) {
537 		goto error;
538 	}
539 
540 	if(!rsa_write_pem_public_key(key, f)) {
541 		fprintf(stderr, "Error writing public key!\n");
542 		goto error;
543 	}
544 
545 	fclose(f);
546 	rsa_free(key);
547 
548 	return true;
549 
550 error:
551 
552 	if(f) {
553 		fclose(f);
554 	}
555 
556 	rsa_free(key);
557 	return false;
558 }
559 #endif
560 
561 char buffer[4096];
562 size_t blen = 0;
563 
564 bool recvline(int fd, char *line, size_t len) {
565 	char *newline = NULL;
566 
567 	if(!fd) {
568 		return false;
569 	}
570 
571 	while(!(newline = memchr(buffer, '\n', blen))) {
572 		int result = recv(fd, buffer + blen, sizeof(buffer) - blen, 0);
573 
574 		if(result == -1 && sockerrno == EINTR) {
575 			continue;
576 		} else if(result <= 0) {
577 			return false;
578 		}
579 
580 		blen += result;
581 	}
582 
583 	if((size_t)(newline - buffer) >= len) {
584 		return false;
585 	}
586 
587 	len = newline - buffer;
588 
589 	memcpy(line, buffer, len);
590 	line[len] = 0;
591 	memmove(buffer, newline + 1, blen - len - 1);
592 	blen -= len + 1;
593 
594 	return true;
595 }
596 
597 static bool recvdata(int fd, char *data, size_t len) {
598 	while(blen < len) {
599 		int result = recv(fd, buffer + blen, sizeof(buffer) - blen, 0);
600 
601 		if(result == -1 && sockerrno == EINTR) {
602 			continue;
603 		} else if(result <= 0) {
604 			return false;
605 		}
606 
607 		blen += result;
608 	}
609 
610 	memcpy(data, buffer, len);
611 	memmove(buffer, buffer + len, blen - len);
612 	blen -= len;
613 
614 	return true;
615 }
616 
617 bool sendline(int fd, char *format, ...) {
618 	static char buffer[4096];
619 	char *p = buffer;
620 	int blen;
621 	va_list ap;
622 
623 	va_start(ap, format);
624 	blen = vsnprintf(buffer, sizeof(buffer), format, ap);
625 	buffer[sizeof(buffer) - 1] = 0;
626 	va_end(ap);
627 
628 	if(blen < 1 || (size_t)blen >= sizeof(buffer)) {
629 		return false;
630 	}
631 
632 	buffer[blen] = '\n';
633 	blen++;
634 
635 	while(blen) {
636 		int result = send(fd, p, blen, MSG_NOSIGNAL);
637 
638 		if(result == -1 && sockerrno == EINTR) {
639 			continue;
640 		} else if(result <= 0) {
641 			return false;
642 		}
643 
644 		p += result;
645 		blen -= result;
646 	}
647 
648 	return true;
649 }
650 
651 static void pcap(int fd, FILE *out, uint32_t snaplen) {
652 	sendline(fd, "%d %d %d", CONTROL, REQ_PCAP, snaplen);
653 	char data[9018];
654 
655 	struct {
656 		uint32_t magic;
657 		uint16_t major;
658 		uint16_t minor;
659 		uint32_t tz_offset;
660 		uint32_t tz_accuracy;
661 		uint32_t snaplen;
662 		uint32_t ll_type;
663 	} header = {
664 		0xa1b2c3d4,
665 		2, 4,
666 		0, 0,
667 		snaplen ? snaplen : sizeof(data),
668 		1,
669 	};
670 
671 	struct {
672 		uint32_t tv_sec;
673 		uint32_t tv_usec;
674 		uint32_t len;
675 		uint32_t origlen;
676 	} packet;
677 
678 	struct timeval tv;
679 
680 	fwrite(&header, sizeof(header), 1, out);
681 	fflush(out);
682 
683 	char line[32];
684 
685 	while(recvline(fd, line, sizeof(line))) {
686 		int code, req, len;
687 		int n = sscanf(line, "%d %d %d", &code, &req, &len);
688 		gettimeofday(&tv, NULL);
689 
690 		if(n != 3 || code != CONTROL || req != REQ_PCAP || len < 0 || (size_t)len > sizeof(data)) {
691 			break;
692 		}
693 
694 		if(!recvdata(fd, data, len)) {
695 			break;
696 		}
697 
698 		packet.tv_sec = tv.tv_sec;
699 		packet.tv_usec = tv.tv_usec;
700 		packet.len = len;
701 		packet.origlen = len;
702 		fwrite(&packet, sizeof(packet), 1, out);
703 		fwrite(data, len, 1, out);
704 		fflush(out);
705 	}
706 }
707 
708 static void logcontrol(int fd, FILE *out, int level) {
709 	sendline(fd, "%d %d %d", CONTROL, REQ_LOG, level);
710 	char data[1024];
711 	char line[32];
712 
713 	while(recvline(fd, line, sizeof(line))) {
714 		int code, req, len;
715 		int n = sscanf(line, "%d %d %d", &code, &req, &len);
716 
717 		if(n != 3 || code != CONTROL || req != REQ_LOG || len < 0 || (size_t)len > sizeof(data)) {
718 			break;
719 		}
720 
721 		if(!recvdata(fd, data, len)) {
722 			break;
723 		}
724 
725 		fwrite(data, len, 1, out);
726 		fputc('\n', out);
727 		fflush(out);
728 	}
729 }
730 
731 static bool stop_tincd(void) {
732 	if(!connect_tincd(true)) {
733 		return false;
734 	}
735 
736 	sendline(fd, "%d %d", CONTROL, REQ_STOP);
737 
738 	while(recvline(fd, line, sizeof(line))) {
739 		// wait for tincd to close the connection...
740 	}
741 
742 	close(fd);
743 	pid = 0;
744 	fd = -1;
745 
746 	return true;
747 }
748 
749 #ifdef HAVE_MINGW
750 static bool remove_service(void) {
751 	SC_HANDLE manager = NULL;
752 	SC_HANDLE service = NULL;
753 	SERVICE_STATUS status = {0};
754 	bool success = false;
755 
756 	manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
757 
758 	if(!manager) {
759 		fprintf(stderr, "Could not open service manager: %s\n", winerror(GetLastError()));
760 		goto exit;
761 	}
762 
763 	service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
764 
765 	if(!service) {
766 		if(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) {
767 			success = stop_tincd();
768 		} else {
769 			fprintf(stderr, "Could not open %s service: %s\n", identname, winerror(GetLastError()));
770 		}
771 
772 		goto exit;
773 	}
774 
775 	if(!ControlService(service, SERVICE_CONTROL_STOP, &status)) {
776 		fprintf(stderr, "Could not stop %s service: %s\n", identname, winerror(GetLastError()));
777 	} else {
778 		fprintf(stderr, "%s service stopped\n", identname);
779 	}
780 
781 	if(!DeleteService(service)) {
782 		fprintf(stderr, "Could not remove %s service: %s\n", identname, winerror(GetLastError()));
783 		goto exit;
784 	}
785 
786 	success = true;
787 
788 exit:
789 
790 	if(service) {
791 		CloseServiceHandle(service);
792 	}
793 
794 	if(manager) {
795 		CloseServiceHandle(manager);
796 	}
797 
798 	if(success) {
799 		fprintf(stderr, "%s service removed\n", identname);
800 	}
801 
802 	return success;
803 }
804 #endif
805 
806 bool connect_tincd(bool verbose) {
807 	if(fd >= 0) {
808 		fd_set r;
809 		FD_ZERO(&r);
810 		FD_SET(fd, &r);
811 		struct timeval tv = {0, 0};
812 
813 		if(select(fd + 1, &r, NULL, NULL, &tv)) {
814 			fprintf(stderr, "Previous connection to tincd lost, reconnecting.\n");
815 			close(fd);
816 			fd = -1;
817 		} else {
818 			return true;
819 		}
820 	}
821 
822 	FILE *f = fopen(pidfilename, "r");
823 
824 	if(!f) {
825 		if(verbose) {
826 			fprintf(stderr, "Could not open pid file %s: %s\n", pidfilename, strerror(errno));
827 		}
828 
829 		return false;
830 	}
831 
832 	char host[129];
833 	char port[129];
834 
835 	if(fscanf(f, "%20d %1024s %128s port %128s", &pid, controlcookie, host, port) != 4) {
836 		if(verbose) {
837 			fprintf(stderr, "Could not parse pid file %s\n", pidfilename);
838 		}
839 
840 		fclose(f);
841 		return false;
842 	}
843 
844 	fclose(f);
845 
846 #ifndef HAVE_MINGW
847 
848 	if((pid == 0) || (kill(pid, 0) && (errno == ESRCH))) {
849 		fprintf(stderr, "Could not find tincd running at pid %d\n", pid);
850 		/* clean up the stale socket and pid file */
851 		unlink(pidfilename);
852 		unlink(unixsocketname);
853 		return false;
854 	}
855 
856 	struct sockaddr_un sa;
857 
858 	sa.sun_family = AF_UNIX;
859 
860 	strncpy(sa.sun_path, unixsocketname, sizeof(sa.sun_path));
861 
862 	sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
863 
864 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
865 
866 	if(fd < 0) {
867 		if(verbose) {
868 			fprintf(stderr, "Cannot create UNIX socket: %s\n", sockstrerror(sockerrno));
869 		}
870 
871 		return false;
872 	}
873 
874 	if(connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
875 		if(verbose) {
876 			fprintf(stderr, "Cannot connect to UNIX socket %s: %s\n", unixsocketname, sockstrerror(sockerrno));
877 		}
878 
879 		close(fd);
880 		fd = -1;
881 		return false;
882 	}
883 
884 #else
885 	struct addrinfo hints = {
886 		.ai_family = AF_UNSPEC,
887 		.ai_socktype = SOCK_STREAM,
888 		.ai_protocol = IPPROTO_TCP,
889 		.ai_flags = 0,
890 	};
891 
892 	struct addrinfo *res = NULL;
893 
894 	if(getaddrinfo(host, port, &hints, &res) || !res) {
895 		if(verbose) {
896 			fprintf(stderr, "Cannot resolve %s port %s: %s\n", host, port, sockstrerror(sockerrno));
897 		}
898 
899 		return false;
900 	}
901 
902 	fd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP);
903 
904 	if(fd < 0) {
905 		if(verbose) {
906 			fprintf(stderr, "Cannot create TCP socket: %s\n", sockstrerror(sockerrno));
907 		}
908 
909 		return false;
910 	}
911 
912 	unsigned long arg = 0;
913 
914 	if(ioctlsocket(fd, FIONBIO, &arg) != 0) {
915 		if(verbose) {
916 			fprintf(stderr, "System call `%s' failed: %s\n", "ioctlsocket", sockstrerror(sockerrno));
917 		}
918 	}
919 
920 	if(connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
921 		if(verbose) {
922 			fprintf(stderr, "Cannot connect to %s port %s: %s\n", host, port, sockstrerror(sockerrno));
923 		}
924 
925 		close(fd);
926 		fd = -1;
927 		return false;
928 	}
929 
930 	freeaddrinfo(res);
931 #endif
932 
933 #ifdef SO_NOSIGPIPE
934 	static const int one = 1;
935 	setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof(one));
936 #endif
937 
938 	sendline(fd, "%d ^%s %d", ID, controlcookie, TINC_CTL_VERSION_CURRENT);
939 
940 	char data[4096];
941 	int version;
942 
943 	if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %4095s %d", &code, data, &version) != 3 || code != 0) {
944 		if(verbose) {
945 			fprintf(stderr, "Cannot read greeting from control socket: %s\n", sockstrerror(sockerrno));
946 		}
947 
948 		close(fd);
949 		fd = -1;
950 		return false;
951 	}
952 
953 	if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &version, &pid) != 3 || code != 4 || version != TINC_CTL_VERSION_CURRENT) {
954 		if(verbose) {
955 			fprintf(stderr, "Could not fully establish control socket connection\n");
956 		}
957 
958 		close(fd);
959 		fd = -1;
960 		return false;
961 	}
962 
963 	return true;
964 }
965 
966 
967 static int cmd_start(int argc, char *argv[]) {
968 	if(connect_tincd(false)) {
969 		if(netname) {
970 			fprintf(stderr, "A tincd is already running for net `%s' with pid %d.\n", netname, pid);
971 		} else {
972 			fprintf(stderr, "A tincd is already running with pid %d.\n", pid);
973 		}
974 
975 		return 0;
976 	}
977 
978 	char *c;
979 	char *slash = strrchr(program_name, '/');
980 
981 #ifdef HAVE_MINGW
982 
983 	if((c = strrchr(program_name, '\\')) > slash) {
984 		slash = c;
985 	}
986 
987 #endif
988 
989 	if(slash++) {
990 		xasprintf(&c, "%.*stincd", (int)(slash - program_name), program_name);
991 	} else {
992 		c = "tincd";
993 	}
994 
995 	int nargc = 0;
996 	char **nargv = xzalloc((optind + argc) * sizeof(*nargv));
997 
998 	char *arg0 = c;
999 #ifdef HAVE_MINGW
1000 	/*
1001 	   Windows has no real concept of an "argv array". A command line is just one string.
1002 	   The CRT of the new process will decode the command line string to generate argv before calling main(), and (by convention)
1003 	   it uses quotes to handle spaces in arguments.
1004 	   Therefore we need to quote all arguments that might contain spaces. No, execvp() won't do that for us (see MSDN).
1005 	   If we don't do that, then execvp() will run fine but any spaces in the filename contained in arg0 will bleed
1006 	   into the next arguments when the spawned process' CRT parses its command line, resulting in chaos.
1007 	*/
1008 	xasprintf(&arg0, "\"%s\"", arg0);
1009 #endif
1010 	nargv[nargc++] = arg0;
1011 
1012 	for(int i = 1; i < optind; i++) {
1013 		nargv[nargc++] = orig_argv[i];
1014 	}
1015 
1016 	for(int i = 1; i < argc; i++) {
1017 		nargv[nargc++] = argv[i];
1018 	}
1019 
1020 #ifdef HAVE_MINGW
1021 	int status = spawnvp(_P_WAIT, c, nargv);
1022 
1023 	if(status == -1) {
1024 		fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno));
1025 		return 1;
1026 	}
1027 
1028 	return status;
1029 #else
1030 	int pfd[2] = {-1, -1};
1031 
1032 	if(socketpair(AF_UNIX, SOCK_STREAM, 0, pfd)) {
1033 		fprintf(stderr, "Could not create umbilical socket: %s\n", strerror(errno));
1034 		free(nargv);
1035 		return 1;
1036 	}
1037 
1038 	pid_t pid = fork();
1039 
1040 	if(pid == -1) {
1041 		fprintf(stderr, "Could not fork: %s\n", strerror(errno));
1042 		free(nargv);
1043 		return 1;
1044 	}
1045 
1046 	if(!pid) {
1047 		close(pfd[0]);
1048 		char buf[100];
1049 		snprintf(buf, sizeof(buf), "%d", pfd[1]);
1050 		setenv("TINC_UMBILICAL", buf, true);
1051 		exit(execvp(c, nargv));
1052 	} else {
1053 		close(pfd[1]);
1054 	}
1055 
1056 	free(nargv);
1057 
1058 	int status = -1, result;
1059 #ifdef SIGINT
1060 	signal(SIGINT, SIG_IGN);
1061 #endif
1062 
1063 	// Pass all log messages from the umbilical to stderr.
1064 	// A nul-byte right before closure means tincd started successfully.
1065 	bool failure = true;
1066 	char buf[1024];
1067 	ssize_t len;
1068 
1069 	while((len = read(pfd[0], buf, sizeof(buf))) > 0) {
1070 		failure = buf[len - 1];
1071 
1072 		if(!failure) {
1073 			len--;
1074 		}
1075 
1076 		write(2, buf, len);
1077 	}
1078 
1079 	if(len) {
1080 		failure = true;
1081 	}
1082 
1083 	close(pfd[0]);
1084 
1085 	// Make sure the child process is really gone.
1086 	result = waitpid(pid, &status, 0);
1087 
1088 #ifdef SIGINT
1089 	signal(SIGINT, SIG_DFL);
1090 #endif
1091 
1092 	if(failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
1093 		fprintf(stderr, "Error starting %s\n", c);
1094 		return 1;
1095 	}
1096 
1097 	return 0;
1098 #endif
1099 }
1100 
1101 static int cmd_stop(int argc, char *argv[]) {
1102 	(void)argv;
1103 
1104 	if(argc > 1) {
1105 		fprintf(stderr, "Too many arguments!\n");
1106 		return 1;
1107 	}
1108 
1109 #ifdef HAVE_MINGW
1110 	return remove_service();
1111 #else
1112 
1113 	if(!stop_tincd()) {
1114 		if(pid) {
1115 			if(kill(pid, SIGTERM)) {
1116 				fprintf(stderr, "Could not send TERM signal to process with PID %d: %s\n", pid, strerror(errno));
1117 				return 1;
1118 			}
1119 
1120 			fprintf(stderr, "Sent TERM signal to process with PID %d.\n", pid);
1121 			waitpid(pid, NULL, 0);
1122 			return 0;
1123 		}
1124 
1125 		return 1;
1126 	}
1127 
1128 	return 0;
1129 #endif
1130 }
1131 
1132 static int cmd_restart(int argc, char *argv[]) {
1133 	cmd_stop(1, argv);
1134 	return cmd_start(argc, argv);
1135 }
1136 
1137 static int cmd_reload(int argc, char *argv[]) {
1138 	(void)argv;
1139 
1140 	if(argc > 1) {
1141 		fprintf(stderr, "Too many arguments!\n");
1142 		return 1;
1143 	}
1144 
1145 	if(!connect_tincd(true)) {
1146 		return 1;
1147 	}
1148 
1149 	sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
1150 
1151 	if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RELOAD || result) {
1152 		fprintf(stderr, "Could not reload configuration.\n");
1153 		return 1;
1154 	}
1155 
1156 	return 0;
1157 
1158 }
1159 
1160 static int dump_invitations(void) {
1161 	char dname[PATH_MAX];
1162 	snprintf(dname, sizeof(dname), "%s" SLASH "invitations", confbase);
1163 	DIR *dir = opendir(dname);
1164 
1165 	if(!dir) {
1166 		if(errno == ENOENT) {
1167 			fprintf(stderr, "No outstanding invitations.\n");
1168 			return 0;
1169 		}
1170 
1171 		fprintf(stderr, "Cannot not read directory %s: %s\n", dname, strerror(errno));
1172 		return 1;
1173 	}
1174 
1175 	struct dirent *ent;
1176 
1177 	bool found = false;
1178 
1179 	while((ent = readdir(dir))) {
1180 		char buf[MAX_STRING_SIZE];
1181 
1182 		if(b64decode(ent->d_name, buf, 24) != 18) {
1183 			continue;
1184 		}
1185 
1186 		char fname[PATH_MAX];
1187 
1188 		if((size_t)snprintf(fname, sizeof(fname), "%s" SLASH "%s", dname, ent->d_name) >= sizeof(fname)) {
1189 			fprintf(stderr, "Filename too long: %s" SLASH "%s\n", dname, ent->d_name);
1190 			continue;
1191 		}
1192 
1193 		FILE *f = fopen(fname, "r");
1194 
1195 		if(!f) {
1196 			fprintf(stderr, "Cannot open %s: %s\n", fname, strerror(errno));
1197 			continue;
1198 		}
1199 
1200 		buf[0] = 0;
1201 
1202 		if(!fgets(buf, sizeof(buf), f)) {
1203 			fprintf(stderr, "Invalid invitation file %s\n", fname);
1204 			fclose(f);
1205 			continue;
1206 		}
1207 
1208 		fclose(f);
1209 
1210 		char *eol = buf + strlen(buf);
1211 
1212 		while(strchr("\t \r\n", *--eol)) {
1213 			*eol = 0;
1214 		}
1215 
1216 		if(strncmp(buf, "Name = ", 7) || !check_id(buf + 7)) {
1217 			fprintf(stderr, "Invalid invitation file %s\n", fname);
1218 			continue;
1219 		}
1220 
1221 		found = true;
1222 		printf("%s %s\n", ent->d_name, buf + 7);
1223 	}
1224 
1225 	closedir(dir);
1226 
1227 	if(!found) {
1228 		fprintf(stderr, "No outstanding invitations.\n");
1229 	}
1230 
1231 	return 0;
1232 }
1233 
1234 static int cmd_dump(int argc, char *argv[]) {
1235 	bool only_reachable = false;
1236 
1237 	if(argc > 2 && !strcasecmp(argv[1], "reachable")) {
1238 		if(strcasecmp(argv[2], "nodes")) {
1239 			fprintf(stderr, "`reachable' only supported for nodes.\n");
1240 			usage(true);
1241 			return 1;
1242 		}
1243 
1244 		only_reachable = true;
1245 		argv++;
1246 		argc--;
1247 	}
1248 
1249 	if(argc != 2) {
1250 		fprintf(stderr, "Invalid number of arguments.\n");
1251 		usage(true);
1252 		return 1;
1253 	}
1254 
1255 	if(!strcasecmp(argv[1], "invitations")) {
1256 		return dump_invitations();
1257 	}
1258 
1259 	if(!connect_tincd(true)) {
1260 		return 1;
1261 	}
1262 
1263 	int do_graph = 0;
1264 
1265 	if(!strcasecmp(argv[1], "nodes")) {
1266 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1267 	} else if(!strcasecmp(argv[1], "edges")) {
1268 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1269 	} else if(!strcasecmp(argv[1], "subnets")) {
1270 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
1271 	} else if(!strcasecmp(argv[1], "connections")) {
1272 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS);
1273 	} else if(!strcasecmp(argv[1], "graph")) {
1274 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1275 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1276 		do_graph = 1;
1277 	} else if(!strcasecmp(argv[1], "digraph")) {
1278 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1279 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1280 		do_graph = 2;
1281 	} else {
1282 		fprintf(stderr, "Unknown dump type '%s'.\n", argv[1]);
1283 		usage(true);
1284 		return 1;
1285 	}
1286 
1287 	if(do_graph == 1) {
1288 		printf("graph {\n");
1289 	} else if(do_graph == 2) {
1290 		printf("digraph {\n");
1291 	}
1292 
1293 	while(recvline(fd, line, sizeof(line))) {
1294 		char node1[4096], node2[4096];
1295 		int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, node1, node2);
1296 
1297 		if(n == 2) {
1298 			if(do_graph && req == REQ_DUMP_NODES) {
1299 				continue;
1300 			} else {
1301 				if(do_graph) {
1302 					printf("}\n");
1303 				}
1304 
1305 				return 0;
1306 			}
1307 		}
1308 
1309 		if(n < 2) {
1310 			break;
1311 		}
1312 
1313 		char node[4096];
1314 		char id[4096];
1315 		char from[4096];
1316 		char to[4096];
1317 		char subnet[4096];
1318 		char host[4096];
1319 		char port[4096];
1320 		char local_host[4096];
1321 		char local_port[4096];
1322 		char via[4096];
1323 		char nexthop[4096];
1324 		int cipher, digest, maclength, compression, distance, socket, weight;
1325 		short int pmtu, minmtu, maxmtu;
1326 		unsigned int options, status_int;
1327 		node_status_t status;
1328 		long int last_state_change;
1329 		int udp_ping_rtt;
1330 		uint64_t in_packets, in_bytes, out_packets, out_bytes;
1331 
1332 		switch(req) {
1333 		case REQ_DUMP_NODES: {
1334 			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);
1335 
1336 			if(n != 22) {
1337 				fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
1338 				return 1;
1339 			}
1340 
1341 			memcpy(&status, &status_int, sizeof(status));
1342 
1343 			if(do_graph) {
1344 				const char *color = "black";
1345 
1346 				if(!strcmp(host, "MYSELF")) {
1347 					color = "green";
1348 				} else if(!status.reachable) {
1349 					color = "red";
1350 				} else if(strcmp(via, node)) {
1351 					color = "orange";
1352 				} else if(!status.validkey) {
1353 					color = "black";
1354 				} else if(minmtu > 0) {
1355 					color = "green";
1356 				}
1357 
1358 				printf(" \"%s\" [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\"");
1359 			} else {
1360 				if(only_reachable && !status.reachable) {
1361 					continue;
1362 				}
1363 
1364 				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,
1365 				       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);
1366 
1367 				if(udp_ping_rtt != -1) {
1368 					printf(" rtt %d.%03d", udp_ping_rtt / 1000, udp_ping_rtt % 1000);
1369 				}
1370 
1371 				printf("\n");
1372 			}
1373 		}
1374 		break;
1375 
1376 		case REQ_DUMP_EDGES: {
1377 			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);
1378 
1379 			if(n != 8) {
1380 				fprintf(stderr, "Unable to parse edge dump from tincd.\n");
1381 				return 1;
1382 			}
1383 
1384 			if(do_graph) {
1385 				float w = 1 + 65536.0 / weight;
1386 
1387 				if(do_graph == 1 && strcmp(node1, node2) > 0) {
1388 					printf(" \"%s\" -- \"%s\" [w = %f, weight = %f];\n", node1, node2, w, w);
1389 				} else if(do_graph == 2) {
1390 					printf(" \"%s\" -> \"%s\" [w = %f, weight = %f];\n", node1, node2, w, w);
1391 				}
1392 			} else {
1393 				printf("%s to %s at %s port %s local %s port %s options %x weight %d\n", from, to, host, port, local_host, local_port, options, weight);
1394 			}
1395 		}
1396 		break;
1397 
1398 		case REQ_DUMP_SUBNETS: {
1399 			int n = sscanf(line, "%*d %*d %4095s %4095s", subnet, node);
1400 
1401 			if(n != 2) {
1402 				fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
1403 				return 1;
1404 			}
1405 
1406 			printf("%s owner %s\n", strip_weight(subnet), node);
1407 		}
1408 		break;
1409 
1410 		case REQ_DUMP_CONNECTIONS: {
1411 			int n = sscanf(line, "%*d %*d %4095s %4095s port %4095s %x %d %x", node, host, port, &options, &socket, &status_int);
1412 
1413 			if(n != 6) {
1414 				fprintf(stderr, "Unable to parse connection dump from tincd.\n");
1415 				return 1;
1416 			}
1417 
1418 			printf("%s at %s port %s options %x socket %d status %x\n", node, host, port, options, socket, status_int);
1419 		}
1420 		break;
1421 
1422 		default:
1423 			fprintf(stderr, "Unable to parse dump from tincd.\n");
1424 			return 1;
1425 		}
1426 	}
1427 
1428 	fprintf(stderr, "Error receiving dump.\n");
1429 	return 1;
1430 }
1431 
1432 static int cmd_purge(int argc, char *argv[]) {
1433 	(void)argv;
1434 
1435 	if(argc > 1) {
1436 		fprintf(stderr, "Too many arguments!\n");
1437 		return 1;
1438 	}
1439 
1440 	if(!connect_tincd(true)) {
1441 		return 1;
1442 	}
1443 
1444 	sendline(fd, "%d %d", CONTROL, REQ_PURGE);
1445 
1446 	if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_PURGE || result) {
1447 		fprintf(stderr, "Could not purge old information.\n");
1448 		return 1;
1449 	}
1450 
1451 	return 0;
1452 }
1453 
1454 static int cmd_debug(int argc, char *argv[]) {
1455 	if(argc != 2) {
1456 		fprintf(stderr, "Invalid number of arguments.\n");
1457 		return 1;
1458 	}
1459 
1460 	if(!connect_tincd(true)) {
1461 		return 1;
1462 	}
1463 
1464 	int debuglevel = atoi(argv[1]);
1465 	int origlevel;
1466 
1467 	sendline(fd, "%d %d %d", CONTROL, REQ_SET_DEBUG, debuglevel);
1468 
1469 	if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &origlevel) != 3 || code != CONTROL || req != REQ_SET_DEBUG) {
1470 		fprintf(stderr, "Could not set debug level.\n");
1471 		return 1;
1472 	}
1473 
1474 	fprintf(stderr, "Old level %d, new level %d.\n", origlevel, debuglevel);
1475 	return 0;
1476 }
1477 
1478 static int cmd_retry(int argc, char *argv[]) {
1479 	(void)argv;
1480 
1481 	if(argc > 1) {
1482 		fprintf(stderr, "Too many arguments!\n");
1483 		return 1;
1484 	}
1485 
1486 	if(!connect_tincd(true)) {
1487 		return 1;
1488 	}
1489 
1490 	sendline(fd, "%d %d", CONTROL, REQ_RETRY);
1491 
1492 	if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RETRY || result) {
1493 		fprintf(stderr, "Could not retry outgoing connections.\n");
1494 		return 1;
1495 	}
1496 
1497 	return 0;
1498 }
1499 
1500 static int cmd_connect(int argc, char *argv[]) {
1501 	if(argc != 2) {
1502 		fprintf(stderr, "Invalid number of arguments.\n");
1503 		return 1;
1504 	}
1505 
1506 	if(!check_id(argv[1])) {
1507 		fprintf(stderr, "Invalid name for node.\n");
1508 		return 1;
1509 	}
1510 
1511 	if(!connect_tincd(true)) {
1512 		return 1;
1513 	}
1514 
1515 	sendline(fd, "%d %d %s", CONTROL, REQ_CONNECT, argv[1]);
1516 
1517 	if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_CONNECT || result) {
1518 		fprintf(stderr, "Could not connect to %s.\n", argv[1]);
1519 		return 1;
1520 	}
1521 
1522 	return 0;
1523 }
1524 
1525 static int cmd_disconnect(int argc, char *argv[]) {
1526 	if(argc != 2) {
1527 		fprintf(stderr, "Invalid number of arguments.\n");
1528 		return 1;
1529 	}
1530 
1531 	if(!check_id(argv[1])) {
1532 		fprintf(stderr, "Invalid name for node.\n");
1533 		return 1;
1534 	}
1535 
1536 	if(!connect_tincd(true)) {
1537 		return 1;
1538 	}
1539 
1540 	sendline(fd, "%d %d %s", CONTROL, REQ_DISCONNECT, argv[1]);
1541 
1542 	if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_DISCONNECT || result) {
1543 		fprintf(stderr, "Could not disconnect %s.\n", argv[1]);
1544 		return 1;
1545 	}
1546 
1547 	return 0;
1548 }
1549 
1550 static int cmd_top(int argc, char *argv[]) {
1551 	(void)argv;
1552 
1553 	if(argc > 1) {
1554 		fprintf(stderr, "Too many arguments!\n");
1555 		return 1;
1556 	}
1557 
1558 #ifdef HAVE_CURSES
1559 
1560 	if(!connect_tincd(true)) {
1561 		return 1;
1562 	}
1563 
1564 	top(fd);
1565 	return 0;
1566 #else
1567 	fprintf(stderr, "This version of tinc was compiled without support for the curses library.\n");
1568 	return 1;
1569 #endif
1570 }
1571 
1572 static int cmd_pcap(int argc, char *argv[]) {
1573 	if(argc > 2) {
1574 		fprintf(stderr, "Too many arguments!\n");
1575 		return 1;
1576 	}
1577 
1578 	if(!connect_tincd(true)) {
1579 		return 1;
1580 	}
1581 
1582 	pcap(fd, stdout, argc > 1 ? atoi(argv[1]) : 0);
1583 	return 0;
1584 }
1585 
1586 #ifdef SIGINT
1587 static void sigint_handler(int sig) {
1588 	(void)sig;
1589 
1590 	fprintf(stderr, "\n");
1591 	shutdown(fd, SHUT_RDWR);
1592 }
1593 #endif
1594 
1595 static int cmd_log(int argc, char *argv[]) {
1596 	if(argc > 2) {
1597 		fprintf(stderr, "Too many arguments!\n");
1598 		return 1;
1599 	}
1600 
1601 	if(!connect_tincd(true)) {
1602 		return 1;
1603 	}
1604 
1605 #ifdef SIGINT
1606 	signal(SIGINT, sigint_handler);
1607 #endif
1608 
1609 	logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1);
1610 
1611 #ifdef SIGINT
1612 	signal(SIGINT, SIG_DFL);
1613 #endif
1614 
1615 	close(fd);
1616 	fd = -1;
1617 	return 0;
1618 }
1619 
1620 static int cmd_pid(int argc, char *argv[]) {
1621 	(void)argv;
1622 
1623 	if(argc > 1) {
1624 		fprintf(stderr, "Too many arguments!\n");
1625 		return 1;
1626 	}
1627 
1628 	if(!connect_tincd(true) || !pid) {
1629 		return 1;
1630 	}
1631 
1632 	printf("%d\n", pid);
1633 	return 0;
1634 }
1635 
1636 int rstrip(char *value) {
1637 	int len = strlen(value);
1638 
1639 	while(len && strchr("\t\r\n ", value[len - 1])) {
1640 		value[--len] = 0;
1641 	}
1642 
1643 	return len;
1644 }
1645 
1646 char *get_my_name(bool verbose) {
1647 	FILE *f = fopen(tinc_conf, "r");
1648 
1649 	if(!f) {
1650 		if(verbose) {
1651 			fprintf(stderr, "Could not open %s: %s\n", tinc_conf, strerror(errno));
1652 		}
1653 
1654 		return NULL;
1655 	}
1656 
1657 	char buf[4096];
1658 	char *value;
1659 
1660 	while(fgets(buf, sizeof(buf), f)) {
1661 		int len = strcspn(buf, "\t =");
1662 		value = buf + len;
1663 		value += strspn(value, "\t ");
1664 
1665 		if(*value == '=') {
1666 			value++;
1667 			value += strspn(value, "\t ");
1668 		}
1669 
1670 		if(!rstrip(value)) {
1671 			continue;
1672 		}
1673 
1674 		buf[len] = 0;
1675 
1676 		if(strcasecmp(buf, "Name")) {
1677 			continue;
1678 		}
1679 
1680 		if(*value) {
1681 			fclose(f);
1682 			return replace_name(value);
1683 		}
1684 	}
1685 
1686 	fclose(f);
1687 
1688 	if(verbose) {
1689 		fprintf(stderr, "Could not find Name in %s.\n", tinc_conf);
1690 	}
1691 
1692 	return NULL;
1693 }
1694 
1695 ecdsa_t *get_pubkey(FILE *f) {
1696 	char buf[4096];
1697 	char *value;
1698 
1699 	while(fgets(buf, sizeof(buf), f)) {
1700 		int len = strcspn(buf, "\t =");
1701 		value = buf + len;
1702 		value += strspn(value, "\t ");
1703 
1704 		if(*value == '=') {
1705 			value++;
1706 			value += strspn(value, "\t ");
1707 		}
1708 
1709 		if(!rstrip(value)) {
1710 			continue;
1711 		}
1712 
1713 		buf[len] = 0;
1714 
1715 		if(strcasecmp(buf, "Ed25519PublicKey")) {
1716 			continue;
1717 		}
1718 
1719 		if(*value) {
1720 			return ecdsa_set_base64_public_key(value);
1721 		}
1722 	}
1723 
1724 	return NULL;
1725 }
1726 
1727 const var_t variables[] = {
1728 	/* Server configuration */
1729 	{"AddressFamily", VAR_SERVER | VAR_SAFE},
1730 	{"AutoConnect", VAR_SERVER | VAR_SAFE},
1731 	{"BindToAddress", VAR_SERVER | VAR_MULTIPLE},
1732 	{"BindToInterface", VAR_SERVER},
1733 	{"Broadcast", VAR_SERVER | VAR_SAFE},
1734 	{"BroadcastSubnet", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1735 	{"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1736 	{"DecrementTTL", VAR_SERVER | VAR_SAFE},
1737 	{"Device", VAR_SERVER},
1738 	{"DeviceStandby", VAR_SERVER},
1739 	{"DeviceType", VAR_SERVER},
1740 	{"DirectOnly", VAR_SERVER | VAR_SAFE},
1741 	{"Ed25519PrivateKeyFile", VAR_SERVER},
1742 	{"ExperimentalProtocol", VAR_SERVER},
1743 	{"Forwarding", VAR_SERVER},
1744 	{"FWMark", VAR_SERVER},
1745 	{"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
1746 	{"Hostnames", VAR_SERVER},
1747 	{"IffOneQueue", VAR_SERVER},
1748 	{"Interface", VAR_SERVER},
1749 	{"InvitationExpire", VAR_SERVER},
1750 	{"KeyExpire", VAR_SERVER | VAR_SAFE},
1751 	{"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
1752 	{"LocalDiscovery", VAR_SERVER | VAR_SAFE},
1753 	{"LogLevel", VAR_SERVER},
1754 	{"MACExpire", VAR_SERVER | VAR_SAFE},
1755 	{"MaxConnectionBurst", VAR_SERVER | VAR_SAFE},
1756 	{"MaxOutputBufferSize", VAR_SERVER | VAR_SAFE},
1757 	{"MaxTimeout", VAR_SERVER | VAR_SAFE},
1758 	{"Mode", VAR_SERVER | VAR_SAFE},
1759 	{"Name", VAR_SERVER},
1760 	{"PingInterval", VAR_SERVER | VAR_SAFE},
1761 	{"PingTimeout", VAR_SERVER | VAR_SAFE},
1762 	{"PriorityInheritance", VAR_SERVER},
1763 	{"PrivateKey", VAR_SERVER | VAR_OBSOLETE},
1764 	{"PrivateKeyFile", VAR_SERVER},
1765 	{"ProcessPriority", VAR_SERVER},
1766 	{"Proxy", VAR_SERVER},
1767 	{"ReplayWindow", VAR_SERVER | VAR_SAFE},
1768 	{"ScriptsExtension", VAR_SERVER},
1769 	{"ScriptsInterpreter", VAR_SERVER},
1770 	{"StrictSubnets", VAR_SERVER | VAR_SAFE},
1771 	{"TunnelServer", VAR_SERVER | VAR_SAFE},
1772 	{"UDPDiscovery", VAR_SERVER | VAR_SAFE},
1773 	{"UDPDiscoveryKeepaliveInterval", VAR_SERVER | VAR_SAFE},
1774 	{"UDPDiscoveryInterval", VAR_SERVER | VAR_SAFE},
1775 	{"UDPDiscoveryTimeout", VAR_SERVER | VAR_SAFE},
1776 	{"MTUInfoInterval", VAR_SERVER | VAR_SAFE},
1777 	{"UDPInfoInterval", VAR_SERVER | VAR_SAFE},
1778 	{"UDPRcvBuf", VAR_SERVER},
1779 	{"UDPSndBuf", VAR_SERVER},
1780 	{"UPnP", VAR_SERVER},
1781 	{"UPnPDiscoverWait", VAR_SERVER},
1782 	{"UPnPRefreshPeriod", VAR_SERVER},
1783 	{"VDEGroup", VAR_SERVER},
1784 	{"VDEPort", VAR_SERVER},
1785 	/* Host configuration */
1786 	{"Address", VAR_HOST | VAR_MULTIPLE},
1787 	{"Cipher", VAR_SERVER | VAR_HOST},
1788 	{"ClampMSS", VAR_SERVER | VAR_HOST | VAR_SAFE},
1789 	{"Compression", VAR_SERVER | VAR_HOST | VAR_SAFE},
1790 	{"Digest", VAR_SERVER | VAR_HOST},
1791 	{"Ed25519PublicKey", VAR_HOST},
1792 	{"Ed25519PublicKeyFile", VAR_SERVER | VAR_HOST},
1793 	{"IndirectData", VAR_SERVER | VAR_HOST | VAR_SAFE},
1794 	{"MACLength", VAR_SERVER | VAR_HOST},
1795 	{"PMTU", VAR_SERVER | VAR_HOST},
1796 	{"PMTUDiscovery", VAR_SERVER | VAR_HOST},
1797 	{"Port", VAR_HOST},
1798 	{"PublicKey", VAR_HOST | VAR_OBSOLETE},
1799 	{"PublicKeyFile", VAR_SERVER | VAR_HOST | VAR_OBSOLETE},
1800 	{"Subnet", VAR_HOST | VAR_MULTIPLE | VAR_SAFE},
1801 	{"TCPOnly", VAR_SERVER | VAR_HOST | VAR_SAFE},
1802 	{"Weight", VAR_HOST | VAR_SAFE},
1803 	{NULL, 0}
1804 };
1805 
1806 static int cmd_config(int argc, char *argv[]) {
1807 	if(argc < 2) {
1808 		fprintf(stderr, "Invalid number of arguments.\n");
1809 		return 1;
1810 	}
1811 
1812 	if(strcasecmp(argv[0], "config")) {
1813 		argv--, argc++;
1814 	}
1815 
1816 	int action = -2;
1817 
1818 	if(!strcasecmp(argv[1], "get")) {
1819 		argv++, argc--;
1820 	} else if(!strcasecmp(argv[1], "add")) {
1821 		argv++, argc--, action = 1;
1822 	} else if(!strcasecmp(argv[1], "del")) {
1823 		argv++, argc--, action = -1;
1824 	} else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) {
1825 		argv++, argc--, action = 0;
1826 	}
1827 
1828 	if(argc < 2) {
1829 		fprintf(stderr, "Invalid number of arguments.\n");
1830 		return 1;
1831 	}
1832 
1833 	// Concatenate the rest of the command line
1834 	strncpy(line, argv[1], sizeof(line) - 1);
1835 
1836 	for(int i = 2; i < argc; i++) {
1837 		strncat(line, " ", sizeof(line) - 1 - strlen(line));
1838 		strncat(line, argv[i], sizeof(line) - 1 - strlen(line));
1839 	}
1840 
1841 	// Liberal parsing into node name, variable name and value.
1842 	char *node = NULL;
1843 	char *variable;
1844 	char *value;
1845 	int len;
1846 
1847 	len = strcspn(line, "\t =");
1848 	value = line + len;
1849 	value += strspn(value, "\t ");
1850 
1851 	if(*value == '=') {
1852 		value++;
1853 		value += strspn(value, "\t ");
1854 	}
1855 
1856 	line[len] = '\0';
1857 	variable = strchr(line, '.');
1858 
1859 	if(variable) {
1860 		node = line;
1861 		*variable++ = 0;
1862 	} else {
1863 		variable = line;
1864 	}
1865 
1866 	if(!*variable) {
1867 		fprintf(stderr, "No variable given.\n");
1868 		return 1;
1869 	}
1870 
1871 	if(action >= 0 && !*value) {
1872 		fprintf(stderr, "No value for variable given.\n");
1873 		return 1;
1874 	}
1875 
1876 	if(action < -1 && *value) {
1877 		action = 0;
1878 	}
1879 
1880 	/* Some simple checks. */
1881 	bool found = false;
1882 	bool warnonremove = false;
1883 
1884 	for(int i = 0; variables[i].name; i++) {
1885 		if(strcasecmp(variables[i].name, variable)) {
1886 			continue;
1887 		}
1888 
1889 		found = true;
1890 		variable = (char *)variables[i].name;
1891 
1892 		if(!strcasecmp(variable, "Subnet")) {
1893 			subnet_t s = {0};
1894 
1895 			if(!str2net(&s, value)) {
1896 				fprintf(stderr, "Malformed subnet definition %s\n", value);
1897 			}
1898 
1899 			if(!subnetcheck(s)) {
1900 				fprintf(stderr, "Network address and prefix length do not match: %s\n", value);
1901 				return 1;
1902 			}
1903 		}
1904 
1905 		/* Discourage use of obsolete variables. */
1906 
1907 		if(variables[i].type & VAR_OBSOLETE && action >= 0) {
1908 			if(force) {
1909 				fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable);
1910 			} else {
1911 				fprintf(stderr, "%s is an obsolete variable! Use --force to use it anyway.\n", variable);
1912 				return 1;
1913 			}
1914 		}
1915 
1916 		/* Don't put server variables in host config files */
1917 
1918 		if(node && !(variables[i].type & VAR_HOST) && action >= 0) {
1919 			if(force) {
1920 				fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable);
1921 			} else {
1922 				fprintf(stderr, "%s is not a host configuration variable! Use --force to use it anyway.\n", variable);
1923 				return 1;
1924 			}
1925 		}
1926 
1927 		/* Should this go into our own host config file? */
1928 
1929 		if(!node && !(variables[i].type & VAR_SERVER)) {
1930 			node = get_my_name(true);
1931 
1932 			if(!node) {
1933 				return 1;
1934 			}
1935 		}
1936 
1937 		/* Change "add" into "set" for variables that do not allow multiple occurrences.
1938 		   Turn on warnings when it seems variables might be removed unintentionally. */
1939 
1940 		if(action == 1 && !(variables[i].type & VAR_MULTIPLE)) {
1941 			warnonremove = true;
1942 			action = 0;
1943 		} else if(action == 0 && (variables[i].type & VAR_MULTIPLE)) {
1944 			warnonremove = true;
1945 		}
1946 
1947 		break;
1948 	}
1949 
1950 	if(node && !check_id(node)) {
1951 		fprintf(stderr, "Invalid name for node.\n");
1952 		return 1;
1953 	}
1954 
1955 	if(!found) {
1956 		if(force || action < 0) {
1957 			fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable);
1958 		} else {
1959 			fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable);
1960 			return 1;
1961 		}
1962 	}
1963 
1964 	// Open the right configuration file.
1965 	char filename[PATH_MAX];
1966 
1967 	if(node) {
1968 		snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node);
1969 	} else {
1970 		snprintf(filename, sizeof(filename), "%s", tinc_conf);
1971 	}
1972 
1973 	FILE *f = fopen(filename, "r");
1974 
1975 	if(!f) {
1976 		fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
1977 		return 1;
1978 	}
1979 
1980 	char tmpfile[PATH_MAX];
1981 	FILE *tf = NULL;
1982 
1983 	if(action >= -1) {
1984 		if((size_t)snprintf(tmpfile, sizeof(tmpfile), "%s.config.tmp", filename) >= sizeof(tmpfile)) {
1985 			fprintf(stderr, "Filename too long: %s.config.tmp\n", filename);
1986 			return 1;
1987 		}
1988 
1989 		tf = fopen(tmpfile, "w");
1990 
1991 		if(!tf) {
1992 			fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
1993 			fclose(f);
1994 			return 1;
1995 		}
1996 	}
1997 
1998 	// Copy the file, making modifications on the fly, unless we are just getting a value.
1999 	char buf1[4096];
2000 	char buf2[4096];
2001 	bool set = false;
2002 	bool removed = false;
2003 	found = false;
2004 
2005 	while(fgets(buf1, sizeof(buf1), f)) {
2006 		buf1[sizeof(buf1) - 1] = 0;
2007 		strncpy(buf2, buf1, sizeof(buf2));
2008 
2009 		// Parse line in a simple way
2010 		char *bvalue;
2011 		int len;
2012 
2013 		len = strcspn(buf2, "\t =");
2014 		bvalue = buf2 + len;
2015 		bvalue += strspn(bvalue, "\t ");
2016 
2017 		if(*bvalue == '=') {
2018 			bvalue++;
2019 			bvalue += strspn(bvalue, "\t ");
2020 		}
2021 
2022 		rstrip(bvalue);
2023 		buf2[len] = '\0';
2024 
2025 		// Did it match?
2026 		if(!strcasecmp(buf2, variable)) {
2027 			// Get
2028 			if(action < -1) {
2029 				found = true;
2030 				printf("%s\n", bvalue);
2031 				// Del
2032 			} else if(action == -1) {
2033 				if(!*value || !strcasecmp(bvalue, value)) {
2034 					removed = true;
2035 					continue;
2036 				}
2037 
2038 				// Set
2039 			} else if(action == 0) {
2040 				// Warn if "set" was used for variables that can occur multiple times
2041 				if(warnonremove && strcasecmp(bvalue, value)) {
2042 					fprintf(stderr, "Warning: removing %s = %s\n", variable, bvalue);
2043 				}
2044 
2045 				// Already set? Delete the rest...
2046 				if(set) {
2047 					continue;
2048 				}
2049 
2050 				// Otherwise, replace.
2051 				if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
2052 					fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2053 					return 1;
2054 				}
2055 
2056 				set = true;
2057 				continue;
2058 				// Add
2059 			} else if(action > 0) {
2060 				// Check if we've already seen this variable with the same value
2061 				if(!strcasecmp(bvalue, value)) {
2062 					found = true;
2063 				}
2064 			}
2065 		}
2066 
2067 		if(action >= -1) {
2068 			// Copy original line...
2069 			if(fputs(buf1, tf) < 0) {
2070 				fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2071 				return 1;
2072 			}
2073 
2074 			// Add newline if it is missing...
2075 			if(*buf1 && buf1[strlen(buf1) - 1] != '\n') {
2076 				if(fputc('\n', tf) < 0) {
2077 					fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2078 					return 1;
2079 				}
2080 			}
2081 		}
2082 	}
2083 
2084 	// Make sure we read everything...
2085 	if(ferror(f) || !feof(f)) {
2086 		fprintf(stderr, "Error while reading from configuration file %s: %s\n", filename, strerror(errno));
2087 		return 1;
2088 	}
2089 
2090 	if(fclose(f)) {
2091 		fprintf(stderr, "Error closing configuration file %s: %s\n", filename, strerror(errno));
2092 		return 1;
2093 	}
2094 
2095 	// Add new variable if necessary.
2096 	if((action > 0 && !found) || (action == 0 && !set)) {
2097 		if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
2098 			fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2099 			return 1;
2100 		}
2101 	}
2102 
2103 	if(action < -1) {
2104 		if(found) {
2105 			return 0;
2106 		} else {
2107 			fprintf(stderr, "No matching configuration variables found.\n");
2108 			return 1;
2109 		}
2110 	}
2111 
2112 	// Make sure we wrote everything...
2113 	if(fclose(tf)) {
2114 		fprintf(stderr, "Error closing temporary file %s: %s\n", tmpfile, strerror(errno));
2115 		return 1;
2116 	}
2117 
2118 	// Could we find what we had to remove?
2119 	if(action < 0 && !removed) {
2120 		remove(tmpfile);
2121 		fprintf(stderr, "No configuration variables deleted.\n");
2122 		return 1;
2123 	}
2124 
2125 	// Replace the configuration file with the new one
2126 #ifdef HAVE_MINGW
2127 
2128 	if(remove(filename)) {
2129 		fprintf(stderr, "Error replacing file %s: %s\n", filename, strerror(errno));
2130 		return 1;
2131 	}
2132 
2133 #endif
2134 
2135 	if(rename(tmpfile, filename)) {
2136 		fprintf(stderr, "Error renaming temporary file %s to configuration file %s: %s\n", tmpfile, filename, strerror(errno));
2137 		return 1;
2138 	}
2139 
2140 	// Silently try notifying a running tincd of changes.
2141 	if(connect_tincd(false)) {
2142 		sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
2143 	}
2144 
2145 	return 0;
2146 }
2147 
2148 static bool try_bind(int port) {
2149 	struct addrinfo *ai = NULL, *aip;
2150 	struct addrinfo hint = {
2151 		.ai_flags = AI_PASSIVE,
2152 		.ai_family = AF_UNSPEC,
2153 		.ai_socktype = SOCK_STREAM,
2154 		.ai_protocol = IPPROTO_TCP,
2155 	};
2156 
2157 	bool success = true;
2158 	char portstr[16];
2159 	snprintf(portstr, sizeof(portstr), "%d", port);
2160 
2161 	if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) {
2162 		return false;
2163 	}
2164 
2165 	for(aip = ai; aip; aip = aip->ai_next) {
2166 		int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
2167 
2168 		if(!fd) {
2169 			success = false;
2170 			break;
2171 		}
2172 
2173 		int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
2174 		closesocket(fd);
2175 
2176 		if(result) {
2177 			success = false;
2178 			break;
2179 		}
2180 	}
2181 
2182 	freeaddrinfo(ai);
2183 	return success;
2184 }
2185 
2186 int check_port(const char *name) {
2187 	if(try_bind(655)) {
2188 		return 655;
2189 	}
2190 
2191 	fprintf(stderr, "Warning: could not bind to port 655. ");
2192 
2193 	for(int i = 0; i < 100; i++) {
2194 		int port = 0x1000 + (rand() & 0x7fff);
2195 
2196 		if(try_bind(port)) {
2197 			char filename[PATH_MAX];
2198 			snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", confbase, name);
2199 			FILE *f = fopen(filename, "a");
2200 
2201 			if(!f) {
2202 				fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
2203 				fprintf(stderr, "Please change tinc's Port manually.\n");
2204 				return 0;
2205 			}
2206 
2207 			fprintf(f, "Port = %d\n", port);
2208 			fclose(f);
2209 			fprintf(stderr, "Tinc will instead listen on port %d.\n", port);
2210 			return port;
2211 		}
2212 	}
2213 
2214 	fprintf(stderr, "Please change tinc's Port manually.\n");
2215 	return 0;
2216 }
2217 
2218 static int cmd_init(int argc, char *argv[]) {
2219 	if(!access(tinc_conf, F_OK)) {
2220 		fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
2221 		return 1;
2222 	}
2223 
2224 	if(argc > 2) {
2225 		fprintf(stderr, "Too many arguments!\n");
2226 		return 1;
2227 	} else if(argc < 2) {
2228 		if(tty) {
2229 			char buf[1024];
2230 			fprintf(stderr, "Enter the Name you want your tinc node to have: ");
2231 
2232 			if(!fgets(buf, sizeof(buf), stdin)) {
2233 				fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
2234 				return 1;
2235 			}
2236 
2237 			int len = rstrip(buf);
2238 
2239 			if(!len) {
2240 				fprintf(stderr, "No name given!\n");
2241 				return 1;
2242 			}
2243 
2244 			name = strdup(buf);
2245 		} else {
2246 			fprintf(stderr, "No Name given!\n");
2247 			return 1;
2248 		}
2249 	} else {
2250 		name = strdup(argv[1]);
2251 
2252 		if(!*name) {
2253 			fprintf(stderr, "No Name given!\n");
2254 			return 1;
2255 		}
2256 	}
2257 
2258 	if(!check_id(name)) {
2259 		fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n");
2260 		return 1;
2261 	}
2262 
2263 	if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) {
2264 		fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
2265 		return 1;
2266 	}
2267 
2268 	if(mkdir(confbase, 0777) && errno != EEXIST) {
2269 		fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
2270 		return 1;
2271 	}
2272 
2273 	if(mkdir(hosts_dir, 0777) && errno != EEXIST) {
2274 		fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno));
2275 		return 1;
2276 	}
2277 
2278 	FILE *f = fopen(tinc_conf, "w");
2279 
2280 	if(!f) {
2281 		fprintf(stderr, "Could not create file %s: %s\n", tinc_conf, strerror(errno));
2282 		return 1;
2283 	}
2284 
2285 	fprintf(f, "Name = %s\n", name);
2286 	fclose(f);
2287 
2288 #ifndef DISABLE_LEGACY
2289 
2290 	if(!rsa_keygen(2048, false)) {
2291 		return 1;
2292 	}
2293 
2294 #endif
2295 
2296 	if(!ed25519_keygen(false)) {
2297 		return 1;
2298 	}
2299 
2300 	check_port(name);
2301 
2302 #ifndef HAVE_MINGW
2303 	char filename[PATH_MAX];
2304 	snprintf(filename, sizeof(filename), "%s" SLASH "tinc-up", confbase);
2305 
2306 	if(access(filename, F_OK)) {
2307 		FILE *f = fopenmask(filename, "w", 0777);
2308 
2309 		if(!f) {
2310 			fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
2311 			return 1;
2312 		}
2313 
2314 		fprintf(f, "#!/bin/sh\n\necho 'Unconfigured tinc-up script, please edit '$0'!'\n\n#ifconfig $INTERFACE <your vpn IP address> netmask <netmask of whole VPN>\n");
2315 		fclose(f);
2316 	}
2317 
2318 #endif
2319 
2320 	return 0;
2321 
2322 }
2323 
2324 static int cmd_generate_keys(int argc, char *argv[]) {
2325 #ifdef DISABLE_LEGACY
2326 	(void)argv;
2327 
2328 	if(argc > 1) {
2329 #else
2330 
2331 	if(argc > 2) {
2332 #endif
2333 		fprintf(stderr, "Too many arguments!\n");
2334 		return 1;
2335 	}
2336 
2337 	if(!name) {
2338 		name = get_my_name(false);
2339 	}
2340 
2341 #ifndef DISABLE_LEGACY
2342 
2343 	if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true)) {
2344 		return 1;
2345 	}
2346 
2347 #endif
2348 
2349 	if(!ed25519_keygen(true)) {
2350 		return 1;
2351 	}
2352 
2353 	return 0;
2354 }
2355 
2356 #ifndef DISABLE_LEGACY
2357 static int cmd_generate_rsa_keys(int argc, char *argv[]) {
2358 	if(argc > 2) {
2359 		fprintf(stderr, "Too many arguments!\n");
2360 		return 1;
2361 	}
2362 
2363 	if(!name) {
2364 		name = get_my_name(false);
2365 	}
2366 
2367 	return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
2368 }
2369 #endif
2370 
2371 static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
2372 	(void)argv;
2373 
2374 	if(argc > 1) {
2375 		fprintf(stderr, "Too many arguments!\n");
2376 		return 1;
2377 	}
2378 
2379 	if(!name) {
2380 		name = get_my_name(false);
2381 	}
2382 
2383 	return !ed25519_keygen(true);
2384 }
2385 
2386 static int cmd_help(int argc, char *argv[]) {
2387 	(void)argc;
2388 	(void)argv;
2389 
2390 	usage(false);
2391 	return 0;
2392 }
2393 
2394 static int cmd_version(int argc, char *argv[]) {
2395 	(void)argv;
2396 
2397 	if(argc > 1) {
2398 		fprintf(stderr, "Too many arguments!\n");
2399 		return 1;
2400 	}
2401 
2402 	version();
2403 	return 0;
2404 }
2405 
2406 static int cmd_info(int argc, char *argv[]) {
2407 	if(argc != 2) {
2408 		fprintf(stderr, "Invalid number of arguments.\n");
2409 		return 1;
2410 	}
2411 
2412 	if(!connect_tincd(true)) {
2413 		return 1;
2414 	}
2415 
2416 	return info(fd, argv[1]);
2417 }
2418 
2419 static const char *conffiles[] = {
2420 	"tinc.conf",
2421 	"tinc-up",
2422 	"tinc-down",
2423 	"subnet-up",
2424 	"subnet-down",
2425 	"host-up",
2426 	"host-down",
2427 	NULL,
2428 };
2429 
2430 static int cmd_edit(int argc, char *argv[]) {
2431 	if(argc != 2) {
2432 		fprintf(stderr, "Invalid number of arguments.\n");
2433 		return 1;
2434 	}
2435 
2436 	char filename[PATH_MAX] = "";
2437 
2438 	if(strncmp(argv[1], "hosts" SLASH, 6)) {
2439 		for(int i = 0; conffiles[i]; i++) {
2440 			if(!strcmp(argv[1], conffiles[i])) {
2441 				snprintf(filename, sizeof(filename), "%s" SLASH "%s", confbase, argv[1]);
2442 				break;
2443 			}
2444 		}
2445 	} else {
2446 		argv[1] += 6;
2447 	}
2448 
2449 	if(!*filename) {
2450 		snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, argv[1]);
2451 		char *dash = strchr(argv[1], '-');
2452 
2453 		if(dash) {
2454 			*dash++ = 0;
2455 
2456 			if((strcmp(dash, "up") && strcmp(dash, "down")) || !check_id(argv[1])) {
2457 				fprintf(stderr, "Invalid configuration filename.\n");
2458 				return 1;
2459 			}
2460 		}
2461 	}
2462 
2463 	char *command;
2464 #ifndef HAVE_MINGW
2465 	const char *editor = getenv("VISUAL");
2466 
2467 	if(!editor) {
2468 		editor = getenv("EDITOR");
2469 	}
2470 
2471 	if(!editor) {
2472 		editor = "vi";
2473 	}
2474 
2475 	xasprintf(&command, "\"%s\" \"%s\"", editor, filename);
2476 #else
2477 	xasprintf(&command, "edit \"%s\"", filename);
2478 #endif
2479 	int result = system(command);
2480 	free(command);
2481 
2482 	if(result) {
2483 		return result;
2484 	}
2485 
2486 	// Silently try notifying a running tincd of changes.
2487 	if(connect_tincd(false)) {
2488 		sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
2489 	}
2490 
2491 	return 0;
2492 }
2493 
2494 static int export(const char *name, FILE *out) {
2495 	char filename[PATH_MAX];
2496 	snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name);
2497 	FILE *in = fopen(filename, "r");
2498 
2499 	if(!in) {
2500 		fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
2501 		return 1;
2502 	}
2503 
2504 	fprintf(out, "Name = %s\n", name);
2505 	char buf[4096];
2506 
2507 	while(fgets(buf, sizeof(buf), in)) {
2508 		if(strcspn(buf, "\t =") != 4 || strncasecmp(buf, "Name", 4)) {
2509 			fputs(buf, out);
2510 		}
2511 	}
2512 
2513 	if(ferror(in)) {
2514 		fprintf(stderr, "Error while reading configuration file %s: %s\n", filename, strerror(errno));
2515 		fclose(in);
2516 		return 1;
2517 	}
2518 
2519 	fclose(in);
2520 	return 0;
2521 }
2522 
2523 static int cmd_export(int argc, char *argv[]) {
2524 	(void)argv;
2525 
2526 	if(argc > 1) {
2527 		fprintf(stderr, "Too many arguments!\n");
2528 		return 1;
2529 	}
2530 
2531 	char *name = get_my_name(true);
2532 
2533 	if(!name) {
2534 		return 1;
2535 	}
2536 
2537 	int result = export(name, stdout);
2538 
2539 	if(!tty) {
2540 		fclose(stdout);
2541 	}
2542 
2543 	free(name);
2544 	return result;
2545 }
2546 
2547 static int cmd_export_all(int argc, char *argv[]) {
2548 	(void)argv;
2549 
2550 	if(argc > 1) {
2551 		fprintf(stderr, "Too many arguments!\n");
2552 		return 1;
2553 	}
2554 
2555 	DIR *dir = opendir(hosts_dir);
2556 
2557 	if(!dir) {
2558 		fprintf(stderr, "Could not open host configuration directory %s: %s\n", hosts_dir, strerror(errno));
2559 		return 1;
2560 	}
2561 
2562 	bool first = true;
2563 	int result = 0;
2564 	struct dirent *ent;
2565 
2566 	while((ent = readdir(dir))) {
2567 		if(!check_id(ent->d_name)) {
2568 			continue;
2569 		}
2570 
2571 		if(first) {
2572 			first = false;
2573 		} else {
2574 			printf("#---------------------------------------------------------------#\n");
2575 		}
2576 
2577 		result |= export(ent->d_name, stdout);
2578 	}
2579 
2580 	closedir(dir);
2581 
2582 	if(!tty) {
2583 		fclose(stdout);
2584 	}
2585 
2586 	return result;
2587 }
2588 
2589 static int cmd_import(int argc, char *argv[]) {
2590 	(void)argv;
2591 
2592 	if(argc > 1) {
2593 		fprintf(stderr, "Too many arguments!\n");
2594 		return 1;
2595 	}
2596 
2597 	FILE *in = stdin;
2598 	FILE *out = NULL;
2599 
2600 	char buf[4096];
2601 	char name[4096];
2602 	char filename[PATH_MAX] = "";
2603 	int count = 0;
2604 	bool firstline = true;
2605 
2606 	while(fgets(buf, sizeof(buf), in)) {
2607 		if(sscanf(buf, "Name = %4095s", name) == 1) {
2608 			firstline = false;
2609 
2610 			if(!check_id(name)) {
2611 				fprintf(stderr, "Invalid Name in input!\n");
2612 				return 1;
2613 			}
2614 
2615 			if(out) {
2616 				fclose(out);
2617 			}
2618 
2619 			if((size_t)snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name) >= sizeof(filename)) {
2620 				fprintf(stderr, "Filename too long: %s" SLASH "%s\n", hosts_dir, name);
2621 				return 1;
2622 			}
2623 
2624 			if(!force && !access(filename, F_OK)) {
2625 				fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
2626 				out = NULL;
2627 				continue;
2628 			}
2629 
2630 			out = fopen(filename, "w");
2631 
2632 			if(!out) {
2633 				fprintf(stderr, "Error creating configuration file %s: %s\n", filename, strerror(errno));
2634 				return 1;
2635 			}
2636 
2637 			count++;
2638 			continue;
2639 		} else if(firstline) {
2640 			fprintf(stderr, "Junk at the beginning of the input, ignoring.\n");
2641 			firstline = false;
2642 		}
2643 
2644 
2645 		if(!strcmp(buf, "#---------------------------------------------------------------#\n")) {
2646 			continue;
2647 		}
2648 
2649 		if(out) {
2650 			if(fputs(buf, out) < 0) {
2651 				fprintf(stderr, "Error writing to host configuration file %s: %s\n", filename, strerror(errno));
2652 				return 1;
2653 			}
2654 		}
2655 	}
2656 
2657 	if(out) {
2658 		fclose(out);
2659 	}
2660 
2661 	if(count) {
2662 		fprintf(stderr, "Imported %d host configuration files.\n", count);
2663 		return 0;
2664 	} else {
2665 		fprintf(stderr, "No host configuration files imported.\n");
2666 		return 1;
2667 	}
2668 }
2669 
2670 static int cmd_exchange(int argc, char *argv[]) {
2671 	return cmd_export(argc, argv) ? 1 : cmd_import(argc, argv);
2672 }
2673 
2674 static int cmd_exchange_all(int argc, char *argv[]) {
2675 	return cmd_export_all(argc, argv) ? 1 : cmd_import(argc, argv);
2676 }
2677 
2678 static int switch_network(char *name) {
2679 	if(strcmp(name, ".")) {
2680 		if(!check_netname(name, false)) {
2681 			fprintf(stderr, "Invalid character in netname!\n");
2682 			return 1;
2683 		}
2684 
2685 		if(!check_netname(name, true)) {
2686 			fprintf(stderr, "Warning: unsafe character in netname!\n");
2687 		}
2688 	}
2689 
2690 	if(fd >= 0) {
2691 		close(fd);
2692 		fd = -1;
2693 	}
2694 
2695 	free_names();
2696 	netname = strcmp(name, ".") ? xstrdup(name) : NULL;
2697 	make_names(false);
2698 
2699 	free(tinc_conf);
2700 	free(hosts_dir);
2701 	free(prompt);
2702 
2703 	xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
2704 	xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
2705 	xasprintf(&prompt, "%s> ", identname);
2706 
2707 	return 0;
2708 }
2709 
2710 static int cmd_network(int argc, char *argv[]) {
2711 	if(argc > 2) {
2712 		fprintf(stderr, "Too many arguments!\n");
2713 		return 1;
2714 	}
2715 
2716 	if(argc == 2) {
2717 		return switch_network(argv[1]);
2718 	}
2719 
2720 	DIR *dir = opendir(confdir);
2721 
2722 	if(!dir) {
2723 		fprintf(stderr, "Could not read directory %s: %s\n", confdir, strerror(errno));
2724 		return 1;
2725 	}
2726 
2727 	struct dirent *ent;
2728 
2729 	while((ent = readdir(dir))) {
2730 		if(*ent->d_name == '.') {
2731 			continue;
2732 		}
2733 
2734 		if(!strcmp(ent->d_name, "tinc.conf")) {
2735 			printf(".\n");
2736 			continue;
2737 		}
2738 
2739 		char fname[PATH_MAX];
2740 		snprintf(fname, sizeof(fname), "%s/%s/tinc.conf", confdir, ent->d_name);
2741 
2742 		if(!access(fname, R_OK)) {
2743 			printf("%s\n", ent->d_name);
2744 		}
2745 	}
2746 
2747 	closedir(dir);
2748 
2749 	return 0;
2750 }
2751 
2752 static int cmd_fsck(int argc, char *argv[]) {
2753 	(void)argv;
2754 
2755 	if(argc > 1) {
2756 		fprintf(stderr, "Too many arguments!\n");
2757 		return 1;
2758 	}
2759 
2760 	return fsck(orig_argv[0]);
2761 }
2762 
2763 static void *readfile(FILE *in, size_t *len) {
2764 	size_t count = 0;
2765 	size_t bufsize = 4096;
2766 	char *buf = xmalloc(bufsize);
2767 
2768 	while(!feof(in)) {
2769 		size_t read = fread(buf + count, 1, bufsize - count, in);
2770 
2771 		if(!read) {
2772 			break;
2773 		}
2774 
2775 		count += read;
2776 
2777 		if(count >= bufsize) {
2778 			bufsize *= 2;
2779 			buf = xrealloc(buf, bufsize);
2780 		}
2781 	}
2782 
2783 	if(len) {
2784 		*len = count;
2785 	}
2786 
2787 	return buf;
2788 }
2789 
2790 static int cmd_sign(int argc, char *argv[]) {
2791 	if(argc > 2) {
2792 		fprintf(stderr, "Too many arguments!\n");
2793 		return 1;
2794 	}
2795 
2796 	if(!name) {
2797 		name = get_my_name(true);
2798 
2799 		if(!name) {
2800 			return 1;
2801 		}
2802 	}
2803 
2804 	char fname[PATH_MAX];
2805 	snprintf(fname, sizeof(fname), "%s" SLASH "ed25519_key.priv", confbase);
2806 	FILE *fp = fopen(fname, "r");
2807 
2808 	if(!fp) {
2809 		fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
2810 		return 1;
2811 	}
2812 
2813 	ecdsa_t *key = ecdsa_read_pem_private_key(fp);
2814 
2815 	if(!key) {
2816 		fprintf(stderr, "Could not read private key from %s\n", fname);
2817 		fclose(fp);
2818 		return 1;
2819 	}
2820 
2821 	fclose(fp);
2822 
2823 	FILE *in;
2824 
2825 	if(argc == 2) {
2826 		in = fopen(argv[1], "rb");
2827 
2828 		if(!in) {
2829 			fprintf(stderr, "Could not open %s: %s\n", argv[1], strerror(errno));
2830 			ecdsa_free(key);
2831 			return 1;
2832 		}
2833 	} else {
2834 		in = stdin;
2835 	}
2836 
2837 	size_t len;
2838 	char *data = readfile(in, &len);
2839 
2840 	if(in != stdin) {
2841 		fclose(in);
2842 	}
2843 
2844 	if(!data) {
2845 		fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
2846 		ecdsa_free(key);
2847 		return 1;
2848 	}
2849 
2850 	// Ensure we sign our name and current time as well
2851 	long t = time(NULL);
2852 	char *trailer;
2853 	xasprintf(&trailer, " %s %ld", name, t);
2854 	int trailer_len = strlen(trailer);
2855 
2856 	data = xrealloc(data, len + trailer_len);
2857 	memcpy(data + len, trailer, trailer_len);
2858 	free(trailer);
2859 
2860 	char sig[87];
2861 
2862 	if(!ecdsa_sign(key, data, len + trailer_len, sig)) {
2863 		fprintf(stderr, "Error generating signature\n");
2864 		free(data);
2865 		ecdsa_free(key);
2866 		return 1;
2867 	}
2868 
2869 	b64encode(sig, sig, 64);
2870 	ecdsa_free(key);
2871 
2872 	fprintf(stdout, "Signature = %s %ld %s\n", name, t, sig);
2873 	fwrite(data, len, 1, stdout);
2874 
2875 	free(data);
2876 	return 0;
2877 }
2878 
2879 static int cmd_verify(int argc, char *argv[]) {
2880 	if(argc < 2) {
2881 		fprintf(stderr, "Not enough arguments!\n");
2882 		return 1;
2883 	}
2884 
2885 	if(argc > 3) {
2886 		fprintf(stderr, "Too many arguments!\n");
2887 		return 1;
2888 	}
2889 
2890 	char *node = argv[1];
2891 
2892 	if(!strcmp(node, ".")) {
2893 		if(!name) {
2894 			name = get_my_name(true);
2895 
2896 			if(!name) {
2897 				return 1;
2898 			}
2899 		}
2900 
2901 		node = name;
2902 	} else if(!strcmp(node, "*")) {
2903 		node = NULL;
2904 	} else {
2905 		if(!check_id(node)) {
2906 			fprintf(stderr, "Invalid node name\n");
2907 			return 1;
2908 		}
2909 	}
2910 
2911 	FILE *in;
2912 
2913 	if(argc == 3) {
2914 		in = fopen(argv[2], "rb");
2915 
2916 		if(!in) {
2917 			fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
2918 			return 1;
2919 		}
2920 	} else {
2921 		in = stdin;
2922 	}
2923 
2924 	size_t len;
2925 	char *data = readfile(in, &len);
2926 
2927 	if(in != stdin) {
2928 		fclose(in);
2929 	}
2930 
2931 	if(!data) {
2932 		fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
2933 		return 1;
2934 	}
2935 
2936 	char *newline = memchr(data, '\n', len);
2937 
2938 	if(!newline || (newline - data > MAX_STRING_SIZE - 1)) {
2939 		fprintf(stderr, "Invalid input\n");
2940 		free(data);
2941 		return 1;
2942 	}
2943 
2944 	*newline++ = '\0';
2945 	size_t skip = newline - data;
2946 
2947 	char signer[MAX_STRING_SIZE] = "";
2948 	char sig[MAX_STRING_SIZE] = "";
2949 	long t = 0;
2950 
2951 	if(sscanf(data, "Signature = %s %ld %s", signer, &t, sig) != 3 || strlen(sig) != 86 || !t || !check_id(signer)) {
2952 		fprintf(stderr, "Invalid input\n");
2953 		free(data);
2954 		return 1;
2955 	}
2956 
2957 	if(node && strcmp(node, signer)) {
2958 		fprintf(stderr, "Signature is not made by %s\n", node);
2959 		free(data);
2960 		return 1;
2961 	}
2962 
2963 	if(!node) {
2964 		node = signer;
2965 	}
2966 
2967 	char *trailer;
2968 	xasprintf(&trailer, " %s %ld", signer, t);
2969 	int trailer_len = strlen(trailer);
2970 
2971 	data = xrealloc(data, len + trailer_len);
2972 	memcpy(data + len, trailer, trailer_len);
2973 	free(trailer);
2974 
2975 	newline = data + skip;
2976 
2977 	char fname[PATH_MAX];
2978 	snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, node);
2979 	FILE *fp = fopen(fname, "r");
2980 
2981 	if(!fp) {
2982 		fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
2983 		free(data);
2984 		return 1;
2985 	}
2986 
2987 	ecdsa_t *key = get_pubkey(fp);
2988 
2989 	if(!key) {
2990 		rewind(fp);
2991 		key = ecdsa_read_pem_public_key(fp);
2992 	}
2993 
2994 	if(!key) {
2995 		fprintf(stderr, "Could not read public key from %s\n", fname);
2996 		fclose(fp);
2997 		free(data);
2998 		return 1;
2999 	}
3000 
3001 	fclose(fp);
3002 
3003 	if(b64decode(sig, sig, 86) != 64 || !ecdsa_verify(key, newline, len + trailer_len - (newline - data), sig)) {
3004 		fprintf(stderr, "Invalid signature\n");
3005 		free(data);
3006 		ecdsa_free(key);
3007 		return 1;
3008 	}
3009 
3010 	ecdsa_free(key);
3011 
3012 	fwrite(newline, len - (newline - data), 1, stdout);
3013 
3014 	free(data);
3015 	return 0;
3016 }
3017 
3018 static const struct {
3019 	const char *command;
3020 	int (*function)(int argc, char *argv[]);
3021 	bool hidden;
3022 } commands[] = {
3023 	{"start", cmd_start, false},
3024 	{"stop", cmd_stop, false},
3025 	{"restart", cmd_restart, false},
3026 	{"reload", cmd_reload, false},
3027 	{"dump", cmd_dump, false},
3028 	{"list", cmd_dump, false},
3029 	{"purge", cmd_purge, false},
3030 	{"debug", cmd_debug, false},
3031 	{"retry", cmd_retry, false},
3032 	{"connect", cmd_connect, false},
3033 	{"disconnect", cmd_disconnect, false},
3034 	{"top", cmd_top, false},
3035 	{"pcap", cmd_pcap, false},
3036 	{"log", cmd_log, false},
3037 	{"pid", cmd_pid, false},
3038 	{"config", cmd_config, true},
3039 	{"add", cmd_config, false},
3040 	{"del", cmd_config, false},
3041 	{"get", cmd_config, false},
3042 	{"set", cmd_config, false},
3043 	{"init", cmd_init, false},
3044 	{"generate-keys", cmd_generate_keys, false},
3045 #ifndef DISABLE_LEGACY
3046 	{"generate-rsa-keys", cmd_generate_rsa_keys, false},
3047 #endif
3048 	{"generate-ed25519-keys", cmd_generate_ed25519_keys, false},
3049 	{"help", cmd_help, false},
3050 	{"version", cmd_version, false},
3051 	{"info", cmd_info, false},
3052 	{"edit", cmd_edit, false},
3053 	{"export", cmd_export, false},
3054 	{"export-all", cmd_export_all, false},
3055 	{"import", cmd_import, false},
3056 	{"exchange", cmd_exchange, false},
3057 	{"exchange-all", cmd_exchange_all, false},
3058 	{"invite", cmd_invite, false},
3059 	{"join", cmd_join, false},
3060 	{"network", cmd_network, false},
3061 	{"fsck", cmd_fsck, false},
3062 	{"sign", cmd_sign, false},
3063 	{"verify", cmd_verify, false},
3064 	{NULL, NULL, false},
3065 };
3066 
3067 #ifdef HAVE_READLINE
3068 static char *complete_command(const char *text, int state) {
3069 	static int i;
3070 
3071 	if(!state) {
3072 		i = 0;
3073 	} else {
3074 		i++;
3075 	}
3076 
3077 	while(commands[i].command) {
3078 		if(!commands[i].hidden && !strncasecmp(commands[i].command, text, strlen(text))) {
3079 			return xstrdup(commands[i].command);
3080 		}
3081 
3082 		i++;
3083 	}
3084 
3085 	return NULL;
3086 }
3087 
3088 static char *complete_dump(const char *text, int state) {
3089 	const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL};
3090 	static int i;
3091 
3092 	if(!state) {
3093 		i = 0;
3094 	} else {
3095 		i++;
3096 	}
3097 
3098 	while(matches[i]) {
3099 		if(!strncasecmp(matches[i], text, strlen(text))) {
3100 			return xstrdup(matches[i]);
3101 		}
3102 
3103 		i++;
3104 	}
3105 
3106 	return NULL;
3107 }
3108 
3109 static char *complete_config(const char *text, int state) {
3110 	static int i;
3111 
3112 	if(!state) {
3113 		i = 0;
3114 	} else {
3115 		i++;
3116 	}
3117 
3118 	while(variables[i].name) {
3119 		char *dot = strchr(text, '.');
3120 
3121 		if(dot) {
3122 			if((variables[i].type & VAR_HOST) && !strncasecmp(variables[i].name, dot + 1, strlen(dot + 1))) {
3123 				char *match;
3124 				xasprintf(&match, "%.*s.%s", (int)(dot - text), text, variables[i].name);
3125 				return match;
3126 			}
3127 		} else {
3128 			if(!strncasecmp(variables[i].name, text, strlen(text))) {
3129 				return xstrdup(variables[i].name);
3130 			}
3131 		}
3132 
3133 		i++;
3134 	}
3135 
3136 	return NULL;
3137 }
3138 
3139 static char *complete_info(const char *text, int state) {
3140 	static int i;
3141 
3142 	if(!state) {
3143 		i = 0;
3144 
3145 		if(!connect_tincd(false)) {
3146 			return NULL;
3147 		}
3148 
3149 		// Check the list of nodes
3150 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
3151 		sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
3152 	}
3153 
3154 	while(recvline(fd, line, sizeof(line))) {
3155 		char item[4096];
3156 		int n = sscanf(line, "%d %d %4095s", &code, &req, item);
3157 
3158 		if(n == 2) {
3159 			i++;
3160 
3161 			if(i >= 2) {
3162 				break;
3163 			} else {
3164 				continue;
3165 			}
3166 		}
3167 
3168 		if(n != 3) {
3169 			fprintf(stderr, "Unable to parse dump from tincd, n = %d, i = %d.\n", n, i);
3170 			break;
3171 		}
3172 
3173 		if(!strncmp(item, text, strlen(text))) {
3174 			return xstrdup(strip_weight(item));
3175 		}
3176 	}
3177 
3178 	return NULL;
3179 }
3180 
3181 static char *complete_nothing(const char *text, int state) {
3182 	(void)text;
3183 	(void)state;
3184 	return NULL;
3185 }
3186 
3187 static char **completion(const char *text, int start, int end) {
3188 	(void)end;
3189 	char **matches = NULL;
3190 
3191 	if(!start) {
3192 		matches = rl_completion_matches(text, complete_command);
3193 	} else if(!strncasecmp(rl_line_buffer, "dump ", 5)) {
3194 		matches = rl_completion_matches(text, complete_dump);
3195 	} else if(!strncasecmp(rl_line_buffer, "add ", 4)) {
3196 		matches = rl_completion_matches(text, complete_config);
3197 	} else if(!strncasecmp(rl_line_buffer, "del ", 4)) {
3198 		matches = rl_completion_matches(text, complete_config);
3199 	} else if(!strncasecmp(rl_line_buffer, "get ", 4)) {
3200 		matches = rl_completion_matches(text, complete_config);
3201 	} else if(!strncasecmp(rl_line_buffer, "set ", 4)) {
3202 		matches = rl_completion_matches(text, complete_config);
3203 	} else if(!strncasecmp(rl_line_buffer, "info ", 5)) {
3204 		matches = rl_completion_matches(text, complete_info);
3205 	}
3206 
3207 	return matches;
3208 }
3209 #endif
3210 
3211 static int cmd_shell(int argc, char *argv[]) {
3212 	xasprintf(&prompt, "%s> ", identname);
3213 	int result = 0;
3214 	char buf[4096];
3215 	char *line = NULL;
3216 	int maxargs = argc + 16;
3217 	char **nargv = xmalloc(maxargs * sizeof(*nargv));
3218 
3219 	for(int i = 0; i < argc; i++) {
3220 		nargv[i] = argv[i];
3221 	}
3222 
3223 #ifdef HAVE_READLINE
3224 	rl_readline_name = "tinc";
3225 	rl_completion_entry_function = complete_nothing;
3226 	rl_attempted_completion_function = completion;
3227 	rl_filename_completion_desired = 0;
3228 	char *copy = NULL;
3229 #endif
3230 
3231 	while(true) {
3232 #ifdef HAVE_READLINE
3233 
3234 		if(tty) {
3235 			free(copy);
3236 			free(line);
3237 			rl_basic_word_break_characters = "\t\n ";
3238 			line = readline(prompt);
3239 			copy = line ? xstrdup(line) : NULL;
3240 		} else {
3241 			line = fgets(buf, sizeof(buf), stdin);
3242 		}
3243 
3244 #else
3245 
3246 		if(tty) {
3247 			fputs(prompt, stdout);
3248 		}
3249 
3250 		line = fgets(buf, sizeof(buf), stdin);
3251 #endif
3252 
3253 		if(!line) {
3254 			break;
3255 		}
3256 
3257 		/* Ignore comments */
3258 
3259 		if(*line == '#') {
3260 			continue;
3261 		}
3262 
3263 		/* Split */
3264 
3265 		int nargc = argc;
3266 		char *p = line + strspn(line, " \t\n");
3267 		char *next = strtok(p, " \t\n");
3268 
3269 		while(p && *p) {
3270 			if(nargc >= maxargs) {
3271 				maxargs *= 2;
3272 				nargv = xrealloc(nargv, maxargs * sizeof(*nargv));
3273 			}
3274 
3275 			nargv[nargc++] = p;
3276 			p = next;
3277 			next = strtok(NULL, " \t\n");
3278 		}
3279 
3280 		if(nargc == argc) {
3281 			continue;
3282 		}
3283 
3284 		if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit")) {
3285 #ifdef HAVE_READLINE
3286 			free(copy);
3287 #endif
3288 			free(nargv);
3289 			return result;
3290 		}
3291 
3292 		bool found = false;
3293 
3294 		for(int i = 0; commands[i].command; i++) {
3295 			if(!strcasecmp(nargv[argc], commands[i].command)) {
3296 				result |= commands[i].function(nargc - argc - 1, nargv + argc + 1);
3297 				found = true;
3298 				break;
3299 			}
3300 		}
3301 
3302 #ifdef HAVE_READLINE
3303 
3304 		if(tty && found) {
3305 			add_history(copy);
3306 		}
3307 
3308 #endif
3309 
3310 		if(!found) {
3311 			fprintf(stderr, "Unknown command `%s'.\n", nargv[argc]);
3312 			result |= 1;
3313 		}
3314 	}
3315 
3316 #ifdef HAVE_READLINE
3317 	free(copy);
3318 #endif
3319 	free(nargv);
3320 
3321 	if(tty) {
3322 		printf("\n");
3323 	}
3324 
3325 	return result;
3326 }
3327 
3328 
3329 int main(int argc, char *argv[]) {
3330 	program_name = argv[0];
3331 	orig_argv = argv;
3332 	orig_argc = argc;
3333 	tty = isatty(0) && isatty(1);
3334 
3335 	if(!parse_options(argc, argv)) {
3336 		return 1;
3337 	}
3338 
3339 	make_names(false);
3340 	xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
3341 	xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
3342 
3343 	if(show_version) {
3344 		version();
3345 		return 0;
3346 	}
3347 
3348 	if(show_help) {
3349 		usage(false);
3350 		return 0;
3351 	}
3352 
3353 #ifdef HAVE_MINGW
3354 	static struct WSAData wsa_state;
3355 
3356 	if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
3357 		fprintf(stderr, "System call `%s' failed: %s\n", "WSAStartup", winerror(GetLastError()));
3358 		return false;
3359 	}
3360 
3361 #endif
3362 
3363 	srand(time(NULL));
3364 	crypto_init();
3365 
3366 	if(optind >= argc) {
3367 		return cmd_shell(argc, argv);
3368 	}
3369 
3370 	for(int i = 0; commands[i].command; i++) {
3371 		if(!strcasecmp(argv[optind], commands[i].command)) {
3372 			return commands[i].function(argc - optind, argv + optind);
3373 		}
3374 	}
3375 
3376 	fprintf(stderr, "Unknown command `%s'.\n", argv[optind]);
3377 	usage(true);
3378 	return 1;
3379 }
3380