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