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