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