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