Dump through control socket
authorScott Lamb <slamb@slamb.org>
Wed, 7 Nov 2007 02:49:25 +0000 (02:49 +0000)
committerScott Lamb <slamb@slamb.org>
Wed, 7 Nov 2007 02:49:25 +0000 (02:49 +0000)
Note this removes SIGUSR1, SIGUSR2, and the graph dumping config option.
It seems cleaner to do everything through the control socket.

18 files changed:
doc/tinc.conf.5.in
doc/tinc.texi
doc/tincctl.8.in
doc/tincd.8.in
src/connection.c
src/connection.h
src/control.c
src/control_common.h
src/edge.c
src/edge.h
src/graph.c
src/graph.h
src/net.c
src/node.c
src/node.h
src/subnet.c
src/subnet.h
src/tincctl.c

index 978bdc1..83d2541 100644 (file)
@@ -147,18 +147,6 @@ instead of
 .Va Device .
 The info pages of the tinc package contain more information
 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
 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
index 2ea54be..541d2de 100644 (file)
@@ -885,16 +885,6 @@ Under Windows, use @var{Interface} instead of @var{Device}.
 Note that you can only use one device per daemon.
 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
 @item Hostnames = <yes|no> (no)
 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.
 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
 Purges all information remembered about unreachable nodes.
 
index eeb5031..734bb4f 100644 (file)
@@ -78,7 +78,7 @@ Dump a graph of the VPN in
 format.
 .El
 .Sh BUGS
-The "start", "restart", "reload", and "dump" commands are not yet implemented.
+The "start", "restart", and "reload" commands are not yet implemented.
 .Pp
 If you find any bugs, report them to tinc@tinc-vpn.org.
 .Sh SEE ALSO
index 37a134e..f136a1b 100644 (file)
@@ -98,10 +98,6 @@ will be made.
 .It INT
 Temporarily increases debug level to 5.
 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
 Purges all information remembered about unreachable nodes.
 .El
index 21cb6aa..06f51b5 100644 (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) {
index 2426a22..ddff03b 100644 (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__ */
index 7b27f69..19ac37a 100644 (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;
 
index 3fa034e..750098e 100644 (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
index 861b945..3b584f3 100644 (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;
 }
index 082ea5d..dd3d670 100644 (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__ */
index 5bf6361..e6d70af 100644 (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});
 }
index 0d5be20..88de9f6 100644 (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__ */
index a4bff6d..1be4ed8 100644 (file)
--- a/src/net.c
+++ b/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) {
        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);
index cbafe71..0960ca7 100644 (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;
 }
index 83af5e3..0476cdb 100644 (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__ */
index bbf4edd..9d84ec2 100644 (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;
 }
index f73aaf9..48eec52 100644 (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__ */
index 3944fa2..4982e6b 100644 (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);