Check that UNIX socket filenames are not too long.
[tinc] / src / tincctl.c
1 /*
2     tincctl.c -- Controlling a running tincd
3     Copyright (C) 2007-2021 Guus Sliepen <guus@tinc-vpn.org>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "system.h"
21
22 #include <getopt.h>
23
24 #ifdef HAVE_READLINE
25 #include "readline/readline.h"
26 #include "readline/history.h"
27 #endif
28
29 #include "xalloc.h"
30 #include "protocol.h"
31 #include "control_common.h"
32 #include "crypto.h"
33 #include "ecdsagen.h"
34 #include "fsck.h"
35 #include "info.h"
36 #include "invitation.h"
37 #include "names.h"
38 #include "rsagen.h"
39 #include "utils.h"
40 #include "tincctl.h"
41 #include "top.h"
42 #include "version.h"
43 #include "subnet.h"
44
45 #ifndef MSG_NOSIGNAL
46 #define MSG_NOSIGNAL 0
47 #endif
48
49 static char **orig_argv;
50 static int orig_argc;
51
52 /* If nonzero, display usage information and exit. */
53 static bool show_help = false;
54
55 /* If nonzero, print the version on standard output and exit.  */
56 static bool show_version = false;
57
58 static char *name = NULL;
59 static char controlcookie[1025];
60 char *tinc_conf = NULL;
61 char *hosts_dir = NULL;
62 struct timeval now;
63
64 // Horrible global variables...
65 static int pid = 0;
66 int fd = -1;
67 char line[4096];
68 static int code;
69 static int req;
70 static int result;
71 bool force = false;
72 bool tty = true;
73 bool confbasegiven = false;
74 bool netnamegiven = false;
75 char *scriptinterpreter = NULL;
76 char *scriptextension = "";
77 static char *prompt;
78 char *device = NULL;
79 char *iface = NULL;
80 int debug_level = -1;
81
82 static struct option const long_options[] = {
83         {"batch", no_argument, NULL, 'b'},
84         {"config", required_argument, NULL, 'c'},
85         {"net", required_argument, NULL, 'n'},
86         {"help", no_argument, NULL, 1},
87         {"version", no_argument, NULL, 2},
88         {"pidfile", required_argument, NULL, 3},
89         {"force", no_argument, NULL, 4},
90         {NULL, 0, NULL, 0}
91 };
92
93 static void version(void) {
94         printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
95                BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
96         printf("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                 .sun_family = AF_UNIX,
858         };
859
860         if(strlen(unixsocketname) >= sizeof(sa.sun_path)) {
861                 fprintf(stderr, "UNIX socket filename %s is too long!", unixsocketname);
862                 return false;
863         }
864
865         strncpy(sa.sun_path, unixsocketname, sizeof(sa.sun_path));
866
867         fd = socket(AF_UNIX, SOCK_STREAM, 0);
868
869         if(fd < 0) {
870                 if(verbose) {
871                         fprintf(stderr, "Cannot create UNIX socket: %s\n", sockstrerror(sockerrno));
872                 }
873
874                 return false;
875         }
876
877         if(connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
878                 if(verbose) {
879                         fprintf(stderr, "Cannot connect to UNIX socket %s: %s\n", unixsocketname, sockstrerror(sockerrno));
880                 }
881
882                 close(fd);
883                 fd = -1;
884                 return false;
885         }
886
887 #else
888         struct addrinfo hints = {
889                 .ai_family = AF_UNSPEC,
890                 .ai_socktype = SOCK_STREAM,
891                 .ai_protocol = IPPROTO_TCP,
892                 .ai_flags = 0,
893         };
894
895         struct addrinfo *res = NULL;
896
897         if(getaddrinfo(host, port, &hints, &res) || !res) {
898                 if(verbose) {
899                         fprintf(stderr, "Cannot resolve %s port %s: %s\n", host, port, sockstrerror(sockerrno));
900                 }
901
902                 return false;
903         }
904
905         fd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP);
906
907         if(fd < 0) {
908                 if(verbose) {
909                         fprintf(stderr, "Cannot create TCP socket: %s\n", sockstrerror(sockerrno));
910                 }
911
912                 return false;
913         }
914
915         unsigned long arg = 0;
916
917         if(ioctlsocket(fd, FIONBIO, &arg) != 0) {
918                 if(verbose) {
919                         fprintf(stderr, "System call `%s' failed: %s\n", "ioctlsocket", sockstrerror(sockerrno));
920                 }
921         }
922
923         if(connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
924                 if(verbose) {
925                         fprintf(stderr, "Cannot connect to %s port %s: %s\n", host, port, sockstrerror(sockerrno));
926                 }
927
928                 close(fd);
929                 fd = -1;
930                 return false;
931         }
932
933         freeaddrinfo(res);
934 #endif
935
936 #ifdef SO_NOSIGPIPE
937         static const int one = 1;
938         setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof(one));
939 #endif
940
941         sendline(fd, "%d ^%s %d", ID, controlcookie, TINC_CTL_VERSION_CURRENT);
942
943         char data[4096];
944         int version;
945
946         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %4095s %d", &code, data, &version) != 3 || code != 0) {
947                 if(verbose) {
948                         fprintf(stderr, "Cannot read greeting from control socket: %s\n", sockstrerror(sockerrno));
949                 }
950
951                 close(fd);
952                 fd = -1;
953                 return false;
954         }
955
956         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &version, &pid) != 3 || code != 4 || version != TINC_CTL_VERSION_CURRENT) {
957                 if(verbose) {
958                         fprintf(stderr, "Could not fully establish control socket connection\n");
959                 }
960
961                 close(fd);
962                 fd = -1;
963                 return false;
964         }
965
966         return true;
967 }
968
969
970 static int cmd_start(int argc, char *argv[]) {
971         if(connect_tincd(false)) {
972                 if(netname) {
973                         fprintf(stderr, "A tincd is already running for net `%s' with pid %d.\n", netname, pid);
974                 } else {
975                         fprintf(stderr, "A tincd is already running with pid %d.\n", pid);
976                 }
977
978                 return 0;
979         }
980
981         char *c;
982         char *slash = strrchr(program_name, '/');
983
984 #ifdef HAVE_MINGW
985
986         if((c = strrchr(program_name, '\\')) > slash) {
987                 slash = c;
988         }
989
990 #endif
991
992         if(slash++) {
993                 xasprintf(&c, "%.*stincd", (int)(slash - program_name), program_name);
994         } else {
995                 c = "tincd";
996         }
997
998         int nargc = 0;
999         char **nargv = xzalloc((optind + argc) * sizeof(*nargv));
1000
1001         char *arg0 = c;
1002 #ifdef HAVE_MINGW
1003         /*
1004            Windows has no real concept of an "argv array". A command line is just one string.
1005            The CRT of the new process will decode the command line string to generate argv before calling main(), and (by convention)
1006            it uses quotes to handle spaces in arguments.
1007            Therefore we need to quote all arguments that might contain spaces. No, execvp() won't do that for us (see MSDN).
1008            If we don't do that, then execvp() will run fine but any spaces in the filename contained in arg0 will bleed
1009            into the next arguments when the spawned process' CRT parses its command line, resulting in chaos.
1010         */
1011         xasprintf(&arg0, "\"%s\"", arg0);
1012 #endif
1013         nargv[nargc++] = arg0;
1014
1015         for(int i = 1; i < optind; i++) {
1016                 nargv[nargc++] = orig_argv[i];
1017         }
1018
1019         for(int i = 1; i < argc; i++) {
1020                 nargv[nargc++] = argv[i];
1021         }
1022
1023 #ifdef HAVE_MINGW
1024         int status = spawnvp(_P_WAIT, c, nargv);
1025
1026         if(status == -1) {
1027                 fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno));
1028                 return 1;
1029         }
1030
1031         return status;
1032 #else
1033         int pfd[2] = {-1, -1};
1034
1035         if(socketpair(AF_UNIX, SOCK_STREAM, 0, pfd)) {
1036                 fprintf(stderr, "Could not create umbilical socket: %s\n", strerror(errno));
1037                 free(nargv);
1038                 return 1;
1039         }
1040
1041         pid_t pid = fork();
1042
1043         if(pid == -1) {
1044                 fprintf(stderr, "Could not fork: %s\n", strerror(errno));
1045                 free(nargv);
1046                 return 1;
1047         }
1048
1049         if(!pid) {
1050                 close(pfd[0]);
1051                 char buf[100];
1052                 snprintf(buf, sizeof(buf), "%d", pfd[1]);
1053                 setenv("TINC_UMBILICAL", buf, true);
1054                 exit(execvp(c, nargv));
1055         } else {
1056                 close(pfd[1]);
1057         }
1058
1059         free(nargv);
1060
1061         int status = -1, result;
1062 #ifdef SIGINT
1063         signal(SIGINT, SIG_IGN);
1064 #endif
1065
1066         // Pass all log messages from the umbilical to stderr.
1067         // A nul-byte right before closure means tincd started successfully.
1068         bool failure = true;
1069         char buf[1024];
1070         ssize_t len;
1071
1072         while((len = read(pfd[0], buf, sizeof(buf))) > 0) {
1073                 failure = buf[len - 1];
1074
1075                 if(!failure) {
1076                         len--;
1077                 }
1078
1079                 write(2, buf, len);
1080         }
1081
1082         if(len) {
1083                 failure = true;
1084         }
1085
1086         close(pfd[0]);
1087
1088         // Make sure the child process is really gone.
1089         result = waitpid(pid, &status, 0);
1090
1091 #ifdef SIGINT
1092         signal(SIGINT, SIG_DFL);
1093 #endif
1094
1095         if(failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
1096                 fprintf(stderr, "Error starting %s\n", c);
1097                 return 1;
1098         }
1099
1100         return 0;
1101 #endif
1102 }
1103
1104 static int cmd_stop(int argc, char *argv[]) {
1105         (void)argv;
1106
1107         if(argc > 1) {
1108                 fprintf(stderr, "Too many arguments!\n");
1109                 return 1;
1110         }
1111
1112 #ifdef HAVE_MINGW
1113         return remove_service() ? EXIT_SUCCESS : EXIT_FAILURE;
1114 #else
1115
1116         if(!stop_tincd()) {
1117                 if(pid) {
1118                         if(kill(pid, SIGTERM)) {
1119                                 fprintf(stderr, "Could not send TERM signal to process with PID %d: %s\n", pid, strerror(errno));
1120                                 return 1;
1121                         }
1122
1123                         fprintf(stderr, "Sent TERM signal to process with PID %d.\n", pid);
1124                         waitpid(pid, NULL, 0);
1125                         return 0;
1126                 }
1127
1128                 return 1;
1129         }
1130
1131         return 0;
1132 #endif
1133 }
1134
1135 static int cmd_restart(int argc, char *argv[]) {
1136         cmd_stop(1, argv);
1137         return cmd_start(argc, argv);
1138 }
1139
1140 static int cmd_reload(int argc, char *argv[]) {
1141         (void)argv;
1142
1143         if(argc > 1) {
1144                 fprintf(stderr, "Too many arguments!\n");
1145                 return 1;
1146         }
1147
1148         if(!connect_tincd(true)) {
1149                 return 1;
1150         }
1151
1152         sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
1153
1154         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RELOAD || result) {
1155                 fprintf(stderr, "Could not reload configuration.\n");
1156                 return 1;
1157         }
1158
1159         return 0;
1160
1161 }
1162
1163 static int dump_invitations(void) {
1164         char dname[PATH_MAX];
1165         snprintf(dname, sizeof(dname), "%s" SLASH "invitations", confbase);
1166         DIR *dir = opendir(dname);
1167
1168         if(!dir) {
1169                 if(errno == ENOENT) {
1170                         fprintf(stderr, "No outstanding invitations.\n");
1171                         return 0;
1172                 }
1173
1174                 fprintf(stderr, "Cannot not read directory %s: %s\n", dname, strerror(errno));
1175                 return 1;
1176         }
1177
1178         struct dirent *ent;
1179
1180         bool found = false;
1181
1182         while((ent = readdir(dir))) {
1183                 char buf[MAX_STRING_SIZE];
1184
1185                 if(b64decode(ent->d_name, buf, 24) != 18) {
1186                         continue;
1187                 }
1188
1189                 char fname[PATH_MAX];
1190
1191                 if((size_t)snprintf(fname, sizeof(fname), "%s" SLASH "%s", dname, ent->d_name) >= sizeof(fname)) {
1192                         fprintf(stderr, "Filename too long: %s" SLASH "%s\n", dname, ent->d_name);
1193                         continue;
1194                 }
1195
1196                 FILE *f = fopen(fname, "r");
1197
1198                 if(!f) {
1199                         fprintf(stderr, "Cannot open %s: %s\n", fname, strerror(errno));
1200                         continue;
1201                 }
1202
1203                 buf[0] = 0;
1204
1205                 if(!fgets(buf, sizeof(buf), f)) {
1206                         fprintf(stderr, "Invalid invitation file %s\n", fname);
1207                         fclose(f);
1208                         continue;
1209                 }
1210
1211                 fclose(f);
1212
1213                 char *eol = buf + strlen(buf);
1214
1215                 while(strchr("\t \r\n", *--eol)) {
1216                         *eol = 0;
1217                 }
1218
1219                 if(strncmp(buf, "Name = ", 7) || !check_id(buf + 7)) {
1220                         fprintf(stderr, "Invalid invitation file %s\n", fname);
1221                         continue;
1222                 }
1223
1224                 found = true;
1225                 printf("%s %s\n", ent->d_name, buf + 7);
1226         }
1227
1228         closedir(dir);
1229
1230         if(!found) {
1231                 fprintf(stderr, "No outstanding invitations.\n");
1232         }
1233
1234         return 0;
1235 }
1236
1237 static int cmd_dump(int argc, char *argv[]) {
1238         bool only_reachable = false;
1239
1240         if(argc > 2 && !strcasecmp(argv[1], "reachable")) {
1241                 if(strcasecmp(argv[2], "nodes")) {
1242                         fprintf(stderr, "`reachable' only supported for nodes.\n");
1243                         usage(true);
1244                         return 1;
1245                 }
1246
1247                 only_reachable = true;
1248                 argv++;
1249                 argc--;
1250         }
1251
1252         if(argc != 2) {
1253                 fprintf(stderr, "Invalid number of arguments.\n");
1254                 usage(true);
1255                 return 1;
1256         }
1257
1258         if(!strcasecmp(argv[1], "invitations")) {
1259                 return dump_invitations();
1260         }
1261
1262         if(!connect_tincd(true)) {
1263                 return 1;
1264         }
1265
1266         int do_graph = 0;
1267
1268         if(!strcasecmp(argv[1], "nodes")) {
1269                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1270         } else if(!strcasecmp(argv[1], "edges")) {
1271                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1272         } else if(!strcasecmp(argv[1], "subnets")) {
1273                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
1274         } else if(!strcasecmp(argv[1], "connections")) {
1275                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS);
1276         } else if(!strcasecmp(argv[1], "graph")) {
1277                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1278                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1279                 do_graph = 1;
1280         } else if(!strcasecmp(argv[1], "digraph")) {
1281                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1282                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1283                 do_graph = 2;
1284         } else {
1285                 fprintf(stderr, "Unknown dump type '%s'.\n", argv[1]);
1286                 usage(true);
1287                 return 1;
1288         }
1289
1290         if(do_graph == 1) {
1291                 printf("graph {\n");
1292         } else if(do_graph == 2) {
1293                 printf("digraph {\n");
1294         }
1295
1296         while(recvline(fd, line, sizeof(line))) {
1297                 char node1[4096], node2[4096];
1298                 int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, node1, node2);
1299
1300                 if(n == 2) {
1301                         if(do_graph && req == REQ_DUMP_NODES) {
1302                                 continue;
1303                         } else {
1304                                 if(do_graph) {
1305                                         printf("}\n");
1306                                 }
1307
1308                                 return 0;
1309                         }
1310                 }
1311
1312                 if(n < 2) {
1313                         break;
1314                 }
1315
1316                 char node[4096];
1317                 char id[4096];
1318                 char from[4096];
1319                 char to[4096];
1320                 char subnet[4096];
1321                 char host[4096];
1322                 char port[4096];
1323                 char local_host[4096];
1324                 char local_port[4096];
1325                 char via[4096];
1326                 char nexthop[4096];
1327                 int cipher, digest, maclength, compression, distance, socket, weight;
1328                 short int pmtu, minmtu, maxmtu;
1329                 unsigned int options, status_int;
1330                 node_status_t status;
1331                 long int last_state_change;
1332                 int udp_ping_rtt;
1333                 uint64_t in_packets, in_bytes, out_packets, out_bytes;
1334
1335                 switch(req) {
1336                 case REQ_DUMP_NODES: {
1337                         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);
1338
1339                         if(n != 22) {
1340                                 fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
1341                                 return 1;
1342                         }
1343
1344                         memcpy(&status, &status_int, sizeof(status));
1345
1346                         if(do_graph) {
1347                                 const char *color = "black";
1348
1349                                 if(!strcmp(host, "MYSELF")) {
1350                                         color = "green";
1351                                 } else if(!status.reachable) {
1352                                         color = "red";
1353                                 } else if(strcmp(via, node)) {
1354                                         color = "orange";
1355                                 } else if(!status.validkey) {
1356                                         color = "black";
1357                                 } else if(minmtu > 0) {
1358                                         color = "green";
1359                                 }
1360
1361                                 printf(" \"%s\" [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\"");
1362                         } else {
1363                                 if(only_reachable && !status.reachable) {
1364                                         continue;
1365                                 }
1366
1367                                 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,
1368                                        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);
1369
1370                                 if(udp_ping_rtt != -1) {
1371                                         printf(" rtt %d.%03d", udp_ping_rtt / 1000, udp_ping_rtt % 1000);
1372                                 }
1373
1374                                 printf("\n");
1375                         }
1376                 }
1377                 break;
1378
1379                 case REQ_DUMP_EDGES: {
1380                         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);
1381
1382                         if(n != 8) {
1383                                 fprintf(stderr, "Unable to parse edge dump from tincd.\n");
1384                                 return 1;
1385                         }
1386
1387                         if(do_graph) {
1388                                 float w = 1 + 65536.0 / weight;
1389
1390                                 if(do_graph == 1 && strcmp(node1, node2) > 0) {
1391                                         printf(" \"%s\" -- \"%s\" [w = %f, weight = %f];\n", node1, node2, w, w);
1392                                 } else if(do_graph == 2) {
1393                                         printf(" \"%s\" -> \"%s\" [w = %f, weight = %f];\n", node1, node2, w, w);
1394                                 }
1395                         } else {
1396                                 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);
1397                         }
1398                 }
1399                 break;
1400
1401                 case REQ_DUMP_SUBNETS: {
1402                         int n = sscanf(line, "%*d %*d %4095s %4095s", subnet, node);
1403
1404                         if(n != 2) {
1405                                 fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
1406                                 return 1;
1407                         }
1408
1409                         printf("%s owner %s\n", strip_weight(subnet), node);
1410                 }
1411                 break;
1412
1413                 case REQ_DUMP_CONNECTIONS: {
1414                         int n = sscanf(line, "%*d %*d %4095s %4095s port %4095s %x %d %x", node, host, port, &options, &socket, &status_int);
1415
1416                         if(n != 6) {
1417                                 fprintf(stderr, "Unable to parse connection dump from tincd.\n");
1418                                 return 1;
1419                         }
1420
1421                         printf("%s at %s port %s options %x socket %d status %x\n", node, host, port, options, socket, status_int);
1422                 }
1423                 break;
1424
1425                 default:
1426                         fprintf(stderr, "Unable to parse dump from tincd.\n");
1427                         return 1;
1428                 }
1429         }
1430
1431         fprintf(stderr, "Error receiving dump.\n");
1432         return 1;
1433 }
1434
1435 static int cmd_purge(int argc, char *argv[]) {
1436         (void)argv;
1437
1438         if(argc > 1) {
1439                 fprintf(stderr, "Too many arguments!\n");
1440                 return 1;
1441         }
1442
1443         if(!connect_tincd(true)) {
1444                 return 1;
1445         }
1446
1447         sendline(fd, "%d %d", CONTROL, REQ_PURGE);
1448
1449         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_PURGE || result) {
1450                 fprintf(stderr, "Could not purge old information.\n");
1451                 return 1;
1452         }
1453
1454         return 0;
1455 }
1456
1457 static int cmd_debug(int argc, char *argv[]) {
1458         if(argc != 2) {
1459                 fprintf(stderr, "Invalid number of arguments.\n");
1460                 return 1;
1461         }
1462
1463         if(!connect_tincd(true)) {
1464                 return 1;
1465         }
1466
1467         int debuglevel = atoi(argv[1]);
1468         int origlevel;
1469
1470         sendline(fd, "%d %d %d", CONTROL, REQ_SET_DEBUG, debuglevel);
1471
1472         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &origlevel) != 3 || code != CONTROL || req != REQ_SET_DEBUG) {
1473                 fprintf(stderr, "Could not set debug level.\n");
1474                 return 1;
1475         }
1476
1477         fprintf(stderr, "Old level %d, new level %d.\n", origlevel, debuglevel);
1478         return 0;
1479 }
1480
1481 static int cmd_retry(int argc, char *argv[]) {
1482         (void)argv;
1483
1484         if(argc > 1) {
1485                 fprintf(stderr, "Too many arguments!\n");
1486                 return 1;
1487         }
1488
1489         if(!connect_tincd(true)) {
1490                 return 1;
1491         }
1492
1493         sendline(fd, "%d %d", CONTROL, REQ_RETRY);
1494
1495         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RETRY || result) {
1496                 fprintf(stderr, "Could not retry outgoing connections.\n");
1497                 return 1;
1498         }
1499
1500         return 0;
1501 }
1502
1503 static int cmd_connect(int argc, char *argv[]) {
1504         if(argc != 2) {
1505                 fprintf(stderr, "Invalid number of arguments.\n");
1506                 return 1;
1507         }
1508
1509         if(!check_id(argv[1])) {
1510                 fprintf(stderr, "Invalid name for node.\n");
1511                 return 1;
1512         }
1513
1514         if(!connect_tincd(true)) {
1515                 return 1;
1516         }
1517
1518         sendline(fd, "%d %d %s", CONTROL, REQ_CONNECT, argv[1]);
1519
1520         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_CONNECT || result) {
1521                 fprintf(stderr, "Could not connect to %s.\n", argv[1]);
1522                 return 1;
1523         }
1524
1525         return 0;
1526 }
1527
1528 static int cmd_disconnect(int argc, char *argv[]) {
1529         if(argc != 2) {
1530                 fprintf(stderr, "Invalid number of arguments.\n");
1531                 return 1;
1532         }
1533
1534         if(!check_id(argv[1])) {
1535                 fprintf(stderr, "Invalid name for node.\n");
1536                 return 1;
1537         }
1538
1539         if(!connect_tincd(true)) {
1540                 return 1;
1541         }
1542
1543         sendline(fd, "%d %d %s", CONTROL, REQ_DISCONNECT, argv[1]);
1544
1545         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_DISCONNECT || result) {
1546                 fprintf(stderr, "Could not disconnect %s.\n", argv[1]);
1547                 return 1;
1548         }
1549
1550         return 0;
1551 }
1552
1553 static int cmd_top(int argc, char *argv[]) {
1554         (void)argv;
1555
1556         if(argc > 1) {
1557                 fprintf(stderr, "Too many arguments!\n");
1558                 return 1;
1559         }
1560
1561 #ifdef HAVE_CURSES
1562
1563         if(!connect_tincd(true)) {
1564                 return 1;
1565         }
1566
1567         top(fd);
1568         return 0;
1569 #else
1570         fprintf(stderr, "This version of tinc was compiled without support for the curses library.\n");
1571         return 1;
1572 #endif
1573 }
1574
1575 static int cmd_pcap(int argc, char *argv[]) {
1576         if(argc > 2) {
1577                 fprintf(stderr, "Too many arguments!\n");
1578                 return 1;
1579         }
1580
1581         if(!connect_tincd(true)) {
1582                 return 1;
1583         }
1584
1585         pcap(fd, stdout, argc > 1 ? atoi(argv[1]) : 0);
1586         return 0;
1587 }
1588
1589 #ifdef SIGINT
1590 static void sigint_handler(int sig) {
1591         (void)sig;
1592
1593         fprintf(stderr, "\n");
1594         shutdown(fd, SHUT_RDWR);
1595 }
1596 #endif
1597
1598 static int cmd_log(int argc, char *argv[]) {
1599         if(argc > 2) {
1600                 fprintf(stderr, "Too many arguments!\n");
1601                 return 1;
1602         }
1603
1604         if(!connect_tincd(true)) {
1605                 return 1;
1606         }
1607
1608 #ifdef SIGINT
1609         signal(SIGINT, sigint_handler);
1610 #endif
1611
1612         logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1);
1613
1614 #ifdef SIGINT
1615         signal(SIGINT, SIG_DFL);
1616 #endif
1617
1618         close(fd);
1619         fd = -1;
1620         return 0;
1621 }
1622
1623 static int cmd_pid(int argc, char *argv[]) {
1624         (void)argv;
1625
1626         if(argc > 1) {
1627                 fprintf(stderr, "Too many arguments!\n");
1628                 return 1;
1629         }
1630
1631         if(!connect_tincd(true) || !pid) {
1632                 return 1;
1633         }
1634
1635         printf("%d\n", pid);
1636         return 0;
1637 }
1638
1639 int rstrip(char *value) {
1640         int len = strlen(value);
1641
1642         while(len && strchr("\t\r\n ", value[len - 1])) {
1643                 value[--len] = 0;
1644         }
1645
1646         return len;
1647 }
1648
1649 char *get_my_name(bool verbose) {
1650         FILE *f = fopen(tinc_conf, "r");
1651
1652         if(!f) {
1653                 if(verbose) {
1654                         fprintf(stderr, "Could not open %s: %s\n", tinc_conf, strerror(errno));
1655                 }
1656
1657                 return NULL;
1658         }
1659
1660         char buf[4096];
1661         char *value;
1662
1663         while(fgets(buf, sizeof(buf), f)) {
1664                 int len = strcspn(buf, "\t =");
1665                 value = buf + len;
1666                 value += strspn(value, "\t ");
1667
1668                 if(*value == '=') {
1669                         value++;
1670                         value += strspn(value, "\t ");
1671                 }
1672
1673                 if(!rstrip(value)) {
1674                         continue;
1675                 }
1676
1677                 buf[len] = 0;
1678
1679                 if(strcasecmp(buf, "Name")) {
1680                         continue;
1681                 }
1682
1683                 if(*value) {
1684                         fclose(f);
1685                         return replace_name(value);
1686                 }
1687         }
1688
1689         fclose(f);
1690
1691         if(verbose) {
1692                 fprintf(stderr, "Could not find Name in %s.\n", tinc_conf);
1693         }
1694
1695         return NULL;
1696 }
1697
1698 ecdsa_t *get_pubkey(FILE *f) {
1699         char buf[4096];
1700         char *value;
1701
1702         while(fgets(buf, sizeof(buf), f)) {
1703                 int len = strcspn(buf, "\t =");
1704                 value = buf + len;
1705                 value += strspn(value, "\t ");
1706
1707                 if(*value == '=') {
1708                         value++;
1709                         value += strspn(value, "\t ");
1710                 }
1711
1712                 if(!rstrip(value)) {
1713                         continue;
1714                 }
1715
1716                 buf[len] = 0;
1717
1718                 if(strcasecmp(buf, "Ed25519PublicKey")) {
1719                         continue;
1720                 }
1721
1722                 if(*value) {
1723                         return ecdsa_set_base64_public_key(value);
1724                 }
1725         }
1726
1727         return NULL;
1728 }
1729
1730 const var_t variables[] = {
1731         /* Server configuration */
1732         {"AddressFamily", VAR_SERVER | VAR_SAFE},
1733         {"AutoConnect", VAR_SERVER | VAR_SAFE},
1734         {"BindToAddress", VAR_SERVER | VAR_MULTIPLE},
1735         {"BindToInterface", VAR_SERVER},
1736         {"Broadcast", VAR_SERVER | VAR_SAFE},
1737         {"BroadcastSubnet", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1738         {"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1739         {"DecrementTTL", VAR_SERVER | VAR_SAFE},
1740         {"Device", VAR_SERVER},
1741         {"DeviceStandby", VAR_SERVER},
1742         {"DeviceType", VAR_SERVER},
1743         {"DirectOnly", VAR_SERVER | VAR_SAFE},
1744         {"Ed25519PrivateKeyFile", VAR_SERVER},
1745         {"ExperimentalProtocol", VAR_SERVER},
1746         {"Forwarding", VAR_SERVER},
1747         {"FWMark", VAR_SERVER},
1748         {"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
1749         {"Hostnames", VAR_SERVER},
1750         {"IffOneQueue", VAR_SERVER},
1751         {"Interface", VAR_SERVER},
1752         {"InvitationExpire", VAR_SERVER},
1753         {"KeyExpire", VAR_SERVER | VAR_SAFE},
1754         {"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
1755         {"LocalDiscovery", VAR_SERVER | VAR_SAFE},
1756         {"LogLevel", VAR_SERVER},
1757         {"MACExpire", VAR_SERVER | VAR_SAFE},
1758         {"MaxConnectionBurst", VAR_SERVER | VAR_SAFE},
1759         {"MaxOutputBufferSize", VAR_SERVER | VAR_SAFE},
1760         {"MaxTimeout", VAR_SERVER | VAR_SAFE},
1761         {"Mode", VAR_SERVER | VAR_SAFE},
1762         {"Name", VAR_SERVER},
1763         {"PingInterval", VAR_SERVER | VAR_SAFE},
1764         {"PingTimeout", VAR_SERVER | VAR_SAFE},
1765         {"PriorityInheritance", VAR_SERVER},
1766         {"PrivateKey", VAR_SERVER | VAR_OBSOLETE},
1767         {"PrivateKeyFile", VAR_SERVER},
1768         {"ProcessPriority", VAR_SERVER},
1769         {"Proxy", VAR_SERVER},
1770         {"ReplayWindow", VAR_SERVER | VAR_SAFE},
1771         {"ScriptsExtension", VAR_SERVER},
1772         {"ScriptsInterpreter", VAR_SERVER},
1773         {"StrictSubnets", VAR_SERVER | VAR_SAFE},
1774         {"TunnelServer", VAR_SERVER | VAR_SAFE},
1775         {"UDPDiscovery", VAR_SERVER | VAR_SAFE},
1776         {"UDPDiscoveryKeepaliveInterval", VAR_SERVER | VAR_SAFE},
1777         {"UDPDiscoveryInterval", VAR_SERVER | VAR_SAFE},
1778         {"UDPDiscoveryTimeout", VAR_SERVER | VAR_SAFE},
1779         {"MTUInfoInterval", VAR_SERVER | VAR_SAFE},
1780         {"UDPInfoInterval", VAR_SERVER | VAR_SAFE},
1781         {"UDPRcvBuf", VAR_SERVER},
1782         {"UDPSndBuf", VAR_SERVER},
1783         {"UPnP", VAR_SERVER},
1784         {"UPnPDiscoverWait", VAR_SERVER},
1785         {"UPnPRefreshPeriod", VAR_SERVER},
1786         {"VDEGroup", VAR_SERVER},
1787         {"VDEPort", VAR_SERVER},
1788         /* Host configuration */
1789         {"Address", VAR_HOST | VAR_MULTIPLE},
1790         {"Cipher", VAR_SERVER | VAR_HOST},
1791         {"ClampMSS", VAR_SERVER | VAR_HOST | VAR_SAFE},
1792         {"Compression", VAR_SERVER | VAR_HOST | VAR_SAFE},
1793         {"Digest", VAR_SERVER | VAR_HOST},
1794         {"Ed25519PublicKey", VAR_HOST},
1795         {"Ed25519PublicKeyFile", VAR_SERVER | VAR_HOST},
1796         {"IndirectData", VAR_SERVER | VAR_HOST | VAR_SAFE},
1797         {"MACLength", VAR_SERVER | VAR_HOST},
1798         {"PMTU", VAR_SERVER | VAR_HOST},
1799         {"PMTUDiscovery", VAR_SERVER | VAR_HOST},
1800         {"Port", VAR_HOST},
1801         {"PublicKey", VAR_HOST | VAR_OBSOLETE},
1802         {"PublicKeyFile", VAR_SERVER | VAR_HOST | VAR_OBSOLETE},
1803         {"Subnet", VAR_HOST | VAR_MULTIPLE | VAR_SAFE},
1804         {"TCPOnly", VAR_SERVER | VAR_HOST | VAR_SAFE},
1805         {"Weight", VAR_HOST | VAR_SAFE},
1806         {NULL, 0}
1807 };
1808
1809 static int cmd_config(int argc, char *argv[]) {
1810         if(argc < 2) {
1811                 fprintf(stderr, "Invalid number of arguments.\n");
1812                 return 1;
1813         }
1814
1815         if(strcasecmp(argv[0], "config")) {
1816                 argv--, argc++;
1817         }
1818
1819         int action = -2;
1820
1821         if(!strcasecmp(argv[1], "get")) {
1822                 argv++, argc--;
1823         } else if(!strcasecmp(argv[1], "add")) {
1824                 argv++, argc--, action = 1;
1825         } else if(!strcasecmp(argv[1], "del")) {
1826                 argv++, argc--, action = -1;
1827         } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) {
1828                 argv++, argc--, action = 0;
1829         }
1830
1831         if(argc < 2) {
1832                 fprintf(stderr, "Invalid number of arguments.\n");
1833                 return 1;
1834         }
1835
1836         // Concatenate the rest of the command line
1837         strncpy(line, argv[1], sizeof(line) - 1);
1838
1839         for(int i = 2; i < argc; i++) {
1840                 strncat(line, " ", sizeof(line) - 1 - strlen(line));
1841                 strncat(line, argv[i], sizeof(line) - 1 - strlen(line));
1842         }
1843
1844         // Liberal parsing into node name, variable name and value.
1845         char *node = NULL;
1846         char *variable;
1847         char *value;
1848         int len;
1849
1850         len = strcspn(line, "\t =");
1851         value = line + len;
1852         value += strspn(value, "\t ");
1853
1854         if(*value == '=') {
1855                 value++;
1856                 value += strspn(value, "\t ");
1857         }
1858
1859         line[len] = '\0';
1860         variable = strchr(line, '.');
1861
1862         if(variable) {
1863                 node = line;
1864                 *variable++ = 0;
1865         } else {
1866                 variable = line;
1867         }
1868
1869         if(!*variable) {
1870                 fprintf(stderr, "No variable given.\n");
1871                 return 1;
1872         }
1873
1874         if(action >= 0 && !*value) {
1875                 fprintf(stderr, "No value for variable given.\n");
1876                 return 1;
1877         }
1878
1879         if(action < -1 && *value) {
1880                 action = 0;
1881         }
1882
1883         /* Some simple checks. */
1884         bool found = false;
1885         bool warnonremove = false;
1886
1887         for(int i = 0; variables[i].name; i++) {
1888                 if(strcasecmp(variables[i].name, variable)) {
1889                         continue;
1890                 }
1891
1892                 found = true;
1893                 variable = (char *)variables[i].name;
1894
1895                 if(!strcasecmp(variable, "Subnet")) {
1896                         subnet_t s = {0};
1897
1898                         if(!str2net(&s, value)) {
1899                                 fprintf(stderr, "Malformed subnet definition %s\n", value);
1900                         }
1901
1902                         if(!subnetcheck(s)) {
1903                                 fprintf(stderr, "Network address and prefix length do not match: %s\n", value);
1904                                 return 1;
1905                         }
1906                 }
1907
1908                 /* Discourage use of obsolete variables. */
1909
1910                 if(variables[i].type & VAR_OBSOLETE && action >= 0) {
1911                         if(force) {
1912                                 fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable);
1913                         } else {
1914                                 fprintf(stderr, "%s is an obsolete variable! Use --force to use it anyway.\n", variable);
1915                                 return 1;
1916                         }
1917                 }
1918
1919                 /* Don't put server variables in host config files */
1920
1921                 if(node && !(variables[i].type & VAR_HOST) && action >= 0) {
1922                         if(force) {
1923                                 fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable);
1924                         } else {
1925                                 fprintf(stderr, "%s is not a host configuration variable! Use --force to use it anyway.\n", variable);
1926                                 return 1;
1927                         }
1928                 }
1929
1930                 /* Should this go into our own host config file? */
1931
1932                 if(!node && !(variables[i].type & VAR_SERVER)) {
1933                         node = get_my_name(true);
1934
1935                         if(!node) {
1936                                 return 1;
1937                         }
1938                 }
1939
1940                 /* Change "add" into "set" for variables that do not allow multiple occurrences.
1941                    Turn on warnings when it seems variables might be removed unintentionally. */
1942
1943                 if(action == 1 && !(variables[i].type & VAR_MULTIPLE)) {
1944                         warnonremove = true;
1945                         action = 0;
1946                 } else if(action == 0 && (variables[i].type & VAR_MULTIPLE)) {
1947                         warnonremove = true;
1948                 }
1949
1950                 break;
1951         }
1952
1953         if(node && !check_id(node)) {
1954                 fprintf(stderr, "Invalid name for node.\n");
1955                 return 1;
1956         }
1957
1958         if(!found) {
1959                 if(force || action < 0) {
1960                         fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable);
1961                 } else {
1962                         fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable);
1963                         return 1;
1964                 }
1965         }
1966
1967         // Open the right configuration file.
1968         char filename[PATH_MAX];
1969
1970         if(node) {
1971                 snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node);
1972         } else {
1973                 snprintf(filename, sizeof(filename), "%s", tinc_conf);
1974         }
1975
1976         FILE *f = fopen(filename, "r");
1977
1978         if(!f) {
1979                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
1980                 return 1;
1981         }
1982
1983         char tmpfile[PATH_MAX];
1984         FILE *tf = NULL;
1985
1986         if(action >= -1) {
1987                 if((size_t)snprintf(tmpfile, sizeof(tmpfile), "%s.config.tmp", filename) >= sizeof(tmpfile)) {
1988                         fprintf(stderr, "Filename too long: %s.config.tmp\n", filename);
1989                         return 1;
1990                 }
1991
1992                 tf = fopen(tmpfile, "w");
1993
1994                 if(!tf) {
1995                         fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
1996                         fclose(f);
1997                         return 1;
1998                 }
1999         }
2000
2001         // Copy the file, making modifications on the fly, unless we are just getting a value.
2002         char buf1[4096];
2003         char buf2[4096];
2004         bool set = false;
2005         bool removed = false;
2006         found = false;
2007
2008         while(fgets(buf1, sizeof(buf1), f)) {
2009                 buf1[sizeof(buf1) - 1] = 0;
2010                 strncpy(buf2, buf1, sizeof(buf2));
2011
2012                 // Parse line in a simple way
2013                 char *bvalue;
2014                 int len;
2015
2016                 len = strcspn(buf2, "\t =");
2017                 bvalue = buf2 + len;
2018                 bvalue += strspn(bvalue, "\t ");
2019
2020                 if(*bvalue == '=') {
2021                         bvalue++;
2022                         bvalue += strspn(bvalue, "\t ");
2023                 }
2024
2025                 rstrip(bvalue);
2026                 buf2[len] = '\0';
2027
2028                 // Did it match?
2029                 if(!strcasecmp(buf2, variable)) {
2030                         // Get
2031                         if(action < -1) {
2032                                 found = true;
2033                                 printf("%s\n", bvalue);
2034                                 // Del
2035                         } else if(action == -1) {
2036                                 if(!*value || !strcasecmp(bvalue, value)) {
2037                                         removed = true;
2038                                         continue;
2039                                 }
2040
2041                                 // Set
2042                         } else if(action == 0) {
2043                                 // Warn if "set" was used for variables that can occur multiple times
2044                                 if(warnonremove && strcasecmp(bvalue, value)) {
2045                                         fprintf(stderr, "Warning: removing %s = %s\n", variable, bvalue);
2046                                 }
2047
2048                                 // Already set? Delete the rest...
2049                                 if(set) {
2050                                         continue;
2051                                 }
2052
2053                                 // Otherwise, replace.
2054                                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
2055                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2056                                         return 1;
2057                                 }
2058
2059                                 set = true;
2060                                 continue;
2061                                 // Add
2062                         } else if(action > 0) {
2063                                 // Check if we've already seen this variable with the same value
2064                                 if(!strcasecmp(bvalue, value)) {
2065                                         found = true;
2066                                 }
2067                         }
2068                 }
2069
2070                 if(action >= -1) {
2071                         // Copy original line...
2072                         if(fputs(buf1, tf) < 0) {
2073                                 fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2074                                 return 1;
2075                         }
2076
2077                         // Add newline if it is missing...
2078                         if(*buf1 && buf1[strlen(buf1) - 1] != '\n') {
2079                                 if(fputc('\n', tf) < 0) {
2080                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2081                                         return 1;
2082                                 }
2083                         }
2084                 }
2085         }
2086
2087         // Make sure we read everything...
2088         if(ferror(f) || !feof(f)) {
2089                 fprintf(stderr, "Error while reading from configuration file %s: %s\n", filename, strerror(errno));
2090                 return 1;
2091         }
2092
2093         if(fclose(f)) {
2094                 fprintf(stderr, "Error closing configuration file %s: %s\n", filename, strerror(errno));
2095                 return 1;
2096         }
2097
2098         // Add new variable if necessary.
2099         if((action > 0 && !found) || (action == 0 && !set)) {
2100                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
2101                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2102                         return 1;
2103                 }
2104         }
2105
2106         if(action < -1) {
2107                 if(found) {
2108                         return 0;
2109                 } else {
2110                         fprintf(stderr, "No matching configuration variables found.\n");
2111                         return 1;
2112                 }
2113         }
2114
2115         // Make sure we wrote everything...
2116         if(fclose(tf)) {
2117                 fprintf(stderr, "Error closing temporary file %s: %s\n", tmpfile, strerror(errno));
2118                 return 1;
2119         }
2120
2121         // Could we find what we had to remove?
2122         if(action < 0 && !removed) {
2123                 remove(tmpfile);
2124                 fprintf(stderr, "No configuration variables deleted.\n");
2125                 return 1;
2126         }
2127
2128         // Replace the configuration file with the new one
2129 #ifdef HAVE_MINGW
2130
2131         if(remove(filename)) {
2132                 fprintf(stderr, "Error replacing file %s: %s\n", filename, strerror(errno));
2133                 return 1;
2134         }
2135
2136 #endif
2137
2138         if(rename(tmpfile, filename)) {
2139                 fprintf(stderr, "Error renaming temporary file %s to configuration file %s: %s\n", tmpfile, filename, strerror(errno));
2140                 return 1;
2141         }
2142
2143         // Silently try notifying a running tincd of changes.
2144         if(connect_tincd(false)) {
2145                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
2146         }
2147
2148         return 0;
2149 }
2150
2151 static bool try_bind(int port) {
2152         struct addrinfo *ai = NULL, *aip;
2153         struct addrinfo hint = {
2154                 .ai_flags = AI_PASSIVE,
2155                 .ai_family = AF_UNSPEC,
2156                 .ai_socktype = SOCK_STREAM,
2157                 .ai_protocol = IPPROTO_TCP,
2158         };
2159
2160         bool success = true;
2161         char portstr[16];
2162         snprintf(portstr, sizeof(portstr), "%d", port);
2163
2164         if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) {
2165                 return false;
2166         }
2167
2168         for(aip = ai; aip; aip = aip->ai_next) {
2169                 int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
2170
2171                 if(!fd) {
2172                         success = false;
2173                         break;
2174                 }
2175
2176                 int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
2177                 closesocket(fd);
2178
2179                 if(result) {
2180                         success = false;
2181                         break;
2182                 }
2183         }
2184
2185         freeaddrinfo(ai);
2186         return success;
2187 }
2188
2189 int check_port(const char *name) {
2190         if(try_bind(655)) {
2191                 return 655;
2192         }
2193
2194         fprintf(stderr, "Warning: could not bind to port 655. ");
2195
2196         for(int i = 0; i < 100; i++) {
2197                 int port = 0x1000 + (rand() & 0x7fff);
2198
2199                 if(try_bind(port)) {
2200                         char filename[PATH_MAX];
2201                         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", confbase, name);
2202                         FILE *f = fopen(filename, "a");
2203
2204                         if(!f) {
2205                                 fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
2206                                 fprintf(stderr, "Please change tinc's Port manually.\n");
2207                                 return 0;
2208                         }
2209
2210                         fprintf(f, "Port = %d\n", port);
2211                         fclose(f);
2212                         fprintf(stderr, "Tinc will instead listen on port %d.\n", port);
2213                         return port;
2214                 }
2215         }
2216
2217         fprintf(stderr, "Please change tinc's Port manually.\n");
2218         return 0;
2219 }
2220
2221 static int cmd_init(int argc, char *argv[]) {
2222         if(!access(tinc_conf, F_OK)) {
2223                 fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
2224                 return 1;
2225         }
2226
2227         if(argc > 2) {
2228                 fprintf(stderr, "Too many arguments!\n");
2229                 return 1;
2230         } else if(argc < 2) {
2231                 if(tty) {
2232                         char buf[1024];
2233                         fprintf(stderr, "Enter the Name you want your tinc node to have: ");
2234
2235                         if(!fgets(buf, sizeof(buf), stdin)) {
2236                                 fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
2237                                 return 1;
2238                         }
2239
2240                         int len = rstrip(buf);
2241
2242                         if(!len) {
2243                                 fprintf(stderr, "No name given!\n");
2244                                 return 1;
2245                         }
2246
2247                         name = strdup(buf);
2248                 } else {
2249                         fprintf(stderr, "No Name given!\n");
2250                         return 1;
2251                 }
2252         } else {
2253                 name = strdup(argv[1]);
2254
2255                 if(!*name) {
2256                         fprintf(stderr, "No Name given!\n");
2257                         return 1;
2258                 }
2259         }
2260
2261         if(!check_id(name)) {
2262                 fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n");
2263                 return 1;
2264         }
2265
2266         if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) {
2267                 fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
2268                 return 1;
2269         }
2270
2271         if(mkdir(confbase, 0777) && errno != EEXIST) {
2272                 fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
2273                 return 1;
2274         }
2275
2276         if(mkdir(hosts_dir, 0777) && errno != EEXIST) {
2277                 fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno));
2278                 return 1;
2279         }
2280
2281         FILE *f = fopen(tinc_conf, "w");
2282
2283         if(!f) {
2284                 fprintf(stderr, "Could not create file %s: %s\n", tinc_conf, strerror(errno));
2285                 return 1;
2286         }
2287
2288         fprintf(f, "Name = %s\n", name);
2289         fclose(f);
2290
2291 #ifndef DISABLE_LEGACY
2292
2293         if(!rsa_keygen(2048, false)) {
2294                 return 1;
2295         }
2296
2297 #endif
2298
2299         if(!ed25519_keygen(false)) {
2300                 return 1;
2301         }
2302
2303         check_port(name);
2304
2305 #ifndef HAVE_MINGW
2306         char filename[PATH_MAX];
2307         snprintf(filename, sizeof(filename), "%s" SLASH "tinc-up", confbase);
2308
2309         if(access(filename, F_OK)) {
2310                 FILE *f = fopenmask(filename, "w", 0777);
2311
2312                 if(!f) {
2313                         fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
2314                         return 1;
2315                 }
2316
2317                 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");
2318                 fclose(f);
2319         }
2320
2321 #endif
2322
2323         return 0;
2324
2325 }
2326
2327 static int cmd_generate_keys(int argc, char *argv[]) {
2328 #ifdef DISABLE_LEGACY
2329         (void)argv;
2330
2331         if(argc > 1) {
2332 #else
2333
2334         if(argc > 2) {
2335 #endif
2336                 fprintf(stderr, "Too many arguments!\n");
2337                 return 1;
2338         }
2339
2340         if(!name) {
2341                 name = get_my_name(false);
2342         }
2343
2344 #ifndef DISABLE_LEGACY
2345
2346         if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true)) {
2347                 return 1;
2348         }
2349
2350 #endif
2351
2352         if(!ed25519_keygen(true)) {
2353                 return 1;
2354         }
2355
2356         return 0;
2357 }
2358
2359 #ifndef DISABLE_LEGACY
2360 static int cmd_generate_rsa_keys(int argc, char *argv[]) {
2361         if(argc > 2) {
2362                 fprintf(stderr, "Too many arguments!\n");
2363                 return 1;
2364         }
2365
2366         if(!name) {
2367                 name = get_my_name(false);
2368         }
2369
2370         return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
2371 }
2372 #endif
2373
2374 static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
2375         (void)argv;
2376
2377         if(argc > 1) {
2378                 fprintf(stderr, "Too many arguments!\n");
2379                 return 1;
2380         }
2381
2382         if(!name) {
2383                 name = get_my_name(false);
2384         }
2385
2386         return !ed25519_keygen(true);
2387 }
2388
2389 static int cmd_help(int argc, char *argv[]) {
2390         (void)argc;
2391         (void)argv;
2392
2393         usage(false);
2394         return 0;
2395 }
2396
2397 static int cmd_version(int argc, char *argv[]) {
2398         (void)argv;
2399
2400         if(argc > 1) {
2401                 fprintf(stderr, "Too many arguments!\n");
2402                 return 1;
2403         }
2404
2405         version();
2406         return 0;
2407 }
2408
2409 static int cmd_info(int argc, char *argv[]) {
2410         if(argc != 2) {
2411                 fprintf(stderr, "Invalid number of arguments.\n");
2412                 return 1;
2413         }
2414
2415         if(!connect_tincd(true)) {
2416                 return 1;
2417         }
2418
2419         return info(fd, argv[1]);
2420 }
2421
2422 static const char *conffiles[] = {
2423         "tinc.conf",
2424         "tinc-up",
2425         "tinc-down",
2426         "subnet-up",
2427         "subnet-down",
2428         "host-up",
2429         "host-down",
2430         NULL,
2431 };
2432
2433 static int cmd_edit(int argc, char *argv[]) {
2434         if(argc != 2) {
2435                 fprintf(stderr, "Invalid number of arguments.\n");
2436                 return 1;
2437         }
2438
2439         char filename[PATH_MAX] = "";
2440
2441         if(strncmp(argv[1], "hosts" SLASH, 6)) {
2442                 for(int i = 0; conffiles[i]; i++) {
2443                         if(!strcmp(argv[1], conffiles[i])) {
2444                                 snprintf(filename, sizeof(filename), "%s" SLASH "%s", confbase, argv[1]);
2445                                 break;
2446                         }
2447                 }
2448         } else {
2449                 argv[1] += 6;
2450         }
2451
2452         if(!*filename) {
2453                 snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, argv[1]);
2454                 char *dash = strchr(argv[1], '-');
2455
2456                 if(dash) {
2457                         *dash++ = 0;
2458
2459                         if((strcmp(dash, "up") && strcmp(dash, "down")) || !check_id(argv[1])) {
2460                                 fprintf(stderr, "Invalid configuration filename.\n");
2461                                 return 1;
2462                         }
2463                 }
2464         }
2465
2466         char *command;
2467 #ifndef HAVE_MINGW
2468         const char *editor = getenv("VISUAL");
2469
2470         if(!editor) {
2471                 editor = getenv("EDITOR");
2472         }
2473
2474         if(!editor) {
2475                 editor = "vi";
2476         }
2477
2478         xasprintf(&command, "\"%s\" \"%s\"", editor, filename);
2479 #else
2480         xasprintf(&command, "edit \"%s\"", filename);
2481 #endif
2482         int result = system(command);
2483         free(command);
2484
2485         if(result) {
2486                 return result;
2487         }
2488
2489         // Silently try notifying a running tincd of changes.
2490         if(connect_tincd(false)) {
2491                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
2492         }
2493
2494         return 0;
2495 }
2496
2497 static int export(const char *name, FILE *out) {
2498         char filename[PATH_MAX];
2499         snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name);
2500         FILE *in = fopen(filename, "r");
2501
2502         if(!in) {
2503                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
2504                 return 1;
2505         }
2506
2507         fprintf(out, "Name = %s\n", name);
2508         char buf[4096];
2509
2510         while(fgets(buf, sizeof(buf), in)) {
2511                 if(strcspn(buf, "\t =") != 4 || strncasecmp(buf, "Name", 4)) {
2512                         fputs(buf, out);
2513                 }
2514         }
2515
2516         if(ferror(in)) {
2517                 fprintf(stderr, "Error while reading configuration file %s: %s\n", filename, strerror(errno));
2518                 fclose(in);
2519                 return 1;
2520         }
2521
2522         fclose(in);
2523         return 0;
2524 }
2525
2526 static int cmd_export(int argc, char *argv[]) {
2527         (void)argv;
2528
2529         if(argc > 1) {
2530                 fprintf(stderr, "Too many arguments!\n");
2531                 return 1;
2532         }
2533
2534         char *name = get_my_name(true);
2535
2536         if(!name) {
2537                 return 1;
2538         }
2539
2540         int result = export(name, stdout);
2541
2542         if(!tty) {
2543                 fclose(stdout);
2544         }
2545
2546         free(name);
2547         return result;
2548 }
2549
2550 static int cmd_export_all(int argc, char *argv[]) {
2551         (void)argv;
2552
2553         if(argc > 1) {
2554                 fprintf(stderr, "Too many arguments!\n");
2555                 return 1;
2556         }
2557
2558         DIR *dir = opendir(hosts_dir);
2559
2560         if(!dir) {
2561                 fprintf(stderr, "Could not open host configuration directory %s: %s\n", hosts_dir, strerror(errno));
2562                 return 1;
2563         }
2564
2565         bool first = true;
2566         int result = 0;
2567         struct dirent *ent;
2568
2569         while((ent = readdir(dir))) {
2570                 if(!check_id(ent->d_name)) {
2571                         continue;
2572                 }
2573
2574                 if(first) {
2575                         first = false;
2576                 } else {
2577                         printf("#---------------------------------------------------------------#\n");
2578                 }
2579
2580                 result |= export(ent->d_name, stdout);
2581         }
2582
2583         closedir(dir);
2584
2585         if(!tty) {
2586                 fclose(stdout);
2587         }
2588
2589         return result;
2590 }
2591
2592 static int cmd_import(int argc, char *argv[]) {
2593         (void)argv;
2594
2595         if(argc > 1) {
2596                 fprintf(stderr, "Too many arguments!\n");
2597                 return 1;
2598         }
2599
2600         FILE *in = stdin;
2601         FILE *out = NULL;
2602
2603         char buf[4096];
2604         char name[4096];
2605         char filename[PATH_MAX] = "";
2606         int count = 0;
2607         bool firstline = true;
2608
2609         while(fgets(buf, sizeof(buf), in)) {
2610                 if(sscanf(buf, "Name = %4095s", name) == 1) {
2611                         firstline = false;
2612
2613                         if(!check_id(name)) {
2614                                 fprintf(stderr, "Invalid Name in input!\n");
2615                                 return 1;
2616                         }
2617
2618                         if(out) {
2619                                 fclose(out);
2620                         }
2621
2622                         if((size_t)snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name) >= sizeof(filename)) {
2623                                 fprintf(stderr, "Filename too long: %s" SLASH "%s\n", hosts_dir, name);
2624                                 return 1;
2625                         }
2626
2627                         if(!force && !access(filename, F_OK)) {
2628                                 fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
2629                                 out = NULL;
2630                                 continue;
2631                         }
2632
2633                         out = fopen(filename, "w");
2634
2635                         if(!out) {
2636                                 fprintf(stderr, "Error creating configuration file %s: %s\n", filename, strerror(errno));
2637                                 return 1;
2638                         }
2639
2640                         count++;
2641                         continue;
2642                 } else if(firstline) {
2643                         fprintf(stderr, "Junk at the beginning of the input, ignoring.\n");
2644                         firstline = false;
2645                 }
2646
2647
2648                 if(!strcmp(buf, "#---------------------------------------------------------------#\n")) {
2649                         continue;
2650                 }
2651
2652                 if(out) {
2653                         if(fputs(buf, out) < 0) {
2654                                 fprintf(stderr, "Error writing to host configuration file %s: %s\n", filename, strerror(errno));
2655                                 return 1;
2656                         }
2657                 }
2658         }
2659
2660         if(out) {
2661                 fclose(out);
2662         }
2663
2664         if(count) {
2665                 fprintf(stderr, "Imported %d host configuration files.\n", count);
2666                 return 0;
2667         } else {
2668                 fprintf(stderr, "No host configuration files imported.\n");
2669                 return 1;
2670         }
2671 }
2672
2673 static int cmd_exchange(int argc, char *argv[]) {
2674         return cmd_export(argc, argv) ? 1 : cmd_import(argc, argv);
2675 }
2676
2677 static int cmd_exchange_all(int argc, char *argv[]) {
2678         return cmd_export_all(argc, argv) ? 1 : cmd_import(argc, argv);
2679 }
2680
2681 static int switch_network(char *name) {
2682         if(strcmp(name, ".")) {
2683                 if(!check_netname(name, false)) {
2684                         fprintf(stderr, "Invalid character in netname!\n");
2685                         return 1;
2686                 }
2687
2688                 if(!check_netname(name, true)) {
2689                         fprintf(stderr, "Warning: unsafe character in netname!\n");
2690                 }
2691         }
2692
2693         if(fd >= 0) {
2694                 close(fd);
2695                 fd = -1;
2696         }
2697
2698         free_names();
2699         netname = strcmp(name, ".") ? xstrdup(name) : NULL;
2700         make_names(false);
2701
2702         free(tinc_conf);
2703         free(hosts_dir);
2704         free(prompt);
2705
2706         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
2707         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
2708         xasprintf(&prompt, "%s> ", identname);
2709
2710         return 0;
2711 }
2712
2713 static int cmd_network(int argc, char *argv[]) {
2714         if(argc > 2) {
2715                 fprintf(stderr, "Too many arguments!\n");
2716                 return 1;
2717         }
2718
2719         if(argc == 2) {
2720                 return switch_network(argv[1]);
2721         }
2722
2723         DIR *dir = opendir(confdir);
2724
2725         if(!dir) {
2726                 fprintf(stderr, "Could not read directory %s: %s\n", confdir, strerror(errno));
2727                 return 1;
2728         }
2729
2730         struct dirent *ent;
2731
2732         while((ent = readdir(dir))) {
2733                 if(*ent->d_name == '.') {
2734                         continue;
2735                 }
2736
2737                 if(!strcmp(ent->d_name, "tinc.conf")) {
2738                         printf(".\n");
2739                         continue;
2740                 }
2741
2742                 char fname[PATH_MAX];
2743                 snprintf(fname, sizeof(fname), "%s/%s/tinc.conf", confdir, ent->d_name);
2744
2745                 if(!access(fname, R_OK)) {
2746                         printf("%s\n", ent->d_name);
2747                 }
2748         }
2749
2750         closedir(dir);
2751
2752         return 0;
2753 }
2754
2755 static int cmd_fsck(int argc, char *argv[]) {
2756         (void)argv;
2757
2758         if(argc > 1) {
2759                 fprintf(stderr, "Too many arguments!\n");
2760                 return 1;
2761         }
2762
2763         return fsck(orig_argv[0]);
2764 }
2765
2766 static void *readfile(FILE *in, size_t *len) {
2767         size_t count = 0;
2768         size_t bufsize = 4096;
2769         char *buf = xmalloc(bufsize);
2770
2771         while(!feof(in)) {
2772                 size_t read = fread(buf + count, 1, bufsize - count, in);
2773
2774                 if(!read) {
2775                         break;
2776                 }
2777
2778                 count += read;
2779
2780                 if(count >= bufsize) {
2781                         bufsize *= 2;
2782                         buf = xrealloc(buf, bufsize);
2783                 }
2784         }
2785
2786         if(len) {
2787                 *len = count;
2788         }
2789
2790         return buf;
2791 }
2792
2793 static int cmd_sign(int argc, char *argv[]) {
2794         if(argc > 2) {
2795                 fprintf(stderr, "Too many arguments!\n");
2796                 return 1;
2797         }
2798
2799         if(!name) {
2800                 name = get_my_name(true);
2801
2802                 if(!name) {
2803                         return 1;
2804                 }
2805         }
2806
2807         char fname[PATH_MAX];
2808         snprintf(fname, sizeof(fname), "%s" SLASH "ed25519_key.priv", confbase);
2809         FILE *fp = fopen(fname, "r");
2810
2811         if(!fp) {
2812                 fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
2813                 return 1;
2814         }
2815
2816         ecdsa_t *key = ecdsa_read_pem_private_key(fp);
2817
2818         if(!key) {
2819                 fprintf(stderr, "Could not read private key from %s\n", fname);
2820                 fclose(fp);
2821                 return 1;
2822         }
2823
2824         fclose(fp);
2825
2826         FILE *in;
2827
2828         if(argc == 2) {
2829                 in = fopen(argv[1], "rb");
2830
2831                 if(!in) {
2832                         fprintf(stderr, "Could not open %s: %s\n", argv[1], strerror(errno));
2833                         ecdsa_free(key);
2834                         return 1;
2835                 }
2836         } else {
2837                 in = stdin;
2838         }
2839
2840         size_t len;
2841         char *data = readfile(in, &len);
2842
2843         if(in != stdin) {
2844                 fclose(in);
2845         }
2846
2847         if(!data) {
2848                 fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
2849                 ecdsa_free(key);
2850                 return 1;
2851         }
2852
2853         // Ensure we sign our name and current time as well
2854         long t = time(NULL);
2855         char *trailer;
2856         xasprintf(&trailer, " %s %ld", name, t);
2857         int trailer_len = strlen(trailer);
2858
2859         data = xrealloc(data, len + trailer_len);
2860         memcpy(data + len, trailer, trailer_len);
2861         free(trailer);
2862
2863         char sig[87];
2864
2865         if(!ecdsa_sign(key, data, len + trailer_len, sig)) {
2866                 fprintf(stderr, "Error generating signature\n");
2867                 free(data);
2868                 ecdsa_free(key);
2869                 return 1;
2870         }
2871
2872         b64encode(sig, sig, 64);
2873         ecdsa_free(key);
2874
2875         fprintf(stdout, "Signature = %s %ld %s\n", name, t, sig);
2876         fwrite(data, len, 1, stdout);
2877
2878         free(data);
2879         return 0;
2880 }
2881
2882 static int cmd_verify(int argc, char *argv[]) {
2883         if(argc < 2) {
2884                 fprintf(stderr, "Not enough arguments!\n");
2885                 return 1;
2886         }
2887
2888         if(argc > 3) {
2889                 fprintf(stderr, "Too many arguments!\n");
2890                 return 1;
2891         }
2892
2893         char *node = argv[1];
2894
2895         if(!strcmp(node, ".")) {
2896                 if(!name) {
2897                         name = get_my_name(true);
2898
2899                         if(!name) {
2900                                 return 1;
2901                         }
2902                 }
2903
2904                 node = name;
2905         } else if(!strcmp(node, "*")) {
2906                 node = NULL;
2907         } else {
2908                 if(!check_id(node)) {
2909                         fprintf(stderr, "Invalid node name\n");
2910                         return 1;
2911                 }
2912         }
2913
2914         FILE *in;
2915
2916         if(argc == 3) {
2917                 in = fopen(argv[2], "rb");
2918
2919                 if(!in) {
2920                         fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
2921                         return 1;
2922                 }
2923         } else {
2924                 in = stdin;
2925         }
2926
2927         size_t len;
2928         char *data = readfile(in, &len);
2929
2930         if(in != stdin) {
2931                 fclose(in);
2932         }
2933
2934         if(!data) {
2935                 fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
2936                 return 1;
2937         }
2938
2939         char *newline = memchr(data, '\n', len);
2940
2941         if(!newline || (newline - data > MAX_STRING_SIZE - 1)) {
2942                 fprintf(stderr, "Invalid input\n");
2943                 free(data);
2944                 return 1;
2945         }
2946
2947         *newline++ = '\0';
2948         size_t skip = newline - data;
2949
2950         char signer[MAX_STRING_SIZE] = "";
2951         char sig[MAX_STRING_SIZE] = "";
2952         long t = 0;
2953
2954         if(sscanf(data, "Signature = %s %ld %s", signer, &t, sig) != 3 || strlen(sig) != 86 || !t || !check_id(signer)) {
2955                 fprintf(stderr, "Invalid input\n");
2956                 free(data);
2957                 return 1;
2958         }
2959
2960         if(node && strcmp(node, signer)) {
2961                 fprintf(stderr, "Signature is not made by %s\n", node);
2962                 free(data);
2963                 return 1;
2964         }
2965
2966         if(!node) {
2967                 node = signer;
2968         }
2969
2970         char *trailer;
2971         xasprintf(&trailer, " %s %ld", signer, t);
2972         int trailer_len = strlen(trailer);
2973
2974         data = xrealloc(data, len + trailer_len);
2975         memcpy(data + len, trailer, trailer_len);
2976         free(trailer);
2977
2978         newline = data + skip;
2979
2980         char fname[PATH_MAX];
2981         snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, node);
2982         FILE *fp = fopen(fname, "r");
2983
2984         if(!fp) {
2985                 fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
2986                 free(data);
2987                 return 1;
2988         }
2989
2990         ecdsa_t *key = get_pubkey(fp);
2991
2992         if(!key) {
2993                 rewind(fp);
2994                 key = ecdsa_read_pem_public_key(fp);
2995         }
2996
2997         if(!key) {
2998                 fprintf(stderr, "Could not read public key from %s\n", fname);
2999                 fclose(fp);
3000                 free(data);
3001                 return 1;
3002         }
3003
3004         fclose(fp);
3005
3006         if(b64decode(sig, sig, 86) != 64 || !ecdsa_verify(key, newline, len + trailer_len - (newline - data), sig)) {
3007                 fprintf(stderr, "Invalid signature\n");
3008                 free(data);
3009                 ecdsa_free(key);
3010                 return 1;
3011         }
3012
3013         ecdsa_free(key);
3014
3015         fwrite(newline, len - (newline - data), 1, stdout);
3016
3017         free(data);
3018         return 0;
3019 }
3020
3021 static const struct {
3022         const char *command;
3023         int (*function)(int argc, char *argv[]);
3024         bool hidden;
3025 } commands[] = {
3026         {"start", cmd_start, false},
3027         {"stop", cmd_stop, false},
3028         {"restart", cmd_restart, false},
3029         {"reload", cmd_reload, false},
3030         {"dump", cmd_dump, false},
3031         {"list", cmd_dump, false},
3032         {"purge", cmd_purge, false},
3033         {"debug", cmd_debug, false},
3034         {"retry", cmd_retry, false},
3035         {"connect", cmd_connect, false},
3036         {"disconnect", cmd_disconnect, false},
3037         {"top", cmd_top, false},
3038         {"pcap", cmd_pcap, false},
3039         {"log", cmd_log, false},
3040         {"pid", cmd_pid, false},
3041         {"config", cmd_config, true},
3042         {"add", cmd_config, false},
3043         {"del", cmd_config, false},
3044         {"get", cmd_config, false},
3045         {"set", cmd_config, false},
3046         {"init", cmd_init, false},
3047         {"generate-keys", cmd_generate_keys, false},
3048 #ifndef DISABLE_LEGACY
3049         {"generate-rsa-keys", cmd_generate_rsa_keys, false},
3050 #endif
3051         {"generate-ed25519-keys", cmd_generate_ed25519_keys, false},
3052         {"help", cmd_help, false},
3053         {"version", cmd_version, false},
3054         {"info", cmd_info, false},
3055         {"edit", cmd_edit, false},
3056         {"export", cmd_export, false},
3057         {"export-all", cmd_export_all, false},
3058         {"import", cmd_import, false},
3059         {"exchange", cmd_exchange, false},
3060         {"exchange-all", cmd_exchange_all, false},
3061         {"invite", cmd_invite, false},
3062         {"join", cmd_join, false},
3063         {"network", cmd_network, false},
3064         {"fsck", cmd_fsck, false},
3065         {"sign", cmd_sign, false},
3066         {"verify", cmd_verify, false},
3067         {NULL, NULL, false},
3068 };
3069
3070 #ifdef HAVE_READLINE
3071 static char *complete_command(const char *text, int state) {
3072         static int i;
3073
3074         if(!state) {
3075                 i = 0;
3076         } else {
3077                 i++;
3078         }
3079
3080         while(commands[i].command) {
3081                 if(!commands[i].hidden && !strncasecmp(commands[i].command, text, strlen(text))) {
3082                         return xstrdup(commands[i].command);
3083                 }
3084
3085                 i++;
3086         }
3087
3088         return NULL;
3089 }
3090
3091 static char *complete_dump(const char *text, int state) {
3092         const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL};
3093         static int i;
3094
3095         if(!state) {
3096                 i = 0;
3097         } else {
3098                 i++;
3099         }
3100
3101         while(matches[i]) {
3102                 if(!strncasecmp(matches[i], text, strlen(text))) {
3103                         return xstrdup(matches[i]);
3104                 }
3105
3106                 i++;
3107         }
3108
3109         return NULL;
3110 }
3111
3112 static char *complete_config(const char *text, int state) {
3113         static int i;
3114
3115         if(!state) {
3116                 i = 0;
3117         } else {
3118                 i++;
3119         }
3120
3121         while(variables[i].name) {
3122                 char *dot = strchr(text, '.');
3123
3124                 if(dot) {
3125                         if((variables[i].type & VAR_HOST) && !strncasecmp(variables[i].name, dot + 1, strlen(dot + 1))) {
3126                                 char *match;
3127                                 xasprintf(&match, "%.*s.%s", (int)(dot - text), text, variables[i].name);
3128                                 return match;
3129                         }
3130                 } else {
3131                         if(!strncasecmp(variables[i].name, text, strlen(text))) {
3132                                 return xstrdup(variables[i].name);
3133                         }
3134                 }
3135
3136                 i++;
3137         }
3138
3139         return NULL;
3140 }
3141
3142 static char *complete_info(const char *text, int state) {
3143         static int i;
3144
3145         if(!state) {
3146                 i = 0;
3147
3148                 if(!connect_tincd(false)) {
3149                         return NULL;
3150                 }
3151
3152                 // Check the list of nodes
3153                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
3154                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
3155         }
3156
3157         while(recvline(fd, line, sizeof(line))) {
3158                 char item[4096];
3159                 int n = sscanf(line, "%d %d %4095s", &code, &req, item);
3160
3161                 if(n == 2) {
3162                         i++;
3163
3164                         if(i >= 2) {
3165                                 break;
3166                         } else {
3167                                 continue;
3168                         }
3169                 }
3170
3171                 if(n != 3) {
3172                         fprintf(stderr, "Unable to parse dump from tincd, n = %d, i = %d.\n", n, i);
3173                         break;
3174                 }
3175
3176                 if(!strncmp(item, text, strlen(text))) {
3177                         return xstrdup(strip_weight(item));
3178                 }
3179         }
3180
3181         return NULL;
3182 }
3183
3184 static char *complete_nothing(const char *text, int state) {
3185         (void)text;
3186         (void)state;
3187         return NULL;
3188 }
3189
3190 static char **completion(const char *text, int start, int end) {
3191         (void)end;
3192         char **matches = NULL;
3193
3194         if(!start) {
3195                 matches = rl_completion_matches(text, complete_command);
3196         } else if(!strncasecmp(rl_line_buffer, "dump ", 5)) {
3197                 matches = rl_completion_matches(text, complete_dump);
3198         } else if(!strncasecmp(rl_line_buffer, "add ", 4)) {
3199                 matches = rl_completion_matches(text, complete_config);
3200         } else if(!strncasecmp(rl_line_buffer, "del ", 4)) {
3201                 matches = rl_completion_matches(text, complete_config);
3202         } else if(!strncasecmp(rl_line_buffer, "get ", 4)) {
3203                 matches = rl_completion_matches(text, complete_config);
3204         } else if(!strncasecmp(rl_line_buffer, "set ", 4)) {
3205                 matches = rl_completion_matches(text, complete_config);
3206         } else if(!strncasecmp(rl_line_buffer, "info ", 5)) {
3207                 matches = rl_completion_matches(text, complete_info);
3208         }
3209
3210         return matches;
3211 }
3212 #endif
3213
3214 static int cmd_shell(int argc, char *argv[]) {
3215         xasprintf(&prompt, "%s> ", identname);
3216         int result = 0;
3217         char buf[4096];
3218         char *line = NULL;
3219         int maxargs = argc + 16;
3220         char **nargv = xmalloc(maxargs * sizeof(*nargv));
3221
3222         for(int i = 0; i < argc; i++) {
3223                 nargv[i] = argv[i];
3224         }
3225
3226 #ifdef HAVE_READLINE
3227         rl_readline_name = "tinc";
3228         rl_completion_entry_function = complete_nothing;
3229         rl_attempted_completion_function = completion;
3230         rl_filename_completion_desired = 0;
3231         char *copy = NULL;
3232 #endif
3233
3234         while(true) {
3235 #ifdef HAVE_READLINE
3236
3237                 if(tty) {
3238                         free(copy);
3239                         free(line);
3240                         rl_basic_word_break_characters = "\t\n ";
3241                         line = readline(prompt);
3242                         copy = line ? xstrdup(line) : NULL;
3243                 } else {
3244                         line = fgets(buf, sizeof(buf), stdin);
3245                 }
3246
3247 #else
3248
3249                 if(tty) {
3250                         fputs(prompt, stdout);
3251                 }
3252
3253                 line = fgets(buf, sizeof(buf), stdin);
3254 #endif
3255
3256                 if(!line) {
3257                         break;
3258                 }
3259
3260                 /* Ignore comments */
3261
3262                 if(*line == '#') {
3263                         continue;
3264                 }
3265
3266                 /* Split */
3267
3268                 int nargc = argc;
3269                 char *p = line + strspn(line, " \t\n");
3270                 char *next = strtok(p, " \t\n");
3271
3272                 while(p && *p) {
3273                         if(nargc >= maxargs) {
3274                                 maxargs *= 2;
3275                                 nargv = xrealloc(nargv, maxargs * sizeof(*nargv));
3276                         }
3277
3278                         nargv[nargc++] = p;
3279                         p = next;
3280                         next = strtok(NULL, " \t\n");
3281                 }
3282
3283                 if(nargc == argc) {
3284                         continue;
3285                 }
3286
3287                 if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit")) {
3288 #ifdef HAVE_READLINE
3289                         free(copy);
3290 #endif
3291                         free(nargv);
3292                         return result;
3293                 }
3294
3295                 bool found = false;
3296
3297                 for(int i = 0; commands[i].command; i++) {
3298                         if(!strcasecmp(nargv[argc], commands[i].command)) {
3299                                 result |= commands[i].function(nargc - argc - 1, nargv + argc + 1);
3300                                 found = true;
3301                                 break;
3302                         }
3303                 }
3304
3305 #ifdef HAVE_READLINE
3306
3307                 if(tty && found) {
3308                         add_history(copy);
3309                 }
3310
3311 #endif
3312
3313                 if(!found) {
3314                         fprintf(stderr, "Unknown command `%s'.\n", nargv[argc]);
3315                         result |= 1;
3316                 }
3317         }
3318
3319 #ifdef HAVE_READLINE
3320         free(copy);
3321 #endif
3322         free(nargv);
3323
3324         if(tty) {
3325                 printf("\n");
3326         }
3327
3328         return result;
3329 }
3330
3331
3332 int main(int argc, char *argv[]) {
3333         program_name = argv[0];
3334         orig_argv = argv;
3335         orig_argc = argc;
3336         tty = isatty(0) && isatty(1);
3337
3338         if(!parse_options(argc, argv)) {
3339                 return 1;
3340         }
3341
3342         make_names(false);
3343         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
3344         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
3345
3346         if(show_version) {
3347                 version();
3348                 return 0;
3349         }
3350
3351         if(show_help) {
3352                 usage(false);
3353                 return 0;
3354         }
3355
3356 #ifdef HAVE_MINGW
3357         static struct WSAData wsa_state;
3358
3359         if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
3360                 fprintf(stderr, "System call `%s' failed: %s\n", "WSAStartup", winerror(GetLastError()));
3361                 return false;
3362         }
3363
3364 #endif
3365
3366         srand(time(NULL));
3367         crypto_init();
3368
3369         if(optind >= argc) {
3370                 return cmd_shell(argc, argv);
3371         }
3372
3373         for(int i = 0; commands[i].command; i++) {
3374                 if(!strcasecmp(argv[optind], commands[i].command)) {
3375                         return commands[i].function(argc - optind, argv + optind);
3376                 }
3377         }
3378
3379         fprintf(stderr, "Unknown command `%s'.\n", argv[optind]);
3380         usage(true);
3381         return 1;
3382 }