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