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