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