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:
Scott Lamb 2007-11-07 02:49:25 +00:00
parent 50ad3f2a89
commit 6eaefb4dbc
18 changed files with 113 additions and 125 deletions

View file

@ -106,21 +106,22 @@ void connection_del(connection_t *c) {
splay_delete(connection_tree, c);
}
void dump_connections(void) {
int dump_connections(struct evbuffer *out) {
splay_node_t *node;
connection_t *c;
cp();
logger(LOG_DEBUG, _("Connections:"));
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
logger(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"),
c->name, c->hostname, c->options, c->socket, c->status.value);
if(evbuffer_add_printf(out,
_(" %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) {

View file

@ -109,7 +109,7 @@ extern connection_t *new_connection(void) __attribute__ ((__malloc__));
extern void free_connection(connection_t *);
extern void connection_add(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 *);
#endif /* __TINC_CONNECTION_H__ */

View file

@ -62,11 +62,41 @@ static void handle_control_data(struct bufferevent *event, void *data) {
}
if(req.type == REQ_STOP) {
logger(LOG_NOTICE, _("Got stop command"));
logger(LOG_NOTICE, _("Got '%s' command"), "stop");
event_loopexit(NULL);
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"));
res.res_errno = EINVAL;

View file

@ -26,6 +26,11 @@ enum request_type {
REQ_STOP,
REQ_RELOAD,
REQ_RESTART,
REQ_DUMP_NODES,
REQ_DUMP_EDGES,
REQ_DUMP_SUBNETS,
REQ_DUMP_CONNECTIONS,
REQ_DUMP_GRAPH,
};
#define TINC_CTL_VERSION_CURRENT 0

View file

@ -125,7 +125,7 @@ edge_t *lookup_edge(node_t *from, node_t *to) {
return splay_search(from->edge_tree, &v);
}
void dump_edges(void) {
int dump_edges(struct evbuffer *out) {
splay_node_t *node, *node2;
node_t *n;
edge_t *e;
@ -133,18 +133,21 @@ void dump_edges(void) {
cp();
logger(LOG_DEBUG, _("Edges:"));
for(node = node_tree->head; node; node = node->next) {
n = node->data;
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
e = node2->data;
address = sockaddr2hostname(&e->address);
logger(LOG_DEBUG, _(" %s to %s at %s options %lx weight %d"),
e->from->name, e->to->name, address, e->options, e->weight);
if(evbuffer_add_printf(out,
_(" %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);
}
}
logger(LOG_DEBUG, _("End of edges."));
return 0;
}

View file

@ -51,6 +51,6 @@ extern void free_edge_tree(splay_tree_t *);
extern void edge_add(edge_t *);
extern void edge_del(edge_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__ */

View file

@ -313,66 +313,37 @@ void sssp_bfs(void) {
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;
node_t *n;
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(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");
if(evbuffer_add_printf(out, "digraph {\n") == -1)
return errno;
/* dump all nodes first */
for(node = node_tree->head; node; node = node->next) {
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 */
for(node = edge_weight_tree->head; node; node = node->next) {
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(filename[0] == '|') {
pclose(file);
} else {
fclose(file);
#ifdef HAVE_MINGW
unlink(filename);
#endif
rename(tmpname, filename);
free(tmpname);
}
if(evbuffer_add_printf(out, "}\n") == -1)
return errno;
return 0;
}
void graph(void) {
static struct event ev;
sssp_bfs();
mst_kruskal();
if(!timeout_initialized(&ev))
timeout_set(&ev, dump_graph, NULL);
event_add(&ev, &(struct timeval){5, 0});
}

View file

@ -26,6 +26,6 @@
extern void graph(void);
extern void mst_kruskal(void);
extern void sssp_bfs(void);
extern void dump_graph(void);
extern int dump_graph(struct evbuffer *);
#endif /* __TINC_GRAPH_H__ */

View file

@ -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) {
logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
purge();
@ -346,8 +333,6 @@ int main_loop(void) {
struct event sigint_event;
struct event sigterm_event;
struct event sigquit_event;
struct event sigusr1_event;
struct event sigusr2_event;
struct event sigwinch_event;
struct event sigalrm_event;
@ -363,10 +348,6 @@ int main_loop(void) {
signal_add(&sigterm_event, NULL);
signal_set(&sigquit_event, SIGQUIT, sigterm_handler, 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_add(&sigwinch_event, NULL);
signal_set(&sigalrm_event, SIGALRM, sigalrm_handler, NULL);
@ -381,8 +362,6 @@ int main_loop(void) {
signal_del(&sigint_event);
signal_del(&sigterm_event);
signal_del(&sigquit_event);
signal_del(&sigusr1_event);
signal_del(&sigusr2_event);
signal_del(&sigwinch_event);
signal_del(&sigalrm_event);
event_del(&timeout_event);

View file

@ -160,22 +160,21 @@ node_t *lookup_node_udp(const sockaddr_t *sa) {
return splay_search(node_udp_tree, &n);
}
void dump_nodes(void) {
int dump_nodes(struct evbuffer *out) {
splay_node_t *node;
node_t *n;
cp();
logger(LOG_DEBUG, _("Nodes:"));
for(node = node_tree->head; node; node = node->next) {
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->digest ? n->digest->type : 0, n->maclength, n->compression,
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;
}

View file

@ -94,6 +94,6 @@ extern void node_add(node_t *);
extern void node_del(node_t *);
extern node_t *lookup_node(char *);
extern node_t *lookup_node_udp(const sockaddr_t *);
extern void dump_nodes(void);
extern int dump_nodes(struct evbuffer *);
#endif /* __TINC_NODE_H__ */

View file

@ -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];
subnet_t *subnet;
@ -446,14 +446,14 @@ void dump_subnets(void)
cp();
logger(LOG_DEBUG, _("Subnet list:"));
for(node = subnet_tree->head; node; node = node->next) {
subnet = node->data;
if(!net2str(netstr, sizeof netstr, subnet))
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;
}

View file

@ -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_ipv4(const ipv4_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__ */

View file

@ -546,6 +546,38 @@ int main(int argc, char *argv[], char *envp[]) {
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]);
usage(true);