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