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