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