Add "network" command to list or switch networks.
authorGuus Sliepen <guus@tinc-vpn.org>
Wed, 26 Feb 2014 10:00:30 +0000 (11:00 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Wed, 26 Feb 2014 10:04:42 +0000 (11:04 +0100)
bash_completion.d/tinc
doc/tinc.8.in
doc/tinc.texi
src/tincctl.c

index 536503bb76bfeb66bb86c996d7adc53ceb9a0047..8145d43f8e4741396e283fc38e094c10f0a3eadd 100644 (file)
@@ -5,7 +5,7 @@ _tinc() {
        prev="${COMP_WORDS[COMP_CWORD-1]}"
        opts="-c -d -D -K -n -o -L -R -U --config --no-detach --debug --net --option --mlock --logfile --pidfile --chroot --user --help --version"
        confvars="Address AddressFamily BindToAddress BindToInterface Broadcast Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceType Digest DirectOnly ECDSAPrivateKeyFile ECDSAPublicKey ECDSAPublicKeyFile ExperimentalProtocol Forwarding GraphDumpFile Hostnames IffOneQueue IndirectData Interface KeyExpire ListenAddress LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPRcvBuf UDPSndBuf VDEGroup VDEPort Weight"
-       commands="add connect debug del disconnect dump edit export export-all generate-ecdsa-keys generate-keys generate-rsa-keys get help import info init invite join log pcap pid purge reload restart retry set start stop top version"
+       commands="add connect debug del disconnect dump edit export export-all generate-ecdsa-keys generate-keys generate-rsa-keys get help import info init invite join log network pcap pid purge reload restart retry set start stop top version"
 
        case ${prev} in
                -c|--config)
@@ -61,6 +61,18 @@ _tinc() {
                COMPREPLY=( $(compgen -W "reachable nodes edges subnets connections graph" -- ${cur}) )
                return 0
                ;;
+               network)
+               nets=""
+               pushd /etc/tinc >/dev/null 2>/dev/null
+               for dir in *; do
+                       if [[ -f "$dir/tinc.conf" ]]; then
+                               nets="$nets $dir"
+                       fi
+               done
+               popd >/dev/null 2>/dev/null
+               COMPREPLY=( $(compgen -W "${nets}" -- ${cur}) )
+               return 0
+               ;;
        esac
        if [[ -z ${cur} ]] ; then 
                COMPREPLY=( $(compgen -W "${opts} ${commands}" -- ${cur}) )
index 374ad42fb2a220faca7c3aff23391da70c48d7db..74f182a98c959a67b3adefb263337986e4c8a6a6 100644 (file)
@@ -210,6 +210,11 @@ format to standard output,
 from where it can be redirected to a file or piped through a program that can parse it directly,
 such as
 .Xr tcpdump 8 .
+.It network Op Ar netname
+If
+.Ar netname
+is given, switch to that network.
+Otherwise, display a list of all networks for which configuration files exist.
 .El
 .Sh EXAMPLES
 Examples of some commands:
index c39e7c2682207adfe7ebcc2bcd16898b2ef9615e..555b816bfd7448c75b9f8cb0ae984ea2b7eff822 100644 (file)
@@ -2399,6 +2399,11 @@ Dump VPN traffic going through the local tinc node in pcap-savefile format to st
 from where it can be redirected to a file or piped through a program that can parse it directly,
 such as tcpdump.
 
+@cindex network [@var{netname}]
+@item network
+If @var{netname} is given, switch to that network.
+Otherwise, display a list of all networks for which configuration files exist.
+
 @end table
 
 @c ==================================================================
index c3fa2fa75a1ffeb3362f5c81c498c46ab21dd6ac..fdb72e05469e4634b5ee411ce99e5b71e24a0520 100644 (file)
@@ -67,6 +67,7 @@ bool confbasegiven = false;
 bool netnamegiven = false;
 char *scriptinterpreter = NULL;
 char *scriptextension = "";
+static char *prompt;
 
 static struct option const long_options[] = {
        {"config", required_argument, NULL, 'c'},
@@ -137,6 +138,7 @@ static void usage(bool status) {
                                "  exchange-all [--force]     Same as export-all followed by import\n"
                                "  invite NODE [...]          Generate an invitation for NODE\n"
                                "  join INVITATION            Join a VPN using an INVITIATION\n"
+                               "  network [NETNAME]          List all known networks, or switch to the one named NETNAME.\n"
                                "\n");
                printf("Report bugs to tinc@tinc-vpn.org.\n");
        }
@@ -2066,6 +2068,70 @@ static int cmd_exchange_all(int argc, char *argv[]) {
        return cmd_export_all(argc, argv) ?: cmd_import(argc, argv);
 }
 
+static int switch_network(char *name) {
+       if(fd >= 0) {
+               close(fd);
+               fd = -1;
+       }
+
+       free(confbase);
+       confbase = NULL;
+       free(pidfilename);
+       pidfilename = NULL;
+       free(logfilename);
+       logfilename = NULL;
+       free(unixsocketname);
+       unixsocketname = NULL;
+       free(tinc_conf);
+       free(hosts_dir);
+       free(prompt);
+
+       free(netname);
+       netname = strcmp(name, ".") ? xstrdup(name) : NULL;
+
+       make_names();
+        xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
+        xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
+       xasprintf(&prompt, "%s> ", identname);
+
+       return 0;
+}
+
+static int cmd_network(int argc, char *argv[]) {
+       if(argc > 2) {
+               fprintf(stderr, "Too many arguments!\n");
+               return 1;
+       }
+
+       if(argc == 2)
+               return switch_network(argv[1]);
+
+       DIR *dir = opendir(confdir);
+       if(!dir) {
+               fprintf(stderr, "Could not read directory %s: %s\n", confdir, strerror(errno));
+                return 1;
+        }
+
+       struct dirent *ent;
+       while((ent = readdir(dir))) {
+               if(*ent->d_name == '.')
+                       continue;
+
+               if(!strcmp(ent->d_name, "tinc.conf")) {
+                       printf(".\n");
+                       continue;
+               }
+
+               char *fname;
+               xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name);
+               if(!access(fname, R_OK))
+                       printf("%s\n", ent->d_name);
+               free(fname);
+       }
+
+       return 0;
+}
+
 static const struct {
        const char *command;
        int (*function)(int argc, char *argv[]);
@@ -2105,6 +2171,7 @@ static const struct {
        {"exchange-all", cmd_exchange_all},
        {"invite", cmd_invite},
        {"join", cmd_join},
+       {"network", cmd_network},
        {NULL, NULL},
 };
 
@@ -2231,7 +2298,6 @@ static char **completion (const char *text, int start, int end) {
 #endif
 
 static int cmd_shell(int argc, char *argv[]) {
-       char *prompt;
        xasprintf(&prompt, "%s> ", identname);
        int result = 0;
        char buf[4096];