Add an easy way to export and import host configuration files.
This commit is contained in:
parent
6319dc9dde
commit
c52c46f871
3 changed files with 158 additions and 0 deletions
|
@ -2060,6 +2060,16 @@ If no @var{value} is given, all configuration variables with the same name will
|
|||
Start an editor for the given configuration file.
|
||||
You do not need to specify the full path to the file.
|
||||
|
||||
@item export
|
||||
Export the host configuration file of the local node to standard output.
|
||||
|
||||
@item export-all
|
||||
Export all host configuration files to standard output.
|
||||
|
||||
@item import [--force]
|
||||
Import host configuration file(s) from standard input.
|
||||
Already existing host configuration files are not overwritten unless the option --force is used.
|
||||
|
||||
@item start [tincd options]
|
||||
Start @samp{tincd}, optionally with the given extra options.
|
||||
|
||||
|
@ -2153,6 +2163,7 @@ tincctl -n vpn init foo
|
|||
tincctl -n vpn config Subnet 192.168.1.0/24
|
||||
tincctl -n vpn config bar.Address bar.example.com
|
||||
tincctl -n vpn config ConnectTo bar
|
||||
tincctl -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@@example.com
|
||||
@end example
|
||||
|
||||
@c ==================================================================
|
||||
|
|
|
@ -71,6 +71,15 @@ is given, all configuration variables with the same name will be removed.
|
|||
.It edit Ar filename
|
||||
Start an editor for the given configuration file.
|
||||
You do not need to specify the full path to the file.
|
||||
.It export
|
||||
Export the host configuration file of the local node to standard output.
|
||||
.It export-all
|
||||
Export all host configuration files to standard output.
|
||||
.It import Op Fl -force
|
||||
Import host configuration file(s) from standard input.
|
||||
Already existing host configuration files are not overwritten unless the option
|
||||
.Fl -force
|
||||
is used.
|
||||
.It start Op tincd options
|
||||
Start
|
||||
.Xr tincd 8 ,
|
||||
|
@ -172,6 +181,7 @@ tincctl -n vpn init foo
|
|||
tincctl -n vpn config Subnet 192.168.1.0/24
|
||||
tincctl -n vpn config bar.Address bar.example.com
|
||||
tincctl -n vpn config ConnectTo bar
|
||||
tincctl -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@example.com
|
||||
.Sh TOP
|
||||
The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters.
|
||||
It displays a list of all the known nodes in the left-most column,
|
||||
|
|
137
src/tincctl.c
137
src/tincctl.c
|
@ -56,6 +56,7 @@ static char line[4096];
|
|||
static int code;
|
||||
static int req;
|
||||
static int result;
|
||||
static bool force = false;
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
static struct WSAData wsa_state;
|
||||
|
@ -75,6 +76,7 @@ static struct option const long_options[] = {
|
|||
{"chroot", no_argument, NULL, 0},
|
||||
{"user", required_argument, NULL, 0},
|
||||
{"option", required_argument, NULL, 0},
|
||||
{"force", no_argument, NULL, 6},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -131,6 +133,9 @@ static void usage(bool status) {
|
|||
#endif
|
||||
" pcap [snaplen] Dump traffic in pcap format [up to snaplen bytes per packet]\n"
|
||||
" log [level] Dump log output [up to the specified level]\n"
|
||||
" export Export host configuration of local node to standard output\n"
|
||||
" export-all Export all host configuration files to standard output\n"
|
||||
" import [--force] Import host configuration file(s) from standard input\n"
|
||||
"\n");
|
||||
printf("Report bugs to tinc@tinc-vpn.org.\n");
|
||||
}
|
||||
|
@ -165,6 +170,10 @@ static bool parse_options(int argc, char **argv) {
|
|||
pidfilename = xstrdup(optarg);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
force = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
usage(true);
|
||||
return false;
|
||||
|
@ -1363,6 +1372,131 @@ static int cmd_edit(int argc, char *argv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int export(const char *name, FILE *out) {
|
||||
char *filename;
|
||||
xasprintf(&filename, "%s/%s", hosts_dir, name);
|
||||
FILE *in = fopen(filename, "r");
|
||||
if(!in) {
|
||||
fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(out, "Name = %s\n", name);
|
||||
char buf[4096];
|
||||
while(fgets(buf, sizeof buf, in))
|
||||
fputs(buf, out);
|
||||
|
||||
if(ferror(in)) {
|
||||
fprintf(stderr, "Error while reading configuration file %s: %s\n", filename, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_export(int argc, char *argv[]) {
|
||||
char *name = get_my_name();
|
||||
if(!name)
|
||||
return 1;
|
||||
|
||||
return export(name, stdout);
|
||||
}
|
||||
|
||||
static int cmd_export_all(int argc, char *argv[]) {
|
||||
DIR *dir = opendir(hosts_dir);
|
||||
if(!dir) {
|
||||
fprintf(stderr, "Could not open host configuration directory %s: %s\n", hosts_dir, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
int result = 0;
|
||||
struct dirent *ent;
|
||||
|
||||
while((ent = readdir(dir))) {
|
||||
if(!check_id(ent->d_name))
|
||||
continue;
|
||||
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
printf("#---------------------------------------------------------------#\n");
|
||||
|
||||
result |= export(ent->d_name, stdout);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int cmd_import(int argc, char *argv[]) {
|
||||
FILE *in = stdin;
|
||||
FILE *out = NULL;
|
||||
|
||||
char buf[4096];
|
||||
char name[4096];
|
||||
char *filename;
|
||||
int count = 0;
|
||||
bool firstline = true;
|
||||
|
||||
while(fgets(buf, sizeof buf, in)) {
|
||||
if(sscanf(buf, "Name = %s", name) == 1) {
|
||||
if(!check_id(name)) {
|
||||
fprintf(stderr, "Invalid Name in input!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(out)
|
||||
fclose(out);
|
||||
|
||||
free(filename);
|
||||
xasprintf(&filename, "%s/%s", hosts_dir, name);
|
||||
|
||||
if(!force && !access(filename, F_OK)) {
|
||||
fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
|
||||
out = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
out = fopen(filename, "w");
|
||||
if(!out) {
|
||||
fprintf(stderr, "Error creating configuration file %s: %s\n", filename, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
count++;
|
||||
firstline = false;
|
||||
continue;
|
||||
} else if(firstline) {
|
||||
fprintf(stderr, "Junk at the beginning of the input, ignoring.\n");
|
||||
firstline = false;
|
||||
}
|
||||
|
||||
|
||||
if(!strcmp(buf, "#---------------------------------------------------------------#\n"))
|
||||
continue;
|
||||
|
||||
if(out) {
|
||||
if(fputs(buf, out) < 0) {
|
||||
fprintf(stderr, "Error writing to host configuration file %s: %s\n", filename, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(out)
|
||||
fclose(out);
|
||||
|
||||
if(count) {
|
||||
fprintf(stderr, "Imported %d host configuration files.\n", count);
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "No host configuration files imported.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *command;
|
||||
int (*function)(int argc, char *argv[]);
|
||||
|
@ -1390,6 +1524,9 @@ static const struct {
|
|||
{"version", cmd_version},
|
||||
{"info", cmd_info},
|
||||
{"edit", cmd_edit},
|
||||
{"export", cmd_export},
|
||||
{"export-all", cmd_export_all},
|
||||
{"import", cmd_import},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue