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