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