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