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