1 #include "config.h"
2
3 #include <stdlib.h>
4 #include <search.h>
5 #include <string.h>
6
7 #include "data.h"
8 #include "parser.h"
9 #include "log.h"
10
11 void *macs = NULL;
12 void *vlans = NULL;
13 void *ports = NULL;
14 void *vlan_groups = NULL;
15 void *port_groups = NULL;
16
17 char vmps_domain[VLAN_NAME_MAX+1];
18 int vmps_mode_open;
19 char vmps_fallback[VLAN_NAME_MAX+1];
20 int vmps_no_domain_req;
21
22 #ifdef HAVE_SNMP
23 char community[255];
24 #endif
25
26 /* --------------------------------------------------------------------------- */
27
xmalloc(unsigned n)28 void *xmalloc(unsigned n) {
29 void *p;
30 p = malloc(n);
31 if(p != NULL) {
32 vmps_log(DEBUG|SYSTEM, "ALLOCATE: %x : %d bytes",p,n);
33 return p;
34 }
35 vmps_log(FATAL|SYSTEM, "Insufficient memory.");
36 exit(1);
37 }
38
xfree(void * p)39 void xfree(void *p) {
40
41 if (p == NULL) return;
42 vmps_log(DEBUG|SYSTEM, "FREE: %x",p);
43 free(p);
44
45 }
46
47 /* --------------------------------------------------------------------------- */
48
compare_mac(const void * pa,const void * pb)49 int compare_mac(const void *pa, const void *pb) {
50 return memcmp( ((MAC_ENTRY *)pa)->mac, ((MAC_ENTRY *)pb)->mac, 6 );
51 }
52
print_mac(const void * nodep,const VISIT which,const int depth)53 void print_mac(const void *nodep, const VISIT which, const int depth)
54 {
55 MAC_ENTRY *m;
56 u_char x[ETH_ALEN];
57
58 switch(which)
59 {
60 case postorder:
61 case leaf:
62 m = *(MAC_ENTRY **)nodep;
63 memcpy(x, m->mac, 6);
64 #ifdef HAVE_SNMP
65 vmps_log(PARSER|DEBUG, "MAC: %02x%02x%02x%02x%02x%02x VLAN: %s SPEED: %ld DUPLEX: %d",
66 x[0], x[1], x[2], x[3], x[4], x[5], m->vlan, m->speed, m->duplex);
67 #else
68 vmps_log(PARSER|DEBUG, "MAC: %02x%02x%02x%02x%02x%02x VLAN: %s",
69 x[0], x[1], x[2], x[3], x[4], x[5], m->vlan);
70 #endif
71
72 break;
73 case preorder:
74 break;
75 case endorder:
76 break;
77 }
78 return;
79 }
80
81 #ifdef HAVE_SNMP
insert_mac(u_char * x,const char * vlan,const long speed,const int duplex)82 int insert_mac(u_char *x, const char *vlan, const long speed, const int duplex)
83 #else
84 int insert_mac(u_char *x, const char *vlan)
85 #endif
86 {
87 MAC_ENTRY *ptr;
88 MAC_ENTRY **val;
89
90 ptr=(MAC_ENTRY *)xmalloc(sizeof(MAC_ENTRY));
91 memcpy(ptr->mac, x, ETH_ALEN);
92 #ifdef HAVE_SNMP
93 ptr->speed = speed;
94 ptr->duplex = duplex;
95 #endif
96 ptr->vlan = (char *)xmalloc(strlen(vlan)+1);
97 strcpy(ptr->vlan, vlan);
98
99 if ( strcasecmp(vlan,"--NONE--") )
100 insert_vlan(vlan);
101
102 val = (MAC_ENTRY **)tsearch((void *)ptr, &macs, compare_mac);
103 if ( val == NULL ) {
104 vmps_log(SYSTEM|FATAL,"MAC insert failed.");
105 exit(1);
106 }
107
108 if ( *val != ptr ) free_mac(ptr);
109
110 return 0;
111 }
112
find_mac(u_char mac[ETH_ALEN])113 MAC_ENTRY *find_mac(u_char mac[ETH_ALEN])
114 {
115 MAC_ENTRY **mp;
116 MAC_ENTRY m;
117
118 memcpy(m.mac, mac, ETH_ALEN);
119 mp=tfind(&m,&macs,compare_mac);
120
121 if ( mp ) return (*mp); else return NULL;
122
123 }
124
discard_macs1()125 void discard_macs1()
126 {
127 MAC_ENTRY *m;
128 u_char x[ETH_ALEN];
129
130 while ( macs != NULL ) {
131 m = *(MAC_ENTRY **)macs;
132 memcpy(x, m->mac, 6);
133 vmps_log(PARSER|DEBUG, "DELETING MAC: %02x%02x%02x%02x%02x%02x VLAN: %s",
134 x[0], x[1], x[2], x[3], x[4], x[5], m->vlan);
135 tdelete(m, &macs, compare_mac);
136 xfree(m->vlan);
137 xfree(m);
138 }
139 }
140
free_mac(MAC_ENTRY * mac)141 void free_mac(MAC_ENTRY *mac)
142 {
143 if (mac == NULL) return;
144
145 xfree(mac->vlan);
146 xfree(mac);
147 }
148
drop_macs(void ** macs)149 void drop_macs(void **macs)
150 {
151 MAC_ENTRY *m;
152 u_char x[ETH_ALEN];
153
154 if ( macs == NULL ) return;
155
156 while ( *macs != NULL ) {
157 m = **(MAC_ENTRY ***) macs;
158 memcpy(x, m->mac, 6);
159 vmps_log(PARSER|DEBUG, "DELETING MAC: %02x%02x%02x%02x%02x%02x VLAN: %s",
160 x[0], x[1], x[2], x[3], x[4], x[5], m->vlan);
161 tdelete(m, macs, compare_mac);
162 free_mac(m);
163 }
164 }
165
166 /* --------------------------------------------------------------------------- */
167
compare_vlan(const void * pa,const void * pb)168 int compare_vlan(const void *pa, const void *pb) {
169 return strcmp( ((VLAN_ENTRY *)pa)->name, ((VLAN_ENTRY *)pb)->name );
170 }
171
print_vlan(const void * nodep,const VISIT which,const int depth)172 void print_vlan(const void *nodep, const VISIT which, const int depth)
173 {
174 VLAN_ENTRY *vl;
175
176 switch(which)
177 {
178 case postorder:
179 case leaf:
180 vl = *(VLAN_ENTRY **)nodep;
181 vmps_log(PARSER|DEBUG, "VLAN: %s, RESTRICTED: %d", vl->name, vl->restricted);
182 twalk(vl->ports, print_port);
183 break;
184 case preorder:
185 break;
186 case endorder:
187 break;
188 }
189 return;
190 }
191
new_vlan(const char * vlan_name)192 VLAN_ENTRY *new_vlan(const char *vlan_name)
193 {
194 VLAN_ENTRY *ptr;
195
196 ptr=(VLAN_ENTRY *)xmalloc(sizeof(VLAN_ENTRY));
197 ptr->restricted = 0;
198 ptr->name = (char *)xmalloc(strlen(vlan_name)+1);
199 strcpy(ptr->name, vlan_name);
200 ptr->ports = NULL;
201
202 return ptr;
203 }
204
insert_vlan(const char * vlan_name)205 int insert_vlan(const char *vlan_name)
206 {
207 VLAN_ENTRY *ptr;
208 VLAN_ENTRY **val;
209
210 ptr=(VLAN_ENTRY *)xmalloc(sizeof(VLAN_ENTRY));
211 ptr->restricted = 0;
212 ptr->name = (char *)xmalloc(strlen(vlan_name)+1);
213 strcpy(ptr->name, vlan_name);
214 ptr->ports = NULL;
215
216 val = (VLAN_ENTRY **)tsearch((void *)ptr, &vlans, compare_vlan);
217 if ( val == NULL ) {
218 vmps_log(SYSTEM|FATAL,"VLAN insert failed.");
219 exit(1);
220 }
221
222 if ( *val != ptr ) free_vlan(ptr);
223
224 return 0;
225 }
226
find_vlan(char * vlan)227 VLAN_ENTRY *find_vlan(char *vlan)
228 {
229 VLAN_ENTRY **vp;
230 VLAN_ENTRY v;
231
232 v.name=vlan;
233 vp=tfind(&v,&vlans,compare_vlan);
234
235 if ( vp ) return (*vp); else return NULL;
236
237 }
238
free_vlan(VLAN_ENTRY * vlan)239 void free_vlan(VLAN_ENTRY *vlan)
240 {
241 if (vlan == NULL) return;
242
243 xfree(vlan->name);
244 if (vlan->ports != NULL)
245 if ( (*(PORT_ENTRY **)vlan->ports) != NULL )
246 drop_ports(&(vlan->ports));
247 xfree(vlan);
248 }
249
drop_vlans(void ** vlans)250 void drop_vlans(void **vlans)
251 {
252 VLAN_ENTRY *v;
253
254 if ( vlans == NULL ) return;
255
256 while ( *vlans != NULL ) {
257 v = **(VLAN_ENTRY ***) vlans;
258 vmps_log(PARSER|DEBUG, "DELETING VLAN: %s, RESTRICTED: %d", v->name, v->restricted);
259 tdelete(v, vlans, compare_vlan);
260 free_vlan(v);
261 }
262 }
263
264 /* --------------------------------------------------------------------------- */
265
compare_str(const void * pa,const void * pb)266 int compare_str(const void *pa, const void *pb) {
267 return strcmp( (char *)pa, (char *)pb );
268 }
269
print_str(const void * nodep,const VISIT which,const int depth)270 void print_str(const void *nodep, const VISIT which, const int depth)
271 {
272 char *str;
273
274 switch(which) {
275
276 case postorder:
277 case leaf:
278 str = *(char **)nodep;
279 vmps_log(PARSER|DEBUG, " MEMBER: %s", str);
280 break;
281 case preorder:
282 break;
283 case endorder:
284 break;
285 }
286 return;
287 }
288
insert_string(void ** root,const char * str)289 int insert_string(void **root, const char *str)
290 {
291 char *ptr;
292 void **val;
293
294 ptr=(char *)xmalloc(strlen(str)+1);
295 strcpy(ptr, str);
296
297 val = tsearch((void *)ptr, root, compare_str);
298 if ( val == NULL ) {
299 vmps_log(SYSTEM|FATAL,"STRING insert failed.");
300 exit(1);
301 }
302
303 if ( *val != ptr ) xfree(ptr);
304
305 return 0;
306 }
307
308 /* --------------------------------------------------------------------------- */
309
compare_vlan_group_member(const void * pa,const void * pb)310 int compare_vlan_group_member(const void *pa, const void *pb) {
311 return strcmp( (char *)pa, (char *)pb );
312 }
313
314 /* --------------------------------------------------------------------------- */
315
compare_vlan_group(const void * pa,const void * pb)316 int compare_vlan_group(const void *pa, const void *pb) {
317 return strcmp( ((VLAN_GROUP_ENTRY *)pa)->name,
318 ((VLAN_GROUP_ENTRY *)pb)->name
319 );
320 }
321
print_vlan_group(const void * nodep,const VISIT which,const int depth)322 void print_vlan_group(const void *nodep, const VISIT which, const int depth)
323 {
324 VLAN_GROUP_ENTRY *vg;
325
326 switch(which) {
327 case postorder:
328 case leaf:
329 vg = *(VLAN_GROUP_ENTRY **)nodep;
330 vmps_log(PARSER|DEBUG, "VLAN GROUP: %s", vg->name);
331 twalk(vg->members, print_str);
332 break;
333 case preorder:
334 break;
335 case endorder:
336 break;
337 }
338 return;
339 }
340
insert_vlan_group(const char * vlan_group,char * member)341 int insert_vlan_group(const char *vlan_group, char *member)
342 {
343 VLAN_GROUP_ENTRY *ptr;
344 VLAN_GROUP_ENTRY **val;
345
346 ptr=(VLAN_GROUP_ENTRY *)xmalloc(sizeof(VLAN_GROUP_ENTRY));
347 ptr->name = (char *)xmalloc(strlen(vlan_group)+1);
348 strcpy(ptr->name, vlan_group);
349 ptr->members = NULL;
350
351 val = tsearch((void *)ptr, &vlan_groups, compare_vlan_group);
352 if ( val == NULL ) {
353 vmps_log(SYSTEM|FATAL,"VLAN GROUP insert failed.");
354 exit(1);
355 }
356
357 if ( *val != ptr ) free_vlan_group(ptr);
358
359 if ( member )
360 insert_string( &((*val)->members), member);
361
362 return 0;
363 }
364
find_vlan_group(char * vg_name)365 VLAN_GROUP_ENTRY *find_vlan_group(char *vg_name)
366 {
367
368 VLAN_GROUP_ENTRY **vg;
369 VLAN_GROUP_ENTRY g;
370
371 g.name=vg_name;
372 vg=tfind(&g,&vlan_groups,compare_vlan_group);
373
374 if ( vg ) return (*vg); else return NULL;
375
376 }
377
free_vlan_group(VLAN_GROUP_ENTRY * vg)378 void free_vlan_group(VLAN_GROUP_ENTRY *vg)
379 {
380 char *m;
381
382 if (vg == NULL) return;
383
384 xfree(vg->name);
385 while ( vg->members != NULL ) {
386 m = *(char **) (vg->members);
387 vmps_log(PARSER|DEBUG, " DELETING MEMBER: %s", m);
388 tdelete(m, &(vg->members), compare_str);
389 xfree(m);
390 }
391 xfree(vg);
392 }
393
drop_vlan_groups(void ** vlan_groups)394 void drop_vlan_groups(void **vlan_groups)
395 {
396 VLAN_GROUP_ENTRY *vg;
397
398 if ( vlan_groups == NULL ) return;
399
400 while ( *vlan_groups != NULL ) {
401 vg = **(VLAN_GROUP_ENTRY ***) vlan_groups;
402 vmps_log(PARSER|DEBUG, "DELETING VLAN GROUP: %s", vg->name);
403 tdelete(vg, vlan_groups, compare_vlan_group);
404 free_vlan_group(vg);
405 }
406 }
407
408 /* --------------------------------------------------------------------------- */
409
compare_port_group(const void * pa,const void * pb)410 int compare_port_group(const void *pa, const void *pb) {
411 return strcmp( ((PORT_GROUP_ENTRY *)pa)->name,
412 ((PORT_GROUP_ENTRY *)pb)->name
413 );
414 }
415
print_port_group(const void * nodep,const VISIT which,const int depth)416 void print_port_group(const void *nodep, const VISIT which, const int depth)
417 {
418 PORT_GROUP_ENTRY *pg;
419
420 switch(which) {
421 case postorder:
422 case leaf:
423 pg = *(PORT_GROUP_ENTRY **)nodep;
424 vmps_log(PARSER|DEBUG, "PORT GROUP: %s", pg->name);
425 if ( pg->defaultvlan != NULL)
426 vmps_log(PARSER|DEBUG, " defaultvlan: %s",
427 pg->defaultvlan);
428 if ( pg->fallback != NULL)
429 vmps_log(PARSER|DEBUG, " fallback: %s",
430 pg->fallback);
431 twalk(pg->members, print_port);
432 break;
433 case preorder:
434 break;
435 case endorder:
436 break;
437 }
438 return;
439 }
440
new_port_group(const char * port_group)441 PORT_GROUP_ENTRY *new_port_group(const char *port_group)
442 {
443 PORT_GROUP_ENTRY *ptr;
444
445 ptr=(PORT_GROUP_ENTRY *)xmalloc(sizeof(PORT_GROUP_ENTRY));
446 ptr->name = (char *)xmalloc(strlen(port_group)+1);
447 strcpy(ptr->name, port_group);
448 ptr->members = NULL;
449 ptr->defaultvlan = NULL;
450 ptr->fallback = NULL;
451
452 vmps_log(SYSTEM|DEBUG,"PORT GROUP alloc %s.",ptr->name);
453
454 return ptr;
455 }
456
get_port_group(const char * port_group)457 PORT_GROUP_ENTRY *get_port_group(const char *port_group)
458 {
459 PORT_GROUP_ENTRY *ptr;
460 PORT_GROUP_ENTRY **val;
461
462 ptr = new_port_group(port_group);
463
464 val = tsearch((void *)ptr, &port_groups, compare_port_group);
465 if ( val == NULL ) {
466 vmps_log(SYSTEM|FATAL,"PORT GROUP insert failed.");
467 exit(1);
468 }
469
470 if ( *val != ptr ) {
471 vmps_log(SYSTEM|DEBUG,"PORT GROUP free %s.",ptr->name);
472 xfree(ptr->name);
473 xfree(ptr);
474 }
475
476 return *val;
477 }
478
insert_port_group(const char * port_group,char * device,char * port)479 int insert_port_group(const char *port_group, char *device, char *port)
480 {
481 PORT_GROUP_ENTRY *ptr;
482
483 ptr=get_port_group(port_group);
484
485 if ( device ) {
486 PORT_ENTRY *p, *gp;
487 p = new_port(device, port);
488 insert_port( &(ptr->members), p);
489 gp = copy_port(p);
490 gp->parent=ptr;
491 insert_port( &ports, gp);
492 }
493
494 return 0;
495 }
496
insert_port_group_defaultvlan(const char * port_group,char * defaultvlan)497 int insert_port_group_defaultvlan(const char *port_group, char *defaultvlan)
498 {
499 PORT_GROUP_ENTRY *ptr;
500
501 ptr=get_port_group(port_group);
502 ptr->defaultvlan=(char *)xmalloc(strlen(defaultvlan)+1);
503 strcpy(ptr->defaultvlan, defaultvlan);
504 return insert_vlan(defaultvlan);
505 }
506
insert_port_group_fallback(const char * port_group,char * fallback)507 int insert_port_group_fallback(const char *port_group, char *fallback)
508 {
509 PORT_GROUP_ENTRY *ptr;
510
511 ptr=get_port_group(port_group);
512 ptr->fallback=(char *)xmalloc(strlen(fallback)+1);
513 strcpy(ptr->fallback, fallback);
514 return insert_vlan(fallback);
515 }
516
find_port_group(char * port_group)517 PORT_GROUP_ENTRY *find_port_group(char *port_group)
518 {
519
520 PORT_GROUP_ENTRY **pg;
521 PORT_GROUP_ENTRY g;
522
523 g.name=port_group;
524 pg=tfind(&g,&port_groups,compare_port_group);
525
526 if ( pg ) return (*pg); else return NULL;
527
528 }
529
free_port_group(PORT_GROUP_ENTRY * pg)530 void free_port_group(PORT_GROUP_ENTRY *pg)
531 {
532
533 if (pg == NULL) return;
534
535 vmps_log(SYSTEM|DEBUG, "FREE PORT GROUP: %s", pg->name);
536 xfree(pg->name);
537 if (pg->members != NULL)
538 if ( (*(PORT_ENTRY **)pg->members) != NULL )
539 drop_ports(&(pg->members));
540 if (pg->defaultvlan != NULL) xfree(pg->defaultvlan);
541 if (pg->fallback != NULL) xfree(pg->fallback);
542 xfree(pg);
543 }
544
drop_port_groups(void ** port_groups)545 void drop_port_groups(void **port_groups)
546 {
547 PORT_GROUP_ENTRY *pg;
548
549 if ( port_groups == NULL ) return;
550
551 while ( *port_groups != NULL ) {
552 pg = **(PORT_GROUP_ENTRY ***) port_groups;
553 vmps_log(PARSER|DEBUG, "DELETING PORT GROUP: %s", pg->name);
554 tdelete(pg, port_groups, compare_port_group);
555 free_port_group(pg);
556 }
557 drop_ports(&ports);
558 }
559
560 /* --------------------------------------------------------------------------- */
561
compare_port(const void * pa,const void * pb)562 int compare_port(const void *pa, const void *pb) {
563
564 int ret;
565 ret = memcmp( (void *) &((PORT_ENTRY *)pa)->device,
566 (void *) &((PORT_ENTRY *)pb)->device,
567 sizeof(struct in_addr)
568 );
569
570 if ( !ret ) {
571 ret = strcmp( ((PORT_ENTRY *)pa)->name,
572 ((PORT_ENTRY *)pb)->name
573 );
574 }
575 return ret;
576 }
577
print_port(const void * nodep,const VISIT which,const int depth)578 void print_port(const void *nodep, const VISIT which, const int depth)
579 {
580 PORT_ENTRY *p;
581
582 switch(which)
583 {
584 case postorder:
585 case leaf:
586 p = *(PORT_ENTRY **)nodep;
587 vmps_log(PARSER|DEBUG, " DEVICE: %s PORT: %s", inet_ntoa(p->device), p->name);
588 if (p->parent != NULL)
589 vmps_log(PARSER|DEBUG, " parent: %s",
590 p->parent->name);
591 break;
592 case preorder:
593 break;
594 case endorder:
595 break;
596 }
597 return;
598 }
599
new_port(char * device,const char * port)600 PORT_ENTRY *new_port(char *device, const char *port)
601 {
602 PORT_ENTRY *ptr;
603
604 ptr=(PORT_ENTRY *)xmalloc(sizeof(PORT_ENTRY));
605 ptr->parent = NULL;
606
607 if ( !inet_aton(device, &(ptr->device)) ) {
608 parse_error(device);
609 exit(1);
610 }
611
612 ptr->name = (char *)xmalloc(strlen(port)+1);
613 strcpy(ptr->name, port);
614
615 return ptr;
616 }
617
copy_port(PORT_ENTRY * port)618 PORT_ENTRY *copy_port(PORT_ENTRY *port)
619 {
620 PORT_ENTRY *ptr;
621
622 if ( port == NULL ) return NULL;
623
624 ptr=(PORT_ENTRY *)xmalloc(sizeof(PORT_ENTRY));
625
626 memcpy((void *)ptr,(void *)port,sizeof(*port));
627 ptr->name = (char *)xmalloc(strlen(port->name)+1);
628 strcpy(ptr->name, port->name);
629 ptr->parent = NULL;
630
631 return ptr;
632 }
633
insert_port(void ** root,PORT_ENTRY * port)634 int insert_port(void **root, PORT_ENTRY *port)
635 {
636 PORT_ENTRY **val;
637
638 val = (PORT_ENTRY **) tsearch( (void *)port, root, compare_port);
639 if ( val == NULL ) {
640 vmps_log(SYSTEM|FATAL,"PORT insert failed.");
641 exit(1);
642 }
643
644 if ( *val != port ) free_port(port);
645
646 return 0;
647 }
648
find_port(PORT_ENTRY ** root,struct in_addr device,char * port_name)649 PORT_ENTRY *find_port(PORT_ENTRY **root, struct in_addr device, char *port_name)
650 {
651 PORT_ENTRY **pp;
652 PORT_ENTRY p;
653
654 if ( root == NULL ) root = (PORT_ENTRY **)&ports;
655
656 p.name = port_name;
657 memcpy((void *)&p.device, (void *)&device, sizeof(device));
658
659 pp=tfind(&p,(void **)root,compare_port);
660 if ( pp ) return (*pp);
661
662 p.name = "--ALL--";
663 pp=tfind(&p,(void **)root,compare_port);
664 if ( pp ) return ( *pp); else return NULL;
665
666 }
667
free_port(PORT_ENTRY * port)668 void free_port(PORT_ENTRY *port)
669 {
670 if (port == NULL) return;
671
672 xfree(port->name);
673 xfree(port);
674 }
675
drop_ports(void ** ports)676 void drop_ports(void **ports)
677 {
678 PORT_ENTRY *p;
679
680 if ( ports == NULL ) return;
681
682 while ( *ports != NULL ) {
683 p = **(PORT_ENTRY ***) ports;
684 vmps_log(PARSER|DEBUG, " DELETING PORT: DEVICE: %s PORT: %s", inet_ntoa(p->device), p->name);
685 tdelete(p, ports, compare_port);
686 free_port(p);
687 }
688 }
689
690 /* --------------------------------------------------------------------------- */
drop_data()691 void drop_data()
692 {
693
694 drop_macs(&macs);
695 drop_vlans(&vlans);
696 drop_vlan_groups(&vlan_groups);
697 drop_port_groups(&port_groups);
698
699 }
700
701