Improve use of compiler attributes
[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 static ecdsa_t *get_pubkey(FILE *f) ATTR_MALLOC ATTR_DEALLOCATOR(ecdsa_free);
1627 static ecdsa_t *get_pubkey(FILE *f) {
1628         char buf[4096];
1629         char *value;
1630
1631         while(fgets(buf, sizeof(buf), f)) {
1632                 size_t len = strcspn(buf, "\t =");
1633                 value = buf + len;
1634                 value += strspn(value, "\t ");
1635
1636                 if(*value == '=') {
1637                         value++;
1638                         value += strspn(value, "\t ");
1639                 }
1640
1641                 if(!rstrip(value)) {
1642                         continue;
1643                 }
1644
1645                 buf[len] = 0;
1646
1647                 if(strcasecmp(buf, "Ed25519PublicKey")) {
1648                         continue;
1649                 }
1650
1651                 if(*value) {
1652                         return ecdsa_set_base64_public_key(value);
1653                 }
1654         }
1655
1656         return NULL;
1657 }
1658
1659 const var_t variables[] = {
1660         /* Server configuration */
1661         {"AddressFamily", VAR_SERVER | VAR_SAFE},
1662         {"AutoConnect", VAR_SERVER | VAR_SAFE},
1663         {"BindToAddress", VAR_SERVER | VAR_MULTIPLE},
1664         {"BindToInterface", VAR_SERVER},
1665         {"Broadcast", VAR_SERVER | VAR_SAFE},
1666         {"BroadcastSubnet", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1667         {"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1668         {"DecrementTTL", VAR_SERVER | VAR_SAFE},
1669         {"Device", VAR_SERVER},
1670         {"DeviceStandby", VAR_SERVER},
1671         {"DeviceType", VAR_SERVER},
1672         {"DirectOnly", VAR_SERVER | VAR_SAFE},
1673         {"Ed25519PrivateKeyFile", VAR_SERVER},
1674         {"ExperimentalProtocol", VAR_SERVER},
1675         {"Forwarding", VAR_SERVER},
1676         {"FWMark", VAR_SERVER},
1677         {"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
1678         {"Hostnames", VAR_SERVER},
1679         {"IffOneQueue", VAR_SERVER},
1680         {"Interface", VAR_SERVER},
1681         {"InvitationExpire", VAR_SERVER},
1682         {"KeyExpire", VAR_SERVER | VAR_SAFE},
1683         {"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
1684         {"LocalDiscovery", VAR_SERVER | VAR_SAFE},
1685         {"LogLevel", VAR_SERVER},
1686         {"MACExpire", VAR_SERVER | VAR_SAFE},
1687         {"MaxConnectionBurst", VAR_SERVER | VAR_SAFE},
1688         {"MaxOutputBufferSize", VAR_SERVER | VAR_SAFE},
1689         {"MaxTimeout", VAR_SERVER | VAR_SAFE},
1690         {"Mode", VAR_SERVER | VAR_SAFE},
1691         {"Name", VAR_SERVER},
1692         {"PingInterval", VAR_SERVER | VAR_SAFE},
1693         {"PingTimeout", VAR_SERVER | VAR_SAFE},
1694         {"PriorityInheritance", VAR_SERVER},
1695         {"PrivateKey", VAR_SERVER | VAR_OBSOLETE},
1696         {"PrivateKeyFile", VAR_SERVER},
1697         {"ProcessPriority", VAR_SERVER},
1698         {"Proxy", VAR_SERVER},
1699         {"ReplayWindow", VAR_SERVER | VAR_SAFE},
1700         {"ScriptsExtension", VAR_SERVER},
1701         {"ScriptsInterpreter", VAR_SERVER},
1702         {"StrictSubnets", VAR_SERVER | VAR_SAFE},
1703         {"TunnelServer", VAR_SERVER | VAR_SAFE},
1704         {"UDPDiscovery", VAR_SERVER | VAR_SAFE},
1705         {"UDPDiscoveryKeepaliveInterval", VAR_SERVER | VAR_SAFE},
1706         {"UDPDiscoveryInterval", VAR_SERVER | VAR_SAFE},
1707         {"UDPDiscoveryTimeout", VAR_SERVER | VAR_SAFE},
1708         {"MTUInfoInterval", VAR_SERVER | VAR_SAFE},
1709         {"UDPInfoInterval", VAR_SERVER | VAR_SAFE},
1710         {"UDPRcvBuf", VAR_SERVER},
1711         {"UDPSndBuf", VAR_SERVER},
1712         {"UPnP", VAR_SERVER},
1713         {"UPnPDiscoverWait", VAR_SERVER},
1714         {"UPnPRefreshPeriod", VAR_SERVER},
1715         {"VDEGroup", VAR_SERVER},
1716         {"VDEPort", VAR_SERVER},
1717         /* Host configuration */
1718         {"Address", VAR_HOST | VAR_MULTIPLE},
1719         {"Cipher", VAR_SERVER | VAR_HOST},
1720         {"ClampMSS", VAR_SERVER | VAR_HOST | VAR_SAFE},
1721         {"Compression", VAR_SERVER | VAR_HOST | VAR_SAFE},
1722         {"Digest", VAR_SERVER | VAR_HOST},
1723         {"Ed25519PublicKey", VAR_HOST},
1724         {"Ed25519PublicKeyFile", VAR_SERVER | VAR_HOST},
1725         {"IndirectData", VAR_SERVER | VAR_HOST | VAR_SAFE},
1726         {"MACLength", VAR_SERVER | VAR_HOST},
1727         {"PMTU", VAR_SERVER | VAR_HOST},
1728         {"PMTUDiscovery", VAR_SERVER | VAR_HOST},
1729         {"Port", VAR_HOST},
1730         {"PublicKey", VAR_HOST | VAR_OBSOLETE},
1731         {"PublicKeyFile", VAR_SERVER | VAR_HOST | VAR_OBSOLETE},
1732         {"Subnet", VAR_HOST | VAR_MULTIPLE | VAR_SAFE},
1733         {"TCPOnly", VAR_SERVER | VAR_HOST | VAR_SAFE},
1734         {"Weight", VAR_HOST | VAR_SAFE},
1735         {NULL, 0}
1736 };
1737
1738 // Request actual port from tincd
1739 static bool read_actual_port(void) {
1740         pidfile_t *pidfile = read_pidfile();
1741
1742         if(pidfile) {
1743                 printf("%s\n", pidfile->port);
1744                 free(pidfile);
1745                 return true;
1746         } else {
1747                 fprintf(stderr, "Could not get port from the pidfile.\n");
1748                 return false;
1749         }
1750 }
1751
1752 static int cmd_config(int argc, char *argv[]) {
1753         if(argc < 2) {
1754                 fprintf(stderr, "Invalid number of arguments.\n");
1755                 return 1;
1756         }
1757
1758         if(strcasecmp(argv[0], "config")) {
1759                 argv--, argc++;
1760         }
1761
1762         typedef enum { GET, DEL, SET, ADD } action_t;
1763         action_t action = GET;
1764
1765         if(!strcasecmp(argv[1], "get")) {
1766                 argv++, argc--;
1767         } else if(!strcasecmp(argv[1], "add")) {
1768                 argv++, argc--, action = ADD;
1769         } else if(!strcasecmp(argv[1], "del")) {
1770                 argv++, argc--, action = DEL;
1771         } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) {
1772                 argv++, argc--, action = SET;
1773         }
1774
1775         if(argc < 2) {
1776                 fprintf(stderr, "Invalid number of arguments.\n");
1777                 return 1;
1778         }
1779
1780         // Concatenate the rest of the command line
1781         strncpy(line, argv[1], sizeof(line) - 1);
1782
1783         for(int i = 2; i < argc; i++) {
1784                 strncat(line, " ", sizeof(line) - 1 - strlen(line));
1785                 strncat(line, argv[i], sizeof(line) - 1 - strlen(line));
1786         }
1787
1788         // Liberal parsing into node name, variable name and value.
1789         char *node = NULL;
1790         char *variable;
1791         char *value;
1792         size_t len;
1793
1794         len = strcspn(line, "\t =");
1795         value = line + len;
1796         value += strspn(value, "\t ");
1797
1798         if(*value == '=') {
1799                 value++;
1800                 value += strspn(value, "\t ");
1801         }
1802
1803         line[len] = '\0';
1804         variable = strchr(line, '.');
1805
1806         if(variable) {
1807                 node = line;
1808                 *variable++ = 0;
1809         } else {
1810                 variable = line;
1811         }
1812
1813         if(!*variable) {
1814                 fprintf(stderr, "No variable given.\n");
1815                 return 1;
1816         }
1817
1818         if((action == SET || action == ADD) && !*value) {
1819                 fprintf(stderr, "No value for variable given.\n");
1820                 return 1;
1821         }
1822
1823         if(action == GET && *value) {
1824                 action = SET;
1825         }
1826
1827         // If port is requested, try reading it from the pidfile and fall back to configs if that fails
1828         if(action == GET && !strcasecmp(variable, "Port") && read_actual_port()) {
1829                 return 0;
1830         }
1831
1832         /* Some simple checks. */
1833         bool found = false;
1834         bool warnonremove = false;
1835
1836         for(int i = 0; variables[i].name; i++) {
1837                 if(strcasecmp(variables[i].name, variable)) {
1838                         continue;
1839                 }
1840
1841                 found = true;
1842                 variable = (char *)variables[i].name;
1843
1844                 if(!strcasecmp(variable, "Subnet") && *value) {
1845                         subnet_t s = {0};
1846
1847                         if(!str2net(&s, value)) {
1848                                 fprintf(stderr, "Malformed subnet definition %s\n", value);
1849                                 return 1;
1850                         }
1851
1852                         if(!subnetcheck(s)) {
1853                                 fprintf(stderr, "Network address and prefix length do not match: %s\n", value);
1854                                 return 1;
1855                         }
1856                 }
1857
1858                 /* Discourage use of obsolete variables. */
1859
1860                 if(variables[i].type & VAR_OBSOLETE && (action == SET || action == ADD)) {
1861                         if(force) {
1862                                 fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable);
1863                         } else {
1864                                 fprintf(stderr, "%s is an obsolete variable! Use --force to use it anyway.\n", variable);
1865                                 return 1;
1866                         }
1867                 }
1868
1869                 /* Don't put server variables in host config files */
1870
1871                 if(node && !(variables[i].type & VAR_HOST) && (action == SET || action == ADD)) {
1872                         if(force) {
1873                                 fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable);
1874                         } else {
1875                                 fprintf(stderr, "%s is not a host configuration variable! Use --force to use it anyway.\n", variable);
1876                                 return 1;
1877                         }
1878                 }
1879
1880                 /* Should this go into our own host config file? */
1881
1882                 if(!node && !(variables[i].type & VAR_SERVER)) {
1883                         node = get_my_name(true);
1884
1885                         if(!node) {
1886                                 return 1;
1887                         }
1888                 }
1889
1890                 /* Change "add" into "set" for variables that do not allow multiple occurrences.
1891                    Turn on warnings when it seems variables might be removed unintentionally. */
1892
1893                 if(action == ADD && !(variables[i].type & VAR_MULTIPLE)) {
1894                         warnonremove = true;
1895                         action = SET;
1896                 } else if(action == SET && (variables[i].type & VAR_MULTIPLE)) {
1897                         warnonremove = true;
1898                 }
1899
1900                 break;
1901         }
1902
1903         if(node && !check_id(node)) {
1904                 fprintf(stderr, "Invalid name for node.\n");
1905
1906                 if(node != line) {
1907                         free(node);
1908                 }
1909
1910                 return 1;
1911         }
1912
1913         if(!found) {
1914                 if(force || action == GET || action == DEL) {
1915                         fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable);
1916                 } else {
1917                         fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable);
1918
1919                         if(node && node != line) {
1920                                 free(node);
1921                         }
1922
1923                         return 1;
1924                 }
1925         }
1926
1927         // Open the right configuration file.
1928         char filename[PATH_MAX];
1929
1930         if(node) {
1931                 if((size_t)snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node) >= sizeof(filename)) {
1932                         fprintf(stderr, "Filename too long: %s" SLASH "%s\n", hosts_dir, node);
1933                         free(node);
1934                         return 1;
1935                 }
1936
1937                 if(node != line) {
1938                         free(node);
1939                         node = NULL;
1940                 }
1941         } else {
1942                 snprintf(filename, sizeof(filename), "%s", tinc_conf);
1943         }
1944
1945         FILE *f = fopen(filename, "r");
1946
1947         if(!f) {
1948                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
1949                 return 1;
1950         }
1951
1952         char tmpfile[PATH_MAX];
1953         FILE *tf = NULL;
1954
1955         if(action != GET) {
1956                 if((size_t)snprintf(tmpfile, sizeof(tmpfile), "%s.config.tmp", filename) >= sizeof(tmpfile)) {
1957                         fprintf(stderr, "Filename too long: %s.config.tmp\n", filename);
1958                         return 1;
1959                 }
1960
1961                 tf = fopen(tmpfile, "w");
1962
1963                 if(!tf) {
1964                         fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
1965                         fclose(f);
1966                         return 1;
1967                 }
1968         }
1969
1970         // Copy the file, making modifications on the fly, unless we are just getting a value.
1971         char buf1[4096];
1972         char buf2[4096];
1973         bool set = false;
1974         bool removed = false;
1975         found = false;
1976
1977         while(fgets(buf1, sizeof(buf1), f)) {
1978                 buf1[sizeof(buf1) - 1] = 0;
1979                 strncpy(buf2, buf1, sizeof(buf2));
1980
1981                 // Parse line in a simple way
1982                 char *bvalue;
1983
1984                 size_t len = strcspn(buf2, "\t =");
1985                 bvalue = buf2 + len;
1986                 bvalue += strspn(bvalue, "\t ");
1987
1988                 if(*bvalue == '=') {
1989                         bvalue++;
1990                         bvalue += strspn(bvalue, "\t ");
1991                 }
1992
1993                 rstrip(bvalue);
1994                 buf2[len] = '\0';
1995
1996                 // Did it match?
1997                 if(!strcasecmp(buf2, variable)) {
1998                         if(action == GET) {
1999                                 found = true;
2000                                 printf("%s\n", bvalue);
2001                         } else if(action == DEL) {
2002                                 if(!*value || !strcasecmp(bvalue, value)) {
2003                                         removed = true;
2004                                         continue;
2005                                 }
2006                         } else if(action == SET) {
2007                                 // Warn if "set" was used for variables that can occur multiple times
2008                                 if(warnonremove && strcasecmp(bvalue, value)) {
2009                                         fprintf(stderr, "Warning: removing %s = %s\n", variable, bvalue);
2010                                 }
2011
2012                                 // Already set? Delete the rest...
2013                                 if(set) {
2014                                         continue;
2015                                 }
2016
2017                                 // Otherwise, replace.
2018                                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
2019                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2020                                         return 1;
2021                                 }
2022
2023                                 set = true;
2024                                 continue;
2025                         } else if(action == ADD) {
2026                                 // Check if we've already seen this variable with the same value
2027                                 if(!strcasecmp(bvalue, value)) {
2028                                         found = true;
2029                                 }
2030                         }
2031                 }
2032
2033                 if(action != GET) {
2034                         // Copy original line...
2035                         if(fputs(buf1, tf) < 0) {
2036                                 fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2037                                 return 1;
2038                         }
2039
2040                         // Add newline if it is missing...
2041                         if(*buf1 && buf1[strlen(buf1) - 1] != '\n') {
2042                                 if(fputc('\n', tf) < 0) {
2043                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2044                                         return 1;
2045                                 }
2046                         }
2047                 }
2048         }
2049
2050         // Make sure we read everything...
2051         if(ferror(f) || !feof(f)) {
2052                 fprintf(stderr, "Error while reading from configuration file %s: %s\n", filename, strerror(errno));
2053                 return 1;
2054         }
2055
2056         if(fclose(f)) {
2057                 fprintf(stderr, "Error closing configuration file %s: %s\n", filename, strerror(errno));
2058                 return 1;
2059         }
2060
2061         // Add new variable if necessary.
2062         if((action == ADD && !found) || (action == SET && !set)) {
2063                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
2064                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2065                         return 1;
2066                 }
2067         }
2068
2069         if(action == GET) {
2070                 if(found) {
2071                         return 0;
2072                 } else {
2073                         fprintf(stderr, "No matching configuration variables found.\n");
2074                         return 1;
2075                 }
2076         }
2077
2078         // Make sure we wrote everything...
2079         if(fclose(tf)) {
2080                 fprintf(stderr, "Error closing temporary file %s: %s\n", tmpfile, strerror(errno));
2081                 return 1;
2082         }
2083
2084         // Could we find what we had to remove?
2085         if((action == GET || action == DEL) && !removed) {
2086                 remove(tmpfile);
2087                 fprintf(stderr, "No configuration variables deleted.\n");
2088                 return 1;
2089         }
2090
2091         // Replace the configuration file with the new one
2092 #ifdef HAVE_WINDOWS
2093
2094         if(remove(filename)) {
2095                 fprintf(stderr, "Error replacing file %s: %s\n", filename, strerror(errno));
2096                 return 1;
2097         }
2098
2099 #endif
2100
2101         if(rename(tmpfile, filename)) {
2102                 fprintf(stderr, "Error renaming temporary file %s to configuration file %s: %s\n", tmpfile, filename, strerror(errno));
2103                 return 1;
2104         }
2105
2106         // Silently try notifying a running tincd of changes.
2107         if(connect_tincd(false)) {
2108                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
2109         }
2110
2111         return 0;
2112 }
2113
2114 static bool try_bind(int port) {
2115         struct addrinfo *ai = NULL, *aip;
2116         struct addrinfo hint = {
2117                 .ai_flags = AI_PASSIVE,
2118                 .ai_family = AF_UNSPEC,
2119                 .ai_socktype = SOCK_STREAM,
2120                 .ai_protocol = IPPROTO_TCP,
2121         };
2122
2123         bool success = true;
2124         char portstr[16];
2125         snprintf(portstr, sizeof(portstr), "%d", port);
2126
2127         if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) {
2128                 return false;
2129         }
2130
2131         for(aip = ai; aip; aip = aip->ai_next) {
2132                 int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
2133
2134                 if(!fd) {
2135                         success = false;
2136                         break;
2137                 }
2138
2139                 int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
2140                 closesocket(fd);
2141
2142                 if(result) {
2143                         success = false;
2144                         break;
2145                 }
2146         }
2147
2148         freeaddrinfo(ai);
2149         return success;
2150 }
2151
2152 int check_port(const char *name) {
2153         if(try_bind(655)) {
2154                 return 655;
2155         }
2156
2157         fprintf(stderr, "Warning: could not bind to port 655. ");
2158
2159         for(int i = 0; i < 100; i++) {
2160                 uint16_t port = 0x1000 + prng(0x8000);
2161
2162                 if(try_bind(port)) {
2163                         char filename[PATH_MAX];
2164                         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", confbase, name);
2165                         FILE *f = fopen(filename, "a");
2166
2167                         if(!f) {
2168                                 fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
2169                                 fprintf(stderr, "Please change tinc's Port manually.\n");
2170                                 return 0;
2171                         }
2172
2173                         fprintf(f, "Port = %d\n", port);
2174                         fclose(f);
2175                         fprintf(stderr, "Tinc will instead listen on port %d.\n", port);
2176                         return port;
2177                 }
2178         }
2179
2180         fprintf(stderr, "Please change tinc's Port manually.\n");
2181         return 0;
2182 }
2183
2184 static int cmd_init(int argc, char *argv[]) {
2185         if(!access(tinc_conf, F_OK)) {
2186                 fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
2187                 return 1;
2188         }
2189
2190         if(argc > 2) {
2191                 fprintf(stderr, "Too many arguments!\n");
2192                 return 1;
2193         } else if(argc < 2) {
2194                 if(tty) {
2195                         char buf[1024];
2196                         fprintf(stderr, "Enter the Name you want your tinc node to have: ");
2197
2198                         if(!fgets(buf, sizeof(buf), stdin)) {
2199                                 fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
2200                                 return 1;
2201                         }
2202
2203                         size_t len = rstrip(buf);
2204
2205                         if(!len) {
2206                                 fprintf(stderr, "No name given!\n");
2207                                 return 1;
2208                         }
2209
2210                         name = strdup(buf);
2211                 } else {
2212                         fprintf(stderr, "No Name given!\n");
2213                         return 1;
2214                 }
2215         } else {
2216                 name = strdup(argv[1]);
2217
2218                 if(!*name) {
2219                         fprintf(stderr, "No Name given!\n");
2220                         return 1;
2221                 }
2222         }
2223
2224         if(!check_id(name)) {
2225                 fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n");
2226                 return 1;
2227         }
2228
2229         if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) {
2230                 fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
2231                 return 1;
2232         }
2233
2234         if(mkdir(confbase, 0777) && errno != EEXIST) {
2235                 fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
2236                 return 1;
2237         }
2238
2239         if(mkdir(hosts_dir, 0777) && errno != EEXIST) {
2240                 fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno));
2241                 return 1;
2242         }
2243
2244         FILE *f = fopen(tinc_conf, "w");
2245
2246         if(!f) {
2247                 fprintf(stderr, "Could not create file %s: %s\n", tinc_conf, strerror(errno));
2248                 return 1;
2249         }
2250
2251         fprintf(f, "Name = %s\n", name);
2252         fclose(f);
2253
2254 #ifndef DISABLE_LEGACY
2255
2256         if(!rsa_keygen(2048, false)) {
2257                 return 1;
2258         }
2259
2260 #endif
2261
2262         if(!ed25519_keygen(false)) {
2263                 return 1;
2264         }
2265
2266         check_port(name);
2267
2268 #ifndef HAVE_WINDOWS
2269         char filename[PATH_MAX];
2270         snprintf(filename, sizeof(filename), "%s" SLASH "tinc-up", confbase);
2271
2272         if(access(filename, F_OK)) {
2273                 FILE *f = fopenmask(filename, "w", 0777);
2274
2275                 if(!f) {
2276                         fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
2277                         return 1;
2278                 }
2279
2280                 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");
2281                 fclose(f);
2282         }
2283
2284 #endif
2285
2286         return 0;
2287
2288 }
2289
2290 static int cmd_generate_keys(int argc, char *argv[]) {
2291 #ifdef DISABLE_LEGACY
2292         (void)argv;
2293
2294         if(argc > 1) {
2295 #else
2296
2297         if(argc > 2) {
2298 #endif
2299                 fprintf(stderr, "Too many arguments!\n");
2300                 return 1;
2301         }
2302
2303         if(!name) {
2304                 name = get_my_name(false);
2305         }
2306
2307 #ifndef DISABLE_LEGACY
2308
2309         if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true)) {
2310                 return 1;
2311         }
2312
2313 #endif
2314
2315         if(!ed25519_keygen(true)) {
2316                 return 1;
2317         }
2318
2319         return 0;
2320 }
2321
2322 #ifndef DISABLE_LEGACY
2323 static int cmd_generate_rsa_keys(int argc, char *argv[]) {
2324         if(argc > 2) {
2325                 fprintf(stderr, "Too many arguments!\n");
2326                 return 1;
2327         }
2328
2329         if(!name) {
2330                 name = get_my_name(false);
2331         }
2332
2333         return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
2334 }
2335 #endif
2336
2337 static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
2338         (void)argv;
2339
2340         if(argc > 1) {
2341                 fprintf(stderr, "Too many arguments!\n");
2342                 return 1;
2343         }
2344
2345         if(!name) {
2346                 name = get_my_name(false);
2347         }
2348
2349         return !ed25519_keygen(true);
2350 }
2351
2352 static int cmd_help(int argc, char *argv[]) {
2353         (void)argc;
2354         (void)argv;
2355
2356         usage(false);
2357         return 0;
2358 }
2359
2360 static int cmd_version(int argc, char *argv[]) {
2361         (void)argv;
2362
2363         if(argc > 1) {
2364                 fprintf(stderr, "Too many arguments!\n");
2365                 return 1;
2366         }
2367
2368         version();
2369         return 0;
2370 }
2371
2372 static int cmd_info(int argc, char *argv[]) {
2373         if(argc != 2) {
2374                 fprintf(stderr, "Invalid number of arguments.\n");
2375                 return 1;
2376         }
2377
2378         if(!connect_tincd(true)) {
2379                 return 1;
2380         }
2381
2382         return info(fd, argv[1]);
2383 }
2384
2385 static const char *conffiles[] = {
2386         "tinc.conf",
2387         "tinc-up",
2388         "tinc-down",
2389         "subnet-up",
2390         "subnet-down",
2391         "host-up",
2392         "host-down",
2393         NULL,
2394 };
2395
2396 static int cmd_edit(int argc, char *argv[]) {
2397         if(argc != 2) {
2398                 fprintf(stderr, "Invalid number of arguments.\n");
2399                 return 1;
2400         }
2401
2402         char filename[PATH_MAX] = "";
2403
2404         if(strncmp(argv[1], "hosts" SLASH, 6)) {
2405                 for(int i = 0; conffiles[i]; i++) {
2406                         if(!strcmp(argv[1], conffiles[i])) {
2407                                 snprintf(filename, sizeof(filename), "%s" SLASH "%s", confbase, argv[1]);
2408                                 break;
2409                         }
2410                 }
2411         } else {
2412                 argv[1] += 6;
2413         }
2414
2415         if(!*filename) {
2416                 snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, argv[1]);
2417                 char *dash = strchr(argv[1], '-');
2418
2419                 if(dash) {
2420                         *dash++ = 0;
2421
2422                         if((strcmp(dash, "up") && strcmp(dash, "down")) || !check_id(argv[1])) {
2423                                 fprintf(stderr, "Invalid configuration filename.\n");
2424                                 return 1;
2425                         }
2426                 }
2427         }
2428
2429         char *command;
2430 #ifndef HAVE_WINDOWS
2431         const char *editor = getenv("VISUAL");
2432
2433         if(!editor) {
2434                 editor = getenv("EDITOR");
2435         }
2436
2437         if(!editor) {
2438                 editor = "vi";
2439         }
2440
2441         xasprintf(&command, "\"%s\" \"%s\"", editor, filename);
2442 #else
2443         xasprintf(&command, "edit \"%s\"", filename);
2444 #endif
2445         int result = system(command);
2446         free(command);
2447
2448         if(result) {
2449                 return result;
2450         }
2451
2452         // Silently try notifying a running tincd of changes.
2453         if(connect_tincd(false)) {
2454                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
2455         }
2456
2457         return 0;
2458 }
2459
2460 static int export(const char *name, FILE *out) {
2461         char filename[PATH_MAX];
2462         snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name);
2463         FILE *in = fopen(filename, "r");
2464
2465         if(!in) {
2466                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
2467                 return 1;
2468         }
2469
2470         fprintf(out, "Name = %s\n", name);
2471         char buf[4096];
2472
2473         while(fgets(buf, sizeof(buf), in)) {
2474                 if(strcspn(buf, "\t =") != 4 || strncasecmp(buf, "Name", 4)) {
2475                         fputs(buf, out);
2476                 }
2477         }
2478
2479         if(ferror(in)) {
2480                 fprintf(stderr, "Error while reading configuration file %s: %s\n", filename, strerror(errno));
2481                 fclose(in);
2482                 return 1;
2483         }
2484
2485         fclose(in);
2486         return 0;
2487 }
2488
2489 static int cmd_export(int argc, char *argv[]) {
2490         (void)argv;
2491
2492         if(argc > 1) {
2493                 fprintf(stderr, "Too many arguments!\n");
2494                 return 1;
2495         }
2496
2497         char *name = get_my_name(true);
2498
2499         if(!name) {
2500                 return 1;
2501         }
2502
2503         int result = export(name, stdout);
2504
2505         if(!tty) {
2506                 fclose(stdout);
2507         }
2508
2509         free(name);
2510         return result;
2511 }
2512
2513 static int cmd_export_all(int argc, char *argv[]) {
2514         (void)argv;
2515
2516         if(argc > 1) {
2517                 fprintf(stderr, "Too many arguments!\n");
2518                 return 1;
2519         }
2520
2521         DIR *dir = opendir(hosts_dir);
2522
2523         if(!dir) {
2524                 fprintf(stderr, "Could not open host configuration directory %s: %s\n", hosts_dir, strerror(errno));
2525                 return 1;
2526         }
2527
2528         bool first = true;
2529         int result = 0;
2530         struct dirent *ent;
2531
2532         while((ent = readdir(dir))) {
2533                 if(!check_id(ent->d_name)) {
2534                         continue;
2535                 }
2536
2537                 if(first) {
2538                         first = false;
2539                 } else {
2540                         printf("#---------------------------------------------------------------#\n");
2541                 }
2542
2543                 result |= export(ent->d_name, stdout);
2544         }
2545
2546         closedir(dir);
2547
2548         if(!tty) {
2549                 fclose(stdout);
2550         }
2551
2552         return result;
2553 }
2554
2555 static int cmd_import(int argc, char *argv[]) {
2556         (void)argv;
2557
2558         if(argc > 1) {
2559                 fprintf(stderr, "Too many arguments!\n");
2560                 return 1;
2561         }
2562
2563         FILE *in = stdin;
2564         FILE *out = NULL;
2565
2566         char buf[4096];
2567         char name[4096];
2568         char filename[PATH_MAX] = "";
2569         int count = 0;
2570         bool firstline = true;
2571
2572         while(fgets(buf, sizeof(buf), in)) {
2573                 if(sscanf(buf, "Name = %4095s", name) == 1) {
2574                         firstline = false;
2575
2576                         if(!check_id(name)) {
2577                                 fprintf(stderr, "Invalid Name in input!\n");
2578                                 return 1;
2579                         }
2580
2581                         if(out) {
2582                                 fclose(out);
2583                         }
2584
2585                         if((size_t)snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name) >= sizeof(filename)) {
2586                                 fprintf(stderr, "Filename too long: %s" SLASH "%s\n", hosts_dir, name);
2587                                 return 1;
2588                         }
2589
2590                         if(!force && !access(filename, F_OK)) {
2591                                 fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
2592                                 out = NULL;
2593                                 continue;
2594                         }
2595
2596                         out = fopen(filename, "w");
2597
2598                         if(!out) {
2599                                 fprintf(stderr, "Error creating configuration file %s: %s\n", filename, strerror(errno));
2600                                 return 1;
2601                         }
2602
2603                         count++;
2604                         continue;
2605                 } else if(firstline) {
2606                         fprintf(stderr, "Junk at the beginning of the input, ignoring.\n");
2607                         firstline = false;
2608                 }
2609
2610
2611                 if(!strcmp(buf, "#---------------------------------------------------------------#\n")) {
2612                         continue;
2613                 }
2614
2615                 if(out) {
2616                         if(fputs(buf, out) < 0) {
2617                                 fprintf(stderr, "Error writing to host configuration file %s: %s\n", filename, strerror(errno));
2618                                 return 1;
2619                         }
2620                 }
2621         }
2622
2623         if(out) {
2624                 fclose(out);
2625         }
2626
2627         if(count) {
2628                 fprintf(stderr, "Imported %d host configuration files.\n", count);
2629                 return 0;
2630         } else {
2631                 fprintf(stderr, "No host configuration files imported.\n");
2632                 return 1;
2633         }
2634 }
2635
2636 static int cmd_exchange(int argc, char *argv[]) {
2637         return cmd_export(argc, argv) ? 1 : cmd_import(argc, argv);
2638 }
2639
2640 static int cmd_exchange_all(int argc, char *argv[]) {
2641         return cmd_export_all(argc, argv) ? 1 : cmd_import(argc, argv);
2642 }
2643
2644 static int switch_network(char *name) {
2645         if(strcmp(name, ".")) {
2646                 if(!check_netname(name, false)) {
2647                         fprintf(stderr, "Invalid character in netname!\n");
2648                         return 1;
2649                 }
2650
2651                 if(!check_netname(name, true)) {
2652                         fprintf(stderr, "Warning: unsafe character in netname!\n");
2653                 }
2654         }
2655
2656         if(fd >= 0) {
2657                 closesocket(fd);
2658                 fd = -1;
2659         }
2660
2661         free_names();
2662         netname = strcmp(name, ".") ? xstrdup(name) : NULL;
2663         make_names(false);
2664
2665         free(tinc_conf);
2666         free(hosts_dir);
2667         free(prompt);
2668
2669         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
2670         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
2671         xasprintf(&prompt, "%s> ", identname);
2672
2673         return 0;
2674 }
2675
2676 static int cmd_network(int argc, char *argv[]) {
2677         if(argc > 2) {
2678                 fprintf(stderr, "Too many arguments!\n");
2679                 return 1;
2680         }
2681
2682         if(argc == 2) {
2683                 return switch_network(argv[1]);
2684         }
2685
2686         DIR *dir = opendir(confdir);
2687
2688         if(!dir) {
2689                 fprintf(stderr, "Could not read directory %s: %s\n", confdir, strerror(errno));
2690                 return 1;
2691         }
2692
2693         struct dirent *ent;
2694
2695         while((ent = readdir(dir))) {
2696                 if(*ent->d_name == '.') {
2697                         continue;
2698                 }
2699
2700                 if(!strcmp(ent->d_name, "tinc.conf")) {
2701                         printf(".\n");
2702                         continue;
2703                 }
2704
2705                 char fname[PATH_MAX];
2706                 snprintf(fname, sizeof(fname), "%s/%s/tinc.conf", confdir, ent->d_name);
2707
2708                 if(!access(fname, R_OK)) {
2709                         printf("%s\n", ent->d_name);
2710                 }
2711         }
2712
2713         closedir(dir);
2714
2715         return 0;
2716 }
2717
2718 static int cmd_fsck(int argc, char *argv[]) {
2719         (void)argv;
2720
2721         if(argc > 1) {
2722                 fprintf(stderr, "Too many arguments!\n");
2723                 return 1;
2724         }
2725
2726         return fsck(orig_argv[0]);
2727 }
2728
2729 static void *readfile(FILE *in, size_t *len) {
2730         size_t count = 0;
2731         size_t bufsize = 4096;
2732         char *buf = xmalloc(bufsize);
2733
2734         while(!feof(in)) {
2735                 size_t read = fread(buf + count, 1, bufsize - count, in);
2736
2737                 if(!read) {
2738                         break;
2739                 }
2740
2741                 count += read;
2742
2743                 if(count >= bufsize) {
2744                         bufsize *= 2;
2745                         buf = xrealloc(buf, bufsize);
2746                 }
2747         }
2748
2749         if(len) {
2750                 *len = count;
2751         }
2752
2753         return buf;
2754 }
2755
2756 static int cmd_sign(int argc, char *argv[]) {
2757         if(argc > 2) {
2758                 fprintf(stderr, "Too many arguments!\n");
2759                 return 1;
2760         }
2761
2762         if(!name) {
2763                 name = get_my_name(true);
2764
2765                 if(!name) {
2766                         return 1;
2767                 }
2768         }
2769
2770         char fname[PATH_MAX];
2771         snprintf(fname, sizeof(fname), "%s" SLASH "ed25519_key.priv", confbase);
2772         FILE *fp = fopen(fname, "r");
2773
2774         if(!fp) {
2775                 fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
2776                 return 1;
2777         }
2778
2779         ecdsa_t *key = ecdsa_read_pem_private_key(fp);
2780
2781         if(!key) {
2782                 fprintf(stderr, "Could not read private key from %s\n", fname);
2783                 fclose(fp);
2784                 return 1;
2785         }
2786
2787         fclose(fp);
2788
2789         FILE *in;
2790
2791         if(argc == 2) {
2792                 in = fopen(argv[1], "rb");
2793
2794                 if(!in) {
2795                         fprintf(stderr, "Could not open %s: %s\n", argv[1], strerror(errno));
2796                         ecdsa_free(key);
2797                         return 1;
2798                 }
2799         } else {
2800                 in = stdin;
2801         }
2802
2803         size_t len;
2804         char *data = readfile(in, &len);
2805
2806         if(in != stdin) {
2807                 fclose(in);
2808         }
2809
2810         if(!data) {
2811                 fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
2812                 ecdsa_free(key);
2813                 return 1;
2814         }
2815
2816         // Ensure we sign our name and current time as well
2817         long t = time(NULL);
2818         char *trailer;
2819         xasprintf(&trailer, " %s %ld", name, t);
2820         size_t trailer_len = strlen(trailer);
2821
2822         data = xrealloc(data, len + trailer_len);
2823         memcpy(data + len, trailer, trailer_len);
2824         free(trailer);
2825
2826         char sig[87];
2827
2828         if(!ecdsa_sign(key, data, len + trailer_len, sig)) {
2829                 fprintf(stderr, "Error generating signature\n");
2830                 free(data);
2831                 ecdsa_free(key);
2832                 return 1;
2833         }
2834
2835         b64encode_tinc(sig, sig, 64);
2836         ecdsa_free(key);
2837
2838         fprintf(stdout, "Signature = %s %ld %s\n", name, t, sig);
2839         fwrite(data, len, 1, stdout);
2840
2841         free(data);
2842         return 0;
2843 }
2844
2845 static int cmd_verify(int argc, char *argv[]) {
2846         if(argc < 2) {
2847                 fprintf(stderr, "Not enough arguments!\n");
2848                 return 1;
2849         }
2850
2851         if(argc > 3) {
2852                 fprintf(stderr, "Too many arguments!\n");
2853                 return 1;
2854         }
2855
2856         char *node = argv[1];
2857
2858         if(!strcmp(node, ".")) {
2859                 if(!name) {
2860                         name = get_my_name(true);
2861
2862                         if(!name) {
2863                                 return 1;
2864                         }
2865                 }
2866
2867                 node = name;
2868         } else if(!strcmp(node, "*")) {
2869                 node = NULL;
2870         } else {
2871                 if(!check_id(node)) {
2872                         fprintf(stderr, "Invalid node name\n");
2873                         return 1;
2874                 }
2875         }
2876
2877         FILE *in;
2878
2879         if(argc == 3) {
2880                 in = fopen(argv[2], "rb");
2881
2882                 if(!in) {
2883                         fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
2884                         return 1;
2885                 }
2886         } else {
2887                 in = stdin;
2888         }
2889
2890         size_t len;
2891         char *data = readfile(in, &len);
2892
2893         if(in != stdin) {
2894                 fclose(in);
2895         }
2896
2897         if(!data) {
2898                 fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
2899                 return 1;
2900         }
2901
2902         char *newline = memchr(data, '\n', len);
2903
2904         if(!newline || (newline - data > MAX_STRING_SIZE - 1)) {
2905                 fprintf(stderr, "Invalid input\n");
2906                 free(data);
2907                 return 1;
2908         }
2909
2910         *newline++ = '\0';
2911         size_t skip = newline - data;
2912
2913         char signer[MAX_STRING_SIZE] = "";
2914         char sig[MAX_STRING_SIZE] = "";
2915         long t = 0;
2916
2917         if(sscanf(data, "Signature = %s %ld %s", signer, &t, sig) != 3 || strlen(sig) != 86 || !t || !check_id(signer)) {
2918                 fprintf(stderr, "Invalid input\n");
2919                 free(data);
2920                 return 1;
2921         }
2922
2923         if(node && strcmp(node, signer)) {
2924                 fprintf(stderr, "Signature is not made by %s\n", node);
2925                 free(data);
2926                 return 1;
2927         }
2928
2929         if(!node) {
2930                 node = signer;
2931         }
2932
2933         char *trailer;
2934         xasprintf(&trailer, " %s %ld", signer, t);
2935         size_t trailer_len = strlen(trailer);
2936
2937         data = xrealloc(data, len + trailer_len);
2938         memcpy(data + len, trailer, trailer_len);
2939         free(trailer);
2940
2941         newline = data + skip;
2942
2943         char fname[PATH_MAX];
2944         snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, node);
2945         FILE *fp = fopen(fname, "r");
2946
2947         if(!fp) {
2948                 fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
2949                 free(data);
2950                 return 1;
2951         }
2952
2953         ecdsa_t *key = get_pubkey(fp);
2954
2955         if(!key) {
2956                 rewind(fp);
2957                 key = ecdsa_read_pem_public_key(fp);
2958         }
2959
2960         if(!key) {
2961                 fprintf(stderr, "Could not read public key from %s\n", fname);
2962                 fclose(fp);
2963                 free(data);
2964                 return 1;
2965         }
2966
2967         fclose(fp);
2968
2969         if(b64decode_tinc(sig, sig, 86) != 64 || !ecdsa_verify(key, newline, len + trailer_len - (newline - data), sig)) {
2970                 fprintf(stderr, "Invalid signature\n");
2971                 free(data);
2972                 ecdsa_free(key);
2973                 return 1;
2974         }
2975
2976         ecdsa_free(key);
2977
2978         fwrite(newline, len - (newline - data), 1, stdout);
2979
2980         free(data);
2981         return 0;
2982 }
2983
2984 static const struct {
2985         const char *command;
2986         int (*function)(int argc, char *argv[]);
2987         bool hidden;
2988 } commands[] = {
2989         {"start", cmd_start, false},
2990         {"stop", cmd_stop, false},
2991         {"restart", cmd_restart, false},
2992         {"reload", cmd_reload, false},
2993         {"dump", cmd_dump, false},
2994         {"list", cmd_dump, false},
2995         {"purge", cmd_purge, false},
2996         {"debug", cmd_debug, false},
2997         {"retry", cmd_retry, false},
2998         {"connect", cmd_connect, false},
2999         {"disconnect", cmd_disconnect, false},
3000         {"top", cmd_top, false},
3001         {"pcap", cmd_pcap, false},
3002         {"log", cmd_log, false},
3003         {"pid", cmd_pid, false},
3004         {"config", cmd_config, true},
3005         {"add", cmd_config, false},
3006         {"del", cmd_config, false},
3007         {"get", cmd_config, false},
3008         {"set", cmd_config, false},
3009         {"init", cmd_init, false},
3010         {"generate-keys", cmd_generate_keys, false},
3011 #ifndef DISABLE_LEGACY
3012         {"generate-rsa-keys", cmd_generate_rsa_keys, false},
3013 #endif
3014         {"generate-ed25519-keys", cmd_generate_ed25519_keys, false},
3015         {"help", cmd_help, false},
3016         {"version", cmd_version, false},
3017         {"info", cmd_info, false},
3018         {"edit", cmd_edit, false},
3019         {"export", cmd_export, false},
3020         {"export-all", cmd_export_all, false},
3021         {"import", cmd_import, false},
3022         {"exchange", cmd_exchange, false},
3023         {"exchange-all", cmd_exchange_all, false},
3024         {"invite", cmd_invite, false},
3025         {"join", cmd_join, false},
3026         {"network", cmd_network, false},
3027         {"fsck", cmd_fsck, false},
3028         {"sign", cmd_sign, false},
3029         {"verify", cmd_verify, false},
3030         {NULL, NULL, false},
3031 };
3032
3033 #ifdef HAVE_READLINE
3034 static char *complete_command(const char *text, int state) {
3035         static int i;
3036
3037         if(!state) {
3038                 i = 0;
3039         } else {
3040                 i++;
3041         }
3042
3043         while(commands[i].command) {
3044                 if(!commands[i].hidden && !strncasecmp(commands[i].command, text, strlen(text))) {
3045                         return xstrdup(commands[i].command);
3046                 }
3047
3048                 i++;
3049         }
3050
3051         return NULL;
3052 }
3053
3054 static char *complete_dump(const char *text, int state) {
3055         const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL};
3056         static int i;
3057
3058         if(!state) {
3059                 i = 0;
3060         } else {
3061                 i++;
3062         }
3063
3064         while(matches[i]) {
3065                 if(!strncasecmp(matches[i], text, strlen(text))) {
3066                         return xstrdup(matches[i]);
3067                 }
3068
3069                 i++;
3070         }
3071
3072         return NULL;
3073 }
3074
3075 static char *complete_config(const char *text, int state) {
3076         static int i;
3077
3078         if(!state) {
3079                 i = 0;
3080         } else {
3081                 i++;
3082         }
3083
3084         while(variables[i].name) {
3085                 char *dot = strchr(text, '.');
3086
3087                 if(dot) {
3088                         if((variables[i].type & VAR_HOST) && !strncasecmp(variables[i].name, dot + 1, strlen(dot + 1))) {
3089                                 char *match;
3090                                 xasprintf(&match, "%.*s.%s", (int)(dot - text), text, variables[i].name);
3091                                 return match;
3092                         }
3093                 } else {
3094                         if(!strncasecmp(variables[i].name, text, strlen(text))) {
3095                                 return xstrdup(variables[i].name);
3096                         }
3097                 }
3098
3099                 i++;
3100         }
3101
3102         return NULL;
3103 }
3104
3105 static char *complete_info(const char *text, int state) {
3106         static int i;
3107
3108         if(!state) {
3109                 i = 0;
3110
3111                 if(!connect_tincd(false)) {
3112                         return NULL;
3113                 }
3114
3115                 // Check the list of nodes
3116                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
3117                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
3118         }
3119
3120         while(recvline(fd, line, sizeof(line))) {
3121                 char item[4096];
3122                 int n = sscanf(line, "%d %d %4095s", &code, &req, item);
3123
3124                 if(n == 2) {
3125                         i++;
3126
3127                         if(i >= 2) {
3128                                 break;
3129                         } else {
3130                                 continue;
3131                         }
3132                 }
3133
3134                 if(n != 3) {
3135                         fprintf(stderr, "Unable to parse dump from tincd, n = %d, i = %d.\n", n, i);
3136                         break;
3137                 }
3138
3139                 if(!strncmp(item, text, strlen(text))) {
3140                         return xstrdup(strip_weight(item));
3141                 }
3142         }
3143
3144         return NULL;
3145 }
3146
3147 static char *complete_nothing(const char *text, int state) {
3148         (void)text;
3149         (void)state;
3150         return NULL;
3151 }
3152
3153 static char **completion(const char *text, int start, int end) {
3154         (void)end;
3155         char **matches = NULL;
3156
3157         if(!start) {
3158                 matches = rl_completion_matches(text, complete_command);
3159         } else if(!strncasecmp(rl_line_buffer, "dump ", 5)) {
3160                 matches = rl_completion_matches(text, complete_dump);
3161         } else if(!strncasecmp(rl_line_buffer, "add ", 4)) {
3162                 matches = rl_completion_matches(text, complete_config);
3163         } else if(!strncasecmp(rl_line_buffer, "del ", 4)) {
3164                 matches = rl_completion_matches(text, complete_config);
3165         } else if(!strncasecmp(rl_line_buffer, "get ", 4)) {
3166                 matches = rl_completion_matches(text, complete_config);
3167         } else if(!strncasecmp(rl_line_buffer, "set ", 4)) {
3168                 matches = rl_completion_matches(text, complete_config);
3169         } else if(!strncasecmp(rl_line_buffer, "info ", 5)) {
3170                 matches = rl_completion_matches(text, complete_info);
3171         }
3172
3173         return matches;
3174 }
3175 #endif
3176
3177 static int cmd_shell(int argc, char *argv[]) {
3178         xasprintf(&prompt, "%s> ", identname);
3179         int result = 0;
3180         char buf[4096];
3181         char *line = NULL;
3182         int maxargs = argc + 16;
3183         char **nargv = xmalloc(maxargs * sizeof(*nargv));
3184
3185         for(int i = 0; i < argc; i++) {
3186                 nargv[i] = argv[i];
3187         }
3188
3189 #ifdef HAVE_READLINE
3190         rl_readline_name = "tinc";
3191         rl_basic_word_break_characters = "\t\n ";
3192         rl_completion_entry_function = complete_nothing;
3193         rl_attempted_completion_function = completion;
3194         rl_filename_completion_desired = 0;
3195         char *copy = NULL;
3196 #endif
3197
3198         while(true) {
3199 #ifdef HAVE_READLINE
3200
3201                 if(tty) {
3202                         free(copy);
3203                         free(line);
3204                         line = readline(prompt);
3205                         copy = line ? xstrdup(line) : NULL;
3206                 } else {
3207                         line = fgets(buf, sizeof(buf), stdin);
3208                 }
3209
3210 #else
3211
3212                 if(tty) {
3213                         fputs(prompt, stdout);
3214                 }
3215
3216                 line = fgets(buf, sizeof(buf), stdin);
3217 #endif
3218
3219                 if(!line) {
3220                         break;
3221                 }
3222
3223                 /* Ignore comments */
3224
3225                 if(*line == '#') {
3226                         continue;
3227                 }
3228
3229                 /* Split */
3230
3231                 int nargc = argc;
3232                 char *p = line + strspn(line, " \t\n");
3233                 char *next = strtok(p, " \t\n");
3234
3235                 while(p && *p) {
3236                         if(nargc >= maxargs) {
3237                                 maxargs *= 2;
3238                                 nargv = xrealloc(nargv, maxargs * sizeof(*nargv));
3239                         }
3240
3241                         nargv[nargc++] = p;
3242                         p = next;
3243                         next = strtok(NULL, " \t\n");
3244                 }
3245
3246                 if(nargc == argc) {
3247                         continue;
3248                 }
3249
3250                 if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit")) {
3251 #ifdef HAVE_READLINE
3252                         free(copy);
3253 #endif
3254                         free(nargv);
3255                         return result;
3256                 }
3257
3258                 bool found = false;
3259
3260                 for(int i = 0; commands[i].command; i++) {
3261                         if(!strcasecmp(nargv[argc], commands[i].command)) {
3262                                 result |= commands[i].function(nargc - argc - 1, nargv + argc + 1);
3263                                 found = true;
3264                                 break;
3265                         }
3266                 }
3267
3268 #ifdef HAVE_READLINE
3269
3270                 if(tty && found) {
3271                         add_history(copy);
3272                 }
3273
3274 #endif
3275
3276                 if(!found) {
3277                         fprintf(stderr, "Unknown command `%s'.\n", nargv[argc]);
3278                         result |= 1;
3279                 }
3280         }
3281
3282 #ifdef HAVE_READLINE
3283         free(copy);
3284 #endif
3285         free(nargv);
3286
3287         if(tty) {
3288                 printf("\n");
3289         }
3290
3291         return result;
3292 }
3293
3294 static void cleanup(void) {
3295         free(tinc_conf);
3296         free(hosts_dir);
3297         free_names();
3298 }
3299
3300 static int run_command(int argc, char *argv[]) {
3301         if(optind >= argc) {
3302                 return cmd_shell(argc, argv);
3303         }
3304
3305         for(int i = 0; commands[i].command; i++) {
3306                 if(!strcasecmp(argv[optind], commands[i].command)) {
3307                         return commands[i].function(argc - optind, argv + optind);
3308                 }
3309         }
3310
3311         fprintf(stderr, "Unknown command `%s'.\n", argv[optind]);
3312         usage(true);
3313         return 1;
3314 }
3315
3316 int main(int argc, char *argv[]) {
3317         program_name = argv[0];
3318         orig_argv = argv;
3319         tty = isatty(0) && isatty(1);
3320
3321         if(!parse_options(argc, argv)) {
3322                 return 1;
3323         }
3324
3325         make_names(false);
3326         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
3327         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
3328         atexit(cleanup);
3329
3330         if(show_version) {
3331                 version();
3332                 return 0;
3333         }
3334
3335         if(show_help) {
3336                 usage(false);
3337                 return 0;
3338         }
3339
3340 #ifdef HAVE_WINDOWS
3341         static struct WSAData wsa_state;
3342
3343         if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
3344                 fprintf(stderr, "System call `%s' failed: %s\n", "WSAStartup", winerror(GetLastError()));
3345                 return false;
3346         }
3347
3348 #endif
3349
3350         gettimeofday(&now, NULL);
3351         random_init();
3352         crypto_init();
3353         prng_init();
3354
3355         int result = run_command(argc, argv);
3356
3357         random_exit();
3358
3359         return result;
3360 }