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