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