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