1bbd6d60aSBrian Feldman 2bbd6d60aSBrian Feldman /* 3bbd6d60aSBrian Feldman * dot.c 4bbd6d60aSBrian Feldman * 5bbd6d60aSBrian Feldman * Copyright (c) 2004 Brian Fundakowski Feldman 6bbd6d60aSBrian Feldman * Copyright (c) 1996-1999 Whistle Communications, Inc. 7bbd6d60aSBrian Feldman * All rights reserved. 8bbd6d60aSBrian Feldman * 9bbd6d60aSBrian Feldman * Subject to the following obligations and disclaimer of warranty, use and 10bbd6d60aSBrian Feldman * redistribution of this software, in source or object code forms, with or 11bbd6d60aSBrian Feldman * without modifications are expressly permitted by Whistle Communications; 12bbd6d60aSBrian Feldman * provided, however, that: 13bbd6d60aSBrian Feldman * 1. Any and all reproductions of the source or object code must include the 14bbd6d60aSBrian Feldman * copyright notice above and the following disclaimer of warranties; and 15bbd6d60aSBrian Feldman * 2. No rights are granted, in any manner or form, to use Whistle 16bbd6d60aSBrian Feldman * Communications, Inc. trademarks, including the mark "WHISTLE 17bbd6d60aSBrian Feldman * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 18bbd6d60aSBrian Feldman * such appears in the above copyright notice or in the software. 19bbd6d60aSBrian Feldman * 20bbd6d60aSBrian Feldman * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 21bbd6d60aSBrian Feldman * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 22bbd6d60aSBrian Feldman * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 23bbd6d60aSBrian Feldman * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 24bbd6d60aSBrian Feldman * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 25bbd6d60aSBrian Feldman * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 26bbd6d60aSBrian Feldman * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 27bbd6d60aSBrian Feldman * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 28bbd6d60aSBrian Feldman * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 29bbd6d60aSBrian Feldman * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 30bbd6d60aSBrian Feldman * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31bbd6d60aSBrian Feldman * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 32bbd6d60aSBrian Feldman * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 33bbd6d60aSBrian Feldman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34bbd6d60aSBrian Feldman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35bbd6d60aSBrian Feldman * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 36bbd6d60aSBrian Feldman * OF SUCH DAMAGE. 37bbd6d60aSBrian Feldman * 38bbd6d60aSBrian Feldman * $FreeBSD$ 39bbd6d60aSBrian Feldman */ 40bbd6d60aSBrian Feldman 41bbd6d60aSBrian Feldman #include <inttypes.h> 42bbd6d60aSBrian Feldman 43bbd6d60aSBrian Feldman #include "ngctl.h" 44bbd6d60aSBrian Feldman 45bbd6d60aSBrian Feldman #define UNNAMED "\\<unnamed\\>" 46bbd6d60aSBrian Feldman 47bbd6d60aSBrian Feldman static int DotCmd(int ac, char **av); 48bbd6d60aSBrian Feldman 49bbd6d60aSBrian Feldman const struct ngcmd dot_cmd = { 50bbd6d60aSBrian Feldman DotCmd, 51bbd6d60aSBrian Feldman "dot [outputfile]", 52bbd6d60aSBrian Feldman "Produce a GraphViz (.dot) of the entire netgraph.", 53bbd6d60aSBrian Feldman "If no outputfile is specified, stdout will be assumed.", 54bbd6d60aSBrian Feldman { "graphviz", "confdot" } 55bbd6d60aSBrian Feldman }; 56bbd6d60aSBrian Feldman 57bbd6d60aSBrian Feldman static int 58bbd6d60aSBrian Feldman DotCmd(int ac, char **av) 59bbd6d60aSBrian Feldman { 609fe5fadaSRuslan Ermilov struct ng_mesg *nlresp; 619fe5fadaSRuslan Ermilov struct namelist *nlist; 62bbd6d60aSBrian Feldman FILE *f = stdout; 63723c1c2eSRuslan Ermilov int ch; 64723c1c2eSRuslan Ermilov u_int i; 65bbd6d60aSBrian Feldman 66bbd6d60aSBrian Feldman /* Get options */ 67bbd6d60aSBrian Feldman optind = 1; 68bbd6d60aSBrian Feldman while ((ch = getopt(ac, av, "")) != EOF) { 69bbd6d60aSBrian Feldman switch (ch) { 70bbd6d60aSBrian Feldman case '?': 71bbd6d60aSBrian Feldman default: 72bbd6d60aSBrian Feldman return (CMDRTN_USAGE); 73bbd6d60aSBrian Feldman break; 74bbd6d60aSBrian Feldman } 75bbd6d60aSBrian Feldman } 76bbd6d60aSBrian Feldman ac -= optind; 77bbd6d60aSBrian Feldman av += optind; 78bbd6d60aSBrian Feldman 79bbd6d60aSBrian Feldman /* Get arguments */ 80bbd6d60aSBrian Feldman switch (ac) { 81bbd6d60aSBrian Feldman case 1: 82bbd6d60aSBrian Feldman f = fopen(av[0], "w"); 83bbd6d60aSBrian Feldman if (f == NULL) { 84bbd6d60aSBrian Feldman warn("Could not open %s for writing", av[0]); 85bbd6d60aSBrian Feldman return (CMDRTN_ERROR); 86bbd6d60aSBrian Feldman } 87bbd6d60aSBrian Feldman case 0: 88bbd6d60aSBrian Feldman break; 89bbd6d60aSBrian Feldman default: 90bbd6d60aSBrian Feldman if (f != stdout) 91bbd6d60aSBrian Feldman (void)fclose(f); 92bbd6d60aSBrian Feldman return (CMDRTN_USAGE); 93bbd6d60aSBrian Feldman } 94bbd6d60aSBrian Feldman 95bbd6d60aSBrian Feldman /* Get list of nodes */ 96bbd6d60aSBrian Feldman if (NgSendMsg(csock, ".", NGM_GENERIC_COOKIE, NGM_LISTNODES, NULL, 97bbd6d60aSBrian Feldman 0) < 0) { 98bbd6d60aSBrian Feldman warn("send listnodes msg"); 99bbd6d60aSBrian Feldman goto error; 100bbd6d60aSBrian Feldman } 1019fe5fadaSRuslan Ermilov if (NgAllocRecvMsg(csock, &nlresp, NULL) < 0) { 102bbd6d60aSBrian Feldman warn("recv listnodes msg"); 103bbd6d60aSBrian Feldman goto error; 104bbd6d60aSBrian Feldman } 105bbd6d60aSBrian Feldman 1069fe5fadaSRuslan Ermilov nlist = (struct namelist *)nlresp->data; 107bbd6d60aSBrian Feldman fprintf(f, "graph netgraph {\n"); 108bbd6d60aSBrian Feldman /* TODO: implement rank = same or subgraphs at some point */ 109bbd6d60aSBrian Feldman fprintf(f, "\tedge [ weight = 1.0 ];\n"); 110bbd6d60aSBrian Feldman fprintf(f, "\tnode [ shape = record, fontsize = 12 ] {\n"); 111bbd6d60aSBrian Feldman for (i = 0; i < nlist->numnames; i++) 112bbd6d60aSBrian Feldman fprintf(f, "\t\t\"%jx\" [ label = \"{%s:|{%s|[%jx]:}}\" ];\n", 113bbd6d60aSBrian Feldman (uintmax_t)nlist->nodeinfo[i].id, 114bbd6d60aSBrian Feldman nlist->nodeinfo[i].name[0] != '\0' ? 115bbd6d60aSBrian Feldman nlist->nodeinfo[i].name : UNNAMED, 116bbd6d60aSBrian Feldman nlist->nodeinfo[i].type, (uintmax_t)nlist->nodeinfo[i].id); 117bbd6d60aSBrian Feldman fprintf(f, "\t};\n"); 118bbd6d60aSBrian Feldman 119bbd6d60aSBrian Feldman fprintf(f, "\tsubgraph cluster_disconnected {\n"); 120bbd6d60aSBrian Feldman fprintf(f, "\t\tbgcolor = pink;\n"); 121bbd6d60aSBrian Feldman for (i = 0; i < nlist->numnames; i++) 122bbd6d60aSBrian Feldman if (nlist->nodeinfo[i].hooks == 0) 123bbd6d60aSBrian Feldman fprintf(f, "\t\t\"%jx\";\n", 124bbd6d60aSBrian Feldman (uintmax_t)nlist->nodeinfo[i].id); 125bbd6d60aSBrian Feldman fprintf(f, "\t};\n"); 126bbd6d60aSBrian Feldman 127bbd6d60aSBrian Feldman for (i = 0; i < nlist->numnames; i++) { 1289fe5fadaSRuslan Ermilov struct ng_mesg *hlresp; 1299fe5fadaSRuslan Ermilov struct hooklist *hlist; 1309fe5fadaSRuslan Ermilov struct nodeinfo *ninfo; 131bbd6d60aSBrian Feldman char path[NG_PATHSIZ]; 132723c1c2eSRuslan Ermilov u_int j; 133bbd6d60aSBrian Feldman 134bbd6d60aSBrian Feldman (void)snprintf(path, sizeof(path), "[%jx]:", 135bbd6d60aSBrian Feldman (uintmax_t)nlist->nodeinfo[i].id); 136bbd6d60aSBrian Feldman 137bbd6d60aSBrian Feldman /* Get node info and hook list */ 138bbd6d60aSBrian Feldman if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, 139bbd6d60aSBrian Feldman NULL, 0) < 0) { 1409fe5fadaSRuslan Ermilov free(nlresp); 141bbd6d60aSBrian Feldman warn("send listhooks msg"); 142bbd6d60aSBrian Feldman goto error; 143bbd6d60aSBrian Feldman } 1449fe5fadaSRuslan Ermilov if (NgAllocRecvMsg(csock, &hlresp, NULL) < 0) { 1459fe5fadaSRuslan Ermilov free(nlresp); 146bbd6d60aSBrian Feldman warn("recv listhooks msg"); 147bbd6d60aSBrian Feldman goto error; 148bbd6d60aSBrian Feldman } 149bbd6d60aSBrian Feldman 1509fe5fadaSRuslan Ermilov hlist = (struct hooklist *)hlresp->data; 1519fe5fadaSRuslan Ermilov ninfo = &hlist->nodeinfo; 1529fe5fadaSRuslan Ermilov if (ninfo->hooks == 0) { 1539fe5fadaSRuslan Ermilov free(hlresp); 154bbd6d60aSBrian Feldman continue; 1559fe5fadaSRuslan Ermilov } 156bbd6d60aSBrian Feldman 157bbd6d60aSBrian Feldman fprintf(f, "\tnode [ shape = octagon, fontsize = 10 ] {\n"); 158bbd6d60aSBrian Feldman for (j = 0; j < ninfo->hooks; j++) 159bbd6d60aSBrian Feldman fprintf(f, "\t\t\"%jx.%s\" [ label = \"%s\" ];\n", 160bbd6d60aSBrian Feldman (uintmax_t)nlist->nodeinfo[i].id, 161bbd6d60aSBrian Feldman hlist->link[j].ourhook, hlist->link[j].ourhook); 162bbd6d60aSBrian Feldman fprintf(f, "\t};\n"); 163bbd6d60aSBrian Feldman 164bbd6d60aSBrian Feldman fprintf(f, "\t{\n\t\tedge [ weight = 2.0, style = bold ];\n"); 165bbd6d60aSBrian Feldman for (j = 0; j < ninfo->hooks; j++) 166bbd6d60aSBrian Feldman fprintf(f, "\t\t\"%jx\" -- \"%jx.%s\";\n", 167bbd6d60aSBrian Feldman (uintmax_t)nlist->nodeinfo[i].id, 168bbd6d60aSBrian Feldman (uintmax_t)nlist->nodeinfo[i].id, 169bbd6d60aSBrian Feldman hlist->link[j].ourhook); 170bbd6d60aSBrian Feldman fprintf(f, "\t};\n"); 171bbd6d60aSBrian Feldman 172bbd6d60aSBrian Feldman for (j = 0; j < ninfo->hooks; j++) { 173bbd6d60aSBrian Feldman /* Only print the edges going in one direction. */ 174bbd6d60aSBrian Feldman if (hlist->link[j].nodeinfo.id > nlist->nodeinfo[i].id) 175bbd6d60aSBrian Feldman continue; 176bbd6d60aSBrian Feldman fprintf(f, "\t\"%jx.%s\" -- \"%jx.%s\";\n", 177bbd6d60aSBrian Feldman (uintmax_t)nlist->nodeinfo[i].id, 178bbd6d60aSBrian Feldman hlist->link[j].ourhook, 179bbd6d60aSBrian Feldman (uintmax_t)hlist->link[j].nodeinfo.id, 180bbd6d60aSBrian Feldman hlist->link[j].peerhook); 181bbd6d60aSBrian Feldman } 1829fe5fadaSRuslan Ermilov free(hlresp); 183bbd6d60aSBrian Feldman } 184bbd6d60aSBrian Feldman 185bbd6d60aSBrian Feldman fprintf(f, "};\n"); 186bbd6d60aSBrian Feldman 1879fe5fadaSRuslan Ermilov free(nlresp); 188bbd6d60aSBrian Feldman if (f != stdout) 189bbd6d60aSBrian Feldman (void)fclose(f); 190bbd6d60aSBrian Feldman return (CMDRTN_OK); 191bbd6d60aSBrian Feldman error: 192bbd6d60aSBrian Feldman if (f != stdout) 193bbd6d60aSBrian Feldman (void)fclose(f); 194bbd6d60aSBrian Feldman return (CMDRTN_ERROR); 195bbd6d60aSBrian Feldman } 196