Merge remote-tracking branch 'seehuhn/1.1' into 1.1
[tinc] / src / tincctl.c
1 /*
2     tincctl.c -- Controlling a running tincd
3     Copyright (C) 2007-2014 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
78 static struct option const long_options[] = {
79         {"batch", no_argument, NULL, 'b'},
80         {"config", required_argument, NULL, 'c'},
81         {"net", required_argument, NULL, 'n'},
82         {"help", no_argument, NULL, 1},
83         {"version", no_argument, NULL, 2},
84         {"pidfile", required_argument, NULL, 3},
85         {"force", no_argument, NULL, 4},
86         {NULL, 0, NULL, 0}
87 };
88
89 static void version(void) {
90         printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
91                    VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
92         printf("Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen and others.\n"
93                         "See the AUTHORS file for a complete list.\n\n"
94                         "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
95                         "and you are welcome to redistribute it under certain conditions;\n"
96                         "see the file COPYING for details.\n");
97 }
98
99 static void usage(bool status) {
100         if(status) {
101                 fprintf(stderr, "Try `%s --help\' for more information.\n", program_name);
102         } else {
103                 printf("Usage: %s [options] command\n\n", program_name);
104                 printf("Valid options are:\n"
105                                 "  -b, --batch             Don't ask for anything (non-interactive mode).\n"
106                                 "  -c, --config=DIR        Read configuration options from DIR.\n"
107                                 "  -n, --net=NETNAME       Connect to net NETNAME.\n"
108                                 "      --pidfile=FILENAME  Read control cookie from FILENAME.\n"
109                                 "      --force             Force some commands to work despite warnings.\n"
110                                 "      --help              Display this help and exit.\n"
111                                 "      --version           Output version information and exit.\n"
112                                 "\n"
113                                 "Valid commands are:\n"
114                                 "  init [name]                Create initial configuration files.\n"
115                                 "  get VARIABLE               Print current value of VARIABLE\n"
116                                 "  set VARIABLE VALUE         Set VARIABLE to VALUE\n"
117                                 "  add VARIABLE VALUE         Add VARIABLE with the given VALUE\n"
118                                 "  del VARIABLE [VALUE]       Remove VARIABLE [only ones with watching VALUE]\n"
119                                 "  start [tincd options]      Start tincd.\n"
120                                 "  stop                       Stop tincd.\n"
121                                 "  restart [tincd options]    Restart tincd.\n"
122                                 "  reload                     Partially reload configuration of running tincd.\n"
123                                 "  pid                        Show PID of currently running tincd.\n"
124 #ifdef DISABLE_LEGACY
125                                 "  generate-keys              Generate a new Ed25519 public/private keypair.\n"
126 #else
127                                 "  generate-keys [bits]       Generate new RSA and Ed25519 public/private keypairs.\n"
128                                 "  generate-rsa-keys [bits]   Generate a new RSA public/private keypair.\n"
129 #endif
130                                 "  generate-ed25519-keys      Generate a new Ed25519 public/private keypair.\n"
131                                 "  dump                       Dump a list of one of the following things:\n"
132                                 "    [reachable] nodes        - all known nodes in the VPN\n"
133                                 "    edges                    - all known connections in the VPN\n"
134                                 "    subnets                  - all known subnets in the VPN\n"
135                                 "    connections              - all meta connections with ourself\n"
136                                 "    [di]graph                - graph of the VPN in dotty format\n"
137                                 "  info NODE|SUBNET|ADDRESS   Give information about a particular NODE, SUBNET or ADDRESS.\n"
138                                 "  purge                      Purge unreachable nodes\n"
139                                 "  debug N                    Set debug level\n"
140                                 "  retry                      Retry all outgoing connections\n"
141                                 "  disconnect NODE            Close meta connection with NODE\n"
142 #ifdef HAVE_CURSES
143                                 "  top                        Show real-time statistics\n"
144 #endif
145                                 "  pcap [snaplen]             Dump traffic in pcap format [up to snaplen bytes per packet]\n"
146                                 "  log [level]                Dump log output [up to the specified level]\n"
147                                 "  export                     Export host configuration of local node to standard output\n"
148                                 "  export-all                 Export all host configuration files to standard output\n"
149                                 "  import                     Import host configuration file(s) from standard input\n"
150                                 "  exchange                   Same as export followed by import\n"
151                                 "  exchange-all               Same as export-all followed by import\n"
152                                 "  invite NODE [...]          Generate an invitation for NODE\n"
153                                 "  join INVITATION            Join a VPN using an INVITIATION\n"
154                                 "  network [NETNAME]          List all known networks, or switch to the one named NETNAME.\n"
155                                 "  fsck                       Check the configuration files for problems.\n"
156                                 "\n");
157                 printf("Report bugs to tinc@tinc-vpn.org.\n");
158         }
159 }
160
161 static bool parse_options(int argc, char **argv) {
162         int r;
163         int option_index = 0;
164
165         while((r = getopt_long(argc, argv, "+c:n:", long_options, &option_index)) != EOF) {
166                 switch (r) {
167                         case 0:   /* long option */
168                                 break;
169
170                         case 'b':
171                                 tty = false;
172                                 break;
173
174                         case 'c': /* config file */
175                                 confbase = xstrdup(optarg);
176                                 confbasegiven = true;
177                                 break;
178
179                         case 'n': /* net name given */
180                                 netname = xstrdup(optarg);
181                                 break;
182
183                         case 1:   /* show help */
184                                 show_help = true;
185                                 break;
186
187                         case 2:   /* show version */
188                                 show_version = true;
189                                 break;
190
191                         case 3:   /* open control socket here */
192                                 pidfilename = xstrdup(optarg);
193                                 break;
194
195                         case 4:   /* force */
196                                 force = true;
197                                 break;
198
199                         case '?': /* wrong options */
200                                 usage(true);
201                                 return false;
202
203                         default:
204                                 break;
205                 }
206         }
207
208         if(!netname && (netname = getenv("NETNAME")))
209                 netname = xstrdup(netname);
210
211         /* netname "." is special: a "top-level name" */
212
213         if(netname && (!*netname || !strcmp(netname, "."))) {
214                 free(netname);
215                 netname = NULL;
216         }
217
218         if(netname && (strpbrk(netname, "\\/") || *netname == '.')) {
219                 fprintf(stderr, "Invalid character in netname!\n");
220                 return false;
221         }
222
223         return true;
224 }
225
226 /* Open a file with the desired permissions, minus the umask.
227    Also, if we want to create an executable file, we call fchmod()
228    to set the executable bits. */
229
230 FILE *fopenmask(const char *filename, const char *mode, mode_t perms) {
231         mode_t mask = umask(0);
232         perms &= ~mask;
233         umask(~perms);
234         FILE *f = fopen(filename, mode);
235 #ifdef HAVE_FCHMOD
236         if((perms & 0444) && f)
237                 fchmod(fileno(f), perms);
238 #endif
239         umask(mask);
240         return f;
241 }
242
243 static void disable_old_keys(const char *filename, const char *what) {
244         char tmpfile[PATH_MAX] = "";
245         char buf[1024];
246         bool disabled = false;
247         bool block = false;
248         bool error = false;
249         FILE *r, *w;
250
251         r = fopen(filename, "r");
252         if(!r)
253                 return;
254
255         snprintf(tmpfile, sizeof tmpfile, "%s.tmp", filename);
256
257         struct stat st = {.st_mode = 0600};
258         fstat(fileno(r), &st);
259         w = fopenmask(tmpfile, "w", st.st_mode);
260
261         while(fgets(buf, sizeof buf, r)) {
262                 if(!block && !strncmp(buf, "-----BEGIN ", 11)) {
263                         if((strstr(buf, " ED25519 ") && strstr(what, "Ed25519")) || (strstr(buf, " RSA ") && strstr(what, "RSA"))) {
264                                 disabled = true;
265                                 block = true;
266                         }
267                 }
268
269                 bool ed25519pubkey = !strncasecmp(buf, "Ed25519PublicKey", 16) && strchr(" \t=", buf[16]) && strstr(what, "Ed25519");
270
271                 if(ed25519pubkey)
272                         disabled = true;
273
274                 if(w) {
275                         if(block || ed25519pubkey)
276                                 fputc('#', w);
277                         if(fputs(buf, w) < 0) {
278                                 error = true;
279                                 break;
280                         }
281                 }
282
283                 if(block && !strncmp(buf, "-----END ", 9))
284                         block = false;
285         }
286
287         if(w)
288                 if(fclose(w) < 0)
289                         error = true;
290         if(ferror(r) || fclose(r) < 0)
291                 error = true;
292
293         if(disabled) {
294                 if(!w || error) {
295                         fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
296                         if(w)
297                                 unlink(tmpfile);
298                         return;
299                 }
300
301 #ifdef HAVE_MINGW
302                 // We cannot atomically replace files on Windows.
303                 char bakfile[PATH_MAX] = "";
304                 snprintf(bakfile, sizeof bakfile, "%s.bak", filename);
305                 if(rename(filename, bakfile) || rename(tmpfile, filename)) {
306                         rename(bakfile, filename);
307 #else
308                 if(rename(tmpfile, filename)) {
309 #endif
310                         fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
311                 } else  {
312 #ifdef HAVE_MINGW
313                         unlink(bakfile);
314 #endif
315                         fprintf(stderr, "Warning: old key(s) found and disabled.\n");
316                 }
317         }
318
319         unlink(tmpfile);
320 }
321
322 static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) {
323         FILE *r;
324         char *directory;
325         char buf[PATH_MAX];
326         char buf2[PATH_MAX];
327
328         /* Check stdin and stdout */
329         if(ask && tty) {
330                 /* Ask for a file and/or directory name. */
331                 fprintf(stderr, "Please enter a file to save %s to [%s]: ", what, filename);
332
333                 if(fgets(buf, sizeof buf, stdin) == NULL) {
334                         fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
335                         return NULL;
336                 }
337
338                 size_t len = strlen(buf);
339                 if(len)
340                         buf[--len] = 0;
341
342                 if(len)
343                         filename = buf;
344         }
345
346 #ifdef HAVE_MINGW
347         if(filename[0] != '\\' && filename[0] != '/' && !strchr(filename, ':')) {
348 #else
349         if(filename[0] != '/') {
350 #endif
351                 /* The directory is a relative path or a filename. */
352                 directory = get_current_dir_name();
353                 snprintf(buf2, sizeof buf2, "%s" SLASH "%s", directory, filename);
354                 filename = buf2;
355         }
356
357         disable_old_keys(filename, what);
358
359         /* Open it first to keep the inode busy */
360
361         r = fopenmask(filename, mode, perms);
362
363         if(!r) {
364                 fprintf(stderr, "Error opening file `%s': %s\n", filename, strerror(errno));
365                 return NULL;
366         }
367
368         return r;
369 }
370
371 /*
372   Generate a public/private Ed25519 keypair, and ask for a file to store
373   them in.
374 */
375 static bool ed25519_keygen(bool ask) {
376         ecdsa_t *key;
377         FILE *f;
378         char *pubname, *privname;
379
380         fprintf(stderr, "Generating Ed25519 keypair:\n");
381
382         if(!(key = ecdsa_generate())) {
383                 fprintf(stderr, "Error during key generation!\n");
384                 return false;
385         } else
386                 fprintf(stderr, "Done.\n");
387
388         xasprintf(&privname, "%s" SLASH "ed25519_key.priv", confbase);
389         f = ask_and_open(privname, "private Ed25519 key", "a", ask, 0600);
390         free(privname);
391
392         if(!f)
393                 return false;
394
395         if(!ecdsa_write_pem_private_key(key, f)) {
396                 fprintf(stderr, "Error writing private key!\n");
397                 ecdsa_free(key);
398                 fclose(f);
399                 return false;
400         }
401
402         fclose(f);
403
404         if(name)
405                 xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
406         else
407                 xasprintf(&pubname, "%s" SLASH "ed25519_key.pub", confbase);
408
409         f = ask_and_open(pubname, "public Ed25519 key", "a", ask, 0666);
410         free(pubname);
411
412         if(!f)
413                 return false;
414
415         char *pubkey = ecdsa_get_base64_public_key(key);
416         fprintf(f, "Ed25519PublicKey = %s\n", pubkey);
417         free(pubkey);
418
419         fclose(f);
420         ecdsa_free(key);
421
422         return true;
423 }
424
425 #ifndef DISABLE_LEGACY
426 /*
427   Generate a public/private RSA keypair, and ask for a file to store
428   them in.
429 */
430 static bool rsa_keygen(int bits, bool ask) {
431         rsa_t *key;
432         FILE *f;
433         char *pubname, *privname;
434
435         // Make sure the key size is a multiple of 8 bits.
436         bits &= ~0x7;
437
438         // Force them to be between 1024 and 8192 bits long.
439         if(bits < 1024)
440                 bits = 1024;
441         if(bits > 8192)
442                 bits = 8192;
443
444         fprintf(stderr, "Generating %d bits keys:\n", bits);
445
446         if(!(key = rsa_generate(bits, 0x10001))) {
447                 fprintf(stderr, "Error during key generation!\n");
448                 return false;
449         } else
450                 fprintf(stderr, "Done.\n");
451
452         xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase);
453         f = ask_and_open(privname, "private RSA key", "a", ask, 0600);
454         free(privname);
455
456         if(!f)
457                 return false;
458
459         if(!rsa_write_pem_private_key(key, f)) {
460                 fprintf(stderr, "Error writing private key!\n");
461                 fclose(f);
462                 rsa_free(key);
463                 return false;
464         }
465
466         fclose(f);
467
468         if(name)
469                 xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
470         else
471                 xasprintf(&pubname, "%s" SLASH "rsa_key.pub", confbase);
472
473         f = ask_and_open(pubname, "public RSA key", "a", ask, 0666);
474         free(pubname);
475
476         if(!f)
477                 return false;
478
479         if(!rsa_write_pem_public_key(key, f)) {
480                 fprintf(stderr, "Error writing public key!\n");
481                 fclose(f);
482                 rsa_free(key);
483                 return false;
484         }
485
486         fclose(f);
487         rsa_free(key);
488
489         return true;
490 }
491 #endif
492
493 char buffer[4096];
494 size_t blen = 0;
495
496 bool recvline(int fd, char *line, size_t len) {
497         char *newline = NULL;
498
499         if(!fd)
500                 abort();
501
502         while(!(newline = memchr(buffer, '\n', blen))) {
503                 int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
504                 if(result == -1 && sockerrno == EINTR)
505                         continue;
506                 else if(result <= 0)
507                         return false;
508                 blen += result;
509         }
510
511         if(newline - buffer >= len)
512                 return false;
513
514         len = newline - buffer;
515
516         memcpy(line, buffer, len);
517         line[len] = 0;
518         memmove(buffer, newline + 1, blen - len - 1);
519         blen -= len + 1;
520
521         return true;
522 }
523
524 bool recvdata(int fd, char *data, size_t len) {
525         if(len == -1)
526                 len = blen;
527
528         while(blen < len) {
529                 int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
530                 if(result == -1 && sockerrno == EINTR)
531                         continue;
532                 else if(result <= 0)
533                         return false;
534                 blen += result;
535         }
536
537         memcpy(data, buffer, len);
538         memmove(buffer, buffer + len, blen - len);
539         blen -= len;
540
541         return true;
542 }
543
544 bool sendline(int fd, char *format, ...) {
545         static char buffer[4096];
546         char *p = buffer;
547         int blen = 0;
548         va_list ap;
549
550         va_start(ap, format);
551         blen = vsnprintf(buffer, sizeof buffer, format, ap);
552         va_end(ap);
553
554         if(blen < 1 || blen >= sizeof buffer)
555                 return false;
556
557         buffer[blen] = '\n';
558         blen++;
559
560         while(blen) {
561                 int result = send(fd, p, blen, MSG_NOSIGNAL);
562                 if(result == -1 && sockerrno == EINTR)
563                         continue;
564                 else if(result <= 0)
565                         return false;
566                 p += result;
567                 blen -= result;
568         }
569
570         return true;
571 }
572
573 static void pcap(int fd, FILE *out, int snaplen) {
574         sendline(fd, "%d %d %d", CONTROL, REQ_PCAP, snaplen);
575         char data[9018];
576
577         struct {
578                 uint32_t magic;
579                 uint16_t major;
580                 uint16_t minor;
581                 uint32_t tz_offset;
582                 uint32_t tz_accuracy;
583                 uint32_t snaplen;
584                 uint32_t ll_type;
585         } header = {
586                 0xa1b2c3d4,
587                 2, 4,
588                 0, 0,
589                 snaplen ?: sizeof data,
590                 1,
591         };
592
593         struct {
594                 uint32_t tv_sec;
595                 uint32_t tv_usec;
596                 uint32_t len;
597                 uint32_t origlen;
598         } packet;
599
600         struct timeval tv;
601
602         fwrite(&header, sizeof header, 1, out);
603         fflush(out);
604
605         char line[32];
606         while(recvline(fd, line, sizeof line)) {
607                 int code, req, len;
608                 int n = sscanf(line, "%d %d %d", &code, &req, &len);
609                 gettimeofday(&tv, NULL);
610                 if(n != 3 || code != CONTROL || req != REQ_PCAP || len < 0 || len > sizeof data)
611                         break;
612                 if(!recvdata(fd, data, len))
613                         break;
614                 packet.tv_sec = tv.tv_sec;
615                 packet.tv_usec = tv.tv_usec;
616                 packet.len = len;
617                 packet.origlen = len;
618                 fwrite(&packet, sizeof packet, 1, out);
619                 fwrite(data, len, 1, out);
620                 fflush(out);
621         }
622 }
623
624 static void logcontrol(int fd, FILE *out, int level) {
625         sendline(fd, "%d %d %d", CONTROL, REQ_LOG, level);
626         char data[1024];
627         char line[32];
628
629         while(recvline(fd, line, sizeof line)) {
630                 int code, req, len;
631                 int n = sscanf(line, "%d %d %d", &code, &req, &len);
632                 if(n != 3 || code != CONTROL || req != REQ_LOG || len < 0 || len > sizeof data)
633                         break;
634                 if(!recvdata(fd, data, len))
635                         break;
636                 fwrite(data, len, 1, out);
637                 fputc('\n', out);
638                 fflush(out);
639         }
640 }
641
642 #ifdef HAVE_MINGW
643 static bool remove_service(void) {
644         SC_HANDLE manager = NULL;
645         SC_HANDLE service = NULL;
646         SERVICE_STATUS status = {0};
647
648         manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
649         if(!manager) {
650                 fprintf(stderr, "Could not open service manager: %s\n", winerror(GetLastError()));
651                 return false;
652         }
653
654         service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
655
656         if(!service) {
657                 fprintf(stderr, "Could not open %s service: %s\n", identname, winerror(GetLastError()));
658                 return false;
659         }
660
661         if(!ControlService(service, SERVICE_CONTROL_STOP, &status))
662                 fprintf(stderr, "Could not stop %s service: %s\n", identname, winerror(GetLastError()));
663         else
664                 fprintf(stderr, "%s service stopped\n", identname);
665
666         if(!DeleteService(service)) {
667                 fprintf(stderr, "Could not remove %s service: %s\n", identname, winerror(GetLastError()));
668                 return false;
669         }
670
671         fprintf(stderr, "%s service removed\n", identname);
672
673         return true;
674 }
675 #endif
676
677 bool connect_tincd(bool verbose) {
678         if(fd >= 0) {
679                 fd_set r;
680                 FD_ZERO(&r);
681                 FD_SET(fd, &r);
682                 struct timeval tv = {0, 0};
683                 if(select(fd + 1, &r, NULL, NULL, &tv)) {
684                         fprintf(stderr, "Previous connection to tincd lost, reconnecting.\n");
685                         close(fd);
686                         fd = -1;
687                 } else {
688                         return true;
689                 }
690         }
691
692         FILE *f = fopen(pidfilename, "r");
693         if(!f) {
694                 if(verbose)
695                         fprintf(stderr, "Could not open pid file %s: %s\n", pidfilename, strerror(errno));
696                 return false;
697         }
698
699         char host[129];
700         char port[129];
701
702         if(fscanf(f, "%20d %1024s %128s port %128s", &pid, controlcookie, host, port) != 4) {
703                 if(verbose)
704                         fprintf(stderr, "Could not parse pid file %s\n", pidfilename);
705                 fclose(f);
706                 return false;
707         }
708
709         fclose(f);
710
711 #ifndef HAVE_MINGW
712         struct sockaddr_un sa;
713         sa.sun_family = AF_UNIX;
714         strncpy(sa.sun_path, unixsocketname, sizeof sa.sun_path);
715
716         fd = socket(AF_UNIX, SOCK_STREAM, 0);
717         if(fd < 0) {
718                 if(verbose)
719                         fprintf(stderr, "Cannot create UNIX socket: %s\n", sockstrerror(sockerrno));
720                 return false;
721         }
722
723         if(connect(fd, (struct sockaddr *)&sa, sizeof sa) < 0) {
724                 if(verbose)
725                         fprintf(stderr, "Cannot connect to UNIX socket %s: %s\n", unixsocketname, sockstrerror(sockerrno));
726                 close(fd);
727                 fd = -1;
728                 return false;
729         }
730 #else
731         struct addrinfo hints = {
732                 .ai_family = AF_UNSPEC,
733                 .ai_socktype = SOCK_STREAM,
734                 .ai_protocol = IPPROTO_TCP,
735                 .ai_flags = 0,
736         };
737
738         struct addrinfo *res = NULL;
739
740         if(getaddrinfo(host, port, &hints, &res) || !res) {
741                 if(verbose)
742                         fprintf(stderr, "Cannot resolve %s port %s: %s", host, port, sockstrerror(sockerrno));
743                 return false;
744         }
745
746         fd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP);
747         if(fd < 0) {
748                 if(verbose)
749                         fprintf(stderr, "Cannot create TCP socket: %s\n", sockstrerror(sockerrno));
750                 return false;
751         }
752
753 #ifdef HAVE_MINGW
754         unsigned long arg = 0;
755
756         if(ioctlsocket(fd, FIONBIO, &arg) != 0) {
757                 if(verbose)
758                         fprintf(stderr, "ioctlsocket failed: %s", sockstrerror(sockerrno));
759         }
760 #endif
761
762         if(connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
763                 if(verbose)
764                         fprintf(stderr, "Cannot connect to %s port %s: %s\n", host, port, sockstrerror(sockerrno));
765                 close(fd);
766                 fd = -1;
767                 return false;
768         }
769
770         freeaddrinfo(res);
771 #endif
772
773 #ifdef SO_NOSIGPIPE
774         static const int one = 1;
775         setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof one);
776 #endif
777
778         char data[4096];
779         int version;
780
781         if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %s %d", &code, data, &version) != 3 || code != 0) {
782                 if(verbose)
783                         fprintf(stderr, "Cannot read greeting from control socket: %s\n", sockstrerror(sockerrno));
784                 close(fd);
785                 fd = -1;
786                 return false;
787         }
788
789         sendline(fd, "%d ^%s %d", ID, controlcookie, TINC_CTL_VERSION_CURRENT);
790
791         if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &version, &pid) != 3 || code != 4 || version != TINC_CTL_VERSION_CURRENT) {
792                 if(verbose)
793                         fprintf(stderr, "Could not fully establish control socket connection\n");
794                 close(fd);
795                 fd = -1;
796                 return false;
797         }
798
799         return true;
800 }
801
802
803 static int cmd_start(int argc, char *argv[]) {
804         if(connect_tincd(false)) {
805                 if(netname)
806                         fprintf(stderr, "A tincd is already running for net `%s' with pid %d.\n", netname, pid);
807                 else
808                         fprintf(stderr, "A tincd is already running with pid %d.\n", pid);
809                 return 0;
810         }
811
812         char *c;
813         char *slash = strrchr(program_name, '/');
814
815 #ifdef HAVE_MINGW
816         if ((c = strrchr(program_name, '\\')) > slash)
817                 slash = c;
818 #endif
819
820         if (slash++)
821                 xasprintf(&c, "%.*stincd", (int)(slash - program_name), program_name);
822         else
823                 c = "tincd";
824
825         int nargc = 0;
826         char **nargv = xzalloc((optind + argc) * sizeof *nargv);
827
828         char *arg0 = c;
829 #ifdef HAVE_MINGW
830         /*
831            Windows has no real concept of an "argv array". A command line is just one string.
832            The CRT of the new process will decode the command line string to generate argv before calling main(), and (by convention)
833            it uses quotes to handle spaces in arguments.
834            Therefore we need to quote all arguments that might contain spaces. No, execvp() won't do that for us (see MSDN).
835            If we don't do that, then execvp() will run fine but any spaces in the filename contained in arg0 will bleed
836            into the next arguments when the spawned process' CRT parses its command line, resulting in chaos.
837         */
838         xasprintf(&arg0, "\"%s\"", arg0);
839 #endif
840         nargv[nargc++] = arg0;
841         for(int i = 1; i < optind; i++)
842                 nargv[nargc++] = orig_argv[i];
843         for(int i = 1; i < argc; i++)
844                 nargv[nargc++] = argv[i];
845
846 #ifdef HAVE_MINGW
847         int status = spawnvp(_P_WAIT, c, nargv);
848         if (status == -1) {
849                 fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno));
850                 return 1;
851         }
852         return status;
853 #else
854         pid_t pid = fork();
855         if(pid == -1) {
856                 fprintf(stderr, "Could not fork: %s\n", strerror(errno));
857                 free(nargv);
858                 return 1;
859         }
860
861         if(!pid)
862                 exit(execvp(c, nargv));
863
864         free(nargv);
865
866         int status = -1, result;
867 #ifdef SIGINT
868         signal(SIGINT, SIG_IGN);
869 #endif
870         result = waitpid(pid, &status, 0);
871 #ifdef SIGINT
872         signal(SIGINT, SIG_DFL);
873 #endif
874
875         if(result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
876                 fprintf(stderr, "Error starting %s\n", c);
877                 return 1;
878         }
879
880         return 0;
881 #endif
882 }
883
884 static int cmd_stop(int argc, char *argv[]) {
885         if(argc > 1) {
886                 fprintf(stderr, "Too many arguments!\n");
887                 return 1;
888         }
889
890 #ifndef HAVE_MINGW
891         if(!connect_tincd(true)) {
892                 if(pid) {
893                         if(kill(pid, SIGTERM)) {
894                                 fprintf(stderr, "Could not send TERM signal to process with PID %u: %s\n", pid, strerror(errno));
895                                 return 1;
896                         }
897
898                         fprintf(stderr, "Sent TERM signal to process with PID %u.\n", pid);
899                         waitpid(pid, NULL, 0);
900                         return 0;
901                 }
902
903                 return 1;
904         }
905
906         sendline(fd, "%d %d", CONTROL, REQ_STOP);
907
908         while(recvline(fd, line, sizeof line)) {
909                 // Wait for tincd to close the connection...
910         }
911 #else
912         if(!remove_service())
913                 return 1;
914 #endif
915         close(fd);
916         pid = 0;
917         fd = -1;
918
919         return 0;
920 }
921
922 static int cmd_restart(int argc, char *argv[]) {
923         cmd_stop(1, argv);
924         return cmd_start(argc, argv);
925 }
926
927 static int cmd_reload(int argc, char *argv[]) {
928         if(argc > 1) {
929                 fprintf(stderr, "Too many arguments!\n");
930                 return 1;
931         }
932
933         if(!connect_tincd(true))
934                 return 1;
935
936         sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
937         if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RELOAD || result) {
938                 fprintf(stderr, "Could not reload configuration.\n");
939                 return 1;
940         }
941
942         return 0;
943
944 }
945
946 static int cmd_dump(int argc, char *argv[]) {
947         bool only_reachable = false;
948
949         if(argc > 2 && !strcasecmp(argv[1], "reachable")) {
950                 if(strcasecmp(argv[2], "nodes")) {
951                         fprintf(stderr, "`reachable' only supported for nodes.\n");
952                         usage(true);
953                         return 1;
954                 }
955                 only_reachable = true;
956                 argv++;
957                 argc--;
958         }
959
960         if(argc != 2) {
961                 fprintf(stderr, "Invalid number of arguments.\n");
962                 usage(true);
963                 return 1;
964         }
965
966         if(!connect_tincd(true))
967                 return 1;
968
969         int do_graph = 0;
970
971         if(!strcasecmp(argv[1], "nodes"))
972                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
973         else if(!strcasecmp(argv[1], "edges"))
974                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
975         else if(!strcasecmp(argv[1], "subnets"))
976                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
977         else if(!strcasecmp(argv[1], "connections"))
978                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS);
979         else if(!strcasecmp(argv[1], "graph")) {
980                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
981                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
982                 do_graph = 1;
983         } else if(!strcasecmp(argv[1], "digraph")) {
984                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
985                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES);
986                 do_graph = 2;
987         } else {
988                 fprintf(stderr, "Unknown dump type '%s'.\n", argv[1]);
989                 usage(true);
990                 return 1;
991         }
992
993         if(do_graph == 1)
994                 printf("graph {\n");
995         else if(do_graph == 2)
996                 printf("digraph {\n");
997
998         while(recvline(fd, line, sizeof line)) {
999                 char node1[4096], node2[4096];
1000                 int n = sscanf(line, "%d %d %s %s", &code, &req, node1, node2);
1001                 if(n == 2) {
1002                         if(do_graph && req == REQ_DUMP_NODES)
1003                                 continue;
1004                         else {
1005                                 if(do_graph)
1006                                         printf("}\n");
1007                                 return 0;
1008                         }
1009                 }
1010                 if(n < 2)
1011                         break;
1012
1013                 char node[4096];
1014                 char id[4096];
1015                 char from[4096];
1016                 char to[4096];
1017                 char subnet[4096];
1018                 char host[4096];
1019                 char port[4096];
1020                 char local_host[4096];
1021                 char local_port[4096];
1022                 char via[4096];
1023                 char nexthop[4096];
1024                 int cipher, digest, maclength, compression, distance, socket, weight;
1025                 short int pmtu, minmtu, maxmtu;
1026                 unsigned int options, status_int;
1027                 node_status_t status;
1028                 long int last_state_change;
1029
1030                 switch(req) {
1031                         case REQ_DUMP_NODES: {
1032                                 int n = sscanf(line, "%*d %*d %s %s %s port %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
1033                                 if(n != 17) {
1034                                         fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
1035                                         return 1;
1036                                 }
1037
1038                                 memcpy(&status, &status_int, sizeof status);
1039
1040                                 if(do_graph) {
1041                                         const char *color = "black";
1042                                         if(!strcmp(host, "MYSELF"))
1043                                                 color = "green";
1044                                         else if(!status.reachable)
1045                                                 color = "red";
1046                                         else if(strcmp(via, node))
1047                                                 color = "orange";
1048                                         else if(!status.validkey)
1049                                                 color = "black";
1050                                         else if(minmtu > 0)
1051                                                 color = "green";
1052                                         printf(" %s [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\"");
1053                                 } else {
1054                                         if(only_reachable && !status.reachable)
1055                                                 continue;
1056                                         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 %hd (min %hd max %hd)\n",
1057                                                         node, id, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu);
1058                                 }
1059                         } break;
1060
1061                         case REQ_DUMP_EDGES: {
1062                                 int n = sscanf(line, "%*d %*d %s %s %s port %s %s port %s %x %d", from, to, host, port, local_host, local_port, &options, &weight);
1063                                 if(n != 8) {
1064                                         fprintf(stderr, "Unable to parse edge dump from tincd.\n");
1065                                         return 1;
1066                                 }
1067
1068                                 if(do_graph) {
1069                                         float w = 1 + 65536.0 / weight;
1070                                         if(do_graph == 1 && strcmp(node1, node2) > 0)
1071                                                 printf(" %s -- %s [w = %f, weight = %f];\n", node1, node2, w, w);
1072                                         else if(do_graph == 2)
1073                                                 printf(" %s -> %s [w = %f, weight = %f];\n", node1, node2, w, w);
1074                                 } else {
1075                                         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);
1076                                 }
1077                         } break;
1078
1079                         case REQ_DUMP_SUBNETS: {
1080                                 int n = sscanf(line, "%*d %*d %s %s", subnet, node);
1081                                 if(n != 2) {
1082                                         fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
1083                                         return 1;
1084                                 }
1085                                 printf("%s owner %s\n", strip_weight(subnet), node);
1086                         } break;
1087
1088                         case REQ_DUMP_CONNECTIONS: {
1089                                 int n = sscanf(line, "%*d %*d %s %s port %s %x %d %x", node, host, port, &options, &socket, &status_int);
1090                                 if(n != 6) {
1091                                         fprintf(stderr, "Unable to parse connection dump from tincd.\n");
1092                                         return 1;
1093                                 }
1094                                 printf("%s at %s port %s options %x socket %d status %x\n", node, host, port, options, socket, status_int);
1095                         } break;
1096
1097                         default:
1098                                 fprintf(stderr, "Unable to parse dump from tincd.\n");
1099                                 return 1;
1100                 }
1101         }
1102
1103         fprintf(stderr, "Error receiving dump.\n");
1104         return 1;
1105 }
1106
1107 static int cmd_purge(int argc, char *argv[]) {
1108         if(argc > 1) {
1109                 fprintf(stderr, "Too many arguments!\n");
1110                 return 1;
1111         }
1112
1113         if(!connect_tincd(true))
1114                 return 1;
1115
1116         sendline(fd, "%d %d", CONTROL, REQ_PURGE);
1117         if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_PURGE || result) {
1118                 fprintf(stderr, "Could not purge old information.\n");
1119                 return 1;
1120         }
1121
1122         return 0;
1123 }
1124
1125 static int cmd_debug(int argc, char *argv[]) {
1126         if(argc != 2) {
1127                 fprintf(stderr, "Invalid number of arguments.\n");
1128                 return 1;
1129         }
1130
1131         if(!connect_tincd(true))
1132                 return 1;
1133
1134         int debuglevel = atoi(argv[1]);
1135         int origlevel;
1136
1137         sendline(fd, "%d %d %d", CONTROL, REQ_SET_DEBUG, debuglevel);
1138         if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &origlevel) != 3 || code != CONTROL || req != REQ_SET_DEBUG) {
1139                 fprintf(stderr, "Could not set debug level.\n");
1140                 return 1;
1141         }
1142
1143         fprintf(stderr, "Old level %d, new level %d.\n", origlevel, debuglevel);
1144         return 0;
1145 }
1146
1147 static int cmd_retry(int argc, char *argv[]) {
1148         if(argc > 1) {
1149                 fprintf(stderr, "Too many arguments!\n");
1150                 return 1;
1151         }
1152
1153         if(!connect_tincd(true))
1154                 return 1;
1155
1156         sendline(fd, "%d %d", CONTROL, REQ_RETRY);
1157         if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RETRY || result) {
1158                 fprintf(stderr, "Could not retry outgoing connections.\n");
1159                 return 1;
1160         }
1161
1162         return 0;
1163 }
1164
1165 static int cmd_connect(int argc, char *argv[]) {
1166         if(argc != 2) {
1167                 fprintf(stderr, "Invalid number of arguments.\n");
1168                 return 1;
1169         }
1170
1171         if(!check_id(argv[1])) {
1172                 fprintf(stderr, "Invalid name for node.\n");
1173                 return 1;
1174         }
1175
1176         if(!connect_tincd(true))
1177                 return 1;
1178
1179         sendline(fd, "%d %d %s", CONTROL, REQ_CONNECT, argv[1]);
1180         if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_CONNECT || result) {
1181                 fprintf(stderr, "Could not connect to %s.\n", argv[1]);
1182                 return 1;
1183         }
1184
1185         return 0;
1186 }
1187
1188 static int cmd_disconnect(int argc, char *argv[]) {
1189         if(argc != 2) {
1190                 fprintf(stderr, "Invalid number of arguments.\n");
1191                 return 1;
1192         }
1193
1194         if(!check_id(argv[1])) {
1195                 fprintf(stderr, "Invalid name for node.\n");
1196                 return 1;
1197         }
1198
1199         if(!connect_tincd(true))
1200                 return 1;
1201
1202         sendline(fd, "%d %d %s", CONTROL, REQ_DISCONNECT, argv[1]);
1203         if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_DISCONNECT || result) {
1204                 fprintf(stderr, "Could not disconnect %s.\n", argv[1]);
1205                 return 1;
1206         }
1207
1208         return 0;
1209 }
1210
1211 static int cmd_top(int argc, char *argv[]) {
1212         if(argc > 1) {
1213                 fprintf(stderr, "Too many arguments!\n");
1214                 return 1;
1215         }
1216
1217 #ifdef HAVE_CURSES
1218         if(!connect_tincd(true))
1219                 return 1;
1220
1221         top(fd);
1222         return 0;
1223 #else
1224         fprintf(stderr, "This version of tinc was compiled without support for the curses library.\n");
1225         return 1;
1226 #endif
1227 }
1228
1229 static int cmd_pcap(int argc, char *argv[]) {
1230         if(argc > 2) {
1231                 fprintf(stderr, "Too many arguments!\n");
1232                 return 1;
1233         }
1234
1235         if(!connect_tincd(true))
1236                 return 1;
1237
1238         pcap(fd, stdout, argc > 1 ? atoi(argv[1]) : 0);
1239         return 0;
1240 }
1241
1242 #ifdef SIGINT
1243 static void sigint_handler(int sig) {
1244         fprintf(stderr, "\n");
1245         shutdown(fd, SHUT_RDWR);
1246 }
1247 #endif
1248
1249 static int cmd_log(int argc, char *argv[]) {
1250         if(argc > 2) {
1251                 fprintf(stderr, "Too many arguments!\n");
1252                 return 1;
1253         }
1254
1255         if(!connect_tincd(true))
1256                 return 1;
1257
1258 #ifdef SIGINT
1259         signal(SIGINT, sigint_handler);
1260 #endif
1261
1262         logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1);
1263
1264 #ifdef SIGINT
1265         signal(SIGINT, SIG_DFL);
1266 #endif
1267
1268         close(fd);
1269         fd = -1;
1270         return 0;
1271 }
1272
1273 static int cmd_pid(int argc, char *argv[]) {
1274         if(argc > 1) {
1275                 fprintf(stderr, "Too many arguments!\n");
1276                 return 1;
1277         }
1278
1279         if(!connect_tincd(true) && !pid)
1280                 return 1;
1281
1282         printf("%d\n", pid);
1283         return 0;
1284 }
1285
1286 int rstrip(char *value) {
1287         int len = strlen(value);
1288         while(len && strchr("\t\r\n ", value[len - 1]))
1289                 value[--len] = 0;
1290         return len;
1291 }
1292
1293 char *get_my_name(bool verbose) {
1294         FILE *f = fopen(tinc_conf, "r");
1295         if(!f) {
1296                 if(verbose)
1297                         fprintf(stderr, "Could not open %s: %s\n", tinc_conf, strerror(errno));
1298                 return NULL;
1299         }
1300
1301         char buf[4096];
1302         char *value;
1303         while(fgets(buf, sizeof buf, f)) {
1304                 int len = strcspn(buf, "\t =");
1305                 value = buf + len;
1306                 value += strspn(value, "\t ");
1307                 if(*value == '=') {
1308                         value++;
1309                         value += strspn(value, "\t ");
1310                 }
1311                 if(!rstrip(value))
1312                         continue;
1313                 buf[len] = 0;
1314                 if(strcasecmp(buf, "Name"))
1315                         continue;
1316                 if(*value) {
1317                         fclose(f);
1318                         return replace_name(value);
1319                 }
1320         }
1321
1322         fclose(f);
1323         if(verbose)
1324                 fprintf(stderr, "Could not find Name in %s.\n", tinc_conf);
1325         return NULL;
1326 }
1327
1328 const var_t variables[] = {
1329         /* Server configuration */
1330         {"AddressFamily", VAR_SERVER},
1331         {"AutoConnect", VAR_SERVER | VAR_SAFE},
1332         {"BindToAddress", VAR_SERVER | VAR_MULTIPLE},
1333         {"BindToInterface", VAR_SERVER},
1334         {"Broadcast", VAR_SERVER | VAR_SAFE},
1335         {"BroadcastSubnet", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1336         {"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE},
1337         {"DecrementTTL", VAR_SERVER},
1338         {"Device", VAR_SERVER},
1339         {"DeviceStandby", VAR_SERVER},
1340         {"DeviceType", VAR_SERVER},
1341         {"DirectOnly", VAR_SERVER},
1342         {"Ed25519PrivateKeyFile", VAR_SERVER},
1343         {"ExperimentalProtocol", VAR_SERVER},
1344         {"Forwarding", VAR_SERVER},
1345         {"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
1346         {"Hostnames", VAR_SERVER},
1347         {"IffOneQueue", VAR_SERVER},
1348         {"Interface", VAR_SERVER},
1349         {"KeyExpire", VAR_SERVER},
1350         {"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
1351         {"LocalDiscovery", VAR_SERVER},
1352         {"MACExpire", VAR_SERVER},
1353         {"MaxConnectionBurst", VAR_SERVER},
1354         {"MaxOutputBufferSize", VAR_SERVER},
1355         {"MaxTimeout", VAR_SERVER},
1356         {"Mode", VAR_SERVER | VAR_SAFE},
1357         {"Name", VAR_SERVER},
1358         {"PingInterval", VAR_SERVER},
1359         {"PingTimeout", VAR_SERVER},
1360         {"PriorityInheritance", VAR_SERVER},
1361         {"PrivateKey", VAR_SERVER | VAR_OBSOLETE},
1362         {"PrivateKeyFile", VAR_SERVER},
1363         {"ProcessPriority", VAR_SERVER},
1364         {"Proxy", VAR_SERVER},
1365         {"ReplayWindow", VAR_SERVER},
1366         {"ScriptsExtension", VAR_SERVER},
1367         {"ScriptsInterpreter", VAR_SERVER},
1368         {"StrictSubnets", VAR_SERVER},
1369         {"TunnelServer", VAR_SERVER},
1370         {"UDPDiscovery", VAR_SERVER},
1371         {"UDPDiscoveryKeepaliveInterval", VAR_SERVER},
1372         {"UDPDiscoveryInterval", VAR_SERVER},
1373         {"UDPDiscoveryTimeout", VAR_SERVER},
1374         {"UDPRcvBuf", VAR_SERVER},
1375         {"UDPSndBuf", VAR_SERVER},
1376         {"VDEGroup", VAR_SERVER},
1377         {"VDEPort", VAR_SERVER},
1378         /* Host configuration */
1379         {"Address", VAR_HOST | VAR_MULTIPLE},
1380         {"Cipher", VAR_SERVER | VAR_HOST},
1381         {"ClampMSS", VAR_SERVER | VAR_HOST},
1382         {"Compression", VAR_SERVER | VAR_HOST},
1383         {"Digest", VAR_SERVER | VAR_HOST},
1384         {"Ed25519PublicKey", VAR_HOST},
1385         {"Ed25519PublicKeyFile", VAR_SERVER | VAR_HOST},
1386         {"IndirectData", VAR_SERVER | VAR_HOST},
1387         {"MACLength", VAR_SERVER | VAR_HOST},
1388         {"PMTU", VAR_SERVER | VAR_HOST},
1389         {"PMTUDiscovery", VAR_SERVER | VAR_HOST},
1390         {"Port", VAR_HOST},
1391         {"PublicKey", VAR_HOST | VAR_OBSOLETE},
1392         {"PublicKeyFile", VAR_SERVER | VAR_HOST | VAR_OBSOLETE},
1393         {"Subnet", VAR_HOST | VAR_MULTIPLE | VAR_SAFE},
1394         {"TCPOnly", VAR_SERVER | VAR_HOST},
1395         {"Weight", VAR_HOST | VAR_SAFE},
1396         {NULL, 0}
1397 };
1398
1399 static int cmd_config(int argc, char *argv[]) {
1400         if(argc < 2) {
1401                 fprintf(stderr, "Invalid number of arguments.\n");
1402                 return 1;
1403         }
1404
1405         if(strcasecmp(argv[0], "config"))
1406                 argv--, argc++;
1407
1408         int action = -2;
1409         if(!strcasecmp(argv[1], "get")) {
1410                 argv++, argc--;
1411         } else if(!strcasecmp(argv[1], "add")) {
1412                 argv++, argc--, action = 1;
1413         } else if(!strcasecmp(argv[1], "del")) {
1414                 argv++, argc--, action = -1;
1415         } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) {
1416                 argv++, argc--, action = 0;
1417         }
1418
1419         if(argc < 2) {
1420                 fprintf(stderr, "Invalid number of arguments.\n");
1421                 return 1;
1422         }
1423
1424         // Concatenate the rest of the command line
1425         strncpy(line, argv[1], sizeof line - 1);
1426         for(int i = 2; i < argc; i++) {
1427                 strncat(line, " ", sizeof line - 1 - strlen(line));
1428                 strncat(line, argv[i], sizeof line - 1 - strlen(line));
1429         }
1430
1431         // Liberal parsing into node name, variable name and value.
1432         char *node = NULL;
1433         char *variable;
1434         char *value;
1435         int len;
1436
1437         len = strcspn(line, "\t =");
1438         value = line + len;
1439         value += strspn(value, "\t ");
1440         if(*value == '=') {
1441                 value++;
1442                 value += strspn(value, "\t ");
1443         }
1444         line[len] = '\0';
1445         variable = strchr(line, '.');
1446         if(variable) {
1447                 node = line;
1448                 *variable++ = 0;
1449         } else {
1450                 variable = line;
1451         }
1452
1453         if(!*variable) {
1454                 fprintf(stderr, "No variable given.\n");
1455                 return 1;
1456         }
1457
1458         if(action >= 0 && !*value) {
1459                 fprintf(stderr, "No value for variable given.\n");
1460                 return 1;
1461         }
1462
1463         if(action < -1 && *value)
1464                 action = 0;
1465
1466         /* Some simple checks. */
1467         bool found = false;
1468         bool warnonremove = false;
1469
1470         for(int i = 0; variables[i].name; i++) {
1471                 if(strcasecmp(variables[i].name, variable))
1472                         continue;
1473
1474                 found = true;
1475                 variable = (char *)variables[i].name;
1476
1477                 /* Discourage use of obsolete variables. */
1478
1479                 if(variables[i].type & VAR_OBSOLETE && action >= 0) {
1480                         if(force) {
1481                                 fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable);
1482                         } else {
1483                                 fprintf(stderr, "%s is an obsolete variable! Use --force to use it anyway.\n", variable);
1484                                 return 1;
1485                         }
1486                 }
1487
1488                 /* Don't put server variables in host config files */
1489
1490                 if(node && !(variables[i].type & VAR_HOST) && action >= 0) {
1491                         if(force) {
1492                                 fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable);
1493                         } else {
1494                                 fprintf(stderr, "%s is not a host configuration variable! Use --force to use it anyway.\n", variable);
1495                                 return 1;
1496                         }
1497                 }
1498
1499                 /* Should this go into our own host config file? */
1500
1501                 if(!node && !(variables[i].type & VAR_SERVER)) {
1502                         node = get_my_name(true);
1503                         if(!node)
1504                                 return 1;
1505                 }
1506
1507                 /* Change "add" into "set" for variables that do not allow multiple occurences.
1508                    Turn on warnings when it seems variables might be removed unintentionally. */
1509
1510                 if(action == 1 && !(variables[i].type & VAR_MULTIPLE)) {
1511                         warnonremove = true;
1512                         action = 0;
1513                 } else if(action == 0 && (variables[i].type & VAR_MULTIPLE)) {
1514                         warnonremove = true;
1515                 }
1516
1517                 break;
1518         }
1519
1520         if(node && !check_id(node)) {
1521                 fprintf(stderr, "Invalid name for node.\n");
1522                 return 1;
1523         }
1524
1525         if(!found) {
1526                 if(force || action < 0) {
1527                         fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable);
1528                 } else {
1529                         fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable);
1530                         return 1;
1531                 }
1532         }
1533
1534         // Open the right configuration file.
1535         char *filename;
1536         if(node)
1537                 xasprintf(&filename, "%s" SLASH "%s", hosts_dir, node);
1538         else
1539                 filename = tinc_conf;
1540
1541         FILE *f = fopen(filename, "r");
1542         if(!f) {
1543                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
1544                 return 1;
1545         }
1546
1547         char *tmpfile = NULL;
1548         FILE *tf = NULL;
1549
1550         if(action >= -1) {
1551                 xasprintf(&tmpfile, "%s.config.tmp", filename);
1552                 tf = fopen(tmpfile, "w");
1553                 if(!tf) {
1554                         fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
1555                         fclose(f);
1556                         return 1;
1557                 }
1558         }
1559
1560         // Copy the file, making modifications on the fly, unless we are just getting a value.
1561         char buf1[4096];
1562         char buf2[4096];
1563         bool set = false;
1564         bool removed = false;
1565         found = false;
1566
1567         while(fgets(buf1, sizeof buf1, f)) {
1568                 buf1[sizeof buf1 - 1] = 0;
1569                 strncpy(buf2, buf1, sizeof buf2);
1570
1571                 // Parse line in a simple way
1572                 char *bvalue;
1573                 int len;
1574
1575                 len = strcspn(buf2, "\t =");
1576                 bvalue = buf2 + len;
1577                 bvalue += strspn(bvalue, "\t ");
1578                 if(*bvalue == '=') {
1579                         bvalue++;
1580                         bvalue += strspn(bvalue, "\t ");
1581                 }
1582                 rstrip(bvalue);
1583                 buf2[len] = '\0';
1584
1585                 // Did it match?
1586                 if(!strcasecmp(buf2, variable)) {
1587                         // Get
1588                         if(action < -1) {
1589                                 found = true;
1590                                 printf("%s\n", bvalue);
1591                         // Del
1592                         } else if(action == -1) {
1593                                 if(!*value || !strcasecmp(bvalue, value)) {
1594                                         removed = true;
1595                                         continue;
1596                                 }
1597                         // Set
1598                         } else if(action == 0) {
1599                                 // Warn if "set" was used for variables that can occur multiple times
1600                                 if(warnonremove && strcasecmp(bvalue, value))
1601                                         fprintf(stderr, "Warning: removing %s = %s\n", variable, bvalue);
1602
1603                                 // Already set? Delete the rest...
1604                                 if(set)
1605                                         continue;
1606
1607                                 // Otherwise, replace.
1608                                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
1609                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1610                                         return 1;
1611                                 }
1612                                 set = true;
1613                                 continue;
1614                         // Add
1615                         } else if(action > 0) {
1616                                 // Check if we've already seen this variable with the same value
1617                                 if(!strcasecmp(bvalue, value))
1618                                         found = true;
1619                         }
1620                 }
1621
1622                 if(action >= -1) {
1623                         // Copy original line...
1624                         if(fputs(buf1, tf) < 0) {
1625                                 fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1626                                 return 1;
1627                         }
1628
1629                         // Add newline if it is missing...
1630                         if(*buf1 && buf1[strlen(buf1) - 1] != '\n') {
1631                                 if(fputc('\n', tf) < 0) {
1632                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1633                                         return 1;
1634                                 }
1635                         }
1636                 }
1637         }
1638
1639         // Make sure we read everything...
1640         if(ferror(f) || !feof(f)) {
1641                 fprintf(stderr, "Error while reading from configuration file %s: %s\n", filename, strerror(errno));
1642                 return 1;
1643         }
1644
1645         if(fclose(f)) {
1646                 fprintf(stderr, "Error closing configuration file %s: %s\n", filename, strerror(errno));
1647                 return 1;
1648         }
1649
1650         // Add new variable if necessary.
1651         if((action > 0 && !found)|| (action == 0 && !set)) {
1652                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
1653                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1654                         return 1;
1655                 }
1656         }
1657
1658         if(action < -1) {
1659                 if(found) {
1660                         return 0;
1661                 } else {
1662                         fprintf(stderr, "No matching configuration variables found.\n");
1663                         return 1;
1664                 }
1665         }
1666
1667         // Make sure we wrote everything...
1668         if(fclose(tf)) {
1669                 fprintf(stderr, "Error closing temporary file %s: %s\n", tmpfile, strerror(errno));
1670                 return 1;
1671         }
1672
1673         // Could we find what we had to remove?
1674         if(action < 0 && !removed) {
1675                 remove(tmpfile);
1676                 fprintf(stderr, "No configuration variables deleted.\n");
1677                 return 1;
1678         }
1679
1680         // Replace the configuration file with the new one
1681 #ifdef HAVE_MINGW
1682         if(remove(filename)) {
1683                 fprintf(stderr, "Error replacing file %s: %s\n", filename, strerror(errno));
1684                 return 1;
1685         }
1686 #endif
1687         if(rename(tmpfile, filename)) {
1688                 fprintf(stderr, "Error renaming temporary file %s to configuration file %s: %s\n", tmpfile, filename, strerror(errno));
1689                 return 1;
1690         }
1691
1692         // Silently try notifying a running tincd of changes.
1693         if(connect_tincd(false))
1694                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
1695
1696         return 0;
1697 }
1698
1699 static bool try_bind(int port) {
1700         struct addrinfo *ai = NULL;
1701         struct addrinfo hint = {
1702                 .ai_flags = AI_PASSIVE,
1703                 .ai_family = AF_UNSPEC,
1704                 .ai_socktype = SOCK_STREAM,
1705                 .ai_protocol = IPPROTO_TCP,
1706         };
1707
1708         char portstr[16];
1709         snprintf(portstr, sizeof portstr, "%d", port);
1710
1711         if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai)
1712                 return false;
1713
1714         while(ai) {
1715                 int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
1716                 if(!fd)
1717                         return false;
1718                 int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
1719                 closesocket(fd);
1720                 if(result)
1721                         return false;
1722                 ai = ai->ai_next;
1723         }
1724
1725         return true;
1726 }
1727
1728 int check_port(char *name) {
1729         if(try_bind(655))
1730                 return 655;
1731
1732         fprintf(stderr, "Warning: could not bind to port 655. ");
1733
1734         for(int i = 0; i < 100; i++) {
1735                 int port = 0x1000 + (rand() & 0x7fff);
1736                 if(try_bind(port)) {
1737                         char *filename;
1738                         xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
1739                         FILE *f = fopen(filename, "a");
1740                         free(filename);
1741                         if(!f) {
1742                                 fprintf(stderr, "Please change tinc's Port manually.\n");
1743                                 return 0;
1744                         }
1745
1746                         fprintf(f, "Port = %d\n", port);
1747                         fclose(f);
1748                         fprintf(stderr, "Tinc will instead listen on port %d.\n", port);
1749                         return port;
1750                 }
1751         }
1752
1753         fprintf(stderr, "Please change tinc's Port manually.\n");
1754         return 0;
1755 }
1756
1757 static int cmd_init(int argc, char *argv[]) {
1758         if(!access(tinc_conf, F_OK)) {
1759                 fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
1760                 return 1;
1761         }
1762
1763         if(argc > 2) {
1764                 fprintf(stderr, "Too many arguments!\n");
1765                 return 1;
1766         } else if(argc < 2) {
1767                 if(tty) {
1768                         char buf[1024];
1769                         fprintf(stderr, "Enter the Name you want your tinc node to have: ");
1770                         if(!fgets(buf, sizeof buf, stdin)) {
1771                                 fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
1772                                 return 1;
1773                         }
1774                         int len = rstrip(buf);
1775                         if(!len) {
1776                                 fprintf(stderr, "No name given!\n");
1777                                 return 1;
1778                         }
1779                         name = strdup(buf);
1780                 } else {
1781                         fprintf(stderr, "No Name given!\n");
1782                         return 1;
1783                 }
1784         } else {
1785                 name = strdup(argv[1]);
1786                 if(!*name) {
1787                         fprintf(stderr, "No Name given!\n");
1788                         return 1;
1789                 }
1790         }
1791
1792         if(!check_id(name)) {
1793                 fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n");
1794                 return 1;
1795         }
1796
1797         if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) {
1798                 fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
1799                 return 1;
1800         }
1801
1802         if(mkdir(confbase, 0777) && errno != EEXIST) {
1803                 fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
1804                 return 1;
1805         }
1806
1807         if(mkdir(hosts_dir, 0777) && errno != EEXIST) {
1808                 fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno));
1809                 return 1;
1810         }
1811
1812         FILE *f = fopen(tinc_conf, "w");
1813         if(!f) {
1814                 fprintf(stderr, "Could not create file %s: %s\n", tinc_conf, strerror(errno));
1815                 return 1;
1816         }
1817
1818         fprintf(f, "Name = %s\n", name);
1819         fclose(f);
1820
1821 #ifndef DISABLE_LEGACY
1822         if(!rsa_keygen(2048, false))
1823                 return 1;
1824 #endif
1825
1826         if(!ed25519_keygen(false))
1827                 return 1;
1828
1829         check_port(name);
1830
1831 #ifndef HAVE_MINGW
1832         char *filename;
1833         xasprintf(&filename, "%s" SLASH "tinc-up", confbase);
1834         if(access(filename, F_OK)) {
1835                 FILE *f = fopenmask(filename, "w", 0777);
1836                 if(!f) {
1837                         fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
1838                         return 1;
1839                 }
1840                 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");
1841                 fclose(f);
1842         }
1843 #endif
1844
1845         return 0;
1846
1847 }
1848
1849 static int cmd_generate_keys(int argc, char *argv[]) {
1850 #ifdef DISABLE_LEGACY
1851         if(argc > 1) {
1852 #else
1853         if(argc > 2) {
1854 #endif
1855                 fprintf(stderr, "Too many arguments!\n");
1856                 return 1;
1857         }
1858
1859         if(!name)
1860                 name = get_my_name(false);
1861
1862 #ifndef DISABLE_LEGACY
1863         if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true))
1864                 return 1;
1865 #endif
1866
1867         if(!ed25519_keygen(true))
1868                 return 1;
1869
1870         return 0;
1871 }
1872
1873 #ifndef DISABLE_LEGACY
1874 static int cmd_generate_rsa_keys(int argc, char *argv[]) {
1875         if(argc > 2) {
1876                 fprintf(stderr, "Too many arguments!\n");
1877                 return 1;
1878         }
1879
1880         if(!name)
1881                 name = get_my_name(false);
1882
1883         return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
1884 }
1885 #endif
1886
1887 static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
1888         if(argc > 1) {
1889                 fprintf(stderr, "Too many arguments!\n");
1890                 return 1;
1891         }
1892
1893         if(!name)
1894                 name = get_my_name(false);
1895
1896         return !ed25519_keygen(true);
1897 }
1898
1899 static int cmd_help(int argc, char *argv[]) {
1900         usage(false);
1901         return 0;
1902 }
1903
1904 static int cmd_version(int argc, char *argv[]) {
1905         if(argc > 1) {
1906                 fprintf(stderr, "Too many arguments!\n");
1907                 return 1;
1908         }
1909
1910         version();
1911         return 0;
1912 }
1913
1914 static int cmd_info(int argc, char *argv[]) {
1915         if(argc != 2) {
1916                 fprintf(stderr, "Invalid number of arguments.\n");
1917                 return 1;
1918         }
1919
1920         if(!connect_tincd(true))
1921                 return 1;
1922
1923         return info(fd, argv[1]);
1924 }
1925
1926 static const char *conffiles[] = {
1927         "tinc.conf",
1928         "tinc-up",
1929         "tinc-down",
1930         "subnet-up",
1931         "subnet-down",
1932         "host-up",
1933         "host-down",
1934         NULL,
1935 };
1936
1937 static int cmd_edit(int argc, char *argv[]) {
1938         if(argc != 2) {
1939                 fprintf(stderr, "Invalid number of arguments.\n");
1940                 return 1;
1941         }
1942
1943         char *filename = NULL;
1944
1945         if(strncmp(argv[1], "hosts" SLASH, 6)) {
1946                 for(int i = 0; conffiles[i]; i++) {
1947                         if(!strcmp(argv[1], conffiles[i])) {
1948                                 xasprintf(&filename, "%s" SLASH "%s", confbase, argv[1]);
1949                                 break;
1950                         }
1951                 }
1952         } else {
1953                 argv[1] += 6;
1954         }
1955
1956         if(!filename) {
1957                 xasprintf(&filename, "%s" SLASH "%s", hosts_dir, argv[1]);
1958                 char *dash = strchr(argv[1], '-');
1959                 if(dash) {
1960                         *dash++ = 0;
1961                         if((strcmp(dash, "up") && strcmp(dash, "down")) || !check_id(argv[1])) {
1962                                 fprintf(stderr, "Invalid configuration filename.\n");
1963                                 return 1;
1964                         }
1965                 }
1966         }
1967
1968         char *command;
1969 #ifndef HAVE_MINGW
1970         xasprintf(&command, "\"%s\" \"%s\"", getenv("VISUAL") ?: getenv("EDITOR") ?: "vi", filename);
1971 #else
1972         xasprintf(&command, "edit \"%s\"", filename);
1973 #endif
1974         int result = system(command);
1975         if(result)
1976                 return result;
1977
1978         // Silently try notifying a running tincd of changes.
1979         if(connect_tincd(false))
1980                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
1981
1982         return 0;
1983 }
1984
1985 static int export(const char *name, FILE *out) {
1986         char *filename;
1987         xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
1988         FILE *in = fopen(filename, "r");
1989         if(!in) {
1990                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
1991                 return 1;
1992         }
1993
1994         fprintf(out, "Name = %s\n", name);
1995         char buf[4096];
1996         while(fgets(buf, sizeof buf, in)) {
1997                 if(strcspn(buf, "\t =") != 4 || strncasecmp(buf, "Name", 4))
1998                         fputs(buf, out);
1999         }
2000
2001         if(ferror(in)) {
2002                 fprintf(stderr, "Error while reading configuration file %s: %s\n", filename, strerror(errno));
2003                 fclose(in);
2004                 return 1;
2005         }
2006
2007         fclose(in);
2008         return 0;
2009 }
2010
2011 static int cmd_export(int argc, char *argv[]) {
2012         if(argc > 1) {
2013                 fprintf(stderr, "Too many arguments!\n");
2014                 return 1;
2015         }
2016
2017         char *name = get_my_name(true);
2018         if(!name)
2019                 return 1;
2020
2021         int result = export(name, stdout);
2022         if(!tty)
2023                 fclose(stdout);
2024
2025         free(name);
2026         return result;
2027 }
2028
2029 static int cmd_export_all(int argc, char *argv[]) {
2030         if(argc > 1) {
2031                 fprintf(stderr, "Too many arguments!\n");
2032                 return 1;
2033         }
2034
2035         DIR *dir = opendir(hosts_dir);
2036         if(!dir) {
2037                 fprintf(stderr, "Could not open host configuration directory %s: %s\n", hosts_dir, strerror(errno));
2038                 return 1;
2039         }
2040
2041         bool first = true;
2042         int result = 0;
2043         struct dirent *ent;
2044
2045         while((ent = readdir(dir))) {
2046                 if(!check_id(ent->d_name))
2047                         continue;
2048
2049                 if(first)
2050                         first = false;
2051                 else
2052                         printf("#---------------------------------------------------------------#\n");
2053
2054                 result |= export(ent->d_name, stdout);
2055         }
2056
2057         closedir(dir);
2058         if(!tty)
2059                 fclose(stdout);
2060         return result;
2061 }
2062
2063 static int cmd_import(int argc, char *argv[]) {
2064         if(argc > 1) {
2065                 fprintf(stderr, "Too many arguments!\n");
2066                 return 1;
2067         }
2068
2069         FILE *in = stdin;
2070         FILE *out = NULL;
2071
2072         char buf[4096];
2073         char name[4096];
2074         char *filename = NULL;
2075         int count = 0;
2076         bool firstline = true;
2077
2078         while(fgets(buf, sizeof buf, in)) {
2079                 if(sscanf(buf, "Name = %s", name) == 1) {
2080                         firstline = false;
2081
2082                         if(!check_id(name)) {
2083                                 fprintf(stderr, "Invalid Name in input!\n");
2084                                 return 1;
2085                         }
2086
2087                         if(out)
2088                                 fclose(out);
2089
2090                         free(filename);
2091                         xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
2092
2093                         if(!force && !access(filename, F_OK)) {
2094                                 fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
2095                                 out = NULL;
2096                                 continue;
2097                         }
2098
2099                         out = fopen(filename, "w");
2100                         if(!out) {
2101                                 fprintf(stderr, "Error creating configuration file %s: %s\n", filename, strerror(errno));
2102                                 return 1;
2103                         }
2104
2105                         count++;
2106                         continue;
2107                 } else if(firstline) {
2108                         fprintf(stderr, "Junk at the beginning of the input, ignoring.\n");
2109                         firstline = false;
2110                 }
2111
2112
2113                 if(!strcmp(buf, "#---------------------------------------------------------------#\n"))
2114                         continue;
2115
2116                 if(out) {
2117                         if(fputs(buf, out) < 0) {
2118                                 fprintf(stderr, "Error writing to host configuration file %s: %s\n", filename, strerror(errno));
2119                                 return 1;
2120                         }
2121                 }
2122         }
2123
2124         if(out)
2125                 fclose(out);
2126
2127         if(count) {
2128                 fprintf(stderr, "Imported %d host configuration files.\n", count);
2129                 return 0;
2130         } else {
2131                 fprintf(stderr, "No host configuration files imported.\n");
2132                 return 1;
2133         }
2134 }
2135
2136 static int cmd_exchange(int argc, char *argv[]) {
2137         return cmd_export(argc, argv) ?: cmd_import(argc, argv);
2138 }
2139
2140 static int cmd_exchange_all(int argc, char *argv[]) {
2141         return cmd_export_all(argc, argv) ?: cmd_import(argc, argv);
2142 }
2143
2144 static int switch_network(char *name) {
2145         if(fd >= 0) {
2146                 close(fd);
2147                 fd = -1;
2148         }
2149
2150         free(confbase);
2151         confbase = NULL;
2152         free(pidfilename);
2153         pidfilename = NULL;
2154         free(logfilename);
2155         logfilename = NULL;
2156         free(unixsocketname);
2157         unixsocketname = NULL;
2158         free(tinc_conf);
2159         free(hosts_dir);
2160         free(prompt);
2161
2162         free(netname);
2163         netname = strcmp(name, ".") ? xstrdup(name) : NULL;
2164
2165         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
2166         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
2167         xasprintf(&prompt, "%s> ", identname);
2168
2169         return 0;
2170 }
2171
2172 static int cmd_network(int argc, char *argv[]) {
2173         if(argc > 2) {
2174                 fprintf(stderr, "Too many arguments!\n");
2175                 return 1;
2176         }
2177
2178         if(argc == 2)
2179                 return switch_network(argv[1]);
2180
2181         DIR *dir = opendir(confdir);
2182         if(!dir) {
2183                 fprintf(stderr, "Could not read directory %s: %s\n", confdir, strerror(errno));
2184                 return 1;
2185         }
2186
2187         struct dirent *ent;
2188         while((ent = readdir(dir))) {
2189                 if(*ent->d_name == '.')
2190                         continue;
2191
2192                 if(!strcmp(ent->d_name, "tinc.conf")) {
2193                         printf(".\n");
2194                         continue;
2195                 }
2196
2197                 char *fname;
2198                 xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name);
2199                 if(!access(fname, R_OK))
2200                         printf("%s\n", ent->d_name);
2201                 free(fname);
2202         }
2203
2204         closedir(dir);
2205
2206         return 0;
2207 }
2208
2209 static int cmd_fsck(int argc, char *argv[]) {
2210         if(argc > 1) {
2211                 fprintf(stderr, "Too many arguments!\n");
2212                 return 1;
2213         }
2214
2215         return fsck(orig_argv[0]);
2216 }
2217
2218 static const struct {
2219         const char *command;
2220         int (*function)(int argc, char *argv[]);
2221         bool hidden;
2222 } commands[] = {
2223         {"start", cmd_start},
2224         {"stop", cmd_stop},
2225         {"restart", cmd_restart},
2226         {"reload", cmd_reload},
2227         {"dump", cmd_dump},
2228         {"purge", cmd_purge},
2229         {"debug", cmd_debug},
2230         {"retry", cmd_retry},
2231         {"connect", cmd_connect},
2232         {"disconnect", cmd_disconnect},
2233         {"top", cmd_top},
2234         {"pcap", cmd_pcap},
2235         {"log", cmd_log},
2236         {"pid", cmd_pid},
2237         {"config", cmd_config, true},
2238         {"add", cmd_config},
2239         {"del", cmd_config},
2240         {"get", cmd_config},
2241         {"set", cmd_config},
2242         {"init", cmd_init},
2243         {"generate-keys", cmd_generate_keys},
2244 #ifndef DISABLE_LEGACY
2245         {"generate-rsa-keys", cmd_generate_rsa_keys},
2246 #endif
2247         {"generate-ed25519-keys", cmd_generate_ed25519_keys},
2248         {"help", cmd_help},
2249         {"version", cmd_version},
2250         {"info", cmd_info},
2251         {"edit", cmd_edit},
2252         {"export", cmd_export},
2253         {"export-all", cmd_export_all},
2254         {"import", cmd_import},
2255         {"exchange", cmd_exchange},
2256         {"exchange-all", cmd_exchange_all},
2257         {"invite", cmd_invite},
2258         {"join", cmd_join},
2259         {"network", cmd_network},
2260         {"fsck", cmd_fsck},
2261         {NULL, NULL},
2262 };
2263
2264 #ifdef HAVE_READLINE
2265 static char *complete_command(const char *text, int state) {
2266         static int i;
2267
2268         if(!state)
2269                 i = 0;
2270         else
2271                 i++;
2272
2273         while(commands[i].command) {
2274                 if(!commands[i].hidden && !strncasecmp(commands[i].command, text, strlen(text)))
2275                         return xstrdup(commands[i].command);
2276                 i++;
2277         }
2278
2279         return NULL;
2280 }
2281
2282 static char *complete_dump(const char *text, int state) {
2283         const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL};
2284         static int i;
2285
2286         if(!state)
2287                 i = 0;
2288         else
2289                 i++;
2290
2291         while(matches[i]) {
2292                 if(!strncasecmp(matches[i], text, strlen(text)))
2293                         return xstrdup(matches[i]);
2294                 i++;
2295         }
2296
2297         return NULL;
2298 }
2299
2300 static char *complete_config(const char *text, int state) {
2301         static int i;
2302
2303         if(!state)
2304                 i = 0;
2305         else
2306                 i++;
2307
2308         while(variables[i].name) {
2309                 char *dot = strchr(text, '.');
2310                 if(dot) {
2311                         if((variables[i].type & VAR_HOST) && !strncasecmp(variables[i].name, dot + 1, strlen(dot + 1))) {
2312                                 char *match;
2313                                 xasprintf(&match, "%.*s.%s", (int)(dot - text), text, variables[i].name);
2314                                 return match;
2315                         }
2316                 } else {
2317                         if(!strncasecmp(variables[i].name, text, strlen(text)))
2318                                 return xstrdup(variables[i].name);
2319                 }
2320                 i++;
2321         }
2322
2323         return NULL;
2324 }
2325
2326 static char *complete_info(const char *text, int state) {
2327         static int i;
2328         if(!state) {
2329                 i = 0;
2330                 if(!connect_tincd(false))
2331                         return NULL;
2332                 // Check the list of nodes
2333                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
2334                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
2335         }
2336
2337         while(recvline(fd, line, sizeof line)) {
2338                 char item[4096];
2339                 int n = sscanf(line, "%d %d %s", &code, &req, item);
2340                 if(n == 2) {
2341                         i++;
2342                         if(i >= 2)
2343                                 break;
2344                         else
2345                                 continue;
2346                 }
2347
2348                 if(n != 3) {
2349                         fprintf(stderr, "Unable to parse dump from tincd, n = %d, i = %d.\n", n, i);
2350                         break;
2351                 }
2352
2353                 if(!strncmp(item, text, strlen(text)))
2354                         return xstrdup(strip_weight(item));
2355         }
2356
2357         return NULL;
2358 }
2359
2360 static char *complete_nothing(const char *text, int state) {
2361         return NULL;
2362 }
2363
2364 static char **completion (const char *text, int start, int end) {
2365         char **matches = NULL;
2366
2367         if(!start)
2368                 matches = rl_completion_matches(text, complete_command);
2369         else if(!strncasecmp(rl_line_buffer, "dump ", 5))
2370                 matches = rl_completion_matches(text, complete_dump);
2371         else if(!strncasecmp(rl_line_buffer, "add ", 4))
2372                 matches = rl_completion_matches(text, complete_config);
2373         else if(!strncasecmp(rl_line_buffer, "del ", 4))
2374                 matches = rl_completion_matches(text, complete_config);
2375         else if(!strncasecmp(rl_line_buffer, "get ", 4))
2376                 matches = rl_completion_matches(text, complete_config);
2377         else if(!strncasecmp(rl_line_buffer, "set ", 4))
2378                 matches = rl_completion_matches(text, complete_config);
2379         else if(!strncasecmp(rl_line_buffer, "info ", 5))
2380                 matches = rl_completion_matches(text, complete_info);
2381
2382         return matches;
2383 }
2384 #endif
2385
2386 static int cmd_shell(int argc, char *argv[]) {
2387         xasprintf(&prompt, "%s> ", identname);
2388         int result = 0;
2389         char buf[4096];
2390         char *line = NULL;
2391         int maxargs = argc + 16;
2392         char **nargv = xmalloc(maxargs * sizeof *nargv);
2393
2394         for(int i = 0; i < argc; i++)
2395                 nargv[i] = argv[i];
2396
2397 #ifdef HAVE_READLINE
2398         rl_readline_name = "tinc";
2399         rl_completion_entry_function = complete_nothing;
2400         rl_attempted_completion_function = completion;
2401         rl_filename_completion_desired = 0;
2402         char *copy = NULL;
2403 #endif
2404
2405         while(true) {
2406 #ifdef HAVE_READLINE
2407                 if(tty) {
2408                         free(copy);
2409                         free(line);
2410                         rl_basic_word_break_characters = "\t\n ";
2411                         line = readline(prompt);
2412                         if(line)
2413                                 copy = xstrdup(line);
2414                 } else {
2415                         line = fgets(buf, sizeof buf, stdin);
2416                 }
2417 #else
2418                 if(tty)
2419                         fputs(prompt, stdout);
2420
2421                 line = fgets(buf, sizeof buf, stdin);
2422 #endif
2423
2424                 if(!line)
2425                         break;
2426
2427                 /* Ignore comments */
2428
2429                 if(*line == '#')
2430                         continue;
2431
2432                 /* Split */
2433
2434                 int nargc = argc;
2435                 char *p = line + strspn(line, " \t\n");
2436                 char *next = strtok(p, " \t\n");
2437
2438                 while(p && *p) {
2439                         if(nargc >= maxargs) {
2440                                 fprintf(stderr, "next %p '%s', p %p '%s'\n", next, next, p, p);
2441                                 abort();
2442                                 maxargs *= 2;
2443                                 nargv = xrealloc(nargv, maxargs * sizeof *nargv);
2444                         }
2445
2446                         nargv[nargc++] = p;
2447                         p = next;
2448                         next = strtok(NULL, " \t\n");
2449                 }
2450
2451                 if(nargc == argc)
2452                         continue;
2453
2454                 if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit"))
2455                         return result;
2456
2457                 bool found = false;
2458
2459                 for(int i = 0; commands[i].command; i++) {
2460                         if(!strcasecmp(nargv[argc], commands[i].command)) {
2461                                 result |= commands[i].function(nargc - argc - 1, nargv + argc + 1);
2462                                 found = true;
2463                                 break;
2464                         }
2465                 }
2466
2467 #ifdef HAVE_READLINE
2468                 if(tty && found)
2469                         add_history(copy);
2470 #endif
2471
2472                 if(!found) {
2473                         fprintf(stderr, "Unknown command `%s'.\n", nargv[argc]);
2474                         result |= 1;
2475                 }
2476         }
2477
2478         free(nargv);
2479
2480         if(tty)
2481                 printf("\n");
2482         return result;
2483 }
2484
2485
2486 int main(int argc, char *argv[]) {
2487         program_name = argv[0];
2488         orig_argv = argv;
2489         orig_argc = argc;
2490         tty = isatty(0) && isatty(1);
2491
2492         if(!parse_options(argc, argv))
2493                 return 1;
2494
2495         make_names();
2496         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
2497         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
2498
2499         if(show_version) {
2500                 version();
2501                 return 0;
2502         }
2503
2504         if(show_help) {
2505                 usage(false);
2506                 return 0;
2507         }
2508
2509 #ifdef HAVE_MINGW
2510         static struct WSAData wsa_state;
2511
2512         if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
2513                 fprintf(stderr, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError()));
2514                 return false;
2515         }
2516 #endif
2517
2518         srand(time(NULL));
2519         crypto_init();
2520
2521         if(optind >= argc)
2522                 return cmd_shell(argc, argv);
2523
2524         for(int i = 0; commands[i].command; i++) {
2525                 if(!strcasecmp(argv[optind], commands[i].command))
2526                         return commands[i].function(argc - optind, argv + optind);
2527         }
2528
2529         fprintf(stderr, "Unknown command `%s'.\n", argv[optind]);
2530         usage(true);
2531         return 1;
2532 }