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