From 368727c3dac4a1f8343e2e0eccf5bc62d9b197e2 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 14 Oct 2012 16:07:35 +0200 Subject: [PATCH] tincctl: add node colors and edge weight to graph dump. --- doc/tinc.texi | 3 + doc/tincctl.8.in | 3 + src/tincctl.c | 139 ++++++++++++++++++++++++++--------------------- 3 files changed, 83 insertions(+), 62 deletions(-) diff --git a/doc/tinc.texi b/doc/tinc.texi index 10927b7..ac3a630 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -2213,6 +2213,9 @@ Dump a list of all meta connections with ourself. @item dump graph | digraph Dump a graph of the VPN in dotty format. +Nodes are colored according to their reachability: +red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable. +Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet. @item info @var{node} | @var{subnet} | @var{address} Show information about a particular @var{node}, @var{subnet} or @var{address}. diff --git a/doc/tincctl.8.in b/doc/tincctl.8.in index 04a1ddb..cdd4b81 100644 --- a/doc/tincctl.8.in +++ b/doc/tincctl.8.in @@ -128,6 +128,9 @@ Dump a list of all meta connections with ourself. Dump a graph of the VPN in .Xr dotty 1 format. +Nodes are colored according to their reachability: +red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable. +Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet. .It info Ar node | subnet | address Show information about a particular node, subnet or address. If an address is given, any matching subnet will be shown. diff --git a/src/tincctl.c b/src/tincctl.c index 99c0485..c1cabdb 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -964,71 +964,86 @@ static int cmd_dump(int argc, char *argv[]) { if(n < 2) break; - if(!do_graph) { - char node[4096]; - char from[4096]; - char to[4096]; - char subnet[4096]; - char host[4096]; - char port[4096]; - char via[4096]; - char nexthop[4096]; - int cipher, digest, maclength, compression, distance, socket, weight; - short int pmtu, minmtu, maxmtu; - unsigned int options, status; - long int last_state_change; - - switch(req) { - case REQ_DUMP_NODES: { - int n = sscanf(line, "%*d %*d %s %s port %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", node, host, port, &cipher, &digest, &maclength, &compression, &options, &status, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change); - if(n != 16) { - fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line); - return 1; - } + char node[4096]; + char from[4096]; + char to[4096]; + char subnet[4096]; + char host[4096]; + char port[4096]; + char via[4096]; + char nexthop[4096]; + int cipher, digest, maclength, compression, distance, socket, weight; + short int pmtu, minmtu, maxmtu; + unsigned int options, status_int; + node_status_t status; + long int last_state_change; + + switch(req) { + case REQ_DUMP_NODES: { + int n = sscanf(line, "%*d %*d %s %s port %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", node, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change); + if(n != 16) { + fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line); + return 1; + } + if(do_graph) { + memcpy(&status, &status_int, sizeof status); + const char *color = "black"; + if(!strcmp(host, "MYSELF")) + color = "green"; + else if(!status.reachable) + color = "red"; + else if(strcmp(via, node)) + color = "orange"; + else if(!status.validkey) + color = "black"; + else if(minmtu > 0) + color = "green"; + printf(" %s [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\""); + } else { printf("%s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %hd (min %hd max %hd)\n", - node, host, port, cipher, digest, maclength, compression, options, status, nexthop, via, distance, pmtu, minmtu, maxmtu); - } break; - - case REQ_DUMP_EDGES: { - int n = sscanf(line, "%*d %*d %s %s %s port %s %x %d", from, to, host, port, &options, &weight); - if(n != 6) { - fprintf(stderr, "Unable to parse edge dump from tincd.\n"); - return 1; - } + node, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu); + } + } break; + + case REQ_DUMP_EDGES: { + int n = sscanf(line, "%*d %*d %s %s %s port %s %x %d", from, to, host, port, &options, &weight); + if(n != 6) { + fprintf(stderr, "Unable to parse edge dump from tincd.\n"); + return 1; + } + + if(do_graph) { + float w = 1 + 65536.0 / weight; + if(do_graph == 1 && strcmp(node1, node2) > 0) + printf(" %s -- %s [w = %f, weight = %f];\n", node1, node2, w, w); + else if(do_graph == 2) + printf(" %s -> %s [w = %f, weight = %f];\n", node1, node2, w, w); + } else { printf("%s to %s at %s port %s options %x weight %d\n", from, to, host, port, options, weight); - } break; - - case REQ_DUMP_SUBNETS: { - int n = sscanf(line, "%*d %*d %s %s", subnet, node); - if(n != 2) { - fprintf(stderr, "Unable to parse subnet dump from tincd.\n"); - return 1; - } - printf("%s owner %s\n", strip_weight(subnet), node); - } break; - - case REQ_DUMP_CONNECTIONS: { - int n = sscanf(line, "%*d %*d %s %s port %s %x %d %x", node, host, port, &options, &socket, &status); - if(n != 6) { - fprintf(stderr, "Unable to parse connection dump from tincd.\n"); - return 1; - } - printf("%s at %s port %s options %x socket %d status %x\n", node, host, port, options, socket, status); - } break; - - default: - fprintf(stderr, "Unable to parse dump from tincd.\n"); + } + } break; + + case REQ_DUMP_SUBNETS: { + int n = sscanf(line, "%*d %*d %s %s", subnet, node); + if(n != 2) { + fprintf(stderr, "Unable to parse subnet dump from tincd.\n"); return 1; - } - } else { - if(req == REQ_DUMP_NODES) - printf(" %s [label = \"%s\"];\n", node1, node1); - else { - if(do_graph == 1 && strcmp(node1, node2) > 0) - printf(" %s -- %s;\n", node1, node2); - else if(do_graph == 2) - printf(" %s -> %s;\n", node1, node2); - } + } + printf("%s owner %s\n", strip_weight(subnet), node); + } break; + + case REQ_DUMP_CONNECTIONS: { + int n = sscanf(line, "%*d %*d %s %s port %s %x %d %x", node, host, port, &options, &socket, &status_int); + if(n != 6) { + fprintf(stderr, "Unable to parse connection dump from tincd.\n"); + return 1; + } + printf("%s at %s port %s options %x socket %d status %x\n", node, host, port, options, socket, status_int); + } break; + + default: + fprintf(stderr, "Unable to parse dump from tincd.\n"); + return 1; } } -- 2.25.1