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