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