1 /*
2  */
3 
4 #include "graph.h"
5 
6 /******************************************************************************
7 Example of output format
8 
9 
10 eq crc-cc1 cisco WS-C4506 45464748 <manual|auto>
11 iface GigaEthernet0/1
12     <radio>
13     <M123 ou ->
14     <Ether ou Trunk ou Disabled>
15     {X / L33 crc-rc1 ge-0/0/0}
16     <nativevlan ou -1>
17     <desc> {0 {} <ip> ...} {7 <vlan-desc-en-hexa> 172.16.....} ...
18 <all ifaces>
19 vlan <id> <desc> <voip>
20 
21 with <radio> = {<channel> <power> <ssid> <ssid> ...} ou {}
22 ******************************************************************************/
23 
24 #define	LB	'{'
25 #define	RB	'}'
26 
27 /******************************************************************************
28 Output routines
29 ******************************************************************************/
30 
output_eq(FILE * fp,struct eq * eq)31 void output_eq (FILE *fp, struct eq *eq)
32 {
33     fprintf (fp, "eq %s %s %s %s %s\n", eq->name, eq->type, eq->model,
34 			    (eq->location == NULL ? "-" : eq->location),
35 			    (eq->manual ? "manual" : "auto")
36 		) ;
37 }
38 
output_iface(FILE * fp,struct node * n)39 void output_iface (FILE *fp, struct node *n)
40 {
41     char *ifname ;
42     char *stat ;
43     char *type ;
44     char *desc ;
45     struct node *peer ;
46     struct linklist *ll1, *ll2, *ll3 ;
47     vlan_t native ;
48 
49     ifname = n->u.l1.ifname ;
50     stat = (n->u.l1.stat == NULL) ? "-" : n->u.l1.stat ;
51     switch (n->u.l1.l1type)
52     {
53 	case L1T_DISABLED :
54 	    type = "Disabled" ;
55 	    break ;
56 	case L1T_TRUNK :
57 	    type = "Trunk" ;
58 	    break ;
59 	case L1T_ETHER :
60 	    type = "Ether" ;
61 	    break ;
62     }
63     desc = (n->u.l1.ifdesc == NULL) ? "-" : n->u.l1.ifdesc ;
64 
65     fprintf (fp, "iface %s", ifname) ;
66 
67     /*
68      * Check radio parameters
69      */
70 
71     fprintf (fp, " %c", LB) ;
72     if (n->u.l1.radio.ssid != NULL)
73     {
74 	struct ssid *s ;
75 
76 	switch (n->u.l1.radio.channel)
77 	{
78 	    case CHAN_DFS :
79 		fprintf (fp, "dfs") ;
80 		break ;
81 	    default :
82 		fprintf (fp, "%d", n->u.l1.radio.channel) ;
83 	}
84 	fprintf (fp, " %d", n->u.l1.radio.power) ;
85 	for (s = n->u.l1.radio.ssid ; s != NULL ; s = s->next)
86 	    fprintf (fp, " %s", s->name) ;
87     }
88 
89     fprintf (fp, "%c %s %s %s", RB, stat, type, desc) ;
90 
91     peer = get_neighbour (n, NT_L1) ;
92     if (peer == NULL)
93 	fprintf (fp, " {X}") ;
94     else
95     {
96 	for (ll1 = n->linklist ; ll1 != NULL ; ll1 = ll1->next)
97 	    if (getlinkpeer (ll1->link, n) == peer)
98 		break ;
99 	if (ll1 != NULL)
100 	    fprintf (fp, " {%s %s %s}",
101 			    ll1->link->name,
102 			    peer->eq->name,
103 			    peer->u.l1.ifname) ;
104     }
105 
106     /*
107      * Search all L2 interfaces to detect native vlan if any
108      */
109 
110     native = -1 ;
111     for (ll2 = n->linklist ; ll2 != NULL ; ll2 = ll2->next)
112     {
113 	struct node *peer2 ;
114 
115 	peer2 = getlinkpeer (ll2->link, n) ;
116 	if (peer2->nodetype == NT_L2 && MK_ISSELECTED (peer2))
117 	{
118 	    if (peer2->u.l2.native)
119 		native = peer2->u.l2.vlan ;
120 	}
121     }
122     fprintf (fp, " %d", native) ;
123 
124     /*
125      * Search all L2 interfaces
126      */
127 
128     for (ll2 = n->linklist ; ll2 != NULL ; ll2 = ll2->next)
129     {
130 	struct node *peer2 ;
131 
132 	peer2 = getlinkpeer (ll2->link, n) ;
133 	if (peer2->nodetype == NT_L2 && MK_ISSELECTED (peer2))
134 	{
135 	    vlan_t vlanid ;
136 	    char *desc ;
137 	    int first ;
138 
139 	    vlanid = peer2->u.l2.vlan ;
140 	    stat = (peer2->u.l2.stat == NULL) ? "-" : peer2->u.l2.stat ;
141 	    desc = ((struct vlan *) mobj_data (vlanmobj)) [vlanid].name ;
142 	    if (desc == NULL)
143 		desc = "-" ;
144 	    fprintf (fp, " %c%d %s %s", LB, vlanid, desc, stat) ;
145 
146 	    /*
147 	     * Search all L3 interfaces
148 	     */
149 
150 	    first = 1 ;
151 	    for (ll3 = peer2->linklist ; ll3 != NULL ; ll3 = ll3->next)
152 	    {
153 		struct node *peer3 ;
154 
155 		peer3 = getlinkpeer (ll3->link, peer2) ;
156 		if (peer3->nodetype == NT_L3)
157 		{
158 		    iptext_t a ;
159 
160 		    if (ip_ntop (&peer3->u.l3.addr, a, 1))
161 		    {
162 			if (first)
163 			    fprintf (fp, " %c", LB) ;
164 			else
165 			    fprintf (fp, " ") ;
166 			fprintf (fp, "%s", a) ;
167 			first = 0 ;
168 		    }
169 		}
170 	    }
171 	    if (first == 0)
172 		fprintf (fp, "%c", RB) ;
173 
174 	    fprintf (fp, "%c", RB) ;
175 	}
176     }
177 
178     fprintf (fp, "\n") ;
179 }
180 
output_vlan(FILE * fp,vlan_t v,struct vlan * vobj,struct eq * eq)181 void output_vlan (FILE *fp, vlan_t v, struct vlan *vobj, struct eq *eq)
182 {
183     struct lvlan *lv ;
184     int found ;
185 
186     /*
187      * Is this vlan present on this equipement ?
188      */
189 
190     found = 0 ;
191     for (lv = vobj->lvlan ; lv != NULL ; lv = lv->next)
192     {
193 	if (lv->eq == eq)
194 	{
195 	    found = 1;
196 	    break ;
197 	}
198     }
199 
200     if (found)
201 	fprintf (fp, "vlan %d %s %d\n", v, vobj->name, vobj->voice) ;
202 }
203 
204 /******************************************************************************
205 Main function
206 ******************************************************************************/
207 
208 MOBJ *mobjlist [NB_MOBJ] ;
209 
usage(char * progname)210 void usage (char *progname)
211 {
212     fprintf (stderr, "Usage : %s [-a|-n cidr|-v vlan|-e regexp|-E regexp|-t|-m]* eq [iface]\n", progname) ;
213     exit (1) ;
214 }
215 
main(int argc,char * argv[])216 int main (int argc, char *argv [])
217 {
218     struct node *n ;
219     char *prog, *errstr ;
220     char *eqname, *iface ;
221     struct eq *eq ;
222     int c, err ;
223     vlan_t v ;
224     struct vlan *vlantab ;
225 
226     prog = argv [0] ;
227     err = 0 ;
228 
229     sel_init () ;
230 
231     while ((c = getopt (argc, argv, "an:e:E:tv:m")) != -1)
232     {
233 	switch (c)
234 	{
235 	    case 'a' :
236 	    case 'n' :
237 	    case 'e' :
238 	    case 'E' :
239 	    case 't' :
240 	    case 'v' :
241 	    case 'm' :
242 		if ((errstr = sel_register (c, optarg)) != NULL)
243 		{
244 		    fprintf (stderr, "%s: %s\n", prog, errstr) ;
245 		    err = 1 ;
246 		}
247 		break ;
248 	    case '?' :
249 	    default :
250 		usage (prog) ;
251 	}
252     }
253 
254     if (err)
255 	exit (1) ;
256 
257     argc -= optind ;
258     argv += optind ;
259 
260     switch (argc)
261     {
262 	case 1 :
263 	    eqname = argv [0] ;
264 	    iface = NULL ;
265 	    break ;
266 	case 2 :
267 	    eqname = argv [0] ;
268 	    iface = argv [1] ;
269 	    break ;
270 	default :
271 	    usage (prog) ;
272 	    exit (1) ;			/* to calm down clang */
273     }
274 
275     /*
276      * Read the graph
277      */
278 
279     bin_read (stdin, mobjlist) ;
280     sel_mark () ;
281 
282     /*
283      * Search selected equipement
284      */
285 
286     eq = eq_lookup (eqname) ;
287     if (eq != NULL && MK_ISSELECTED (eq))
288     {
289 	/*
290 	 * Output the final result
291 	 */
292 
293 	output_eq (stdout, eq) ;
294 
295 	for (n = mobj_head (nodemobj) ; n != NULL ; n = n->next)
296 	    if (n->eq == eq && n->nodetype == NT_L1 && MK_ISSELECTED (n))
297 		if (iface == NULL || strcmp (iface, n->u.l1.ifname) == 0)
298 		    output_iface (stdout, n) ;
299 
300 	vlantab = mobj_data (vlanmobj) ;
301 	for (v = 0 ; v < MAXVLAN ; v++)
302 	    if (vlantab [v].name != NULL && MK_ISSELECTED (&vlantab [v]))
303 		output_vlan (stdout, v, &vlantab [v], eq) ;
304     }
305 
306     sel_end () ;
307     exit (0) ;
308 }
309