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.
 .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
 .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}.
 
 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)
 @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.
 
 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.
 
 @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
 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
 .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 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
 .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);
 }
 
        splay_delete(connection_tree, c);
 }
 
-void dump_connections(void) {
+int dump_connections(struct evbuffer *out) {
        splay_node_t *node;
        connection_t *c;
 
        cp();
 
        splay_node_t *node;
        connection_t *c;
 
        cp();
 
-       logger(LOG_DEBUG, _("Connections:"));
-
        for(node = connection_tree->head; node; node = node->next) {
                c = node->data;
        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) {
 }
 
 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 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__ */
 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) {
        }
 
        if(req.type == REQ_STOP) {
-               logger(LOG_NOTICE, _("Got stop command"));
+               logger(LOG_NOTICE, _("Got '%s' command"), "stop");
                event_loopexit(NULL);
                goto respond;
        }
 
                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;
 
        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_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
 };
 
 #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);
 }
 
        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;
        splay_node_t *node, *node2;
        node_t *n;
        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) {
                n = node->data;
                for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
                        e = node2->data;
                        address = sockaddr2hostname(&e->address);
        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);
                }
        }
 
                        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 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__ */
 
 #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
 */
 
    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;
        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;
        
        /* 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;
        }
 
        /* 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) {
 }
 
 void graph(void) {
-       static struct event ev;
-
        sssp_bfs();
        mst_kruskal();
        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 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__ */
 
 #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();
 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 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;
 
        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_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);
        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(&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);
        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);
 }
 
        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();
 
        splay_node_t *node;
        node_t *n;
 
        cp();
 
-       logger(LOG_DEBUG, _("Nodes:"));
-
        for(node = node_tree->head; node; node = node->next) {
                n = node->data;
        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->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 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__ */
 
 #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;
 {
        char netstr[MAXNETSTR];
        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) {
                subnet = node->data;
                if(!net2str(netstr, sizeof netstr, subnet))
                        continue;
        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 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__ */
 
 #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;
        }
 
                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);
        
        fprintf(stderr, _("Unknown command `%s'.\n"), argv[optind]);
        usage(true);