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