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