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