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