Always call res_init() before getaddrinfo().
[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         {"MTUInfoInterval", VAR_SERVER},
1375         {"UDPInfoInterval", VAR_SERVER},
1376         {"UDPRcvBuf", VAR_SERVER},
1377         {"UDPSndBuf", VAR_SERVER},
1378         {"VDEGroup", VAR_SERVER},
1379         {"VDEPort", VAR_SERVER},
1380         /* Host configuration */
1381         {"Address", VAR_HOST | VAR_MULTIPLE},
1382         {"Cipher", VAR_SERVER | VAR_HOST},
1383         {"ClampMSS", VAR_SERVER | VAR_HOST},
1384         {"Compression", VAR_SERVER | VAR_HOST},
1385         {"Digest", VAR_SERVER | VAR_HOST},
1386         {"Ed25519PublicKey", VAR_HOST},
1387         {"Ed25519PublicKeyFile", VAR_SERVER | VAR_HOST},
1388         {"IndirectData", VAR_SERVER | VAR_HOST},
1389         {"MACLength", VAR_SERVER | VAR_HOST},
1390         {"PMTU", VAR_SERVER | VAR_HOST},
1391         {"PMTUDiscovery", VAR_SERVER | VAR_HOST},
1392         {"Port", VAR_HOST},
1393         {"PublicKey", VAR_HOST | VAR_OBSOLETE},
1394         {"PublicKeyFile", VAR_SERVER | VAR_HOST | VAR_OBSOLETE},
1395         {"Subnet", VAR_HOST | VAR_MULTIPLE | VAR_SAFE},
1396         {"TCPOnly", VAR_SERVER | VAR_HOST},
1397         {"Weight", VAR_HOST | VAR_SAFE},
1398         {NULL, 0}
1399 };
1400
1401 static int cmd_config(int argc, char *argv[]) {
1402         if(argc < 2) {
1403                 fprintf(stderr, "Invalid number of arguments.\n");
1404                 return 1;
1405         }
1406
1407         if(strcasecmp(argv[0], "config"))
1408                 argv--, argc++;
1409
1410         int action = -2;
1411         if(!strcasecmp(argv[1], "get")) {
1412                 argv++, argc--;
1413         } else if(!strcasecmp(argv[1], "add")) {
1414                 argv++, argc--, action = 1;
1415         } else if(!strcasecmp(argv[1], "del")) {
1416                 argv++, argc--, action = -1;
1417         } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) {
1418                 argv++, argc--, action = 0;
1419         }
1420
1421         if(argc < 2) {
1422                 fprintf(stderr, "Invalid number of arguments.\n");
1423                 return 1;
1424         }
1425
1426         // Concatenate the rest of the command line
1427         strncpy(line, argv[1], sizeof line - 1);
1428         for(int i = 2; i < argc; i++) {
1429                 strncat(line, " ", sizeof line - 1 - strlen(line));
1430                 strncat(line, argv[i], sizeof line - 1 - strlen(line));
1431         }
1432
1433         // Liberal parsing into node name, variable name and value.
1434         char *node = NULL;
1435         char *variable;
1436         char *value;
1437         int len;
1438
1439         len = strcspn(line, "\t =");
1440         value = line + len;
1441         value += strspn(value, "\t ");
1442         if(*value == '=') {
1443                 value++;
1444                 value += strspn(value, "\t ");
1445         }
1446         line[len] = '\0';
1447         variable = strchr(line, '.');
1448         if(variable) {
1449                 node = line;
1450                 *variable++ = 0;
1451         } else {
1452                 variable = line;
1453         }
1454
1455         if(!*variable) {
1456                 fprintf(stderr, "No variable given.\n");
1457                 return 1;
1458         }
1459
1460         if(action >= 0 && !*value) {
1461                 fprintf(stderr, "No value for variable given.\n");
1462                 return 1;
1463         }
1464
1465         if(action < -1 && *value)
1466                 action = 0;
1467
1468         /* Some simple checks. */
1469         bool found = false;
1470         bool warnonremove = false;
1471
1472         for(int i = 0; variables[i].name; i++) {
1473                 if(strcasecmp(variables[i].name, variable))
1474                         continue;
1475
1476                 found = true;
1477                 variable = (char *)variables[i].name;
1478
1479                 /* Discourage use of obsolete variables. */
1480
1481                 if(variables[i].type & VAR_OBSOLETE && action >= 0) {
1482                         if(force) {
1483                                 fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable);
1484                         } else {
1485                                 fprintf(stderr, "%s is an obsolete variable! Use --force to use it anyway.\n", variable);
1486                                 return 1;
1487                         }
1488                 }
1489
1490                 /* Don't put server variables in host config files */
1491
1492                 if(node && !(variables[i].type & VAR_HOST) && action >= 0) {
1493                         if(force) {
1494                                 fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable);
1495                         } else {
1496                                 fprintf(stderr, "%s is not a host configuration variable! Use --force to use it anyway.\n", variable);
1497                                 return 1;
1498                         }
1499                 }
1500
1501                 /* Should this go into our own host config file? */
1502
1503                 if(!node && !(variables[i].type & VAR_SERVER)) {
1504                         node = get_my_name(true);
1505                         if(!node)
1506                                 return 1;
1507                 }
1508
1509                 /* Change "add" into "set" for variables that do not allow multiple occurences.
1510                    Turn on warnings when it seems variables might be removed unintentionally. */
1511
1512                 if(action == 1 && !(variables[i].type & VAR_MULTIPLE)) {
1513                         warnonremove = true;
1514                         action = 0;
1515                 } else if(action == 0 && (variables[i].type & VAR_MULTIPLE)) {
1516                         warnonremove = true;
1517                 }
1518
1519                 break;
1520         }
1521
1522         if(node && !check_id(node)) {
1523                 fprintf(stderr, "Invalid name for node.\n");
1524                 return 1;
1525         }
1526
1527         if(!found) {
1528                 if(force || action < 0) {
1529                         fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable);
1530                 } else {
1531                         fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable);
1532                         return 1;
1533                 }
1534         }
1535
1536         // Open the right configuration file.
1537         char *filename;
1538         if(node)
1539                 xasprintf(&filename, "%s" SLASH "%s", hosts_dir, node);
1540         else
1541                 filename = tinc_conf;
1542
1543         FILE *f = fopen(filename, "r");
1544         if(!f) {
1545                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
1546                 return 1;
1547         }
1548
1549         char *tmpfile = NULL;
1550         FILE *tf = NULL;
1551
1552         if(action >= -1) {
1553                 xasprintf(&tmpfile, "%s.config.tmp", filename);
1554                 tf = fopen(tmpfile, "w");
1555                 if(!tf) {
1556                         fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
1557                         fclose(f);
1558                         return 1;
1559                 }
1560         }
1561
1562         // Copy the file, making modifications on the fly, unless we are just getting a value.
1563         char buf1[4096];
1564         char buf2[4096];
1565         bool set = false;
1566         bool removed = false;
1567         found = false;
1568
1569         while(fgets(buf1, sizeof buf1, f)) {
1570                 buf1[sizeof buf1 - 1] = 0;
1571                 strncpy(buf2, buf1, sizeof buf2);
1572
1573                 // Parse line in a simple way
1574                 char *bvalue;
1575                 int len;
1576
1577                 len = strcspn(buf2, "\t =");
1578                 bvalue = buf2 + len;
1579                 bvalue += strspn(bvalue, "\t ");
1580                 if(*bvalue == '=') {
1581                         bvalue++;
1582                         bvalue += strspn(bvalue, "\t ");
1583                 }
1584                 rstrip(bvalue);
1585                 buf2[len] = '\0';
1586
1587                 // Did it match?
1588                 if(!strcasecmp(buf2, variable)) {
1589                         // Get
1590                         if(action < -1) {
1591                                 found = true;
1592                                 printf("%s\n", bvalue);
1593                         // Del
1594                         } else if(action == -1) {
1595                                 if(!*value || !strcasecmp(bvalue, value)) {
1596                                         removed = true;
1597                                         continue;
1598                                 }
1599                         // Set
1600                         } else if(action == 0) {
1601                                 // Warn if "set" was used for variables that can occur multiple times
1602                                 if(warnonremove && strcasecmp(bvalue, value))
1603                                         fprintf(stderr, "Warning: removing %s = %s\n", variable, bvalue);
1604
1605                                 // Already set? Delete the rest...
1606                                 if(set)
1607                                         continue;
1608
1609                                 // Otherwise, replace.
1610                                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
1611                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1612                                         return 1;
1613                                 }
1614                                 set = true;
1615                                 continue;
1616                         // Add
1617                         } else if(action > 0) {
1618                                 // Check if we've already seen this variable with the same value
1619                                 if(!strcasecmp(bvalue, value))
1620                                         found = true;
1621                         }
1622                 }
1623
1624                 if(action >= -1) {
1625                         // Copy original line...
1626                         if(fputs(buf1, tf) < 0) {
1627                                 fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1628                                 return 1;
1629                         }
1630
1631                         // Add newline if it is missing...
1632                         if(*buf1 && buf1[strlen(buf1) - 1] != '\n') {
1633                                 if(fputc('\n', tf) < 0) {
1634                                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1635                                         return 1;
1636                                 }
1637                         }
1638                 }
1639         }
1640
1641         // Make sure we read everything...
1642         if(ferror(f) || !feof(f)) {
1643                 fprintf(stderr, "Error while reading from configuration file %s: %s\n", filename, strerror(errno));
1644                 return 1;
1645         }
1646
1647         if(fclose(f)) {
1648                 fprintf(stderr, "Error closing configuration file %s: %s\n", filename, strerror(errno));
1649                 return 1;
1650         }
1651
1652         // Add new variable if necessary.
1653         if((action > 0 && !found)|| (action == 0 && !set)) {
1654                 if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
1655                         fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
1656                         return 1;
1657                 }
1658         }
1659
1660         if(action < -1) {
1661                 if(found) {
1662                         return 0;
1663                 } else {
1664                         fprintf(stderr, "No matching configuration variables found.\n");
1665                         return 1;
1666                 }
1667         }
1668
1669         // Make sure we wrote everything...
1670         if(fclose(tf)) {
1671                 fprintf(stderr, "Error closing temporary file %s: %s\n", tmpfile, strerror(errno));
1672                 return 1;
1673         }
1674
1675         // Could we find what we had to remove?
1676         if(action < 0 && !removed) {
1677                 remove(tmpfile);
1678                 fprintf(stderr, "No configuration variables deleted.\n");
1679                 return 1;
1680         }
1681
1682         // Replace the configuration file with the new one
1683 #ifdef HAVE_MINGW
1684         if(remove(filename)) {
1685                 fprintf(stderr, "Error replacing file %s: %s\n", filename, strerror(errno));
1686                 return 1;
1687         }
1688 #endif
1689         if(rename(tmpfile, filename)) {
1690                 fprintf(stderr, "Error renaming temporary file %s to configuration file %s: %s\n", tmpfile, filename, strerror(errno));
1691                 return 1;
1692         }
1693
1694         // Silently try notifying a running tincd of changes.
1695         if(connect_tincd(false))
1696                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
1697
1698         return 0;
1699 }
1700
1701 static bool try_bind(int port) {
1702         struct addrinfo *ai = NULL;
1703         struct addrinfo hint = {
1704                 .ai_flags = AI_PASSIVE,
1705                 .ai_family = AF_UNSPEC,
1706                 .ai_socktype = SOCK_STREAM,
1707                 .ai_protocol = IPPROTO_TCP,
1708         };
1709
1710         char portstr[16];
1711         snprintf(portstr, sizeof portstr, "%d", port);
1712
1713         if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai)
1714                 return false;
1715
1716         while(ai) {
1717                 int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
1718                 if(!fd)
1719                         return false;
1720                 int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
1721                 closesocket(fd);
1722                 if(result)
1723                         return false;
1724                 ai = ai->ai_next;
1725         }
1726
1727         return true;
1728 }
1729
1730 int check_port(char *name) {
1731         if(try_bind(655))
1732                 return 655;
1733
1734         fprintf(stderr, "Warning: could not bind to port 655. ");
1735
1736         for(int i = 0; i < 100; i++) {
1737                 int port = 0x1000 + (rand() & 0x7fff);
1738                 if(try_bind(port)) {
1739                         char *filename;
1740                         xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
1741                         FILE *f = fopen(filename, "a");
1742                         free(filename);
1743                         if(!f) {
1744                                 fprintf(stderr, "Please change tinc's Port manually.\n");
1745                                 return 0;
1746                         }
1747
1748                         fprintf(f, "Port = %d\n", port);
1749                         fclose(f);
1750                         fprintf(stderr, "Tinc will instead listen on port %d.\n", port);
1751                         return port;
1752                 }
1753         }
1754
1755         fprintf(stderr, "Please change tinc's Port manually.\n");
1756         return 0;
1757 }
1758
1759 static int cmd_init(int argc, char *argv[]) {
1760         if(!access(tinc_conf, F_OK)) {
1761                 fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
1762                 return 1;
1763         }
1764
1765         if(argc > 2) {
1766                 fprintf(stderr, "Too many arguments!\n");
1767                 return 1;
1768         } else if(argc < 2) {
1769                 if(tty) {
1770                         char buf[1024];
1771                         fprintf(stderr, "Enter the Name you want your tinc node to have: ");
1772                         if(!fgets(buf, sizeof buf, stdin)) {
1773                                 fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
1774                                 return 1;
1775                         }
1776                         int len = rstrip(buf);
1777                         if(!len) {
1778                                 fprintf(stderr, "No name given!\n");
1779                                 return 1;
1780                         }
1781                         name = strdup(buf);
1782                 } else {
1783                         fprintf(stderr, "No Name given!\n");
1784                         return 1;
1785                 }
1786         } else {
1787                 name = strdup(argv[1]);
1788                 if(!*name) {
1789                         fprintf(stderr, "No Name given!\n");
1790                         return 1;
1791                 }
1792         }
1793
1794         if(!check_id(name)) {
1795                 fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n");
1796                 return 1;
1797         }
1798
1799         if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) {
1800                 fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
1801                 return 1;
1802         }
1803
1804         if(mkdir(confbase, 0777) && errno != EEXIST) {
1805                 fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
1806                 return 1;
1807         }
1808
1809         if(mkdir(hosts_dir, 0777) && errno != EEXIST) {
1810                 fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno));
1811                 return 1;
1812         }
1813
1814         FILE *f = fopen(tinc_conf, "w");
1815         if(!f) {
1816                 fprintf(stderr, "Could not create file %s: %s\n", tinc_conf, strerror(errno));
1817                 return 1;
1818         }
1819
1820         fprintf(f, "Name = %s\n", name);
1821         fclose(f);
1822
1823 #ifndef DISABLE_LEGACY
1824         if(!rsa_keygen(2048, false))
1825                 return 1;
1826 #endif
1827
1828         if(!ed25519_keygen(false))
1829                 return 1;
1830
1831         check_port(name);
1832
1833 #ifndef HAVE_MINGW
1834         char *filename;
1835         xasprintf(&filename, "%s" SLASH "tinc-up", confbase);
1836         if(access(filename, F_OK)) {
1837                 FILE *f = fopenmask(filename, "w", 0777);
1838                 if(!f) {
1839                         fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
1840                         return 1;
1841                 }
1842                 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");
1843                 fclose(f);
1844         }
1845 #endif
1846
1847         return 0;
1848
1849 }
1850
1851 static int cmd_generate_keys(int argc, char *argv[]) {
1852 #ifdef DISABLE_LEGACY
1853         if(argc > 1) {
1854 #else
1855         if(argc > 2) {
1856 #endif
1857                 fprintf(stderr, "Too many arguments!\n");
1858                 return 1;
1859         }
1860
1861         if(!name)
1862                 name = get_my_name(false);
1863
1864 #ifndef DISABLE_LEGACY
1865         if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true))
1866                 return 1;
1867 #endif
1868
1869         if(!ed25519_keygen(true))
1870                 return 1;
1871
1872         return 0;
1873 }
1874
1875 #ifndef DISABLE_LEGACY
1876 static int cmd_generate_rsa_keys(int argc, char *argv[]) {
1877         if(argc > 2) {
1878                 fprintf(stderr, "Too many arguments!\n");
1879                 return 1;
1880         }
1881
1882         if(!name)
1883                 name = get_my_name(false);
1884
1885         return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
1886 }
1887 #endif
1888
1889 static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
1890         if(argc > 1) {
1891                 fprintf(stderr, "Too many arguments!\n");
1892                 return 1;
1893         }
1894
1895         if(!name)
1896                 name = get_my_name(false);
1897
1898         return !ed25519_keygen(true);
1899 }
1900
1901 static int cmd_help(int argc, char *argv[]) {
1902         usage(false);
1903         return 0;
1904 }
1905
1906 static int cmd_version(int argc, char *argv[]) {
1907         if(argc > 1) {
1908                 fprintf(stderr, "Too many arguments!\n");
1909                 return 1;
1910         }
1911
1912         version();
1913         return 0;
1914 }
1915
1916 static int cmd_info(int argc, char *argv[]) {
1917         if(argc != 2) {
1918                 fprintf(stderr, "Invalid number of arguments.\n");
1919                 return 1;
1920         }
1921
1922         if(!connect_tincd(true))
1923                 return 1;
1924
1925         return info(fd, argv[1]);
1926 }
1927
1928 static const char *conffiles[] = {
1929         "tinc.conf",
1930         "tinc-up",
1931         "tinc-down",
1932         "subnet-up",
1933         "subnet-down",
1934         "host-up",
1935         "host-down",
1936         NULL,
1937 };
1938
1939 static int cmd_edit(int argc, char *argv[]) {
1940         if(argc != 2) {
1941                 fprintf(stderr, "Invalid number of arguments.\n");
1942                 return 1;
1943         }
1944
1945         char *filename = NULL;
1946
1947         if(strncmp(argv[1], "hosts" SLASH, 6)) {
1948                 for(int i = 0; conffiles[i]; i++) {
1949                         if(!strcmp(argv[1], conffiles[i])) {
1950                                 xasprintf(&filename, "%s" SLASH "%s", confbase, argv[1]);
1951                                 break;
1952                         }
1953                 }
1954         } else {
1955                 argv[1] += 6;
1956         }
1957
1958         if(!filename) {
1959                 xasprintf(&filename, "%s" SLASH "%s", hosts_dir, argv[1]);
1960                 char *dash = strchr(argv[1], '-');
1961                 if(dash) {
1962                         *dash++ = 0;
1963                         if((strcmp(dash, "up") && strcmp(dash, "down")) || !check_id(argv[1])) {
1964                                 fprintf(stderr, "Invalid configuration filename.\n");
1965                                 return 1;
1966                         }
1967                 }
1968         }
1969
1970         char *command;
1971 #ifndef HAVE_MINGW
1972         xasprintf(&command, "\"%s\" \"%s\"", getenv("VISUAL") ?: getenv("EDITOR") ?: "vi", filename);
1973 #else
1974         xasprintf(&command, "edit \"%s\"", filename);
1975 #endif
1976         int result = system(command);
1977         if(result)
1978                 return result;
1979
1980         // Silently try notifying a running tincd of changes.
1981         if(connect_tincd(false))
1982                 sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
1983
1984         return 0;
1985 }
1986
1987 static int export(const char *name, FILE *out) {
1988         char *filename;
1989         xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
1990         FILE *in = fopen(filename, "r");
1991         if(!in) {
1992                 fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
1993                 return 1;
1994         }
1995
1996         fprintf(out, "Name = %s\n", name);
1997         char buf[4096];
1998         while(fgets(buf, sizeof buf, in)) {
1999                 if(strcspn(buf, "\t =") != 4 || strncasecmp(buf, "Name", 4))
2000                         fputs(buf, out);
2001         }
2002
2003         if(ferror(in)) {
2004                 fprintf(stderr, "Error while reading configuration file %s: %s\n", filename, strerror(errno));
2005                 fclose(in);
2006                 return 1;
2007         }
2008
2009         fclose(in);
2010         return 0;
2011 }
2012
2013 static int cmd_export(int argc, char *argv[]) {
2014         if(argc > 1) {
2015                 fprintf(stderr, "Too many arguments!\n");
2016                 return 1;
2017         }
2018
2019         char *name = get_my_name(true);
2020         if(!name)
2021                 return 1;
2022
2023         int result = export(name, stdout);
2024         if(!tty)
2025                 fclose(stdout);
2026
2027         free(name);
2028         return result;
2029 }
2030
2031 static int cmd_export_all(int argc, char *argv[]) {
2032         if(argc > 1) {
2033                 fprintf(stderr, "Too many arguments!\n");
2034                 return 1;
2035         }
2036
2037         DIR *dir = opendir(hosts_dir);
2038         if(!dir) {
2039                 fprintf(stderr, "Could not open host configuration directory %s: %s\n", hosts_dir, strerror(errno));
2040                 return 1;
2041         }
2042
2043         bool first = true;
2044         int result = 0;
2045         struct dirent *ent;
2046
2047         while((ent = readdir(dir))) {
2048                 if(!check_id(ent->d_name))
2049                         continue;
2050
2051                 if(first)
2052                         first = false;
2053                 else
2054                         printf("#---------------------------------------------------------------#\n");
2055
2056                 result |= export(ent->d_name, stdout);
2057         }
2058
2059         closedir(dir);
2060         if(!tty)
2061                 fclose(stdout);
2062         return result;
2063 }
2064
2065 static int cmd_import(int argc, char *argv[]) {
2066         if(argc > 1) {
2067                 fprintf(stderr, "Too many arguments!\n");
2068                 return 1;
2069         }
2070
2071         FILE *in = stdin;
2072         FILE *out = NULL;
2073
2074         char buf[4096];
2075         char name[4096];
2076         char *filename = NULL;
2077         int count = 0;
2078         bool firstline = true;
2079
2080         while(fgets(buf, sizeof buf, in)) {
2081                 if(sscanf(buf, "Name = %s", name) == 1) {
2082                         firstline = false;
2083
2084                         if(!check_id(name)) {
2085                                 fprintf(stderr, "Invalid Name in input!\n");
2086                                 return 1;
2087                         }
2088
2089                         if(out)
2090                                 fclose(out);
2091
2092                         free(filename);
2093                         xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
2094
2095                         if(!force && !access(filename, F_OK)) {
2096                                 fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
2097                                 out = NULL;
2098                                 continue;
2099                         }
2100
2101                         out = fopen(filename, "w");
2102                         if(!out) {
2103                                 fprintf(stderr, "Error creating configuration file %s: %s\n", filename, strerror(errno));
2104                                 return 1;
2105                         }
2106
2107                         count++;
2108                         continue;
2109                 } else if(firstline) {
2110                         fprintf(stderr, "Junk at the beginning of the input, ignoring.\n");
2111                         firstline = false;
2112                 }
2113
2114
2115                 if(!strcmp(buf, "#---------------------------------------------------------------#\n"))
2116                         continue;
2117
2118                 if(out) {
2119                         if(fputs(buf, out) < 0) {
2120                                 fprintf(stderr, "Error writing to host configuration file %s: %s\n", filename, strerror(errno));
2121                                 return 1;
2122                         }
2123                 }
2124         }
2125
2126         if(out)
2127                 fclose(out);
2128
2129         if(count) {
2130                 fprintf(stderr, "Imported %d host configuration files.\n", count);
2131                 return 0;
2132         } else {
2133                 fprintf(stderr, "No host configuration files imported.\n");
2134                 return 1;
2135         }
2136 }
2137
2138 static int cmd_exchange(int argc, char *argv[]) {
2139         return cmd_export(argc, argv) ?: cmd_import(argc, argv);
2140 }
2141
2142 static int cmd_exchange_all(int argc, char *argv[]) {
2143         return cmd_export_all(argc, argv) ?: cmd_import(argc, argv);
2144 }
2145
2146 static int switch_network(char *name) {
2147         if(fd >= 0) {
2148                 close(fd);
2149                 fd = -1;
2150         }
2151
2152         free(confbase);
2153         confbase = NULL;
2154         free(pidfilename);
2155         pidfilename = NULL;
2156         free(logfilename);
2157         logfilename = NULL;
2158         free(unixsocketname);
2159         unixsocketname = NULL;
2160         free(tinc_conf);
2161         free(hosts_dir);
2162         free(prompt);
2163
2164         free(netname);
2165         netname = strcmp(name, ".") ? xstrdup(name) : NULL;
2166
2167         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
2168         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
2169         xasprintf(&prompt, "%s> ", identname);
2170
2171         return 0;
2172 }
2173
2174 static int cmd_network(int argc, char *argv[]) {
2175         if(argc > 2) {
2176                 fprintf(stderr, "Too many arguments!\n");
2177                 return 1;
2178         }
2179
2180         if(argc == 2)
2181                 return switch_network(argv[1]);
2182
2183         DIR *dir = opendir(confdir);
2184         if(!dir) {
2185                 fprintf(stderr, "Could not read directory %s: %s\n", confdir, strerror(errno));
2186                 return 1;
2187         }
2188
2189         struct dirent *ent;
2190         while((ent = readdir(dir))) {
2191                 if(*ent->d_name == '.')
2192                         continue;
2193
2194                 if(!strcmp(ent->d_name, "tinc.conf")) {
2195                         printf(".\n");
2196                         continue;
2197                 }
2198
2199                 char *fname;
2200                 xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name);
2201                 if(!access(fname, R_OK))
2202                         printf("%s\n", ent->d_name);
2203                 free(fname);
2204         }
2205
2206         closedir(dir);
2207
2208         return 0;
2209 }
2210
2211 static int cmd_fsck(int argc, char *argv[]) {
2212         if(argc > 1) {
2213                 fprintf(stderr, "Too many arguments!\n");
2214                 return 1;
2215         }
2216
2217         return fsck(orig_argv[0]);
2218 }
2219
2220 static const struct {
2221         const char *command;
2222         int (*function)(int argc, char *argv[]);
2223         bool hidden;
2224 } commands[] = {
2225         {"start", cmd_start},
2226         {"stop", cmd_stop},
2227         {"restart", cmd_restart},
2228         {"reload", cmd_reload},
2229         {"dump", cmd_dump},
2230         {"purge", cmd_purge},
2231         {"debug", cmd_debug},
2232         {"retry", cmd_retry},
2233         {"connect", cmd_connect},
2234         {"disconnect", cmd_disconnect},
2235         {"top", cmd_top},
2236         {"pcap", cmd_pcap},
2237         {"log", cmd_log},
2238         {"pid", cmd_pid},
2239         {"config", cmd_config, true},
2240         {"add", cmd_config},
2241         {"del", cmd_config},
2242         {"get", cmd_config},
2243         {"set", cmd_config},
2244         {"init", cmd_init},
2245         {"generate-keys", cmd_generate_keys},
2246 #ifndef DISABLE_LEGACY
2247         {"generate-rsa-keys", cmd_generate_rsa_keys},
2248 #endif
2249         {"generate-ed25519-keys", cmd_generate_ed25519_keys},
2250         {"help", cmd_help},
2251         {"version", cmd_version},
2252         {"info", cmd_info},
2253         {"edit", cmd_edit},
2254         {"export", cmd_export},
2255         {"export-all", cmd_export_all},
2256         {"import", cmd_import},
2257         {"exchange", cmd_exchange},
2258         {"exchange-all", cmd_exchange_all},
2259         {"invite", cmd_invite},
2260         {"join", cmd_join},
2261         {"network", cmd_network},
2262         {"fsck", cmd_fsck},
2263         {NULL, NULL},
2264 };
2265
2266 #ifdef HAVE_READLINE
2267 static char *complete_command(const char *text, int state) {
2268         static int i;
2269
2270         if(!state)
2271                 i = 0;
2272         else
2273                 i++;
2274
2275         while(commands[i].command) {
2276                 if(!commands[i].hidden && !strncasecmp(commands[i].command, text, strlen(text)))
2277                         return xstrdup(commands[i].command);
2278                 i++;
2279         }
2280
2281         return NULL;
2282 }
2283
2284 static char *complete_dump(const char *text, int state) {
2285         const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL};
2286         static int i;
2287
2288         if(!state)
2289                 i = 0;
2290         else
2291                 i++;
2292
2293         while(matches[i]) {
2294                 if(!strncasecmp(matches[i], text, strlen(text)))
2295                         return xstrdup(matches[i]);
2296                 i++;
2297         }
2298
2299         return NULL;
2300 }
2301
2302 static char *complete_config(const char *text, int state) {
2303         static int i;
2304
2305         if(!state)
2306                 i = 0;
2307         else
2308                 i++;
2309
2310         while(variables[i].name) {
2311                 char *dot = strchr(text, '.');
2312                 if(dot) {
2313                         if((variables[i].type & VAR_HOST) && !strncasecmp(variables[i].name, dot + 1, strlen(dot + 1))) {
2314                                 char *match;
2315                                 xasprintf(&match, "%.*s.%s", (int)(dot - text), text, variables[i].name);
2316                                 return match;
2317                         }
2318                 } else {
2319                         if(!strncasecmp(variables[i].name, text, strlen(text)))
2320                                 return xstrdup(variables[i].name);
2321                 }
2322                 i++;
2323         }
2324
2325         return NULL;
2326 }
2327
2328 static char *complete_info(const char *text, int state) {
2329         static int i;
2330         if(!state) {
2331                 i = 0;
2332                 if(!connect_tincd(false))
2333                         return NULL;
2334                 // Check the list of nodes
2335                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
2336                 sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
2337         }
2338
2339         while(recvline(fd, line, sizeof line)) {
2340                 char item[4096];
2341                 int n = sscanf(line, "%d %d %s", &code, &req, item);
2342                 if(n == 2) {
2343                         i++;
2344                         if(i >= 2)
2345                                 break;
2346                         else
2347                                 continue;
2348                 }
2349
2350                 if(n != 3) {
2351                         fprintf(stderr, "Unable to parse dump from tincd, n = %d, i = %d.\n", n, i);
2352                         break;
2353                 }
2354
2355                 if(!strncmp(item, text, strlen(text)))
2356                         return xstrdup(strip_weight(item));
2357         }
2358
2359         return NULL;
2360 }
2361
2362 static char *complete_nothing(const char *text, int state) {
2363         return NULL;
2364 }
2365
2366 static char **completion (const char *text, int start, int end) {
2367         char **matches = NULL;
2368
2369         if(!start)
2370                 matches = rl_completion_matches(text, complete_command);
2371         else if(!strncasecmp(rl_line_buffer, "dump ", 5))
2372                 matches = rl_completion_matches(text, complete_dump);
2373         else if(!strncasecmp(rl_line_buffer, "add ", 4))
2374                 matches = rl_completion_matches(text, complete_config);
2375         else if(!strncasecmp(rl_line_buffer, "del ", 4))
2376                 matches = rl_completion_matches(text, complete_config);
2377         else if(!strncasecmp(rl_line_buffer, "get ", 4))
2378                 matches = rl_completion_matches(text, complete_config);
2379         else if(!strncasecmp(rl_line_buffer, "set ", 4))
2380                 matches = rl_completion_matches(text, complete_config);
2381         else if(!strncasecmp(rl_line_buffer, "info ", 5))
2382                 matches = rl_completion_matches(text, complete_info);
2383
2384         return matches;
2385 }
2386 #endif
2387
2388 static int cmd_shell(int argc, char *argv[]) {
2389         xasprintf(&prompt, "%s> ", identname);
2390         int result = 0;
2391         char buf[4096];
2392         char *line = NULL;
2393         int maxargs = argc + 16;
2394         char **nargv = xmalloc(maxargs * sizeof *nargv);
2395
2396         for(int i = 0; i < argc; i++)
2397                 nargv[i] = argv[i];
2398
2399 #ifdef HAVE_READLINE
2400         rl_readline_name = "tinc";
2401         rl_completion_entry_function = complete_nothing;
2402         rl_attempted_completion_function = completion;
2403         rl_filename_completion_desired = 0;
2404         char *copy = NULL;
2405 #endif
2406
2407         while(true) {
2408 #ifdef HAVE_READLINE
2409                 if(tty) {
2410                         free(copy);
2411                         free(line);
2412                         rl_basic_word_break_characters = "\t\n ";
2413                         line = readline(prompt);
2414                         if(line)
2415                                 copy = xstrdup(line);
2416                 } else {
2417                         line = fgets(buf, sizeof buf, stdin);
2418                 }
2419 #else
2420                 if(tty)
2421                         fputs(prompt, stdout);
2422
2423                 line = fgets(buf, sizeof buf, stdin);
2424 #endif
2425
2426                 if(!line)
2427                         break;
2428
2429                 /* Ignore comments */
2430
2431                 if(*line == '#')
2432                         continue;
2433
2434                 /* Split */
2435
2436                 int nargc = argc;
2437                 char *p = line + strspn(line, " \t\n");
2438                 char *next = strtok(p, " \t\n");
2439
2440                 while(p && *p) {
2441                         if(nargc >= maxargs) {
2442                                 fprintf(stderr, "next %p '%s', p %p '%s'\n", next, next, p, p);
2443                                 abort();
2444                                 maxargs *= 2;
2445                                 nargv = xrealloc(nargv, maxargs * sizeof *nargv);
2446                         }
2447
2448                         nargv[nargc++] = p;
2449                         p = next;
2450                         next = strtok(NULL, " \t\n");
2451                 }
2452
2453                 if(nargc == argc)
2454                         continue;
2455
2456                 if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit"))
2457                         return result;
2458
2459                 bool found = false;
2460
2461                 for(int i = 0; commands[i].command; i++) {
2462                         if(!strcasecmp(nargv[argc], commands[i].command)) {
2463                                 result |= commands[i].function(nargc - argc - 1, nargv + argc + 1);
2464                                 found = true;
2465                                 break;
2466                         }
2467                 }
2468
2469 #ifdef HAVE_READLINE
2470                 if(tty && found)
2471                         add_history(copy);
2472 #endif
2473
2474                 if(!found) {
2475                         fprintf(stderr, "Unknown command `%s'.\n", nargv[argc]);
2476                         result |= 1;
2477                 }
2478         }
2479
2480         free(nargv);
2481
2482         if(tty)
2483                 printf("\n");
2484         return result;
2485 }
2486
2487
2488 int main(int argc, char *argv[]) {
2489         program_name = argv[0];
2490         orig_argv = argv;
2491         orig_argc = argc;
2492         tty = isatty(0) && isatty(1);
2493
2494         if(!parse_options(argc, argv))
2495                 return 1;
2496
2497         make_names();
2498         xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
2499         xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
2500
2501         if(show_version) {
2502                 version();
2503                 return 0;
2504         }
2505
2506         if(show_help) {
2507                 usage(false);
2508                 return 0;
2509         }
2510
2511 #ifdef HAVE_MINGW
2512         static struct WSAData wsa_state;
2513
2514         if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
2515                 fprintf(stderr, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError()));
2516                 return false;
2517         }
2518 #endif
2519
2520         srand(time(NULL));
2521         crypto_init();
2522
2523         if(optind >= argc)
2524                 return cmd_shell(argc, argv);
2525
2526         for(int i = 0; commands[i].command; i++) {
2527                 if(!strcasecmp(argv[optind], commands[i].command))
2528                         return commands[i].function(argc - optind, argv + optind);
2529         }
2530
2531         fprintf(stderr, "Unknown command `%s'.\n", argv[optind]);
2532         usage(true);
2533         return 1;
2534 }