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