|
Lines 2-7
Link Here
|
| 2 |
/* |
2 |
/* |
| 3 |
* dot.c |
3 |
* dot.c |
| 4 |
* |
4 |
* |
|
|
5 |
* Copyright (c) 2019 Lutz Donnerhacke |
| 5 |
* Copyright (c) 2004 Brian Fundakowski Feldman |
6 |
* Copyright (c) 2004 Brian Fundakowski Feldman |
| 6 |
* Copyright (c) 1996-1999 Whistle Communications, Inc. |
7 |
* Copyright (c) 1996-1999 Whistle Communications, Inc. |
| 7 |
* All rights reserved. |
8 |
* All rights reserved. |
|
Lines 53-61
Link Here
|
| 53 |
|
54 |
|
| 54 |
const struct ngcmd dot_cmd = { |
55 |
const struct ngcmd dot_cmd = { |
| 55 |
DotCmd, |
56 |
DotCmd, |
| 56 |
"dot [outputfile]", |
57 |
"dot [-c] [outputfile]", |
| 57 |
"Produce a GraphViz (.dot) of the entire netgraph.", |
58 |
"Produce a GraphViz (.dot) of the entire netgraph.", |
| 58 |
"If no outputfile is specified, stdout will be assumed.", |
59 |
"If no outputfile is specified, stdout will be assumed." |
|
|
60 |
" The optional -c argument generates a graph without separate" |
| 61 |
" structures for egde names. Such a graph is more compact.", |
| 59 |
{ "graphviz", "confdot" } |
62 |
{ "graphviz", "confdot" } |
| 60 |
}; |
63 |
}; |
| 61 |
|
64 |
|
|
Lines 66-77
Link Here
|
| 66 |
struct namelist *nlist; |
69 |
struct namelist *nlist; |
| 67 |
FILE *f = stdout; |
70 |
FILE *f = stdout; |
| 68 |
int ch; |
71 |
int ch; |
|
|
72 |
int compact = 0; |
| 69 |
u_int i; |
73 |
u_int i; |
| 70 |
|
74 |
|
| 71 |
/* Get options */ |
75 |
/* Get options */ |
| 72 |
optind = 1; |
76 |
optind = 1; |
| 73 |
while ((ch = getopt(ac, av, "")) != -1) { |
77 |
while ((ch = getopt(ac, av, "c")) != -1) { |
| 74 |
switch (ch) { |
78 |
switch (ch) { |
|
|
79 |
case 'c': |
| 80 |
compact = 1; |
| 81 |
break; |
| 75 |
case '?': |
82 |
case '?': |
| 76 |
default: |
83 |
default: |
| 77 |
return (CMDRTN_USAGE); |
84 |
return (CMDRTN_USAGE); |
|
Lines 109-117
Link Here
|
| 109 |
} |
116 |
} |
| 110 |
|
117 |
|
| 111 |
nlist = (struct namelist *)nlresp->data; |
118 |
nlist = (struct namelist *)nlresp->data; |
| 112 |
fprintf(f, "graph netgraph {\n"); |
119 |
if(compact) { |
| 113 |
/* TODO: implement rank = same or subgraphs at some point */ |
120 |
fprintf(f, "digraph netgraph {\n"); |
| 114 |
fprintf(f, "\tedge [ weight = 1.0 ];\n"); |
121 |
fprintf(f, "\tedge [ dir = \"none\", fontsize = 10 ];\n"); |
|
|
122 |
} else { |
| 123 |
fprintf(f, "graph netgraph {\n"); |
| 124 |
/* TODO: implement rank = same or subgraphs at some point */ |
| 125 |
fprintf(f, "\tedge [ weight = 1.0 ];\n"); |
| 126 |
} |
| 115 |
fprintf(f, "\tnode [ shape = record, fontsize = 12 ] {\n"); |
127 |
fprintf(f, "\tnode [ shape = record, fontsize = 12 ] {\n"); |
| 116 |
for (i = 0; i < nlist->numnames; i++) |
128 |
for (i = 0; i < nlist->numnames; i++) |
| 117 |
fprintf(f, "\t\t\"%jx\" [ label = \"{%s:|{%s|[%jx]:}}\" ];\n", |
129 |
fprintf(f, "\t\t\"%jx\" [ label = \"{%s:|{%s|[%jx]:}}\" ];\n", |
|
Lines 159-188
Link Here
|
| 159 |
continue; |
171 |
continue; |
| 160 |
} |
172 |
} |
| 161 |
|
173 |
|
| 162 |
fprintf(f, "\tnode [ shape = octagon, fontsize = 10 ] {\n"); |
174 |
if(!compact) { |
| 163 |
for (j = 0; j < ninfo->hooks; j++) |
175 |
fprintf(f, "\tnode [ shape = octagon, fontsize = 10 ] {\n"); |
| 164 |
fprintf(f, "\t\t\"%jx.%s\" [ label = \"%s\" ];\n", |
176 |
for (j = 0; j < ninfo->hooks; j++) |
| 165 |
(uintmax_t)nlist->nodeinfo[i].id, |
177 |
fprintf(f, "\t\t\"%jx.%s\" [ label = \"%s\" ];\n", |
| 166 |
hlist->link[j].ourhook, hlist->link[j].ourhook); |
178 |
(uintmax_t)nlist->nodeinfo[i].id, |
| 167 |
fprintf(f, "\t};\n"); |
179 |
hlist->link[j].ourhook, hlist->link[j].ourhook); |
|
|
180 |
fprintf(f, "\t};\n"); |
| 181 |
|
| 182 |
fprintf(f, "\t{\n\t\tedge [ weight = 2.0, style = bold ];\n"); |
| 183 |
for (j = 0; j < ninfo->hooks; j++) |
| 184 |
fprintf(f, "\t\t\"%jx\" -- \"%jx.%s\";\n", |
| 185 |
(uintmax_t)nlist->nodeinfo[i].id, |
| 186 |
(uintmax_t)nlist->nodeinfo[i].id, |
| 187 |
hlist->link[j].ourhook); |
| 188 |
fprintf(f, "\t};\n"); |
| 189 |
} |
| 168 |
|
190 |
|
| 169 |
fprintf(f, "\t{\n\t\tedge [ weight = 2.0, style = bold ];\n"); |
|
|
| 170 |
for (j = 0; j < ninfo->hooks; j++) |
| 171 |
fprintf(f, "\t\t\"%jx\" -- \"%jx.%s\";\n", |
| 172 |
(uintmax_t)nlist->nodeinfo[i].id, |
| 173 |
(uintmax_t)nlist->nodeinfo[i].id, |
| 174 |
hlist->link[j].ourhook); |
| 175 |
fprintf(f, "\t};\n"); |
| 176 |
|
| 177 |
for (j = 0; j < ninfo->hooks; j++) { |
191 |
for (j = 0; j < ninfo->hooks; j++) { |
| 178 |
/* Only print the edges going in one direction. */ |
192 |
/* Only print the edges going in one direction. */ |
| 179 |
if (hlist->link[j].nodeinfo.id > nlist->nodeinfo[i].id) |
193 |
if (hlist->link[j].nodeinfo.id > nlist->nodeinfo[i].id) |
| 180 |
continue; |
194 |
continue; |
| 181 |
fprintf(f, "\t\"%jx.%s\" -- \"%jx.%s\";\n", |
195 |
if(compact) { |
| 182 |
(uintmax_t)nlist->nodeinfo[i].id, |
196 |
fprintf(f, "\t\"%jx\" -> \"%jx\" [ headlabel = \"%s\", taillabel =\"%s\" ] ;\n", |
| 183 |
hlist->link[j].ourhook, |
197 |
(uintmax_t)hlist->link[j].nodeinfo.id, |
| 184 |
(uintmax_t)hlist->link[j].nodeinfo.id, |
198 |
(uintmax_t)nlist->nodeinfo[i].id, |
| 185 |
hlist->link[j].peerhook); |
199 |
hlist->link[j].ourhook, |
|
|
200 |
hlist->link[j].peerhook); |
| 201 |
} else { |
| 202 |
fprintf(f, "\t\"%jx.%s\" -- \"%jx.%s\";\n", |
| 203 |
(uintmax_t)nlist->nodeinfo[i].id, |
| 204 |
hlist->link[j].ourhook, |
| 205 |
(uintmax_t)hlist->link[j].nodeinfo.id, |
| 206 |
hlist->link[j].peerhook); |
| 207 |
} |
| 186 |
} |
208 |
} |
| 187 |
free(hlresp); |
209 |
free(hlresp); |
| 188 |
} |
210 |
} |