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