Dump through control socket
Note this removes SIGUSR1, SIGUSR2, and the graph dumping config option. It seems cleaner to do everything through the control socket.
This commit is contained in:
parent
50ad3f2a89
commit
6eaefb4dbc
18 changed files with 113 additions and 125 deletions
|
@ -147,18 +147,6 @@ instead of
|
||||||
.Va Device .
|
.Va Device .
|
||||||
The info pages of the tinc package contain more information
|
The info pages of the tinc package contain more information
|
||||||
about configuring the virtual network device.
|
about configuring the virtual network device.
|
||||||
.It Va GraphDumpFile Li = Ar filename Bq experimental
|
|
||||||
If this option is present,
|
|
||||||
.Nm tinc
|
|
||||||
will dump the current network graph to the file
|
|
||||||
.Ar filename
|
|
||||||
every minute, unless there were no changes to the graph.
|
|
||||||
The file is in a format that can be read by graphviz tools.
|
|
||||||
If
|
|
||||||
.Ar filename
|
|
||||||
starts with a pipe symbol |,
|
|
||||||
then the rest of the filename is interpreted as a shell command
|
|
||||||
that is executed, the graph is then sent to stdin.
|
|
||||||
.It Va Hostnames Li = yes | no Pq no
|
.It Va Hostnames Li = yes | no Pq no
|
||||||
This option selects whether IP addresses (both real and on the VPN) should
|
This option selects whether IP addresses (both real and on the VPN) should
|
||||||
be resolved. Since DNS lookups are blocking, it might affect tinc's
|
be resolved. Since DNS lookups are blocking, it might affect tinc's
|
||||||
|
|
|
@ -885,16 +885,6 @@ Under Windows, use @var{Interface} instead of @var{Device}.
|
||||||
Note that you can only use one device per daemon.
|
Note that you can only use one device per daemon.
|
||||||
See also @ref{Device files}.
|
See also @ref{Device files}.
|
||||||
|
|
||||||
@cindex GraphDumpFile
|
|
||||||
@item GraphDumpFile = <@var{filename}> [experimental]
|
|
||||||
If this option is present,
|
|
||||||
tinc will dump the current network graph to the file @var{filename}
|
|
||||||
every minute, unless there were no changes to the graph.
|
|
||||||
The file is in a format that can be read by graphviz tools.
|
|
||||||
If @var{filename} starts with a pipe symbol |,
|
|
||||||
then the rest of the filename is interpreted as a shell command
|
|
||||||
that is executed, the graph is then sent to stdin.
|
|
||||||
|
|
||||||
@cindex Hostnames
|
@cindex Hostnames
|
||||||
@item Hostnames = <yes|no> (no)
|
@item Hostnames = <yes|no> (no)
|
||||||
This option selects whether IP addresses (both real and on the VPN)
|
This option selects whether IP addresses (both real and on the VPN)
|
||||||
|
@ -1579,12 +1569,6 @@ New outgoing connections specified in @file{tinc.conf} will be made.
|
||||||
Temporarily increases debug level to 5.
|
Temporarily increases debug level to 5.
|
||||||
Send this signal again to revert to the original level.
|
Send this signal again to revert to the original level.
|
||||||
|
|
||||||
@item USR1
|
|
||||||
Dumps the connection list to syslog.
|
|
||||||
|
|
||||||
@item USR2
|
|
||||||
Dumps virtual network device statistics, all known nodes, edges and subnets to syslog.
|
|
||||||
|
|
||||||
@item WINCH
|
@item WINCH
|
||||||
Purges all information remembered about unreachable nodes.
|
Purges all information remembered about unreachable nodes.
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ Dump a graph of the VPN in
|
||||||
format.
|
format.
|
||||||
.El
|
.El
|
||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
The "start", "restart", "reload", and "dump" commands are not yet implemented.
|
The "start", "restart", and "reload" commands are not yet implemented.
|
||||||
.Pp
|
.Pp
|
||||||
If you find any bugs, report them to tinc@tinc-vpn.org.
|
If you find any bugs, report them to tinc@tinc-vpn.org.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
|
|
|
@ -98,10 +98,6 @@ will be made.
|
||||||
.It INT
|
.It INT
|
||||||
Temporarily increases debug level to 5.
|
Temporarily increases debug level to 5.
|
||||||
Send this signal again to revert to the original level.
|
Send this signal again to revert to the original level.
|
||||||
.It USR1
|
|
||||||
Dumps the connection list to syslog.
|
|
||||||
.It USR2
|
|
||||||
Dumps virtual network device statistics, all known nodes, edges and subnets to syslog.
|
|
||||||
.It WINCH
|
.It WINCH
|
||||||
Purges all information remembered about unreachable nodes.
|
Purges all information remembered about unreachable nodes.
|
||||||
.El
|
.El
|
||||||
|
|
|
@ -106,21 +106,22 @@ void connection_del(connection_t *c) {
|
||||||
splay_delete(connection_tree, c);
|
splay_delete(connection_tree, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_connections(void) {
|
int dump_connections(struct evbuffer *out) {
|
||||||
splay_node_t *node;
|
splay_node_t *node;
|
||||||
connection_t *c;
|
connection_t *c;
|
||||||
|
|
||||||
cp();
|
cp();
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("Connections:"));
|
|
||||||
|
|
||||||
for(node = connection_tree->head; node; node = node->next) {
|
for(node = connection_tree->head; node; node = node->next) {
|
||||||
c = node->data;
|
c = node->data;
|
||||||
logger(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"),
|
if(evbuffer_add_printf(out,
|
||||||
c->name, c->hostname, c->options, c->socket, c->status.value);
|
_(" %s at %s options %lx socket %d status %04x\n"),
|
||||||
|
c->name, c->hostname, c->options, c->socket,
|
||||||
|
c->status.value) == -1)
|
||||||
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("End of connections."));
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_connection_config(connection_t *c) {
|
bool read_connection_config(connection_t *c) {
|
||||||
|
|
|
@ -109,7 +109,7 @@ extern connection_t *new_connection(void) __attribute__ ((__malloc__));
|
||||||
extern void free_connection(connection_t *);
|
extern void free_connection(connection_t *);
|
||||||
extern void connection_add(connection_t *);
|
extern void connection_add(connection_t *);
|
||||||
extern void connection_del(connection_t *);
|
extern void connection_del(connection_t *);
|
||||||
extern void dump_connections(void);
|
extern int dump_connections(struct evbuffer *);
|
||||||
extern bool read_connection_config(connection_t *);
|
extern bool read_connection_config(connection_t *);
|
||||||
|
|
||||||
#endif /* __TINC_CONNECTION_H__ */
|
#endif /* __TINC_CONNECTION_H__ */
|
||||||
|
|
|
@ -62,11 +62,41 @@ static void handle_control_data(struct bufferevent *event, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req.type == REQ_STOP) {
|
if(req.type == REQ_STOP) {
|
||||||
logger(LOG_NOTICE, _("Got stop command"));
|
logger(LOG_NOTICE, _("Got '%s' command"), "stop");
|
||||||
event_loopexit(NULL);
|
event_loopexit(NULL);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(req.type == REQ_DUMP_NODES) {
|
||||||
|
logger(LOG_NOTICE, _("Got '%s' command"), "dump nodes");
|
||||||
|
res.res_errno = dump_nodes(res_data);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.type == REQ_DUMP_EDGES) {
|
||||||
|
logger(LOG_NOTICE, _("Got '%s' command"), "dump edges");
|
||||||
|
res.res_errno = dump_edges(res_data);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.type == REQ_DUMP_SUBNETS) {
|
||||||
|
logger(LOG_NOTICE, _("Got '%s' command"), "dump subnets");
|
||||||
|
res.res_errno = dump_subnets(res_data);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.type == REQ_DUMP_CONNECTIONS) {
|
||||||
|
logger(LOG_NOTICE, _("Got '%s' command"), "dump connections");
|
||||||
|
res.res_errno = dump_connections(res_data);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req.type == REQ_DUMP_GRAPH) {
|
||||||
|
logger(LOG_NOTICE, _("Got '%s' command"), "dump graph");
|
||||||
|
res.res_errno = dump_graph(res_data);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("Malformed control command received"));
|
logger(LOG_DEBUG, _("Malformed control command received"));
|
||||||
res.res_errno = EINVAL;
|
res.res_errno = EINVAL;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,11 @@ enum request_type {
|
||||||
REQ_STOP,
|
REQ_STOP,
|
||||||
REQ_RELOAD,
|
REQ_RELOAD,
|
||||||
REQ_RESTART,
|
REQ_RESTART,
|
||||||
|
REQ_DUMP_NODES,
|
||||||
|
REQ_DUMP_EDGES,
|
||||||
|
REQ_DUMP_SUBNETS,
|
||||||
|
REQ_DUMP_CONNECTIONS,
|
||||||
|
REQ_DUMP_GRAPH,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TINC_CTL_VERSION_CURRENT 0
|
#define TINC_CTL_VERSION_CURRENT 0
|
||||||
|
|
15
src/edge.c
15
src/edge.c
|
@ -125,7 +125,7 @@ edge_t *lookup_edge(node_t *from, node_t *to) {
|
||||||
return splay_search(from->edge_tree, &v);
|
return splay_search(from->edge_tree, &v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_edges(void) {
|
int dump_edges(struct evbuffer *out) {
|
||||||
splay_node_t *node, *node2;
|
splay_node_t *node, *node2;
|
||||||
node_t *n;
|
node_t *n;
|
||||||
edge_t *e;
|
edge_t *e;
|
||||||
|
@ -133,18 +133,21 @@ void dump_edges(void) {
|
||||||
|
|
||||||
cp();
|
cp();
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("Edges:"));
|
|
||||||
|
|
||||||
for(node = node_tree->head; node; node = node->next) {
|
for(node = node_tree->head; node; node = node->next) {
|
||||||
n = node->data;
|
n = node->data;
|
||||||
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
|
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
|
||||||
e = node2->data;
|
e = node2->data;
|
||||||
address = sockaddr2hostname(&e->address);
|
address = sockaddr2hostname(&e->address);
|
||||||
logger(LOG_DEBUG, _(" %s to %s at %s options %lx weight %d"),
|
if(evbuffer_add_printf(out,
|
||||||
e->from->name, e->to->name, address, e->options, e->weight);
|
_(" %s to %s at %s options %lx weight %d\n"),
|
||||||
|
e->from->name, e->to->name, address,
|
||||||
|
e->options, e->weight) == -1) {
|
||||||
|
free(address);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
free(address);
|
free(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("End of edges."));
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,6 @@ extern void free_edge_tree(splay_tree_t *);
|
||||||
extern void edge_add(edge_t *);
|
extern void edge_add(edge_t *);
|
||||||
extern void edge_del(edge_t *);
|
extern void edge_del(edge_t *);
|
||||||
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
|
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
|
||||||
extern void dump_edges(void);
|
extern int dump_edges(struct evbuffer *);
|
||||||
|
|
||||||
#endif /* __TINC_EDGE_H__ */
|
#endif /* __TINC_EDGE_H__ */
|
||||||
|
|
55
src/graph.c
55
src/graph.c
|
@ -313,66 +313,37 @@ void sssp_bfs(void) {
|
||||||
dot -Tpng graph_filename -o image_filename.png -Gconcentrate=true
|
dot -Tpng graph_filename -o image_filename.png -Gconcentrate=true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void dump_graph(int fd, short events, void *data) {
|
int dump_graph(struct evbuffer *out) {
|
||||||
splay_node_t *node;
|
splay_node_t *node;
|
||||||
node_t *n;
|
node_t *n;
|
||||||
edge_t *e;
|
edge_t *e;
|
||||||
char *filename = NULL, *tmpname = NULL;
|
|
||||||
FILE *file;
|
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "GraphDumpFile"), &filename))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ifdebug(PROTOCOL) logger(LOG_NOTICE, "Dumping graph");
|
if(evbuffer_add_printf(out, "digraph {\n") == -1)
|
||||||
|
return errno;
|
||||||
if(filename[0] == '|') {
|
|
||||||
file = popen(filename + 1, "w");
|
|
||||||
} else {
|
|
||||||
asprintf(&tmpname, "%s.new", filename);
|
|
||||||
file = fopen(tmpname, "w");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!file) {
|
|
||||||
logger(LOG_ERR, "Unable to open graph dump file %s: %s", filename, strerror(errno));
|
|
||||||
free(tmpname);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(file, "digraph {\n");
|
|
||||||
|
|
||||||
/* dump all nodes first */
|
/* dump all nodes first */
|
||||||
for(node = node_tree->head; node; node = node->next) {
|
for(node = node_tree->head; node; node = node->next) {
|
||||||
n = node->data;
|
n = node->data;
|
||||||
fprintf(file, " %s [label = \"%s\"];\n", n->name, n->name);
|
if(evbuffer_add_printf(out, " %s [label = \"%s\"];\n",
|
||||||
|
n->name, n->name) == -1)
|
||||||
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now dump all edges */
|
/* now dump all edges */
|
||||||
for(node = edge_weight_tree->head; node; node = node->next) {
|
for(node = edge_weight_tree->head; node; node = node->next) {
|
||||||
e = node->data;
|
e = node->data;
|
||||||
fprintf(file, " %s -> %s;\n", e->from->name, e->to->name);
|
if(evbuffer_add_printf(out, " %s -> %s;\n",
|
||||||
|
e->from->name, e->to->name) == -1)
|
||||||
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(file, "}\n");
|
if(evbuffer_add_printf(out, "}\n") == -1)
|
||||||
|
return errno;
|
||||||
if(filename[0] == '|') {
|
|
||||||
pclose(file);
|
return 0;
|
||||||
} else {
|
|
||||||
fclose(file);
|
|
||||||
#ifdef HAVE_MINGW
|
|
||||||
unlink(filename);
|
|
||||||
#endif
|
|
||||||
rename(tmpname, filename);
|
|
||||||
free(tmpname);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void graph(void) {
|
void graph(void) {
|
||||||
static struct event ev;
|
|
||||||
|
|
||||||
sssp_bfs();
|
sssp_bfs();
|
||||||
mst_kruskal();
|
mst_kruskal();
|
||||||
|
|
||||||
if(!timeout_initialized(&ev))
|
|
||||||
timeout_set(&ev, dump_graph, NULL);
|
|
||||||
event_add(&ev, &(struct timeval){5, 0});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,6 @@
|
||||||
extern void graph(void);
|
extern void graph(void);
|
||||||
extern void mst_kruskal(void);
|
extern void mst_kruskal(void);
|
||||||
extern void sssp_bfs(void);
|
extern void sssp_bfs(void);
|
||||||
extern void dump_graph(void);
|
extern int dump_graph(struct evbuffer *);
|
||||||
|
|
||||||
#endif /* __TINC_GRAPH_H__ */
|
#endif /* __TINC_GRAPH_H__ */
|
||||||
|
|
21
src/net.c
21
src/net.c
|
@ -252,19 +252,6 @@ static void sigint_handler(int signal, short events, void *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sigusr1_handler(int signal, short events, void *data) {
|
|
||||||
logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
|
|
||||||
dump_connections();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sigusr2_handler(int signal, short events, void *data) {
|
|
||||||
logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
|
|
||||||
dump_device_stats();
|
|
||||||
dump_nodes();
|
|
||||||
dump_edges();
|
|
||||||
dump_subnets();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sigwinch_handler(int signal, short events, void *data) {
|
static void sigwinch_handler(int signal, short events, void *data) {
|
||||||
logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
|
logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
|
||||||
purge();
|
purge();
|
||||||
|
@ -346,8 +333,6 @@ int main_loop(void) {
|
||||||
struct event sigint_event;
|
struct event sigint_event;
|
||||||
struct event sigterm_event;
|
struct event sigterm_event;
|
||||||
struct event sigquit_event;
|
struct event sigquit_event;
|
||||||
struct event sigusr1_event;
|
|
||||||
struct event sigusr2_event;
|
|
||||||
struct event sigwinch_event;
|
struct event sigwinch_event;
|
||||||
struct event sigalrm_event;
|
struct event sigalrm_event;
|
||||||
|
|
||||||
|
@ -363,10 +348,6 @@ int main_loop(void) {
|
||||||
signal_add(&sigterm_event, NULL);
|
signal_add(&sigterm_event, NULL);
|
||||||
signal_set(&sigquit_event, SIGQUIT, sigterm_handler, NULL);
|
signal_set(&sigquit_event, SIGQUIT, sigterm_handler, NULL);
|
||||||
signal_add(&sigquit_event, NULL);
|
signal_add(&sigquit_event, NULL);
|
||||||
signal_set(&sigusr1_event, SIGUSR1, sigusr1_handler, NULL);
|
|
||||||
signal_add(&sigusr1_event, NULL);
|
|
||||||
signal_set(&sigusr2_event, SIGUSR2, sigusr2_handler, NULL);
|
|
||||||
signal_add(&sigusr2_event, NULL);
|
|
||||||
signal_set(&sigwinch_event, SIGWINCH, sigwinch_handler, NULL);
|
signal_set(&sigwinch_event, SIGWINCH, sigwinch_handler, NULL);
|
||||||
signal_add(&sigwinch_event, NULL);
|
signal_add(&sigwinch_event, NULL);
|
||||||
signal_set(&sigalrm_event, SIGALRM, sigalrm_handler, NULL);
|
signal_set(&sigalrm_event, SIGALRM, sigalrm_handler, NULL);
|
||||||
|
@ -381,8 +362,6 @@ int main_loop(void) {
|
||||||
signal_del(&sigint_event);
|
signal_del(&sigint_event);
|
||||||
signal_del(&sigterm_event);
|
signal_del(&sigterm_event);
|
||||||
signal_del(&sigquit_event);
|
signal_del(&sigquit_event);
|
||||||
signal_del(&sigusr1_event);
|
|
||||||
signal_del(&sigusr2_event);
|
|
||||||
signal_del(&sigwinch_event);
|
signal_del(&sigwinch_event);
|
||||||
signal_del(&sigalrm_event);
|
signal_del(&sigalrm_event);
|
||||||
event_del(&timeout_event);
|
event_del(&timeout_event);
|
||||||
|
|
11
src/node.c
11
src/node.c
|
@ -160,22 +160,21 @@ node_t *lookup_node_udp(const sockaddr_t *sa) {
|
||||||
return splay_search(node_udp_tree, &n);
|
return splay_search(node_udp_tree, &n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_nodes(void) {
|
int dump_nodes(struct evbuffer *out) {
|
||||||
splay_node_t *node;
|
splay_node_t *node;
|
||||||
node_t *n;
|
node_t *n;
|
||||||
|
|
||||||
cp();
|
cp();
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("Nodes:"));
|
|
||||||
|
|
||||||
for(node = node_tree->head; node; node = node->next) {
|
for(node = node_tree->head; node; node = node->next) {
|
||||||
n = node->data;
|
n = node->data;
|
||||||
logger(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s pmtu %d (min %d max %d)"),
|
if(evbuffer_add_printf(out, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s pmtu %d (min %d max %d)\n"),
|
||||||
n->name, n->hostname, n->cipher ? n->cipher->nid : 0,
|
n->name, n->hostname, n->cipher ? n->cipher->nid : 0,
|
||||||
n->digest ? n->digest->type : 0, n->maclength, n->compression,
|
n->digest ? n->digest->type : 0, n->maclength, n->compression,
|
||||||
n->options, *(uint32_t *)&n->status, n->nexthop ? n->nexthop->name : "-",
|
n->options, *(uint32_t *)&n->status, n->nexthop ? n->nexthop->name : "-",
|
||||||
n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu);
|
n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu) == -1)
|
||||||
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("End of nodes."));
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,6 @@ extern void node_add(node_t *);
|
||||||
extern void node_del(node_t *);
|
extern void node_del(node_t *);
|
||||||
extern node_t *lookup_node(char *);
|
extern node_t *lookup_node(char *);
|
||||||
extern node_t *lookup_node_udp(const sockaddr_t *);
|
extern node_t *lookup_node_udp(const sockaddr_t *);
|
||||||
extern void dump_nodes(void);
|
extern int dump_nodes(struct evbuffer *);
|
||||||
|
|
||||||
#endif /* __TINC_NODE_H__ */
|
#endif /* __TINC_NODE_H__ */
|
||||||
|
|
10
src/subnet.c
10
src/subnet.c
|
@ -438,7 +438,7 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_subnets(void)
|
int dump_subnets(struct evbuffer *out)
|
||||||
{
|
{
|
||||||
char netstr[MAXNETSTR];
|
char netstr[MAXNETSTR];
|
||||||
subnet_t *subnet;
|
subnet_t *subnet;
|
||||||
|
@ -446,14 +446,14 @@ void dump_subnets(void)
|
||||||
|
|
||||||
cp();
|
cp();
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("Subnet list:"));
|
|
||||||
|
|
||||||
for(node = subnet_tree->head; node; node = node->next) {
|
for(node = subnet_tree->head; node; node = node->next) {
|
||||||
subnet = node->data;
|
subnet = node->data;
|
||||||
if(!net2str(netstr, sizeof netstr, subnet))
|
if(!net2str(netstr, sizeof netstr, subnet))
|
||||||
continue;
|
continue;
|
||||||
logger(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name);
|
if(evbuffer_add_printf(out, _(" %s owner %s\n"),
|
||||||
|
netstr, subnet->owner->name) == -1)
|
||||||
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger(LOG_DEBUG, _("End of subnet list."));
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,6 @@ extern subnet_t *lookup_subnet(const struct node_t *, const subnet_t *);
|
||||||
extern subnet_t *lookup_subnet_mac(const mac_t *);
|
extern subnet_t *lookup_subnet_mac(const mac_t *);
|
||||||
extern subnet_t *lookup_subnet_ipv4(const ipv4_t *);
|
extern subnet_t *lookup_subnet_ipv4(const ipv4_t *);
|
||||||
extern subnet_t *lookup_subnet_ipv6(const ipv6_t *);
|
extern subnet_t *lookup_subnet_ipv6(const ipv6_t *);
|
||||||
extern void dump_subnets(void);
|
extern int dump_subnets(struct evbuffer *);
|
||||||
|
|
||||||
#endif /* __TINC_SUBNET_H__ */
|
#endif /* __TINC_SUBNET_H__ */
|
||||||
|
|
|
@ -546,6 +546,38 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||||
return send_ctl_request_cooked(fd, REQ_RESTART, NULL, 0) != -1;
|
return send_ctl_request_cooked(fd, REQ_RESTART, NULL, 0) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!strcasecmp(argv[optind], "dump")) {
|
||||||
|
if (argc < optind + 2) {
|
||||||
|
fprintf(stderr, _("Not enough arguments.\n"));
|
||||||
|
usage(true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcasecmp(argv[optind+1], "nodes")) {
|
||||||
|
return send_ctl_request_cooked(fd, REQ_DUMP_NODES, NULL, 0) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcasecmp(argv[optind+1], "edges")) {
|
||||||
|
return send_ctl_request_cooked(fd, REQ_DUMP_EDGES, NULL, 0) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcasecmp(argv[optind+1], "subnets")) {
|
||||||
|
return send_ctl_request_cooked(fd, REQ_DUMP_SUBNETS, NULL, 0) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcasecmp(argv[optind+1], "connections")) {
|
||||||
|
return send_ctl_request_cooked(fd, REQ_DUMP_CONNECTIONS, NULL, 0) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcasecmp(argv[optind+1], "graph")) {
|
||||||
|
return send_ctl_request_cooked(fd, REQ_DUMP_GRAPH, NULL, 0) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, _("Unknown dump type '%s'.\n"), argv[optind+1]);
|
||||||
|
usage(true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stderr, _("Unknown command `%s'.\n"), argv[optind]);
|
fprintf(stderr, _("Unknown command `%s'.\n"), argv[optind]);
|
||||||
usage(true);
|
usage(true);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue