/*
graph.c -- graph algorithms
- Copyright (C) 2001-2006 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2001-2007 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
#include "system.h"
#include "avl_tree.h"
+#include "config.h"
#include "connection.h"
#include "device.h"
#include "edge.h"
#include "subnet.h"
#include "utils.h"
+static bool graph_changed = true;
+
/* Implementation of Kruskal's algorithm.
Running time: O(EN)
Please note that sorting on weight is already done by add_edge().
/* Starting point */
- ((edge_t *) edge_weight_tree->head->data)->from->status.visited = true;
+ for(node = edge_weight_tree->head; node; node = node->next) {
+ e = node->data;
+ if(e->from->status.reachable) {
+ e->from->status.visited = true;
+ break;
+ }
+ }
/* Add safe edges */
asprintf(&envp[5], "REMOTEPORT=%s", port);
envp[6] = NULL;
+ execute_script(n->status.reachable ? "host-up" : "host-down", envp);
+
asprintf(&name,
n->status.reachable ? "hosts/%s-up" : "hosts/%s-down",
n->name);
void graph(void)
{
- mst_kruskal();
sssp_bfs();
+ mst_kruskal();
+ graph_changed = true;
+}
+
+
+
+/* Dump nodes and edges to a graphviz file.
+
+ The file can be converted to an image with
+ dot -Tpng graph_filename -o image_filename.png -Gconcentrate=true
+*/
+
+void dump_graph(void)
+{
+ avl_node_t *node;
+ node_t *n;
+ edge_t *e;
+ char *filename = NULL, *tmpname = NULL;
+ FILE *file;
+
+ if(!graph_changed || !get_config_string(lookup_config(config_tree, "GraphDumpFile"), &filename))
+ return;
+
+ graph_changed = false;
+
+ 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");
+
+ /* 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);
+ }
+
+ /* 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);
+ }
+
+ fprintf(file, "}\n");
+
+ if(filename[0] == '|') {
+ pclose(file);
+ } else {
+ fclose(file);
+#ifdef HAVE_MINGW
+ unlink(filename);
+#endif
+ rename(tmpname, filename);
+ free(tmpname);
+ }
}