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