Releasing 1.1pre16.
[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
1302                 switch(req) {
1303                 case REQ_DUMP_NODES: {
1304                         int n = sscanf(line, "%*d %*d %4095s %4095s %4095s port %4095s %d %d %d %d %x %x %4095s %4095s %d %hd %hd %hd %ld", node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
1305
1306                         if(n != 17) {
1307                                 fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
1308                                 return 1;
1309                         }
1310
1311                         memcpy(&status, &status_int, sizeof(status));
1312
1313                         if(do_graph) {
1314                                 const char *color = "black";
1315
1316                                 if(!strcmp(host, "MYSELF")) {
1317                                         color = "green";
1318                                 } else if(!status.reachable) {
1319                                         color = "red";
1320                                 } else if(strcmp(via, node)) {
1321                                         color = "orange";
1322                                 } else if(!status.validkey) {
1323                                         color = "black";
1324                                 } else if(minmtu > 0) {
1325                                         color = "green";
1326                                 }
1327
1328                                 printf(" %s [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\"");
1329                         } else {
1330                                 if(only_reachable && !status.reachable) {
1331                                         continue;
1332                                 }
1333
1334                                 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)\n",
1335                                        node, id, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu);
1336                         }
1337                 }
1338                 break;
1339
1340                 case REQ_DUMP_EDGES: {
1341                         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);
1342
1343                         if(n != 8) {
1344                                 fprintf(stderr, "Unable to parse edge dump from tincd.\n");
1345                                 return 1;
1346                         }
1347
1348                         if(do_graph) {
1349                                 float w = 1 + 65536.0 / weight;
1350
1351                                 if(do_graph == 1 && strcmp(node1, node2) > 0) {
1352                                         printf(" %s -- %s [w = %f, weight = %f];\n", node1, node2, w, w);
1353                                 } else if(do_graph == 2) {
1354                                         printf(" %s -> %s [w = %f, weight = %f];\n", node1, node2, w, w);
1355                                 }
1356                         } else {
1357                                 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);
1358                         }
1359                 }
1360                 break;
1361
1362                 case REQ_DUMP_SUBNETS: {
1363                         int n = sscanf(line, "%*d %*d %4095s %4095s", subnet, node);
1364
1365                         if(n != 2) {
1366                                 fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
1367                                 return 1;
1368                         }
1369
1370                         printf("%s owner %s\n", strip_weight(subnet), node);
1371                 }
1372                 break;
1373
1374                 case REQ_DUMP_CONNECTIONS: {
1375                         int n = sscanf(line, "%*d %*d %4095s %4095s port %4095s %x %d %x", node, host, port, &options, &socket, &status_int);
1376
1377                         if(n != 6) {
1378                                 fprintf(stderr, "Unable to parse connection dump from tincd.\n");
1379                                 return 1;
1380                         }
1381
1382                         printf("%s at %s port %s options %x socket %d status %x\n", node, host, port, options, socket, status_int);
1383                 }
1384                 break;
1385
1386                 default:
1387                         fprintf(stderr, "Unable to parse dump from tincd.\n");
1388                         return 1;
1389                 }
1390         }
1391
1392         fprintf(stderr, "Error receiving dump.\n");
1393         return 1;
1394 }
1395
1396 static int cmd_purge(int argc, char *argv[]) {
1397         if(argc > 1) {
1398                 fprintf(stderr, "Too many arguments!\n");
1399                 return 1;
1400         }
1401
1402         if(!connect_tincd(true)) {
1403                 return 1;
1404         }
1405
1406         sendline(fd, "%d %d", CONTROL, REQ_PURGE);
1407
1408         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_PURGE || result) {
1409                 fprintf(stderr, "Could not purge old information.\n");
1410                 return 1;
1411         }
1412
1413         return 0;
1414 }
1415
1416 static int cmd_debug(int argc, char *argv[]) {
1417         if(argc != 2) {
1418                 fprintf(stderr, "Invalid number of arguments.\n");
1419                 return 1;
1420         }
1421
1422         if(!connect_tincd(true)) {
1423                 return 1;
1424         }
1425
1426         int debuglevel = atoi(argv[1]);
1427         int origlevel;
1428
1429         sendline(fd, "%d %d %d", CONTROL, REQ_SET_DEBUG, debuglevel);
1430
1431         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &origlevel) != 3 || code != CONTROL || req != REQ_SET_DEBUG) {
1432                 fprintf(stderr, "Could not set debug level.\n");
1433                 return 1;
1434         }
1435
1436         fprintf(stderr, "Old level %d, new level %d.\n", origlevel, debuglevel);
1437         return 0;
1438 }
1439
1440 static int cmd_retry(int argc, char *argv[]) {
1441         if(argc > 1) {
1442                 fprintf(stderr, "Too many arguments!\n");
1443                 return 1;
1444         }
1445
1446         if(!connect_tincd(true)) {
1447                 return 1;
1448         }
1449
1450         sendline(fd, "%d %d", CONTROL, REQ_RETRY);
1451
1452         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RETRY || result) {
1453                 fprintf(stderr, "Could not retry outgoing connections.\n");
1454                 return 1;
1455         }
1456
1457         return 0;
1458 }
1459
1460 static int cmd_connect(int argc, char *argv[]) {
1461         if(argc != 2) {
1462                 fprintf(stderr, "Invalid number of arguments.\n");
1463                 return 1;
1464         }
1465
1466         if(!check_id(argv[1])) {
1467                 fprintf(stderr, "Invalid name for node.\n");
1468                 return 1;
1469         }
1470
1471         if(!connect_tincd(true)) {
1472                 return 1;
1473         }
1474
1475         sendline(fd, "%d %d %s", CONTROL, REQ_CONNECT, argv[1]);
1476
1477         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_CONNECT || result) {
1478                 fprintf(stderr, "Could not connect to %s.\n", argv[1]);
1479                 return 1;
1480         }
1481
1482         return 0;
1483 }
1484
1485 static int cmd_disconnect(int argc, char *argv[]) {
1486         if(argc != 2) {
1487                 fprintf(stderr, "Invalid number of arguments.\n");
1488                 return 1;
1489         }
1490
1491         if(!check_id(argv[1])) {
1492                 fprintf(stderr, "Invalid name for node.\n");
1493                 return 1;
1494         }
1495
1496         if(!connect_tincd(true)) {
1497                 return 1;
1498         }
1499
1500         sendline(fd, "%d %d %s", CONTROL, REQ_DISCONNECT, argv[1]);
1501
1502         if(!recvline(fd, line, sizeof(line)) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_DISCONNECT || result) {
1503                 fprintf(stderr, "Could not disconnect %s.\n", argv[1]);
1504                 return 1;
1505         }
1506
1507         return 0;
1508 }
1509
1510 static int cmd_top(int argc, char *argv[]) {
1511         if(argc > 1) {
1512                 fprintf(stderr, "Too many arguments!\n");
1513                 return 1;
1514         }
1515
1516 #ifdef HAVE_CURSES
1517
1518         if(!connect_tincd(true)) {
1519                 return 1;
1520         }
1521
1522         top(fd);
1523         return 0;
1524 #else
1525         fprintf(stderr, "This version of tinc was compiled without support for the curses library.\n");
1526         return 1;
1527 #endif
1528 }
1529
1530 static int cmd_pcap(int argc, char *argv[]) {
1531         if(argc > 2) {
1532                 fprintf(stderr, "Too many arguments!\n");
1533                 return 1;
1534         }
1535
1536         if(!connect_tincd(true)) {
1537                 return 1;
1538         }
1539
1540         pcap(fd, stdout, argc > 1 ? atoi(argv[1]) : 0);
1541         return 0;
1542 }
1543
1544 #ifdef SIGINT
1545 static void sigint_handler(int sig) {
1546         fprintf(stderr, "\n");
1547         shutdown(fd, SHUT_RDWR);
1548 }
1549 #endif
1550
1551 static int cmd_log(int argc, char *argv[]) {
1552         if(argc > 2) {
1553                 fprintf(stderr, "Too many arguments!\n");
1554                 return 1;
1555         }
1556
1557         if(!connect_tincd(true)) {
1558                 return 1;
1559         }
1560
1561 #ifdef SIGINT
1562         signal(SIGINT, sigint_handler);
1563 #endif
1564
1565         logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1);
1566
1567 #ifdef SIGINT
1568         signal(SIGINT, SIG_DFL);
1569 #endif
1570
1571         close(fd);
1572         fd = -1;
1573         return 0;
1574 }
1575
1576 static int cmd_pid(int argc, char *argv[]) {
1577         if(argc > 1) {
1578                 fprintf(stderr, "Too many arguments!\n");
1579                 return 1;
1580         }
1581
1582         if(!connect_tincd(true) || !pid) {
1583                 return 1;
1584         }
1585
1586         printf("%d\n", pid);
1587         return 0;
1588 }
1589
1590 int rstrip(char *value) {
1591         int len = strlen(value);
1592
1593         while(len && strchr("\t\r\n ", value[len - 1])) {
1594                 value[--len] = 0;
1595         }
1596
1597         return len;
1598 }
1599
1600 char *get_my_name(bool verbose) {
1601         FILE *f = fopen(tinc_conf, "r");
1602
1603         if(!f) {
1604                 if(verbose) {
1605                         fprintf(stderr, "Could not open %s: %s\n", tinc_conf, strerror(errno));
1606                 }
1607
1608                 return NULL;
1609         }
1610
1611         char buf[4096];
1612         char *value;
1613
1614         while(fgets(buf, sizeof(buf), f)) {
1615                 int len = strcspn(buf, "\t =");
1616                 value = buf + len;
1617                 value += strspn(value, "\t ");
1618
1619                 if(*value == '=') {
1620                         value++;
1621                         value += strspn(value, "\t ");
1622                 }
1623
1624                 if(!rstrip(value)) {
1625                         continue;
1626                 }
1627
1628                 buf[len] = 0;
1629
1630                 if(strcasecmp(buf, "Name")) {
1631                         continue;
1632                 }
1633
1634                 if(*value) {
1635                         fclose(f);
1636                         return replace_name(value);
1637                 }
1638         }
1639
1640         fclose(f);
1641
1642         if(verbose) {
1643                 fprintf(stderr, "Could not find Name in %s.\n", tinc_conf);
1644         }
1645
1646         return NULL;
1647 }
1648
1649 ecdsa_t *get_pubkey(FILE *f) {
1650         char buf[4096];
1651         char *value;
1652
1653         while(fgets(buf, sizeof(buf), f)) {
1654                 int len = strcspn(buf, "\t =");
1655                 value = buf + len;
1656                 value += strspn(value, "\t ");
1657
1658                 if(*value == '=') {
1659                         value++;
1660                         value += strspn(value, "\t ");
1661                 }
1662
1663                 if(!rstrip(value)) {
1664                         continue;
1665                 }
1666
1667                 buf[len] = 0;
1668
1669                 if(strcasecmp(buf, "Ed25519PublicKey")) {
1670                         continue;
1671                 }
1672
1673                 if(*value) {
1674                         return ecdsa_set_base64_public_key(value);
1675                 }
1676         }
1677
1678         return NULL;
1679 }
1680
1681 const var_t variables[] = {
1682         /* Server configuration */
1683         {"AddressFamily", VAR_SERVER},
1684         {"AutoConnect", VAR_SERVER | VAR_SAFE},
1685         {"BindToAddress", VAR_SERVER | VAR_MULTIPLE},
1686         {"BindToInterface", VAR_SERVER},
1687         {"Broadcast", VAR_SERVER | VAR_SAFE},
1688         {"BroadcastSubnet", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1689         {"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1690         {"DecrementTTL", VAR_SERVER},
1691         {"Device", VAR_SERVER},
1692         {"DeviceStandby", VAR_SERVER},
1693         {"DeviceType", VAR_SERVER},
1694         {"DirectOnly", VAR_SERVER},
1695         {"Ed25519PrivateKeyFile", VAR_SERVER},
1696         {"ExperimentalProtocol", VAR_SERVER},
1697         {"Forwarding", VAR_SERVER},
1698         {"FWMark", VAR_SERVER},
1699         {"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
1700         {"Hostnames", VAR_SERVER},
1701         {"IffOneQueue", VAR_SERVER},
1702         {"Interface", VAR_SERVER},
1703         {"InvitationExpire", VAR_SERVER},
1704         {"KeyExpire", VAR_SERVER},
1705         {"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
1706         {"LocalDiscovery", VAR_SERVER},
1707         {"LogLevel", VAR_SERVER},
1708         {"MACExpire", VAR_SERVER},
1709         {"MaxConnectionBurst", VAR_SERVER},
1710         {"MaxOutputBufferSize", VAR_SERVER},
1711         {"MaxTimeout", VAR_SERVER},
1712         {"Mode", VAR_SERVER | VAR_SAFE},
1713         {"Name", VAR_SERVER},
1714         {"PingInterval", VAR_SERVER},
1715         {"PingTimeout", VAR_SERVER},
1716         {"PriorityInheritance", VAR_SERVER},
1717         {"PrivateKey", VAR_SERVER | VAR_OBSOLETE},
1718         {"PrivateKeyFile", VAR_SERVER},
1719         {"ProcessPriority", VAR_SERVER},
1720         {"Proxy", VAR_SERVER},
1721         {"ReplayWindow", VAR_SERVER},
1722         {"ScriptsExtension", VAR_SERVER},
1723         {"ScriptsInterpreter", VAR_SERVER},
1724         {"StrictSubnets", VAR_SERVER},
1725         {"TunnelServer", VAR_SERVER},
1726         {"UDPDiscovery", VAR_SERVER},
1727         {"UDPDiscoveryKeepaliveInterval", VAR_SERVER},
1728         {"UDPDiscoveryInterval", VAR_SERVER},
1729         {"UDPDiscoveryTimeout", VAR_SERVER},
1730         {"MTUInfoInterval", VAR_SERVER},
1731         {"UDPInfoInterval", VAR_SERVER},
1732         {"UDPRcvBuf", VAR_SERVER},
1733         {"UDPSndBuf", VAR_SERVER},
1734         {"UPnP", VAR_SERVER},
1735         {"UPnPDiscoverWait", VAR_SERVER},
1736         {"UPnPRefreshPeriod", VAR_SERVER},
1737         {"VDEGroup", VAR_SERVER},
1738         {"VDEPort", VAR_SERVER},
1739         /* Host configuration */
1740         {"Address", VAR_HOST | VAR_MULTIPLE},
1741         {"Cipher", VAR_SERVER | VAR_HOST},
1742         {"ClampMSS", VAR_SERVER | VAR_HOST},
1743         {"Compression", VAR_SERVER | VAR_HOST},
1744         {"Digest", VAR_SERVER | VAR_HOST},
1745         {"Ed25519PublicKey", VAR_HOST},
1746         {"Ed25519PublicKeyFile", VAR_SERVER | VAR_HOST},
1747         {"IndirectData", VAR_SERVER | VAR_HOST},
1748         {"MACLength", VAR_SERVER | VAR_HOST},
1749         {"PMTU", VAR_SERVER | VAR_HOST},
1750         {"PMTUDiscovery", VAR_SERVER | VAR_HOST},
1751         {"Port", VAR_HOST},
1752         {"PublicKey", VAR_HOST | VAR_OBSOLETE},
1753         {"PublicKeyFile", VAR_SERVER | VAR_HOST | VAR_OBSOLETE},
1754         {"Subnet", VAR_HOST | VAR_MULTIPLE | VAR_SAFE},
1755         {"TCPOnly", VAR_SERVER | VAR_HOST},
1756         {"Weight", VAR_HOST | VAR_SAFE},
1757         {NULL, 0}
1758 };
1759
1760 static int cmd_config(int argc, char *argv[]) {
1761         if(argc < 2) {
1762                 fprintf(stderr, "Invalid number of arguments.\n");
1763                 return 1;
1764         }
1765
1766         if(strcasecmp(argv[0], "config")) {
1767                 argv--, argc++;
1768         }
1769
1770         int action = -2;
1771
1772         if(!strcasecmp(argv[1], "get")) {
1773                 argv++, argc--;
1774         } else if(!strcasecmp(argv[1], "add")) {
1775                 argv++, argc--, action = 1;
1776         } else if(!strcasecmp(argv[1], "del")) {
1777                 argv++, argc--, action = -1;
1778         } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) {
1779                 argv++, argc--, action = 0;
1780         }
1781
1782         if(argc < 2) {
1783                 fprintf(stderr, "Invalid number of arguments.\n");
1784                 return 1;
1785         }
1786
1787         // Concatenate the rest of the command line
1788         strncpy(line, argv[1], sizeof(line) - 1);
1789
1790         for(int i = 2; i < argc; i++) {
1791                 strncat(line, " ", sizeof(line) - 1 - strlen(line));
1792                 strncat(line, argv[i], sizeof(line) - 1 - strlen(line));
1793         }
1794
1795         // Liberal parsing into node name, variable name and value.
1796         char *node = NULL;
1797         char *variable;
1798         char *value;
1799         int len;
1800
1801         len = strcspn(line, "\t =");
1802         value = line + len;
1803         value += strspn(value, "\t ");
1804
1805         if(*value == '=') {
1806                 value++;
1807                 value += strspn(value, "\t ");
1808         }
1809
1810         line[len] = '\0';
1811         variable = strchr(line, '.');
1812
1813         if(variable) {
1814                 node = line;
1815                 *variable++ = 0;
1816         } else {
1817                 variable = line;
1818         }
1819
1820         if(!*variable) {
1821                 fprintf(stderr, "No variable given.\n");
1822                 return 1;
1823         }
1824
1825         if(action >= 0 && !*value) {
1826                 fprintf(stderr, "No value for variable given.\n");
1827                 return 1;
1828         }
1829
1830         if(action < -1 && *value) {
1831                 action = 0;
1832         }
1833
1834         /* Some simple checks. */
1835         bool found = false;
1836         bool warnonremove = false;
1837
1838         for(int i = 0; variables[i].name; i++) {
1839                 if(strcasecmp(variables[i].name, variable)) {
1840                         continue;
1841                 }
1842
1843                 found = true;
1844                 variable = (char *)variables[i].name;
1845
1846                 /* Discourage use of obsolete variables. */
1847
1848                 if(variables[i].type & VAR_OBSOLETE && action >= 0) {
1849                         if(force) {
1850                                 fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable);
1851                         } else {
1852                                 fprintf(stderr, "%s is an obsolete variable! Use --force to use it anyway.\n", variable);
1853                                 return 1;
1854                         }
1855                 }
1856
1857                 /* Don't put server variables in host config files */
1858
1859                 if(node && !(variables[i].type & VAR_HOST) && action >= 0) {
1860                         if(force) {
1861                                 fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable);
1862                         } else {
1863                                 fprintf(stderr, "%s is not a host configuration variable! Use --force to use it anyway.\n", variable);
1864                                 return 1;
1865                         }
1866                 }
1867
1868                 /* Should this go into our own host config file? */
1869
1870                 if(!node && !(variables[i].type & VAR_SERVER)) {
1871                         node = get_my_name(true);
1872
1873                         if(!node) {
1874                                 return 1;
1875                         }
1876                 }
1877
1878                 /* Change "add" into "set" for variables that do not allow multiple occurrences.
1879                    Turn on warnings when it seems variables might be removed unintentionally. */
1880
1881                 if(action == 1 && !(variables[i].type & VAR_MULTIPLE)) {
1882                         warnonremove = true;
1883                         action = 0;
1884                 } else if(action == 0 && (variables[i].type & VAR_MULTIPLE)) {
1885                         warnonremove = true;
1886                 }
1887
1888                 break;
1889         }
1890
1891         if(node && !check_id(node)) {
1892                 fprintf(stderr, "Invalid name for node.\n");
1893                 return 1;
1894         }
1895
1896         if(!found) {
1897                 if(force || action < 0) {
1898                         fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable);
1899                 } else {
1900                         fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable);
1901                         return 1;
1902                 }
1903         }
1904
1905         // Open the right configuration file.
1906         char filename[PATH_MAX];
1907
1908         if(node) {
1909                 snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node);
1910         } else {
1911                 snprintf(filename, sizeof(filename), "%s", tinc_conf);
1912         }
1913
1914         FILE *f = fopen(filename, "r");
1915
1916         if(!f) {
1917                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
1918                 return 1;
1919         }
1920
1921         char tmpfile[PATH_MAX];
1922         FILE *tf = NULL;
1923
1924         if(action >= -1) {
1925                 snprintf(tmpfile, sizeof(tmpfile), "%s.config.tmp", filename);
1926                 tf = fopen(tmpfile, "w");
1927
1928                 if(!tf) {
1929                         fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
1930                         fclose(f);
1931                         return 1;
1932                 }
1933         }
1934
1935         // Copy the file, making modifications on the fly, unless we are just getting a value.
1936         char buf1[4096];
1937         char buf2[4096];
1938         bool set = false;
1939         bool removed = false;
1940         found = false;
1941
1942         while(fgets(buf1, sizeof(buf1), f)) {
1943                 buf1[sizeof(buf1) - 1] = 0;
1944                 strncpy(buf2, buf1, sizeof(buf2));
1945
1946                 // Parse line in a simple way
1947                 char *bvalue;
1948                 int len;
1949
1950                 len = strcspn(buf2, "\t =");
1951                 bvalue = buf2 + len;
1952                 bvalue += strspn(bvalue, "\t ");
1953
1954                 if(*bvalue == '=') {
1955                         bvalue++;
1956                         bvalue += strspn(bvalue, "\t ");
1957                 }
1958
1959                 rstrip(bvalue);
1960                 buf2[len] = '\0';
1961
1962                 // Did it match?
1963                 if(!strcasecmp(buf2, variable)) {
1964                         // Get
1965                         if(action < -1) {
1966                                 found = true;
1967                                 printf("%s\n", bvalue);
1968                                 // Del
1969                         } else if(action == -1) {
1970                                 if(!*value || !strcasecmp(bvalue, value)) {
1971                                         removed = true;
1972                                         continue;
1973                                 }
1974
1975                                 // Set
1976                         } else if(action == 0) {
1977                                 // Warn if "set" was used for variables that can occur multiple times
1978                                 if(warnonremove && strcasecmp(bvalue, value)) {
1979                                         fprintf(stderr, "Warning: removing %s = %s\n", variable, bvalue);
1980                                 }
1981
1982                                 // Already set? Delete the rest...
1983                                 if(set) {
1984                                         continue;
1985                                 }
1986
1987                                 // Otherwise, replace.
1988                                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
1989                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1990                                         return 1;
1991                                 }
1992
1993                                 set = true;
1994                                 continue;
1995                                 // Add
1996                         } else if(action > 0) {
1997                                 // Check if we've already seen this variable with the same value
1998                                 if(!strcasecmp(bvalue, value)) {
1999                                         found = true;
2000                                 }
2001                         }
2002                 }
2003
2004                 if(action >= -1) {
2005                         // Copy original line...
2006                         if(fputs(buf1, tf) < 0) {
2007                                 fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2008                                 return 1;
2009                         }
2010
2011                         // Add newline if it is missing...
2012                         if(*buf1 && buf1[strlen(buf1) - 1] != '\n') {
2013                                 if(fputc('\n', tf) < 0) {
2014                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2015                                         return 1;
2016                                 }
2017                         }
2018                 }
2019         }
2020
2021         // Make sure we read everything...
2022         if(ferror(f) || !feof(f)) {
2023                 fprintf(stderr, "Error while reading from configuration file %s: %s\n", filename, strerror(errno));
2024                 return 1;
2025         }
2026
2027         if(fclose(f)) {
2028                 fprintf(stderr, "Error closing configuration file %s: %s\n", filename, strerror(errno));
2029                 return 1;
2030         }
2031
2032         // Add new variable if necessary.
2033         if((action > 0 && !found) || (action == 0 && !set)) {
2034                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
2035                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
2036                         return 1;
2037                 }
2038         }
2039
2040         if(action < -1) {
2041                 if(found) {
2042                         return 0;
2043                 } else {
2044                         fprintf(stderr, "No matching configuration variables found.\n");
2045                         return 1;
2046                 }
2047         }
2048
2049         // Make sure we wrote everything...
2050         if(fclose(tf)) {
2051                 fprintf(stderr, "Error closing temporary file %s: %s\n", tmpfile, strerror(errno));
2052                 return 1;
2053         }
2054
2055         // Could we find what we had to remove?
2056         if(action < 0 && !removed) {
2057                 remove(tmpfile);
2058                 fprintf(stderr, "No configuration variables deleted.\n");
2059                 return 1;
2060         }
2061
2062         // Replace the configuration file with the new one
2063 #ifdef HAVE_MINGW
2064
2065         if(remove(filename)) {
2066                 fprintf(stderr, "Error replacing file %s: %s\n", filename, strerror(errno));
2067                 return 1;
2068         }
2069
2070 #endif
2071
2072         if(rename(tmpfile, filename)) {
2073                 fprintf(stderr, "Error renaming temporary file %s to configuration file %s: %s\n", tmpfile, filename, strerror(errno));
2074                 return 1;
2075         }
2076
2077         // Silently try notifying a running tincd of changes.
2078         if(connect_tincd(false)) {
2079                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
2080         }
2081
2082         return 0;
2083 }
2084
2085 static bool try_bind(int port) {
2086         struct addrinfo *ai = NULL, *aip;
2087         struct addrinfo hint = {
2088                 .ai_flags = AI_PASSIVE,
2089                 .ai_family = AF_UNSPEC,
2090                 .ai_socktype = SOCK_STREAM,
2091                 .ai_protocol = IPPROTO_TCP,
2092         };
2093
2094         bool success = true;
2095         char portstr[16];
2096         snprintf(portstr, sizeof(portstr), "%d", port);
2097
2098         if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) {
2099                 return false;
2100         }
2101
2102         for(aip = ai; aip; aip = aip->ai_next) {
2103                 int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
2104
2105                 if(!fd) {
2106                         success = false;
2107                         break;
2108                 }
2109
2110                 int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
2111                 closesocket(fd);
2112
2113                 if(result) {
2114                         success = false;
2115                         break;
2116                 }
2117         }
2118
2119         freeaddrinfo(ai);
2120         return success;
2121 }
2122
2123 int check_port(char *name) {
2124         if(try_bind(655)) {
2125                 return 655;
2126         }
2127
2128         fprintf(stderr, "Warning: could not bind to port 655. ");
2129
2130         for(int i = 0; i < 100; i++) {
2131                 int port = 0x1000 + (rand() & 0x7fff);
2132
2133                 if(try_bind(port)) {
2134                         char filename[PATH_MAX];
2135                         snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", confbase, name);
2136                         FILE *f = fopen(filename, "a");
2137
2138                         if(!f) {
2139                                 fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
2140                                 fprintf(stderr, "Please change tinc's Port manually.\n");
2141                                 return 0;
2142                         }
2143
2144                         fprintf(f, "Port = %d\n", port);
2145                         fclose(f);
2146                         fprintf(stderr, "Tinc will instead listen on port %d.\n", port);
2147                         return port;
2148                 }
2149         }
2150
2151         fprintf(stderr, "Please change tinc's Port manually.\n");
2152         return 0;
2153 }
2154
2155 static int cmd_init(int argc, char *argv[]) {
2156         if(!access(tinc_conf, F_OK)) {
2157                 fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
2158                 return 1;
2159         }
2160
2161         if(argc > 2) {
2162                 fprintf(stderr, "Too many arguments!\n");
2163                 return 1;
2164         } else if(argc < 2) {
2165                 if(tty) {
2166                         char buf[1024];
2167                         fprintf(stderr, "Enter the Name you want your tinc node to have: ");
2168
2169                         if(!fgets(buf, sizeof(buf), stdin)) {
2170                                 fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
2171                                 return 1;
2172                         }
2173
2174                         int len = rstrip(buf);
2175
2176                         if(!len) {
2177                                 fprintf(stderr, "No name given!\n");
2178                                 return 1;
2179                         }
2180
2181                         name = strdup(buf);
2182                 } else {
2183                         fprintf(stderr, "No Name given!\n");
2184                         return 1;
2185                 }
2186         } else {
2187                 name = strdup(argv[1]);
2188
2189                 if(!*name) {
2190                         fprintf(stderr, "No Name given!\n");
2191                         return 1;
2192                 }
2193         }
2194
2195         if(!check_id(name)) {
2196                 fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n");
2197                 return 1;
2198         }
2199
2200         if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) {
2201                 fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
2202                 return 1;
2203         }
2204
2205         if(mkdir(confbase, 0777) && errno != EEXIST) {
2206                 fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
2207                 return 1;
2208         }
2209
2210         if(mkdir(hosts_dir, 0777) && errno != EEXIST) {
2211                 fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno));
2212                 return 1;
2213         }
2214
2215         FILE *f = fopen(tinc_conf, "w");
2216
2217         if(!f) {
2218                 fprintf(stderr, "Could not create file %s: %s\n", tinc_conf, strerror(errno));
2219                 return 1;
2220         }
2221
2222         fprintf(f, "Name = %s\n", name);
2223         fclose(f);
2224
2225 #ifndef DISABLE_LEGACY
2226
2227         if(!rsa_keygen(2048, false)) {
2228                 return 1;
2229         }
2230
2231 #endif
2232
2233         if(!ed25519_keygen(false)) {
2234                 return 1;
2235         }
2236
2237         check_port(name);
2238
2239 #ifndef HAVE_MINGW
2240         char filename[PATH_MAX];
2241         snprintf(filename, sizeof(filename), "%s" SLASH "tinc-up", confbase);
2242
2243         if(access(filename, F_OK)) {
2244                 FILE *f = fopenmask(filename, "w", 0777);
2245
2246                 if(!f) {
2247                         fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
2248                         return 1;
2249                 }
2250
2251                 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");
2252                 fclose(f);
2253         }
2254
2255 #endif
2256
2257         return 0;
2258
2259 }
2260
2261 static int cmd_generate_keys(int argc, char *argv[]) {
2262 #ifdef DISABLE_LEGACY
2263
2264         if(argc > 1) {
2265 #else
2266
2267         if(argc > 2) {
2268 #endif
2269                 fprintf(stderr, "Too many arguments!\n");
2270                 return 1;
2271         }
2272
2273         if(!name) {
2274                 name = get_my_name(false);
2275         }
2276
2277 #ifndef DISABLE_LEGACY
2278
2279         if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true)) {
2280                 return 1;
2281         }
2282
2283 #endif
2284
2285         if(!ed25519_keygen(true)) {
2286                 return 1;
2287         }
2288
2289         return 0;
2290 }
2291
2292 #ifndef DISABLE_LEGACY
2293 static int cmd_generate_rsa_keys(int argc, char *argv[]) {
2294         if(argc > 2) {
2295                 fprintf(stderr, "Too many arguments!\n");
2296                 return 1;
2297         }
2298
2299         if(!name) {
2300                 name = get_my_name(false);
2301         }
2302
2303         return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
2304 }
2305 #endif
2306
2307 static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
2308         if(argc > 1) {
2309                 fprintf(stderr, "Too many arguments!\n");
2310                 return 1;
2311         }
2312
2313         if(!name) {
2314                 name = get_my_name(false);
2315         }
2316
2317         return !ed25519_keygen(true);
2318 }
2319
2320 static int cmd_help(int argc, char *argv[]) {
2321         usage(false);
2322         return 0;
2323 }
2324
2325 static int cmd_version(int argc, char *argv[]) {
2326         if(argc > 1) {
2327                 fprintf(stderr, "Too many arguments!\n");
2328                 return 1;
2329         }
2330
2331         version();
2332         return 0;
2333 }
2334
2335 static int cmd_info(int argc, char *argv[]) {
2336         if(argc != 2) {
2337                 fprintf(stderr, "Invalid number of arguments.\n");
2338                 return 1;
2339         }
2340
2341         if(!connect_tincd(true)) {
2342                 return 1;
2343         }
2344
2345         return info(fd, argv[1]);
2346 }
2347
2348 static const char *conffiles[] = {
2349         "tinc.conf",
2350         "tinc-up",
2351         "tinc-down",
2352         "subnet-up",
2353         "subnet-down",
2354         "host-up",
2355         "host-down",
2356         NULL,
2357 };
2358
2359 static int cmd_edit(int argc, char *argv[]) {
2360         if(argc != 2) {
2361                 fprintf(stderr, "Invalid number of arguments.\n");
2362                 return 1;
2363         }
2364
2365         char filename[PATH_MAX] = "";
2366
2367         if(strncmp(argv[1], "hosts" SLASH, 6)) {
2368                 for(int i = 0; conffiles[i]; i++) {
2369                         if(!strcmp(argv[1], conffiles[i])) {
2370                                 snprintf(filename, sizeof(filename), "%s" SLASH "%s", confbase, argv[1]);
2371                                 break;
2372                         }
2373                 }
2374         } else {
2375                 argv[1] += 6;
2376         }
2377
2378         if(!*filename) {
2379                 snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, argv[1]);
2380                 char *dash = strchr(argv[1], '-');
2381
2382                 if(dash) {
2383                         *dash++ = 0;
2384
2385                         if((strcmp(dash, "up") && strcmp(dash, "down")) || !check_id(argv[1])) {
2386                                 fprintf(stderr, "Invalid configuration filename.\n");
2387                                 return 1;
2388                         }
2389                 }
2390         }
2391
2392         char *command;
2393 #ifndef HAVE_MINGW
2394         xasprintf(&command, "\"%s\" \"%s\"", getenv("VISUAL") ? : getenv("EDITOR") ? : "vi", filename);
2395 #else
2396         xasprintf(&command, "edit \"%s\"", filename);
2397 #endif
2398         int result = system(command);
2399         free(command);
2400
2401         if(result) {
2402                 return result;
2403         }
2404
2405         // Silently try notifying a running tincd of changes.
2406         if(connect_tincd(false)) {
2407                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
2408         }
2409
2410         return 0;
2411 }
2412
2413 static int export(const char *name, FILE *out) {
2414         char filename[PATH_MAX];
2415         snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name);
2416         FILE *in = fopen(filename, "r");
2417
2418         if(!in) {
2419                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
2420                 return 1;
2421         }
2422
2423         fprintf(out, "Name = %s\n", name);
2424         char buf[4096];
2425
2426         while(fgets(buf, sizeof(buf), in)) {
2427                 if(strcspn(buf, "\t =") != 4 || strncasecmp(buf, "Name", 4)) {
2428                         fputs(buf, out);
2429                 }
2430         }
2431
2432         if(ferror(in)) {
2433                 fprintf(stderr, "Error while reading configuration file %s: %s\n", filename, strerror(errno));
2434                 fclose(in);
2435                 return 1;
2436         }
2437
2438         fclose(in);
2439         return 0;
2440 }
2441
2442 static int cmd_export(int argc, char *argv[]) {
2443         if(argc > 1) {
2444                 fprintf(stderr, "Too many arguments!\n");
2445                 return 1;
2446         }
2447
2448         char *name = get_my_name(true);
2449
2450         if(!name) {
2451                 return 1;
2452         }
2453
2454         int result = export(name, stdout);
2455
2456         if(!tty) {
2457                 fclose(stdout);
2458         }
2459
2460         free(name);
2461         return result;
2462 }
2463
2464 static int cmd_export_all(int argc, char *argv[]) {
2465         if(argc > 1) {
2466                 fprintf(stderr, "Too many arguments!\n");
2467                 return 1;
2468         }
2469
2470         DIR *dir = opendir(hosts_dir);
2471
2472         if(!dir) {
2473                 fprintf(stderr, "Could not open host configuration directory %s: %s\n", hosts_dir, strerror(errno));
2474                 return 1;
2475         }
2476
2477         bool first = true;
2478         int result = 0;
2479         struct dirent *ent;
2480
2481         while((ent = readdir(dir))) {
2482                 if(!check_id(ent->d_name)) {
2483                         continue;
2484                 }
2485
2486                 if(first) {
2487                         first = false;
2488                 } else {
2489                         printf("#---------------------------------------------------------------#\n");
2490                 }
2491
2492                 result |= export(ent->d_name, stdout);
2493         }
2494
2495         closedir(dir);
2496
2497         if(!tty) {
2498                 fclose(stdout);
2499         }
2500
2501         return result;
2502 }
2503
2504 static int cmd_import(int argc, char *argv[]) {
2505         if(argc > 1) {
2506                 fprintf(stderr, "Too many arguments!\n");
2507                 return 1;
2508         }
2509
2510         FILE *in = stdin;
2511         FILE *out = NULL;
2512
2513         char buf[4096];
2514         char name[4096];
2515         char filename[PATH_MAX] = "";
2516         int count = 0;
2517         bool firstline = true;
2518
2519         while(fgets(buf, sizeof(buf), in)) {
2520                 if(sscanf(buf, "Name = %4095s", name) == 1) {
2521                         firstline = false;
2522
2523                         if(!check_id(name)) {
2524                                 fprintf(stderr, "Invalid Name in input!\n");
2525                                 return 1;
2526                         }
2527
2528                         if(out) {
2529                                 fclose(out);
2530                         }
2531
2532                         snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, name);
2533
2534                         if(!force && !access(filename, F_OK)) {
2535                                 fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
2536                                 out = NULL;
2537                                 continue;
2538                         }
2539
2540                         out = fopen(filename, "w");
2541
2542                         if(!out) {
2543                                 fprintf(stderr, "Error creating configuration file %s: %s\n", filename, strerror(errno));
2544                                 return 1;
2545                         }
2546
2547                         count++;
2548                         continue;
2549                 } else if(firstline) {
2550                         fprintf(stderr, "Junk at the beginning of the input, ignoring.\n");
2551                         firstline = false;
2552                 }
2553
2554
2555                 if(!strcmp(buf, "#---------------------------------------------------------------#\n")) {
2556                         continue;
2557                 }
2558
2559                 if(out) {
2560                         if(fputs(buf, out) < 0) {
2561                                 fprintf(stderr, "Error writing to host configuration file %s: %s\n", filename, strerror(errno));
2562                                 return 1;
2563                         }
2564                 }
2565         }
2566
2567         if(out) {
2568                 fclose(out);
2569         }
2570
2571         if(count) {
2572                 fprintf(stderr, "Imported %d host configuration files.\n", count);
2573                 return 0;
2574         } else {
2575                 fprintf(stderr, "No host configuration files imported.\n");
2576                 return 1;
2577         }
2578 }
2579
2580 static int cmd_exchange(int argc, char *argv[]) {
2581         return cmd_export(argc, argv) ? : cmd_import(argc, argv);
2582 }
2583
2584 static int cmd_exchange_all(int argc, char *argv[]) {
2585         return cmd_export_all(argc, argv) ? : cmd_import(argc, argv);
2586 }
2587
2588 static int switch_network(char *name) {
2589         if(strcmp(name, ".")) {
2590                 if(!check_netname(name, false)) {
2591                         fprintf(stderr, "Invalid character in netname!\n");
2592                         return 1;
2593                 }
2594
2595                 if(!check_netname(name, true)) {
2596                         fprintf(stderr, "Warning: unsafe character in netname!\n");
2597                 }
2598         }
2599
2600         if(fd >= 0) {
2601                 close(fd);
2602                 fd = -1;
2603         }
2604
2605         free_names();
2606         netname = strcmp(name, ".") ? xstrdup(name) : NULL;
2607         make_names(false);
2608
2609         free(tinc_conf);
2610         free(hosts_dir);
2611         free(prompt);
2612
2613         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
2614         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
2615         xasprintf(&prompt, "%s> ", identname);
2616
2617         return 0;
2618 }
2619
2620 static int cmd_network(int argc, char *argv[]) {
2621         if(argc > 2) {
2622                 fprintf(stderr, "Too many arguments!\n");
2623                 return 1;
2624         }
2625
2626         if(argc == 2) {
2627                 return switch_network(argv[1]);
2628         }
2629
2630         DIR *dir = opendir(confdir);
2631
2632         if(!dir) {
2633                 fprintf(stderr, "Could not read directory %s: %s\n", confdir, strerror(errno));
2634                 return 1;
2635         }
2636
2637         struct dirent *ent;
2638
2639         while((ent = readdir(dir))) {
2640                 if(*ent->d_name == '.') {
2641                         continue;
2642                 }
2643
2644                 if(!strcmp(ent->d_name, "tinc.conf")) {
2645                         printf(".\n");
2646                         continue;
2647                 }
2648
2649                 char fname[PATH_MAX];
2650                 snprintf(fname, sizeof(fname), "%s/%s/tinc.conf", confdir, ent->d_name);
2651
2652                 if(!access(fname, R_OK)) {
2653                         printf("%s\n", ent->d_name);
2654                 }
2655         }
2656
2657         closedir(dir);
2658
2659         return 0;
2660 }
2661
2662 static int cmd_fsck(int argc, char *argv[]) {
2663         if(argc > 1) {
2664                 fprintf(stderr, "Too many arguments!\n");
2665                 return 1;
2666         }
2667
2668         return fsck(orig_argv[0]);
2669 }
2670
2671 static void *readfile(FILE *in, size_t *len) {
2672         size_t count = 0;
2673         size_t alloced = 4096;
2674         char *buf = xmalloc(alloced);
2675
2676         while(!feof(in)) {
2677                 size_t read = fread(buf + count, 1, alloced - count, in);
2678
2679                 if(!read) {
2680                         break;
2681                 }
2682
2683                 count += read;
2684
2685                 if(count >= alloced) {
2686                         alloced *= 2;
2687                         buf = xrealloc(buf, alloced);
2688                 }
2689         }
2690
2691         if(len) {
2692                 *len = count;
2693         }
2694
2695         return buf;
2696 }
2697
2698 static int cmd_sign(int argc, char *argv[]) {
2699         if(argc > 2) {
2700                 fprintf(stderr, "Too many arguments!\n");
2701                 return 1;
2702         }
2703
2704         if(!name) {
2705                 name = get_my_name(true);
2706
2707                 if(!name) {
2708                         return 1;
2709                 }
2710         }
2711
2712         char fname[PATH_MAX];
2713         snprintf(fname, sizeof(fname), "%s" SLASH "ed25519_key.priv", confbase);
2714         FILE *fp = fopen(fname, "r");
2715
2716         if(!fp) {
2717                 fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
2718                 return 1;
2719         }
2720
2721         ecdsa_t *key = ecdsa_read_pem_private_key(fp);
2722
2723         if(!key) {
2724                 fprintf(stderr, "Could not read private key from %s\n", fname);
2725                 fclose(fp);
2726                 return 1;
2727         }
2728
2729         fclose(fp);
2730
2731         FILE *in;
2732
2733         if(argc == 2) {
2734                 in = fopen(argv[1], "rb");
2735
2736                 if(!in) {
2737                         fprintf(stderr, "Could not open %s: %s\n", argv[1], strerror(errno));
2738                         ecdsa_free(key);
2739                         return 1;
2740                 }
2741         } else {
2742                 in = stdin;
2743         }
2744
2745         size_t len;
2746         char *data = readfile(in, &len);
2747
2748         if(in != stdin) {
2749                 fclose(in);
2750         }
2751
2752         if(!data) {
2753                 fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
2754                 ecdsa_free(key);
2755                 return 1;
2756         }
2757
2758         // Ensure we sign our name and current time as well
2759         long t = time(NULL);
2760         char *trailer;
2761         xasprintf(&trailer, " %s %ld", name, t);
2762         int trailer_len = strlen(trailer);
2763
2764         data = xrealloc(data, len + trailer_len);
2765         memcpy(data + len, trailer, trailer_len);
2766         free(trailer);
2767
2768         char sig[87];
2769
2770         if(!ecdsa_sign(key, data, len + trailer_len, sig)) {
2771                 fprintf(stderr, "Error generating signature\n");
2772                 free(data);
2773                 ecdsa_free(key);
2774                 return 1;
2775         }
2776
2777         b64encode(sig, sig, 64);
2778         ecdsa_free(key);
2779
2780         fprintf(stdout, "Signature = %s %ld %s\n", name, t, sig);
2781         fwrite(data, len, 1, stdout);
2782
2783         free(data);
2784         return 0;
2785 }
2786
2787 static int cmd_verify(int argc, char *argv[]) {
2788         if(argc < 2) {
2789                 fprintf(stderr, "Not enough arguments!\n");
2790                 return 1;
2791         }
2792
2793         if(argc > 3) {
2794                 fprintf(stderr, "Too many arguments!\n");
2795                 return 1;
2796         }
2797
2798         char *node = argv[1];
2799
2800         if(!strcmp(node, ".")) {
2801                 if(!name) {
2802                         name = get_my_name(true);
2803
2804                         if(!name) {
2805                                 return 1;
2806                         }
2807                 }
2808
2809                 node = name;
2810         } else if(!strcmp(node, "*")) {
2811                 node = NULL;
2812         } else {
2813                 if(!check_id(node)) {
2814                         fprintf(stderr, "Invalid node name\n");
2815                         return 1;
2816                 }
2817         }
2818
2819         FILE *in;
2820
2821         if(argc == 3) {
2822                 in = fopen(argv[2], "rb");
2823
2824                 if(!in) {
2825                         fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
2826                         return 1;
2827                 }
2828         } else {
2829                 in = stdin;
2830         }
2831
2832         size_t len;
2833         char *data = readfile(in, &len);
2834
2835         if(in != stdin) {
2836                 fclose(in);
2837         }
2838
2839         if(!data) {
2840                 fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
2841                 return 1;
2842         }
2843
2844         char *newline = memchr(data, '\n', len);
2845
2846         if(!newline || (newline - data > MAX_STRING_SIZE - 1)) {
2847                 fprintf(stderr, "Invalid input\n");
2848                 free(data);
2849                 return 1;
2850         }
2851
2852         *newline++ = '\0';
2853         size_t skip = newline - data;
2854
2855         char signer[MAX_STRING_SIZE] = "";
2856         char sig[MAX_STRING_SIZE] = "";
2857         long t = 0;
2858
2859         if(sscanf(data, "Signature = %s %ld %s", signer, &t, sig) != 3 || strlen(sig) != 86 || !t || !check_id(signer)) {
2860                 fprintf(stderr, "Invalid input\n");
2861                 free(data);
2862                 return 1;
2863         }
2864
2865         if(node && strcmp(node, signer)) {
2866                 fprintf(stderr, "Signature is not made by %s\n", node);
2867                 free(data);
2868                 return 1;
2869         }
2870
2871         if(!node) {
2872                 node = signer;
2873         }
2874
2875         char *trailer;
2876         xasprintf(&trailer, " %s %ld", signer, t);
2877         int trailer_len = strlen(trailer);
2878
2879         data = xrealloc(data, len + trailer_len);
2880         memcpy(data + len, trailer, trailer_len);
2881         free(trailer);
2882
2883         newline = data + skip;
2884
2885         char fname[PATH_MAX];
2886         snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, node);
2887         FILE *fp = fopen(fname, "r");
2888
2889         if(!fp) {
2890                 fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
2891                 free(data);
2892                 return 1;
2893         }
2894
2895         ecdsa_t *key = get_pubkey(fp);
2896
2897         if(!key) {
2898                 rewind(fp);
2899                 key = ecdsa_read_pem_public_key(fp);
2900         }
2901
2902         if(!key) {
2903                 fprintf(stderr, "Could not read public key from %s\n", fname);
2904                 fclose(fp);
2905                 free(data);
2906                 return 1;
2907         }
2908
2909         fclose(fp);
2910
2911         if(b64decode(sig, sig, 86) != 64 || !ecdsa_verify(key, newline, len + trailer_len - (newline - data), sig)) {
2912                 fprintf(stderr, "Invalid signature\n");
2913                 free(data);
2914                 ecdsa_free(key);
2915                 return 1;
2916         }
2917
2918         ecdsa_free(key);
2919
2920         fwrite(newline, len - (newline - data), 1, stdout);
2921
2922         free(data);
2923         return 0;
2924 }
2925
2926 static const struct {
2927         const char *command;
2928         int (*function)(int argc, char *argv[]);
2929         bool hidden;
2930 } commands[] = {
2931         {"start", cmd_start},
2932         {"stop", cmd_stop},
2933         {"restart", cmd_restart},
2934         {"reload", cmd_reload},
2935         {"dump", cmd_dump},
2936         {"list", cmd_dump},
2937         {"purge", cmd_purge},
2938         {"debug", cmd_debug},
2939         {"retry", cmd_retry},
2940         {"connect", cmd_connect},
2941         {"disconnect", cmd_disconnect},
2942         {"top", cmd_top},
2943         {"pcap", cmd_pcap},
2944         {"log", cmd_log},
2945         {"pid", cmd_pid},
2946         {"config", cmd_config, true},
2947         {"add", cmd_config},
2948         {"del", cmd_config},
2949         {"get", cmd_config},
2950         {"set", cmd_config},
2951         {"init", cmd_init},
2952         {"generate-keys", cmd_generate_keys},
2953 #ifndef DISABLE_LEGACY
2954         {"generate-rsa-keys", cmd_generate_rsa_keys},
2955 #endif
2956         {"generate-ed25519-keys", cmd_generate_ed25519_keys},
2957         {"help", cmd_help},
2958         {"version", cmd_version},
2959         {"info", cmd_info},
2960         {"edit", cmd_edit},
2961         {"export", cmd_export},
2962         {"export-all", cmd_export_all},
2963         {"import", cmd_import},
2964         {"exchange", cmd_exchange},
2965         {"exchange-all", cmd_exchange_all},
2966         {"invite", cmd_invite},
2967         {"join", cmd_join},
2968         {"network", cmd_network},
2969         {"fsck", cmd_fsck},
2970         {"sign", cmd_sign},
2971         {"verify", cmd_verify},
2972         {NULL, NULL},
2973 };
2974
2975 #ifdef HAVE_READLINE
2976 static char *complete_command(const char *text, int state) {
2977         static int i;
2978
2979         if(!state) {
2980                 i = 0;
2981         } else {
2982                 i++;
2983         }
2984
2985         while(commands[i].command) {
2986                 if(!commands[i].hidden && !strncasecmp(commands[i].command, text, strlen(text))) {
2987                         return xstrdup(commands[i].command);
2988                 }
2989
2990                 i++;
2991         }
2992
2993         return NULL;
2994 }
2995
2996 static char *complete_dump(const char *text, int state) {
2997         const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL};
2998         static int i;
2999
3000         if(!state) {
3001                 i = 0;
3002         } else {
3003                 i++;
3004         }
3005
3006         while(matches[i]) {
3007                 if(!strncasecmp(matches[i], text, strlen(text))) {
3008                         return xstrdup(matches[i]);
3009                 }
3010
3011                 i++;
3012         }
3013
3014         return NULL;
3015 }
3016
3017 static char *complete_config(const char *text, int state) {
3018         static int i;
3019
3020         if(!state) {
3021                 i = 0;
3022         } else {
3023                 i++;
3024         }
3025
3026         while(variables[i].name) {
3027                 char *dot = strchr(text, '.');
3028
3029                 if(dot) {
3030                         if((variables[i].type & VAR_HOST) && !strncasecmp(variables[i].name, dot + 1, strlen(dot + 1))) {
3031                                 char *match;
3032                                 xasprintf(&match, "%.*s.%s", (int)(dot - text), text, variables[i].name);
3033                                 return match;
3034                         }
3035                 } else {
3036                         if(!strncasecmp(variables[i].name, text, strlen(text))) {
3037                                 return xstrdup(variables[i].name);
3038                         }
3039                 }
3040
3041                 i++;
3042         }
3043
3044         return NULL;
3045 }
3046
3047 static char *complete_info(const char *text, int state) {
3048         static int i;
3049
3050         if(!state) {
3051                 i = 0;
3052
3053                 if(!connect_tincd(false)) {
3054                         return NULL;
3055                 }
3056
3057                 // Check the list of nodes
3058                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
3059                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
3060         }
3061
3062         while(recvline(fd, line, sizeof(line))) {
3063                 char item[4096];
3064                 int n = sscanf(line, "%d %d %4095s", &code, &req, item);
3065
3066                 if(n == 2) {
3067                         i++;
3068
3069                         if(i >= 2) {
3070                                 break;
3071                         } else {
3072                                 continue;
3073                         }
3074                 }
3075
3076                 if(n != 3) {
3077                         fprintf(stderr, "Unable to parse dump from tincd, n = %d, i = %d.\n", n, i);
3078                         break;
3079                 }
3080
3081                 if(!strncmp(item, text, strlen(text))) {
3082                         return xstrdup(strip_weight(item));
3083                 }
3084         }
3085
3086         return NULL;
3087 }
3088
3089 static char *complete_nothing(const char *text, int state) {
3090         return NULL;
3091 }
3092
3093 static char **completion(const char *text, int start, int end) {
3094         char **matches = NULL;
3095
3096         if(!start) {
3097                 matches = rl_completion_matches(text, complete_command);
3098         } else if(!strncasecmp(rl_line_buffer, "dump ", 5)) {
3099                 matches = rl_completion_matches(text, complete_dump);
3100         } else if(!strncasecmp(rl_line_buffer, "add ", 4)) {
3101                 matches = rl_completion_matches(text, complete_config);
3102         } else if(!strncasecmp(rl_line_buffer, "del ", 4)) {
3103                 matches = rl_completion_matches(text, complete_config);
3104         } else if(!strncasecmp(rl_line_buffer, "get ", 4)) {
3105                 matches = rl_completion_matches(text, complete_config);
3106         } else if(!strncasecmp(rl_line_buffer, "set ", 4)) {
3107                 matches = rl_completion_matches(text, complete_config);
3108         } else if(!strncasecmp(rl_line_buffer, "info ", 5)) {
3109                 matches = rl_completion_matches(text, complete_info);
3110         }
3111
3112         return matches;
3113 }
3114 #endif
3115
3116 static int cmd_shell(int argc, char *argv[]) {
3117         xasprintf(&prompt, "%s> ", identname);
3118         int result = 0;
3119         char buf[4096];
3120         char *line = NULL;
3121         int maxargs = argc + 16;
3122         char **nargv = xmalloc(maxargs * sizeof(*nargv));
3123
3124         for(int i = 0; i < argc; i++) {
3125                 nargv[i] = argv[i];
3126         }
3127
3128 #ifdef HAVE_READLINE
3129         rl_readline_name = "tinc";
3130         rl_completion_entry_function = complete_nothing;
3131         rl_attempted_completion_function = completion;
3132         rl_filename_completion_desired = 0;
3133         char *copy = NULL;
3134 #endif
3135
3136         while(true) {
3137 #ifdef HAVE_READLINE
3138
3139                 if(tty) {
3140                         free(copy);
3141                         free(line);
3142                         rl_basic_word_break_characters = "\t\n ";
3143                         line = readline(prompt);
3144
3145                         if(line) {
3146                                 copy = xstrdup(line);
3147                         }
3148                 } else {
3149                         line = fgets(buf, sizeof(buf), stdin);
3150                 }
3151
3152 #else
3153
3154                 if(tty) {
3155                         fputs(prompt, stdout);
3156                 }
3157
3158                 line = fgets(buf, sizeof(buf), stdin);
3159 #endif
3160
3161                 if(!line) {
3162                         break;
3163                 }
3164
3165                 /* Ignore comments */
3166
3167                 if(*line == '#') {
3168                         continue;
3169                 }
3170
3171                 /* Split */
3172
3173                 int nargc = argc;
3174                 char *p = line + strspn(line, " \t\n");
3175                 char *next = strtok(p, " \t\n");
3176
3177                 while(p && *p) {
3178                         if(nargc >= maxargs) {
3179                                 maxargs *= 2;
3180                                 nargv = xrealloc(nargv, maxargs * sizeof(*nargv));
3181                         }
3182
3183                         nargv[nargc++] = p;
3184                         p = next;
3185                         next = strtok(NULL, " \t\n");
3186                 }
3187
3188                 if(nargc == argc) {
3189                         continue;
3190                 }
3191
3192                 if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit")) {
3193                         free(nargv);
3194                         return result;
3195                 }
3196
3197                 bool found = false;
3198
3199                 for(int i = 0; commands[i].command; i++) {
3200                         if(!strcasecmp(nargv[argc], commands[i].command)) {
3201                                 result |= commands[i].function(nargc - argc - 1, nargv + argc + 1);
3202                                 found = true;
3203                                 break;
3204                         }
3205                 }
3206
3207 #ifdef HAVE_READLINE
3208
3209                 if(tty && found) {
3210                         add_history(copy);
3211                 }
3212
3213 #endif
3214
3215                 if(!found) {
3216                         fprintf(stderr, "Unknown command `%s'.\n", nargv[argc]);
3217                         result |= 1;
3218                 }
3219         }
3220
3221         free(nargv);
3222
3223         if(tty) {
3224                 printf("\n");
3225         }
3226
3227         return result;
3228 }
3229
3230
3231 int main(int argc, char *argv[]) {
3232         program_name = argv[0];
3233         orig_argv = argv;
3234         orig_argc = argc;
3235         tty = isatty(0) && isatty(1);
3236
3237         if(!parse_options(argc, argv)) {
3238                 return 1;
3239         }
3240
3241         make_names(false);
3242         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
3243         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
3244
3245         if(show_version) {
3246                 version();
3247                 return 0;
3248         }
3249
3250         if(show_help) {
3251                 usage(false);
3252                 return 0;
3253         }
3254
3255 #ifdef HAVE_MINGW
3256         static struct WSAData wsa_state;
3257
3258         if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
3259                 fprintf(stderr, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError()));
3260                 return false;
3261         }
3262
3263 #endif
3264
3265         srand(time(NULL));
3266         crypto_init();
3267
3268         if(optind >= argc) {
3269                 return cmd_shell(argc, argv);
3270         }
3271
3272         for(int i = 0; commands[i].command; i++) {
3273                 if(!strcasecmp(argv[optind], commands[i].command)) {
3274                         return commands[i].function(argc - optind, argv + optind);
3275                 }
3276         }
3277
3278         fprintf(stderr, "Unknown command `%s'.\n", argv[optind]);
3279         usage(true);
3280         return 1;
3281 }