Refactor crypto RNG; add getrandom() support
[tinc] / src / tincctl.c
1 /*
2     tincctl.c -- Controlling a running tincd
3     Copyright (C) 2007-2022 Guus Sliepen <guus@tinc-vpn.org>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "system.h"
21
22 #ifdef HAVE_READLINE
23 #include "readline/readline.h"
24 #include "readline/history.h"
25 #endif
26
27 #include "xalloc.h"
28 #include "protocol.h"
29 #include "control_common.h"
30 #include "crypto.h"
31 #include "ecdsagen.h"
32 #include "fsck.h"
33 #include "info.h"
34 #include "invitation.h"
35 #include "names.h"
36 #include "rsagen.h"
37 #include "utils.h"
38 #include "tincctl.h"
39 #include "top.h"
40 #include "version.h"
41 #include "subnet.h"
42 #include "keys.h"
43 #include "random.h"
44
45 #ifndef MSG_NOSIGNAL
46 #define MSG_NOSIGNAL 0
47 #endif
48
49 static char **orig_argv;
50
51 /* If nonzero, display usage information and exit. */
52 static bool show_help = false;
53
54 /* If nonzero, print the version on standard output and exit.  */
55 static bool show_version = false;
56
57 static char *name = NULL;
58 static char controlcookie[1025];
59 char *tinc_conf = NULL;
60 char *hosts_dir = NULL;
61 struct timeval now;
62
63 // Horrible global variables...
64 static int pid = 0;
65 int fd = -1;
66 char line[4096];
67 static int code;
68 static int req;
69 static int result;
70 bool force = false;
71 bool tty = true;
72 bool confbasegiven = false;
73 char *scriptinterpreter = NULL;
74 static char defaultextension[] = "";
75 char *scriptextension = defaultextension;
76 static char *prompt;
77 char *device = NULL;
78 char *iface = NULL;
79 int debug_level = -1;
80
81 static struct option const long_options[] = {
82         {"batch", no_argument, NULL, 'b'},
83         {"config", required_argument, NULL, 'c'},
84         {"net", required_argument, NULL, 'n'},
85         {"help", no_argument, NULL, 1},
86         {"version", no_argument, NULL, 2},
87         {"pidfile", required_argument, NULL, 3},
88         {"force", no_argument, NULL, 4},
89         {NULL, 0, NULL, 0}
90 };
91
92 static void version(void) {
93         static const char *message =
94                 "%s version %s (built %s %s, protocol %d.%d)\n"
95                 "Features:"
96 #ifdef HAVE_READLINE
97                 " readline"
98 #endif
99 #ifdef HAVE_CURSES
100                 " curses"
101 #endif
102 #ifndef DISABLE_LEGACY
103                 " legacy_protocol"
104 #endif
105                 "\n\n"
106                 "Copyright (C) 1998-2018 Ivo Timmermans, Guus Sliepen and others.\n"
107                 "See the AUTHORS file for a complete list.\n"
108                 "\n"
109                 "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
110                 "and you are welcome to redistribute it under certain conditions;\n"
111                 "see the file COPYING for details.\n";
112
113         printf(message, PACKAGE, BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
114 }
115
116 static void usage(bool status) {
117         if(status) {
118                 fprintf(stderr, "Try `%s --help\' for more information.\n", program_name);
119         } else {
120                 static const char *message =
121                         "Usage: %s [options] command\n"
122                         "\n"
123                         "Valid options are:\n"
124                         "  -b, --batch             Don't ask for anything (non-interactive mode).\n"
125                         "  -c, --config=DIR        Read configuration options from DIR.\n"
126                         "  -n, --net=NETNAME       Connect to net NETNAME.\n"
127                         "      --pidfile=FILENAME  Read control cookie from FILENAME.\n"
128                         "      --force             Force some commands to work despite warnings.\n"
129                         "      --help              Display this help and exit.\n"
130                         "      --version           Output version information and exit.\n"
131                         "\n"
132                         "Valid commands are:\n"
133                         "  init [name]                Create initial configuration files.\n"
134                         "  get VARIABLE               Print current value of VARIABLE\n"
135                         "  set VARIABLE VALUE         Set VARIABLE to VALUE\n"
136                         "  add VARIABLE VALUE         Add VARIABLE with the given VALUE\n"
137                         "  del VARIABLE [VALUE]       Remove VARIABLE [only ones with watching VALUE]\n"
138                         "  start [tincd options]      Start tincd.\n"
139                         "  stop                       Stop tincd.\n"
140                         "  restart [tincd options]    Restart tincd.\n"
141                         "  reload                     Partially reload configuration of running tincd.\n"
142                         "  pid                        Show PID of currently running tincd.\n"
143 #ifdef DISABLE_LEGACY
144                         "  generate-keys              Generate a new Ed25519 public/private key pair.\n"
145 #else
146                         "  generate-keys [bits]       Generate new RSA and Ed25519 public/private key pairs.\n"
147                         "  generate-rsa-keys [bits]   Generate a new RSA public/private key pair.\n"
148 #endif
149                         "  generate-ed25519-keys      Generate a new Ed25519 public/private key pair.\n"
150                         "  dump                       Dump a list of one of the following things:\n"
151                         "    [reachable] nodes        - all known nodes in the VPN\n"
152                         "    edges                    - all known connections in the VPN\n"
153                         "    subnets                  - all known subnets in the VPN\n"
154                         "    connections              - all meta connections with ourself\n"
155                         "    [di]graph                - graph of the VPN in dotty format\n"
156                         "    invitations              - outstanding invitations\n"
157                         "  info NODE|SUBNET|ADDRESS   Give information about a particular NODE, SUBNET or ADDRESS.\n"
158                         "  purge                      Purge unreachable nodes\n"
159                         "  debug N                    Set debug level\n"
160                         "  retry                      Retry all outgoing connections\n"
161                         "  disconnect NODE            Close meta connection with NODE\n"
162 #ifdef HAVE_CURSES
163                         "  top                        Show real-time statistics\n"
164 #endif
165                         "  pcap [snaplen]             Dump traffic in pcap format [up to snaplen bytes per packet]\n"
166                         "  log [level]                Dump log output [up to the specified level]\n"
167                         "  export                     Export host configuration of local node to standard output\n"
168                         "  export-all                 Export all host configuration files to standard output\n"
169                         "  import                     Import host configuration file(s) from standard input\n"
170                         "  exchange                   Same as export followed by import\n"
171                         "  exchange-all               Same as export-all followed by import\n"
172                         "  invite NODE [...]          Generate an invitation for NODE\n"
173                         "  join INVITATION            Join a VPN using an INVITATION\n"
174                         "  network [NETNAME]          List all known networks, or switch to the one named NETNAME.\n"
175                         "  fsck                       Check the configuration files for problems.\n"
176                         "  sign [FILE]                Generate a signed version of a file.\n"
177                         "  verify NODE [FILE]         Verify that a file was signed by the given NODE.\n"
178                         "\n"
179                         "Report bugs to tinc@tinc-vpn.org.\n";
180
181                 printf(message, program_name);
182         }
183 }
184
185 static bool parse_options(int argc, char **argv) {
186         int r;
187         int option_index = 0;
188
189         while((r = getopt_long(argc, argv, "+bc:n:", long_options, &option_index)) != EOF) {
190                 switch(r) {
191                 case 0:   /* long option */
192                         break;
193
194                 case 'b':
195                         tty = false;
196                         break;
197
198                 case 'c': /* config file */
199                         free(confbase);
200                         confbase = xstrdup(optarg);
201                         confbasegiven = true;
202                         break;
203
204                 case 'n': /* net name given */
205                         free(netname);
206                         netname = xstrdup(optarg);
207                         break;
208
209                 case 1:   /* show help */
210                         show_help = true;
211                         break;
212
213                 case 2:   /* show version */
214                         show_version = true;
215                         break;
216
217                 case 3:   /* open control socket here */
218                         free(pidfilename);
219                         pidfilename = xstrdup(optarg);
220                         break;
221
222                 case 4:   /* force */
223                         force = true;
224                         break;
225
226                 case '?': /* wrong options */
227                         usage(true);
228                         free_names();
229                         return false;
230
231                 default:
232                         break;
233                 }
234         }
235
236         if(!netname && (netname = getenv("NETNAME"))) {
237                 netname = xstrdup(netname);
238         }
239
240         /* netname "." is special: a "top-level name" */
241
242         if(netname && (!*netname || !strcmp(netname, "."))) {
243                 free(netname);
244                 netname = NULL;
245         }
246
247         if(netname && (strpbrk(netname, "\\/") || *netname == '.')) {
248                 fprintf(stderr, "Invalid character in netname!\n");
249                 free_names();
250                 return false;
251         }
252
253         return true;
254 }
255
256 static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) {
257         FILE *r;
258         char directory[PATH_MAX] = ".";
259         char buf[PATH_MAX];
260         char buf2[PATH_MAX];
261
262 ask_filename:
263
264         /* Check stdin and stdout */
265         if(ask && tty) {
266                 /* Ask for a file and/or directory name. */
267                 fprintf(stderr, "Please enter a file to save %s to [%s]: ", what, filename);
268
269                 if(fgets(buf, sizeof(buf), stdin) == NULL) {
270                         fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
271                         return NULL;
272                 }
273
274                 size_t len = strlen(buf);
275
276                 if(len) {
277                         buf[--len] = 0;
278                 }
279
280                 if(len) {
281                         filename = buf;
282                 }
283         }
284
285 #ifdef HAVE_WINDOWS
286
287         if(filename[0] != '\\' && filename[0] != '/' && !strchr(filename, ':')) {
288 #else
289
290         if(filename[0] != '/') {
291 #endif
292
293                 /* The directory is a relative path or a filename. */
294                 if(!getcwd(directory, sizeof(directory))) {
295                         fprintf(stderr, "Could not get current directory: %s\n", strerror(errno));
296                         return NULL;
297                 }
298
299                 if((size_t)snprintf(buf2, sizeof(buf2), "%s" SLASH "%s", directory, filename) >= sizeof(buf2)) {
300                         fprintf(stderr, "Filename too long: %s" SLASH "%s\n", directory, filename);
301
302                         if(ask && tty) {
303                                 goto ask_filename;
304                         } else {
305                                 return NULL;
306                         }
307                 }
308
309                 filename = buf2;
310         }
311
312         disable_old_keys(filename, what);
313
314         /* Open it first to keep the inode busy */
315
316         r = fopenmask(filename, mode, perms);
317
318         if(!r) {
319                 fprintf(stderr, "Error opening file `%s': %s\n", filename, strerror(errno));
320                 return NULL;
321         }
322
323         return r;
324 }
325
326 /*
327   Generate a public/private Ed25519 key pair, and ask for a file to store
328   them in.
329 */
330 static bool ed25519_keygen(bool ask) {
331         ecdsa_t *key;
332         FILE *f;
333         char fname[PATH_MAX];
334
335         fprintf(stderr, "Generating Ed25519 key pair:\n");
336
337         if(!(key = ecdsa_generate())) {
338                 fprintf(stderr, "Error during key generation!\n");
339                 return false;
340         } else {
341                 fprintf(stderr, "Done.\n");
342         }
343
344         snprintf(fname, sizeof(fname), "%s" SLASH "ed25519_key.priv", confbase);
345         f = ask_and_open(fname, "private Ed25519 key", "a", ask, 0600);
346
347         if(!f) {
348                 goto error;
349         }
350
351         if(!ecdsa_write_pem_private_key(key, f)) {
352                 fprintf(stderr, "Error writing private key!\n");
353                 goto error;
354         }
355
356         fclose(f);
357
358         if(name) {
359                 snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, name);
360         } else {
361                 snprintf(fname, sizeof(fname), "%s" SLASH "ed25519_key.pub", confbase);
362         }
363
364         f = ask_and_open(fname, "public Ed25519 key", "a", ask, 0666);
365
366         if(!f) {
367                 return false;
368         }
369
370         char *pubkey = ecdsa_get_base64_public_key(key);
371         fprintf(f, "Ed25519PublicKey = %s\n", pubkey);
372         free(pubkey);
373
374         fclose(f);
375         ecdsa_free(key);
376
377         return true;
378
379 error:
380
381         if(f) {
382                 fclose(f);
383         }
384
385         ecdsa_free(key);
386         return false;
387 }
388
389 #ifndef DISABLE_LEGACY
390 /*
391   Generate a public/private RSA key pair, and ask for a file to store
392   them in.
393 */
394 static bool rsa_keygen(int bits, bool ask) {
395         rsa_t *key;
396         FILE *f;
397         char fname[PATH_MAX];
398
399         // Make sure the key size is a multiple of 8 bits.
400         bits &= ~0x7;
401
402         // Make sure that a valid key size is used.
403         if(bits < 1024 || bits > 8192) {
404                 fprintf(stderr, "Invalid key size %d specified! It should be between 1024 and 8192 bits.\n", bits);
405                 return false;
406         } else if(bits < 2048) {
407                 fprintf(stderr, "WARNING: generating a weak %d bits RSA key! 2048 or more bits are recommended.\n", bits);
408         }
409
410         fprintf(stderr, "Generating %d bits keys:\n", bits);
411
412         if(!(key = rsa_generate(bits, 0x10001))) {
413                 fprintf(stderr, "Error during key generation!\n");
414                 return false;
415         } else {
416                 fprintf(stderr, "Done.\n");
417         }
418
419         snprintf(fname, sizeof(fname), "%s" SLASH "rsa_key.priv", confbase);
420         f = ask_and_open(fname, "private RSA key", "a", ask, 0600);
421
422         if(!f) {
423                 goto error;
424         }
425
426         if(!rsa_write_pem_private_key(key, f)) {
427                 fprintf(stderr, "Error writing private key!\n");
428                 goto error;
429         }
430
431         fclose(f);
432
433         if(name) {
434                 snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, name);
435         } else {
436                 snprintf(fname, sizeof(fname), "%s" SLASH "rsa_key.pub", confbase);
437         }
438
439         f = ask_and_open(fname, "public RSA key", "a", ask, 0666);
440
441         if(!f) {
442                 goto error;
443         }
444
445         if(!rsa_write_pem_public_key(key, f)) {
446                 fprintf(stderr, "Error writing public key!\n");
447                 goto error;
448         }
449
450         fclose(f);
451         rsa_free(key);
452
453         return true;
454
455 error:
456
457         if(f) {
458                 fclose(f);
459         }
460
461         rsa_free(key);
462         return false;
463 }
464 #endif
465
466 char buffer[4096];
467 size_t blen = 0;
468
469 bool recvline(int fd, char *line, size_t len) {
470         char *newline = NULL;
471
472         if(!fd) {
473                 return false;
474         }
475
476         while(!(newline = memchr(buffer, '\n', blen))) {
477                 ssize_t nrecv = recv(fd, buffer + blen, sizeof(buffer) - blen, 0);
478
479                 if(nrecv == -1 && sockerrno == EINTR) {
480                         continue;
481                 } else if(nrecv <= 0) {
482                         return false;
483                 }
484
485                 blen += nrecv;
486         }
487
488         if((size_t)(newline - buffer) >= len) {
489                 return false;
490         }
491
492         len = newline - buffer;
493
494         memcpy(line, buffer, len);
495         line[len] = 0;
496         memmove(buffer, newline + 1, blen - len - 1);
497         blen -= len + 1;
498
499         return true;
500 }
501
502 static bool recvdata(int fd, char *data, size_t len) {
503         while(blen < len) {
504                 ssize_t nrecv = recv(fd, buffer + blen, sizeof(buffer) - blen, 0);
505
506                 if(nrecv == -1 && sockerrno == EINTR) {
507                         continue;
508                 } else if(nrecv <= 0) {
509                         return false;
510                 }
511
512                 blen += nrecv;
513         }
514
515         memcpy(data, buffer, len);
516         memmove(buffer, buffer + len, blen - len);
517         blen -= len;
518
519         return true;
520 }
521
522 bool sendline(int fd, const char *format, ...) {
523         static char buffer[4096];
524         char *p = buffer;
525         ssize_t blen;
526         va_list ap;
527
528         va_start(ap, format);
529         blen = vsnprintf(buffer, sizeof(buffer), format, ap);
530         buffer[sizeof(buffer) - 1] = 0;
531         va_end(ap);
532
533         if(blen < 1 || (size_t)blen >= sizeof(buffer)) {
534                 return false;
535         }
536
537         buffer[blen] = '\n';
538         blen++;
539
540         while(blen) {
541                 ssize_t nsend = send(fd, p, blen, MSG_NOSIGNAL);
542
543                 if(nsend == -1 && sockerrno == EINTR) {
544                         continue;
545                 } else if(nsend <= 0) {
546                         return false;
547                 }
548
549                 p += nsend;
550                 blen -= nsend;
551         }
552
553         return true;
554 }
555
556 static void pcap(int fd, FILE *out, uint32_t snaplen) {
557         sendline(fd, "%d %d %d", CONTROL, REQ_PCAP, snaplen);
558         char data[9018];
559
560         struct {
561                 uint32_t magic;
562                 uint16_t major;
563                 uint16_t minor;
564                 uint32_t tz_offset;
565                 uint32_t tz_accuracy;
566                 uint32_t snaplen;
567                 uint32_t ll_type;
568         } header = {
569                 0xa1b2c3d4,
570                 2, 4,
571                 0, 0,
572                 snaplen ? snaplen : sizeof(data),
573                 1,
574         };
575
576         struct {
577                 uint32_t tv_sec;
578                 uint32_t tv_usec;
579                 uint32_t len;
580                 uint32_t origlen;
581         } packet;
582
583         struct timeval tv;
584
585         fwrite(&header, sizeof(header), 1, out);
586         fflush(out);
587
588         char line[32];
589
590         while(recvline(fd, line, sizeof(line))) {
591                 int code, req;
592                 unsigned long len;
593                 int n = sscanf(line, "%d %d %lu", &code, &req, &len);
594                 gettimeofday(&tv, NULL);
595
596                 if(n != 3 || code != CONTROL || req != REQ_PCAP || len > sizeof(data)) {
597                         break;
598                 }
599
600                 if(!recvdata(fd, data, len)) {
601                         break;
602                 }
603
604                 packet.tv_sec = tv.tv_sec;
605                 packet.tv_usec = tv.tv_usec;
606                 packet.len = len;
607                 packet.origlen = len;
608                 fwrite(&packet, sizeof(packet), 1, out);
609                 fwrite(data, len, 1, out);
610                 fflush(out);
611         }
612 }
613
614 static void logcontrol(int fd, FILE *out, int level) {
615         sendline(fd, "%d %d %d", CONTROL, REQ_LOG, level);
616         char data[1024];
617         char line[32];
618
619         while(recvline(fd, line, sizeof(line))) {
620                 int code, req, len;
621                 int n = sscanf(line, "%d %d %d", &code, &req, &len);
622
623                 if(n != 3 || code != CONTROL || req != REQ_LOG || len < 0 || (size_t)len > sizeof(data)) {
624                         break;
625                 }
626
627                 if(!recvdata(fd, data, len)) {
628                         break;
629                 }
630
631                 fwrite(data, len, 1, out);
632                 fputc('\n', out);
633                 fflush(out);
634         }
635 }
636
637 static bool stop_tincd(void) {
638         if(!connect_tincd(true)) {
639                 return false;
640         }
641
642         sendline(fd, "%d %d", CONTROL, REQ_STOP);
643
644         while(recvline(fd, line, sizeof(line))) {
645                 // wait for tincd to close the connection...
646         }
647
648         closesocket(fd);
649         pid = 0;
650         fd = -1;
651
652         return true;
653 }
654
655 #ifdef HAVE_WINDOWS
656 static bool remove_service(void) {
657         SC_HANDLE manager = NULL;
658         SC_HANDLE service = NULL;
659         SERVICE_STATUS status = {0};
660         bool success = false;
661
662         manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
663
664         if(!manager) {
665                 fprintf(stderr, "Could not open service manager: %s\n", winerror(GetLastError()));
666                 goto exit;
667         }
668
669         service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
670
671         if(!service) {
672                 if(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) {
673                         success = stop_tincd();
674                 } else {
675                         fprintf(stderr, "Could not open %s service: %s\n", identname, winerror(GetLastError()));
676                 }
677
678                 goto exit;
679         }
680
681         if(!ControlService(service, SERVICE_CONTROL_STOP, &status)) {
682                 fprintf(stderr, "Could not stop %s service: %s\n", identname, winerror(GetLastError()));
683         } else {
684                 fprintf(stderr, "%s service stopped\n", identname);
685         }
686
687         if(!DeleteService(service)) {
688                 fprintf(stderr, "Could not remove %s service: %s\n", identname, winerror(GetLastError()));
689                 goto exit;
690         }
691
692         success = true;
693
694 exit:
695
696         if(service) {
697                 CloseServiceHandle(service);
698         }
699
700         if(manager) {
701                 CloseServiceHandle(manager);
702         }
703
704         if(success) {
705                 fprintf(stderr, "%s service removed\n", identname);
706         }
707
708         return success;
709 }
710 #endif
711
712 bool connect_tincd(bool verbose) {
713         if(fd >= 0) {
714                 fd_set r;
715                 FD_ZERO(&r);
716                 FD_SET(fd, &r);
717                 struct timeval tv = {0, 0};
718
719                 if(select(fd + 1, &r, NULL, NULL, &tv)) {
720                         fprintf(stderr, "Previous connection to tincd lost, reconnecting.\n");
721                         closesocket(fd);
722                         fd = -1;
723                 } else {
724                         return true;
725                 }
726         }
727
728         FILE *f = fopen(pidfilename, "r");
729
730         if(!f) {
731                 if(verbose) {
732                         fprintf(stderr, "Could not open pid file %s: %s\n", pidfilename, strerror(errno));
733                 }
734
735                 return false;
736         }
737
738         char host[129];
739         char port[129];
740
741         if(fscanf(f, "%20d %1024s %128s port %128s", &pid, controlcookie, host, port) != 4) {
742                 if(verbose) {
743                         fprintf(stderr, "Could not parse pid file %s\n", pidfilename);
744                 }
745
746                 fclose(f);
747                 return false;
748         }
749
750         fclose(f);
751
752 #ifndef HAVE_WINDOWS
753
754         if((pid == 0) || (kill(pid, 0) && (errno == ESRCH))) {
755                 fprintf(stderr, "Could not find tincd running at pid %d\n", pid);
756                 /* clean up the stale socket and pid file */
757                 unlink(pidfilename);
758                 unlink(unixsocketname);
759                 return false;
760         }
761
762         struct sockaddr_un sa = {
763                 .sun_family = AF_UNIX,
764         };
765
766         if(strlen(unixsocketname) >= sizeof(sa.sun_path)) {
767                 fprintf(stderr, "UNIX socket filename %s is too long!", unixsocketname);
768                 return false;
769         }
770
771         strncpy(sa.sun_path, unixsocketname, sizeof(sa.sun_path));
772
773         fd = socket(AF_UNIX, SOCK_STREAM, 0);
774
775         if(fd < 0) {
776                 if(verbose) {
777                         fprintf(stderr, "Cannot create UNIX socket: %s\n", sockstrerror(sockerrno));
778                 }
779
780                 return false;
781         }
782
783         if(connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
784                 if(verbose) {
785                         fprintf(stderr, "Cannot connect to UNIX socket %s: %s\n", unixsocketname, sockstrerror(sockerrno));
786                 }
787
788                 closesocket(fd);
789                 fd = -1;
790                 return false;
791         }
792
793 #else
794         struct addrinfo hints = {
795                 .ai_family = AF_UNSPEC,
796                 .ai_socktype = SOCK_STREAM,
797                 .ai_protocol = IPPROTO_TCP,
798                 .ai_flags = 0,
799         };
800
801         struct addrinfo *res = NULL;
802
803         if(getaddrinfo(host, port, &hints, &res) || !res) {
804                 if(verbose) {
805                         fprintf(stderr, "Cannot resolve %s port %s: %s\n", host, port, sockstrerror(sockerrno));
806                 }
807
808                 return false;
809         }
810
811         fd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP);
812
813         if(fd < 0) {
814                 if(verbose) {
815                         fprintf(stderr, "Cannot create TCP socket: %s\n", sockstrerror(sockerrno));
816                 }
817
818                 return false;
819         }
820
821         unsigned long arg = 0;
822
823         if(ioctlsocket(fd, FIONBIO, &arg) != 0) {
824                 if(verbose) {
825                         fprintf(stderr, "System call `%s' failed: %s\n", "ioctlsocket", sockstrerror(sockerrno));
826                 }
827         }
828
829         if(connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
830                 if(verbose) {
831                         fprintf(stderr, "Cannot connect to %s port %s: %s\n", host, port, sockstrerror(sockerrno));
832                 }
833
834                 closesocket(fd);
835                 fd = -1;
836                 return false;
837         }
838
839         freeaddrinfo(res);
840 #endif
841
842 #ifdef SO_NOSIGPIPE
843         static const int one = 1;
844         setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof(one));
845 #endif
846
847         sendline(fd, "%d ^%s %d", ID, controlcookie, TINC_CTL_VERSION_CURRENT);
848
849         char data[4096];
850         int version;
851
852         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %4095s %d", &code, data, &version) != 3 || code != 0) {
853                 if(verbose) {
854                         fprintf(stderr, "Cannot read greeting from control socket: %s\n", sockstrerror(sockerrno));
855                 }
856
857                 closesocket(fd);
858                 fd = -1;
859                 return false;
860         }
861
862         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &version, &pid) != 3 || code != 4 || version != TINC_CTL_VERSION_CURRENT) {
863                 if(verbose) {
864                         fprintf(stderr, "Could not fully establish control socket connection\n");
865                 }
866
867                 closesocket(fd);
868                 fd = -1;
869                 return false;
870         }
871
872         return true;
873 }
874
875
876 static int cmd_start(int argc, char *argv[]) {
877         if(connect_tincd(false)) {
878                 if(netname) {
879                         fprintf(stderr, "A tincd is already running for net `%s' with pid %d.\n", netname, pid);
880                 } else {
881                         fprintf(stderr, "A tincd is already running with pid %d.\n", pid);
882                 }
883
884                 return 0;
885         }
886
887         char *c;
888         char *slash = strrchr(program_name, '/');
889
890 #ifdef HAVE_WINDOWS
891
892         if((c = strrchr(program_name, '\\')) > slash) {
893                 slash = c;
894         }
895
896 #endif
897
898         if(slash++) {
899                 xasprintf(&c, "%.*stincd", (int)(slash - program_name), program_name);
900         } else {
901                 c = xstrdup("tincd");
902         }
903
904         int nargc = 0;
905         char **nargv = xzalloc((optind + argc) * sizeof(*nargv));
906
907         char *arg0 = c;
908 #ifdef HAVE_WINDOWS
909         /*
910            Windows has no real concept of an "argv array". A command line is just one string.
911            The CRT of the new process will decode the command line string to generate argv before calling main(), and (by convention)
912            it uses quotes to handle spaces in arguments.
913            Therefore we need to quote all arguments that might contain spaces. No, execvp() won't do that for us (see MSDN).
914            If we don't do that, then execvp() will run fine but any spaces in the filename contained in arg0 will bleed
915            into the next arguments when the spawned process' CRT parses its command line, resulting in chaos.
916         */
917         xasprintf(&arg0, "\"%s\"", arg0);
918 #endif
919         nargv[nargc++] = arg0;
920
921         for(int i = 1; i < optind; i++) {
922                 nargv[nargc++] = orig_argv[i];
923         }
924
925         for(int i = 1; i < argc; i++) {
926                 nargv[nargc++] = argv[i];
927         }
928
929 #ifdef HAVE_WINDOWS
930         int status = spawnvp(_P_WAIT, c, nargv);
931
932         free(nargv);
933         free(c);
934
935         if(status == -1) {
936                 fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno));
937                 return 1;
938         }
939
940         return status;
941 #else
942         int pfd[2] = {-1, -1};
943
944         if(socketpair(AF_UNIX, SOCK_STREAM, 0, pfd)) {
945                 fprintf(stderr, "Could not create umbilical socket: %s\n", strerror(errno));
946                 free(nargv);
947                 free(c);
948                 return 1;
949         }
950
951         pid_t pid = fork();
952
953         if(pid == -1) {
954                 fprintf(stderr, "Could not fork: %s\n", strerror(errno));
955                 free(nargv);
956                 free(c);
957                 return 1;
958         }
959
960         if(!pid) {
961                 close(pfd[0]);
962                 char buf[100];
963                 snprintf(buf, sizeof(buf), "%d", pfd[1]);
964                 setenv("TINC_UMBILICAL", buf, true);
965                 exit(execvp(c, nargv));
966         } else {
967                 close(pfd[1]);
968         }
969
970         free(nargv);
971
972 #ifdef SIGINT
973         signal(SIGINT, SIG_IGN);
974 #endif
975
976         // Pass all log messages from the umbilical to stderr.
977         // A nul-byte right before closure means tincd started successfully.
978         bool failure = true;
979         uint8_t buf[1024];
980         ssize_t len;
981
982         while((len = read(pfd[0], buf, sizeof(buf))) > 0) {
983                 failure = buf[len - 1];
984
985                 if(!failure) {
986                         len--;
987                 }
988
989                 if(write(2, buf, len) != len) {
990                         // Nothing we can do about it.
991                 }
992         }
993
994         if(len) {
995                 failure = true;
996         }
997
998         close(pfd[0]);
999
1000         // Make sure the child process is really gone.
1001         int status = -1;
1002         pid_t result = waitpid(pid, &status, 0);
1003
1004 #ifdef SIGINT
1005         signal(SIGINT, SIG_DFL);
1006 #endif
1007
1008         bool failed = failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status);
1009
1010         if(failed) {
1011                 fprintf(stderr, "Error starting %s\n", c);
1012         }
1013
1014         free(c);
1015
1016         return failed ? EXIT_FAILURE : EXIT_SUCCESS;
1017 #endif
1018 }
1019
1020 static int cmd_stop(int argc, char *argv[]) {
1021         (void)argv;
1022
1023         if(argc > 1) {
1024                 fprintf(stderr, "Too many arguments!\n");
1025                 return 1;
1026         }
1027
1028 #ifdef HAVE_WINDOWS
1029         return remove_service() ? EXIT_SUCCESS : EXIT_FAILURE;
1030 #else
1031
1032         if(!stop_tincd()) {
1033                 if(pid) {
1034                         if(kill(pid, SIGTERM)) {
1035                                 fprintf(stderr, "Could not send TERM signal to process with PID %d: %s\n", pid, strerror(errno));
1036                                 return 1;
1037                         }
1038
1039                         fprintf(stderr, "Sent TERM signal to process with PID %d.\n", pid);
1040                         waitpid(pid, NULL, 0);
1041                         return 0;
1042                 }
1043
1044                 return 1;
1045         }
1046
1047         return 0;
1048 #endif
1049 }
1050
1051 static int cmd_restart(int argc, char *argv[]) {
1052         cmd_stop(1, argv);
1053         return cmd_start(argc, argv);
1054 }
1055
1056 static int cmd_reload(int argc, char *argv[]) {
1057         (void)argv;
1058
1059         if(argc > 1) {
1060                 fprintf(stderr, "Too many arguments!\n");
1061                 return 1;
1062         }
1063
1064         if(!connect_tincd(true)) {
1065                 return 1;
1066         }
1067
1068         sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
1069
1070         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RELOAD || result) {
1071                 fprintf(stderr, "Could not reload configuration.\n");
1072                 return 1;
1073         }
1074
1075         return 0;
1076
1077 }
1078
1079 static int dump_invitations(void) {
1080         char dname[PATH_MAX];
1081         snprintf(dname, sizeof(dname), "%s" SLASH "invitations", confbase);
1082         DIR *dir = opendir(dname);
1083
1084         if(!dir) {
1085                 if(errno == ENOENT) {
1086                         fprintf(stderr, "No outstanding invitations.\n");
1087                         return 0;
1088                 }
1089
1090                 fprintf(stderr, "Cannot not read directory %s: %s\n", dname, strerror(errno));
1091                 return 1;
1092         }
1093
1094         struct dirent *ent;
1095
1096         bool found = false;
1097
1098         while((ent = readdir(dir))) {
1099                 char buf[MAX_STRING_SIZE];
1100
1101                 if(b64decode_tinc(ent->d_name, buf, 24) != 18) {
1102                         continue;
1103                 }
1104
1105                 char fname[PATH_MAX];
1106
1107                 if((size_t)snprintf(fname, sizeof(fname), "%s" SLASH "%s", dname, ent->d_name) >= sizeof(fname)) {
1108                         fprintf(stderr, "Filename too long: %s" SLASH "%s\n", dname, ent->d_name);
1109                         continue;
1110                 }
1111
1112                 FILE *f = fopen(fname, "r");
1113
1114                 if(!f) {
1115                         fprintf(stderr, "Cannot open %s: %s\n", fname, strerror(errno));
1116                         continue;
1117                 }
1118
1119                 buf[0] = 0;
1120
1121                 if(!fgets(buf, sizeof(buf), f)) {
1122                         fprintf(stderr, "Invalid invitation file %s\n", fname);
1123                         fclose(f);
1124                         continue;
1125                 }
1126
1127                 fclose(f);
1128
1129                 char *eol = buf + strlen(buf);
1130
1131                 while(strchr("\t \r\n", *--eol)) {
1132                         *eol = 0;
1133                 }
1134
1135                 if(strncmp(buf, "Name = ", 7) || !check_id(buf + 7)) {
1136                         fprintf(stderr, "Invalid invitation file %s\n", fname);
1137                         continue;
1138                 }
1139
1140                 found = true;
1141                 printf("%s %s\n", ent->d_name, buf + 7);
1142         }
1143
1144         closedir(dir);
1145
1146         if(!found) {
1147                 fprintf(stderr, "No outstanding invitations.\n");
1148         }
1149
1150         return 0;
1151 }
1152
1153 static int cmd_dump(int argc, char *argv[]) {
1154         bool only_reachable = false;
1155
1156         if(argc > 2 && !strcasecmp(argv[1], "reachable")) {
1157                 if(strcasecmp(argv[2], "nodes")) {
1158                         fprintf(stderr, "`reachable' only supported for nodes.\n");
1159                         usage(true);
1160                         return 1;
1161                 }
1162
1163                 only_reachable = true;
1164                 argv++;
1165                 argc--;
1166         }
1167
1168         if(argc != 2) {
1169                 fprintf(stderr, "Invalid number of arguments.\n");
1170                 usage(true);
1171                 return 1;
1172         }
1173
1174         if(!strcasecmp(argv[1], "invitations")) {
1175                 return dump_invitations();
1176         }
1177
1178         if(!connect_tincd(true)) {
1179                 return 1;
1180         }
1181
1182         int do_graph = 0;
1183
1184         if(!strcasecmp(argv[1], "nodes")) {
1185                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1186         } else if(!strcasecmp(argv[1], "edges")) {
1187                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1188         } else if(!strcasecmp(argv[1], "subnets")) {
1189                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
1190         } else if(!strcasecmp(argv[1], "connections")) {
1191                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS);
1192         } else if(!strcasecmp(argv[1], "graph")) {
1193                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1194                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1195                 do_graph = 1;
1196         } else if(!strcasecmp(argv[1], "digraph")) {
1197                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
1198                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
1199                 do_graph = 2;
1200         } else {
1201                 fprintf(stderr, "Unknown dump type '%s'.\n", argv[1]);
1202                 usage(true);
1203                 return 1;
1204         }
1205
1206         if(do_graph == 1) {
1207                 printf("graph {\n");
1208         } else if(do_graph == 2) {
1209                 printf("digraph {\n");
1210         }
1211
1212         while(recvline(fd, line, sizeof(line))) {
1213                 char node1[4096], node2[4096];
1214                 int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, node1, node2);
1215
1216                 if(n == 2) {
1217                         if(do_graph && req == REQ_DUMP_NODES) {
1218                                 continue;
1219                         } else {
1220                                 if(do_graph) {
1221                                         printf("}\n");
1222                                 }
1223
1224                                 return 0;
1225                         }
1226                 }
1227
1228                 if(n < 2) {
1229                         break;
1230                 }
1231
1232                 char node[4096];
1233                 char id[4096];
1234                 char from[4096];
1235                 char to[4096];
1236                 char subnet[4096];
1237                 char host[4096];
1238                 char port[4096];
1239                 char local_host[4096];
1240                 char local_port[4096];
1241                 char via[4096];
1242                 char nexthop[4096];
1243                 int cipher, digest, maclength, compression, distance, socket, weight;
1244                 short int pmtu, minmtu, maxmtu;
1245                 unsigned int options;
1246                 node_status_t status;
1247                 long int last_state_change;
1248                 int udp_ping_rtt;
1249                 uint64_t in_packets, in_bytes, out_packets, out_bytes;
1250
1251                 switch(req) {
1252                 case REQ_DUMP_NODES: {
1253                         int n = sscanf(line, "%*d %*d %4095s %4095s %4095s port %4095s %d %d %d %d %x %"PRIx32" %4095s %4095s %d %hd %hd %hd %ld %d %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status.value, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change, &udp_ping_rtt, &in_packets, &in_bytes, &out_packets, &out_bytes);
1254
1255                         if(n != 22) {
1256                                 fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
1257                                 return 1;
1258                         }
1259
1260                         if(do_graph) {
1261                                 const char *color = "black";
1262
1263                                 if(!strcmp(host, "MYSELF")) {
1264                                         color = "green";
1265                                 } else if(!status.reachable) {
1266                                         color = "red";
1267                                 } else if(strcmp(via, node)) {
1268                                         color = "orange";
1269                                 } else if(!status.validkey) {
1270                                         color = "black";
1271                                 } else if(minmtu > 0) {
1272                                         color = "green";
1273                                 }
1274
1275                                 printf(" \"%s\" [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\"");
1276                         } else {
1277                                 if(only_reachable && !status.reachable) {
1278                                         continue;
1279                                 }
1280
1281                                 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,
1282                                        node, id, host, port, cipher, digest, maclength, compression, options, status.value, nexthop, via, distance, pmtu, minmtu, maxmtu, in_packets, in_bytes, out_packets, out_bytes);
1283
1284                                 if(udp_ping_rtt != -1) {
1285                                         printf(" rtt %d.%03d", udp_ping_rtt / 1000, udp_ping_rtt % 1000);
1286                                 }
1287
1288                                 printf("\n");
1289                         }
1290                 }
1291                 break;
1292
1293                 case REQ_DUMP_EDGES: {
1294                         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);
1295
1296                         if(n != 8) {
1297                                 fprintf(stderr, "Unable to parse edge dump from tincd.\n");
1298                                 return 1;
1299                         }
1300
1301                         if(do_graph) {
1302                                 float w = 1.0f + 65536.0f / (float)weight;
1303
1304                                 if(do_graph == 1 && strcmp(node1, node2) > 0) {
1305                                         printf(" \"%s\" -- \"%s\" [w = %f, weight = %f];\n", node1, node2, w, w);
1306                                 } else if(do_graph == 2) {
1307                                         printf(" \"%s\" -> \"%s\" [w = %f, weight = %f];\n", node1, node2, w, w);
1308                                 }
1309                         } else {
1310                                 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);
1311                         }
1312                 }
1313                 break;
1314
1315                 case REQ_DUMP_SUBNETS: {
1316                         int n = sscanf(line, "%*d %*d %4095s %4095s", subnet, node);
1317
1318                         if(n != 2) {
1319                                 fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
1320                                 return 1;
1321                         }
1322
1323                         printf("%s owner %s\n", strip_weight(subnet), node);
1324                 }
1325                 break;
1326
1327                 case REQ_DUMP_CONNECTIONS: {
1328                         int n = sscanf(line, "%*d %*d %4095s %4095s port %4095s %x %d %x", node, host, port, &options, &socket, &status.value);
1329
1330                         if(n != 6) {
1331                                 fprintf(stderr, "Unable to parse connection dump from tincd.\n");
1332                                 return 1;
1333                         }
1334
1335                         printf("%s at %s port %s options %x socket %d status %x\n", node, host, port, options, socket, status.value);
1336                 }
1337                 break;
1338
1339                 default:
1340                         fprintf(stderr, "Unable to parse dump from tincd.\n");
1341                         return 1;
1342                 }
1343         }
1344
1345         fprintf(stderr, "Error receiving dump.\n");
1346         return 1;
1347 }
1348
1349 static int cmd_purge(int argc, char *argv[]) {
1350         (void)argv;
1351
1352         if(argc > 1) {
1353                 fprintf(stderr, "Too many arguments!\n");
1354                 return 1;
1355         }
1356
1357         if(!connect_tincd(true)) {
1358                 return 1;
1359         }
1360
1361         sendline(fd, "%d %d", CONTROL, REQ_PURGE);
1362
1363         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_PURGE || result) {
1364                 fprintf(stderr, "Could not purge old information.\n");
1365                 return 1;
1366         }
1367
1368         return 0;
1369 }
1370
1371 static int cmd_debug(int argc, char *argv[]) {
1372         if(argc != 2) {
1373                 fprintf(stderr, "Invalid number of arguments.\n");
1374                 return 1;
1375         }
1376
1377         if(!connect_tincd(true)) {
1378                 return 1;
1379         }
1380
1381         int debuglevel = atoi(argv[1]);
1382         int origlevel;
1383
1384         sendline(fd, "%d %d %d", CONTROL, REQ_SET_DEBUG, debuglevel);
1385
1386         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &origlevel) != 3 || code != CONTROL || req != REQ_SET_DEBUG) {
1387                 fprintf(stderr, "Could not set debug level.\n");
1388                 return 1;
1389         }
1390
1391         fprintf(stderr, "Old level %d, new level %d.\n", origlevel, debuglevel);
1392         return 0;
1393 }
1394
1395 static int cmd_retry(int argc, char *argv[]) {
1396         (void)argv;
1397
1398         if(argc > 1) {
1399                 fprintf(stderr, "Too many arguments!\n");
1400                 return 1;
1401         }
1402
1403         if(!connect_tincd(true)) {
1404                 return 1;
1405         }
1406
1407         sendline(fd, "%d %d", CONTROL, REQ_RETRY);
1408
1409         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RETRY || result) {
1410                 fprintf(stderr, "Could not retry outgoing connections.\n");
1411                 return 1;
1412         }
1413
1414         return 0;
1415 }
1416
1417 static int cmd_connect(int argc, char *argv[]) {
1418         if(argc != 2) {
1419                 fprintf(stderr, "Invalid number of arguments.\n");
1420                 return 1;
1421         }
1422
1423         if(!check_id(argv[1])) {
1424                 fprintf(stderr, "Invalid name for node.\n");
1425                 return 1;
1426         }
1427
1428         if(!connect_tincd(true)) {
1429                 return 1;
1430         }
1431
1432         sendline(fd, "%d %d %s", CONTROL, REQ_CONNECT, argv[1]);
1433
1434         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_CONNECT || result) {
1435                 fprintf(stderr, "Could not connect to %s.\n", argv[1]);
1436                 return 1;
1437         }
1438
1439         return 0;
1440 }
1441
1442 static int cmd_disconnect(int argc, char *argv[]) {
1443         if(argc != 2) {
1444                 fprintf(stderr, "Invalid number of arguments.\n");
1445                 return 1;
1446         }
1447
1448         if(!check_id(argv[1])) {
1449                 fprintf(stderr, "Invalid name for node.\n");
1450                 return 1;
1451         }
1452
1453         if(!connect_tincd(true)) {
1454                 return 1;
1455         }
1456
1457         sendline(fd, "%d %d %s", CONTROL, REQ_DISCONNECT, argv[1]);
1458
1459         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_DISCONNECT || result) {
1460                 fprintf(stderr, "Could not disconnect %s.\n", argv[1]);
1461                 return 1;
1462         }
1463
1464         return 0;
1465 }
1466
1467 static int cmd_top(int argc, char *argv[]) {
1468         (void)argv;
1469
1470         if(argc > 1) {
1471                 fprintf(stderr, "Too many arguments!\n");
1472                 return 1;
1473         }
1474
1475 #ifdef HAVE_CURSES
1476
1477         if(!connect_tincd(true)) {
1478                 return 1;
1479         }
1480
1481         top(fd);
1482         return 0;
1483 #else
1484         fprintf(stderr, "This version of tinc was compiled without support for the curses library.\n");
1485         return 1;
1486 #endif
1487 }
1488
1489 static int cmd_pcap(int argc, char *argv[]) {
1490         if(argc > 2) {
1491                 fprintf(stderr, "Too many arguments!\n");
1492                 return 1;
1493         }
1494
1495         if(!connect_tincd(true)) {
1496                 return 1;
1497         }
1498
1499         pcap(fd, stdout, argc > 1 ? atoi(argv[1]) : 0);
1500         return 0;
1501 }
1502
1503 #ifdef SIGINT
1504 static void sigint_handler(int sig) {
1505         (void)sig;
1506
1507         fprintf(stderr, "\n");
1508         shutdown(fd, SHUT_RDWR);
1509 }
1510 #endif
1511
1512 static int cmd_log(int argc, char *argv[]) {
1513         if(argc > 2) {
1514                 fprintf(stderr, "Too many arguments!\n");
1515                 return 1;
1516         }
1517
1518         if(!connect_tincd(true)) {
1519                 return 1;
1520         }
1521
1522 #ifdef SIGINT
1523         signal(SIGINT, sigint_handler);
1524 #endif
1525
1526         logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1);
1527
1528 #ifdef SIGINT
1529         signal(SIGINT, SIG_DFL);
1530 #endif
1531
1532         closesocket(fd);
1533         fd = -1;
1534         return 0;
1535 }
1536
1537 static int cmd_pid(int argc, char *argv[]) {
1538         (void)argv;
1539
1540         if(argc > 1) {
1541                 fprintf(stderr, "Too many arguments!\n");
1542                 return 1;
1543         }
1544
1545         if(!connect_tincd(true) || !pid) {
1546                 return 1;
1547         }
1548
1549         printf("%d\n", pid);
1550         return 0;
1551 }
1552
1553 size_t rstrip(char *value) {
1554         size_t len = strlen(value);
1555
1556         while(len && strchr("\t\r\n ", value[len - 1])) {
1557                 value[--len] = 0;
1558         }
1559
1560         return len;
1561 }
1562
1563 char *get_my_name(bool verbose) {
1564         FILE *f = fopen(tinc_conf, "r");
1565
1566         if(!f) {
1567                 if(verbose) {
1568                         fprintf(stderr, "Could not open %s: %s\n", tinc_conf, strerror(errno));
1569                 }
1570
1571                 return NULL;
1572         }
1573
1574         char buf[4096];
1575         char *value;
1576
1577         while(fgets(buf, sizeof(buf), f)) {
1578                 size_t len = strcspn(buf, "\t =");
1579                 value = buf + len;
1580                 value += strspn(value, "\t ");
1581
1582                 if(*value == '=') {
1583                         value++;
1584                         value += strspn(value, "\t ");
1585                 }
1586
1587                 if(!rstrip(value)) {
1588                         continue;
1589                 }
1590
1591                 buf[len] = 0;
1592
1593                 if(strcasecmp(buf, "Name")) {
1594                         continue;
1595                 }
1596
1597                 if(*value) {
1598                         fclose(f);
1599                         return replace_name(value);
1600                 }
1601         }
1602
1603         fclose(f);
1604
1605         if(verbose) {
1606                 fprintf(stderr, "Could not find Name in %s.\n", tinc_conf);
1607         }
1608
1609         return NULL;
1610 }
1611
1612 ecdsa_t *get_pubkey(FILE *f) {
1613         char buf[4096];
1614         char *value;
1615
1616         while(fgets(buf, sizeof(buf), f)) {
1617                 size_t len = strcspn(buf, "\t =");
1618                 value = buf + len;
1619                 value += strspn(value, "\t ");
1620
1621                 if(*value == '=') {
1622                         value++;
1623                         value += strspn(value, "\t ");
1624                 }
1625
1626                 if(!rstrip(value)) {
1627                         continue;
1628                 }
1629
1630                 buf[len] = 0;
1631
1632                 if(strcasecmp(buf, "Ed25519PublicKey")) {
1633                         continue;
1634                 }
1635
1636                 if(*value) {
1637                         return ecdsa_set_base64_public_key(value);
1638                 }
1639         }
1640
1641         return NULL;
1642 }
1643
1644 const var_t variables[] = {
1645         /* Server configuration */
1646         {"AddressFamily", VAR_SERVER | VAR_SAFE},
1647         {"AutoConnect", VAR_SERVER | VAR_SAFE},
1648         {"BindToAddress", VAR_SERVER | VAR_MULTIPLE},
1649         {"BindToInterface", VAR_SERVER},
1650         {"Broadcast", VAR_SERVER | VAR_SAFE},
1651         {"BroadcastSubnet", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1652         {"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1653         {"DecrementTTL", VAR_SERVER | VAR_SAFE},
1654         {"Device", VAR_SERVER},
1655         {"DeviceStandby", VAR_SERVER},
1656         {"DeviceType", VAR_SERVER},
1657         {"DirectOnly", VAR_SERVER | VAR_SAFE},
1658         {"Ed25519PrivateKeyFile", VAR_SERVER},
1659         {"ExperimentalProtocol", VAR_SERVER},
1660         {"Forwarding", VAR_SERVER},
1661         {"FWMark", VAR_SERVER},
1662         {"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
1663         {"Hostnames", VAR_SERVER},
1664         {"IffOneQueue", VAR_SERVER},
1665         {"Interface", VAR_SERVER},
1666         {"InvitationExpire", VAR_SERVER},
1667         {"KeyExpire", VAR_SERVER | VAR_SAFE},
1668         {"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
1669         {"LocalDiscovery", VAR_SERVER | VAR_SAFE},
1670         {"LogLevel", VAR_SERVER},
1671         {"MACExpire", VAR_SERVER | VAR_SAFE},
1672         {"MaxConnectionBurst", VAR_SERVER | VAR_SAFE},
1673         {"MaxOutputBufferSize", VAR_SERVER | VAR_SAFE},
1674         {"MaxTimeout", VAR_SERVER | VAR_SAFE},
1675         {"Mode", VAR_SERVER | VAR_SAFE},
1676         {"Name", VAR_SERVER},
1677         {"PingInterval", VAR_SERVER | VAR_SAFE},
1678         {"PingTimeout", VAR_SERVER | VAR_SAFE},
1679         {"PriorityInheritance", VAR_SERVER},
1680         {"PrivateKey", VAR_SERVER | VAR_OBSOLETE},
1681         {"PrivateKeyFile", VAR_SERVER},
1682         {"ProcessPriority", VAR_SERVER},
1683         {"Proxy", VAR_SERVER},
1684         {"ReplayWindow", VAR_SERVER | VAR_SAFE},
1685         {"ScriptsExtension", VAR_SERVER},
1686         {"ScriptsInterpreter", VAR_SERVER},
1687         {"StrictSubnets", VAR_SERVER | VAR_SAFE},
1688         {"TunnelServer", VAR_SERVER | VAR_SAFE},
1689         {"UDPDiscovery", VAR_SERVER | VAR_SAFE},
1690         {"UDPDiscoveryKeepaliveInterval", VAR_SERVER | VAR_SAFE},
1691         {"UDPDiscoveryInterval", VAR_SERVER | VAR_SAFE},
1692         {"UDPDiscoveryTimeout", VAR_SERVER | VAR_SAFE},
1693         {"MTUInfoInterval", VAR_SERVER | VAR_SAFE},
1694         {"UDPInfoInterval", VAR_SERVER | VAR_SAFE},
1695         {"UDPRcvBuf", VAR_SERVER},
1696         {"UDPSndBuf", VAR_SERVER},
1697         {"UPnP", VAR_SERVER},
1698         {"UPnPDiscoverWait", VAR_SERVER},
1699         {"UPnPRefreshPeriod", VAR_SERVER},
1700         {"VDEGroup", VAR_SERVER},
1701         {"VDEPort", VAR_SERVER},
1702         /* Host configuration */
1703         {"Address", VAR_HOST | VAR_MULTIPLE},
1704         {"Cipher", VAR_SERVER | VAR_HOST},
1705         {"ClampMSS", VAR_SERVER | VAR_HOST | VAR_SAFE},
1706         {"Compression", VAR_SERVER | VAR_HOST | VAR_SAFE},
1707         {"Digest", VAR_SERVER | VAR_HOST},
1708         {"Ed25519PublicKey", VAR_HOST},
1709         {"Ed25519PublicKeyFile", VAR_SERVER | VAR_HOST},
1710         {"IndirectData", VAR_SERVER | VAR_HOST | VAR_SAFE},
1711         {"MACLength", VAR_SERVER | VAR_HOST},
1712         {"PMTU", VAR_SERVER | VAR_HOST},
1713         {"PMTUDiscovery", VAR_SERVER | VAR_HOST},
1714         {"Port", VAR_HOST},
1715         {"PublicKey", VAR_HOST | VAR_OBSOLETE},
1716         {"PublicKeyFile", VAR_SERVER | VAR_HOST | VAR_OBSOLETE},
1717         {"Subnet", VAR_HOST | VAR_MULTIPLE | VAR_SAFE},
1718         {"TCPOnly", VAR_SERVER | VAR_HOST | VAR_SAFE},
1719         {"Weight", VAR_HOST | VAR_SAFE},
1720         {NULL, 0}
1721 };
1722
1723 static int cmd_config(int argc, char *argv[]) {
1724         if(argc < 2) {
1725                 fprintf(stderr, "Invalid number of arguments.\n");
1726                 return 1;
1727         }
1728
1729         if(strcasecmp(argv[0], "config")) {
1730                 argv--, argc++;
1731         }
1732
1733         int action = -2;
1734
1735         if(!strcasecmp(argv[1], "get")) {
1736                 argv++, argc--;
1737         } else if(!strcasecmp(argv[1], "add")) {
1738                 argv++, argc--, action = 1;
1739         } else if(!strcasecmp(argv[1], "del")) {
1740                 argv++, argc--, action = -1;
1741         } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) {
1742                 argv++, argc--, action = 0;
1743         }
1744
1745         if(argc < 2) {
1746                 fprintf(stderr, "Invalid number of arguments.\n");
1747                 return 1;
1748         }
1749
1750         // Concatenate the rest of the command line
1751         strncpy(line, argv[1], sizeof(line) - 1);
1752
1753         for(int i = 2; i < argc; i++) {
1754                 strncat(line, " ", sizeof(line) - 1 - strlen(line));
1755                 strncat(line, argv[i], sizeof(line) - 1 - strlen(line));
1756         }
1757
1758         // Liberal parsing into node name, variable name and value.
1759         char *node = NULL;
1760         char *variable;
1761         char *value;
1762         size_t len;
1763
1764         len = strcspn(line, "\t =");
1765         value = line + len;
1766         value += strspn(value, "\t ");
1767
1768         if(*value == '=') {
1769                 value++;
1770                 value += strspn(value, "\t ");
1771         }
1772
1773         line[len] = '\0';
1774         variable = strchr(line, '.');
1775
1776         if(variable) {
1777                 node = line;
1778                 *variable++ = 0;
1779         } else {
1780                 variable = line;
1781         }
1782
1783         if(!*variable) {
1784                 fprintf(stderr, "No variable given.\n");
1785                 return 1;
1786         }
1787
1788         if(action >= 0 && !*value) {
1789                 fprintf(stderr, "No value for variable given.\n");
1790                 return 1;
1791         }
1792
1793         if(action < -1 && *value) {
1794                 action = 0;
1795         }
1796
1797         /* Some simple checks. */
1798         bool found = false;
1799         bool warnonremove = false;
1800
1801         for(int i = 0; variables[i].name; i++) {
1802                 if(strcasecmp(variables[i].name, variable)) {
1803                         continue;
1804                 }
1805
1806                 found = true;
1807                 variable = (char *)variables[i].name;
1808
1809                 if(!strcasecmp(variable, "Subnet") && *value) {
1810                         subnet_t s = {0};
1811
1812                         if(!str2net(&s, value)) {
1813                                 fprintf(stderr, "Malformed subnet definition %s\n", value);
1814                                 return 1;
1815                         }
1816
1817                         if(!subnetcheck(s)) {
1818                                 fprintf(stderr, "Network address and prefix length do not match: %s\n", value);
1819                                 return 1;
1820                         }
1821                 }
1822
1823                 /* Discourage use of obsolete variables. */
1824
1825                 if(variables[i].type & VAR_OBSOLETE && action >= 0) {
1826                         if(force) {
1827                                 fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable);
1828                         } else {
1829                                 fprintf(stderr, "%s is an obsolete variable! Use --force to use it anyway.\n", variable);
1830                                 return 1;
1831                         }
1832                 }
1833
1834                 /* Don't put server variables in host config files */
1835
1836                 if(node && !(variables[i].type & VAR_HOST) && action >= 0) {
1837                         if(force) {
1838                                 fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable);
1839                         } else {
1840                                 fprintf(stderr, "%s is not a host configuration variable! Use --force to use it anyway.\n", variable);
1841                                 return 1;
1842                         }
1843                 }
1844
1845                 /* Should this go into our own host config file? */
1846
1847                 if(!node && !(variables[i].type & VAR_SERVER)) {
1848                         node = get_my_name(true);
1849
1850                         if(!node) {
1851                                 return 1;
1852                         }
1853                 }
1854
1855                 /* Change "add" into "set" for variables that do not allow multiple occurrences.
1856                    Turn on warnings when it seems variables might be removed unintentionally. */
1857
1858                 if(action == 1 && !(variables[i].type & VAR_MULTIPLE)) {
1859                         warnonremove = true;
1860                         action = 0;
1861                 } else if(action == 0 && (variables[i].type & VAR_MULTIPLE)) {
1862                         warnonremove = true;
1863                 }
1864
1865                 break;
1866         }
1867
1868         if(node && !check_id(node)) {
1869                 fprintf(stderr, "Invalid name for node.\n");
1870
1871                 if(node != line) {
1872                         free(node);
1873                 }
1874
1875                 return 1;
1876         }
1877
1878         if(!found) {
1879                 if(force || action < 0) {
1880                         fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable);
1881                 } else {
1882                         fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable);
1883
1884                         if(node && node != line) {
1885                                 free(node);
1886                         }
1887
1888                         return 1;
1889                 }
1890         }
1891
1892         // Open the right configuration file.
1893         char filename[PATH_MAX];
1894
1895         if(node) {
1896                 if((size_t)snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node) >= sizeof(filename)) {
1897                         fprintf(stderr, "Filename too long: %s" SLASH "%s\n", hosts_dir, node);
1898                         free(node);
1899                         return 1;
1900                 }
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_WINDOWS
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_WINDOWS
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_WINDOWS
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                 closesocket(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 static int run_command(int argc, char *argv[]) {
3271         if(optind >= argc) {
3272                 return cmd_shell(argc, argv);
3273         }
3274
3275         for(int i = 0; commands[i].command; i++) {
3276                 if(!strcasecmp(argv[optind], commands[i].command)) {
3277                         return commands[i].function(argc - optind, argv + optind);
3278                 }
3279         }
3280
3281         fprintf(stderr, "Unknown command `%s'.\n", argv[optind]);
3282         usage(true);
3283         return 1;
3284 }
3285
3286 int main(int argc, char *argv[]) {
3287         program_name = argv[0];
3288         orig_argv = argv;
3289         tty = isatty(0) && isatty(1);
3290
3291         if(!parse_options(argc, argv)) {
3292                 return 1;
3293         }
3294
3295         make_names(false);
3296         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
3297         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
3298         atexit(cleanup);
3299
3300         if(show_version) {
3301                 version();
3302                 return 0;
3303         }
3304
3305         if(show_help) {
3306                 usage(false);
3307                 return 0;
3308         }
3309
3310 #ifdef HAVE_WINDOWS
3311         static struct WSAData wsa_state;
3312
3313         if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
3314                 fprintf(stderr, "System call `%s' failed: %s\n", "WSAStartup", winerror(GetLastError()));
3315                 return false;
3316         }
3317
3318 #endif
3319
3320         gettimeofday(&now, NULL);
3321         random_init();
3322         crypto_init();
3323         prng_init();
3324
3325         int result = run_command(argc, argv);
3326
3327         random_exit();
3328
3329         return result;
3330 }