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