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