1 /*
2 */
3
4 #include "graph.h"
5
6 /*
7 * Dynamic objects used only during text read
8 */
9
10 MOBJ *mobjlist [NB_MOBJ] ;
11
12 MOBJ *vlistmobj ;
13
14 /******************************************************************************
15 Small memory allocation function
16 ******************************************************************************/
17
my_malloc(size_t s)18 void *my_malloc (size_t s)
19 {
20 void *p ;
21
22 p = malloc (s) ;
23 if (p == NULL)
24 error (1, "cannot malloc") ;
25 memset (p, 0, s) ;
26
27 return p ;
28 }
29
30 /******************************************************************************
31 Check an existing node and returns a pointer to it
32 ******************************************************************************/
33
check_node(char * name,char * context)34 static struct node *check_node (char *name, char *context)
35 {
36 struct node *node ;
37
38 node = symtab_to_node (symtab_get (name)) ;
39 if (node == NULL)
40 {
41 inconsistency ("Reference to a non-existant node '%s' (context '%s')",
42 name, context) ;
43 exit (1) ;
44 }
45 return node ;
46 }
47
48
49 /******************************************************************************
50 Link management
51 ******************************************************************************/
52
create_link(char * name,char * n1,char * n2)53 struct link *create_link (char *name, char *n1, char *n2)
54 {
55 struct link *l ;
56 struct linklist *ll ;
57 char *tab [2] ;
58 int i ;
59
60 l = mobj_alloc (linkmobj, 1) ;
61
62 if (name != NULL)
63 name = symtab_to_name (symtab_get (name)) ;
64 l->name = name ;
65
66 tab [0] = n1 ;
67 tab [1] = n2 ;
68 for (i = 0 ; i < 2 ; i++)
69 {
70 l->node [i] = check_node (tab [i], "link statement") ;
71
72 ll = mobj_alloc (llistmobj, 1) ;
73 ll->link = l ;
74 ll->next = l->node [i]->linklist ;
75 l->node [i]->linklist = ll ;
76 }
77
78 return l ;
79 }
80
81 /******************************************************************************
82 Ssid management
83 ******************************************************************************/
84
create_ssid(char * name,char * mode)85 struct ssid *create_ssid (char *name, char *mode)
86 {
87 struct ssid *s ;
88
89 s = mobj_alloc (ssidmobj, 1) ;
90
91 if (name != NULL)
92 name = symtab_to_name (symtab_get (name)) ;
93 s->name = name ;
94
95 if (strcmp (mode, "open") == 0)
96 s->mode = SSID_OPEN ;
97 else if (strcmp (mode, "auth") == 0)
98 s->mode = SSID_AUTH ;
99 else
100 {
101 inconsistency ("Invalid mode '%s' for ssid '%s'", mode, name) ;
102 exit (1) ;
103 }
104
105 return s ;
106 }
107
108 /******************************************************************************
109 Attribute parsing
110 ******************************************************************************/
111
112 struct attrtab
113 {
114 char *attr ;
115 struct attrvallist *first, *last ;
116 struct attrtab *next ;
117 } ;
118
119 struct attrvallist
120 {
121 char *val ;
122 struct attrvallist *next ;
123 } ;
124
attr_init(void)125 static struct attrtab *attr_init (void)
126 {
127 return NULL ;
128 }
129
attr_close(struct attrtab * at)130 static void attr_close (struct attrtab *at)
131 {
132 while (at != NULL)
133 {
134 struct attrtab *t ;
135 struct attrvallist *av ;
136
137 t = at->next ;
138 av = at->first ;
139 while (av != NULL)
140 {
141 struct attrvallist *tv ;
142
143 tv = av->next ;
144 free (av->val) ;
145 free (av) ;
146 av = tv ;
147 }
148 free (at->attr) ;
149 free (at) ;
150 at = t ;
151 }
152 }
153
attr_get(struct attrtab * at,char * name)154 static struct attrtab *attr_get (struct attrtab *at, char *name)
155 {
156 while (at != NULL)
157 {
158 if (strcmp (at->attr, name) == 0)
159 return at ;
160 at = at->next ;
161 }
162 return NULL ;
163 }
164
attr_get_vallist(struct attrtab * at,char * name)165 static struct attrvallist *attr_get_vallist (struct attrtab *at, char *name)
166 {
167 struct attrtab *a ;
168 struct attrvallist *av ;
169
170 a = attr_get (at, name) ;
171 if (a == NULL)
172 av = NULL ;
173 else
174 av = a->first ;
175
176 return av ;
177 }
178
attr_get_val(struct attrvallist * av)179 static char *attr_get_val (struct attrvallist *av)
180 {
181 return av->val ;
182 }
183
184 /* insert a new attribute (without value) in attr list */
attr_append(struct attrtab ** hd,char * name)185 static struct attrtab *attr_append (struct attrtab **hd, char *name)
186 {
187 struct attrtab *at ;
188
189 at = my_malloc (sizeof *at) ;
190 at->attr = my_malloc (strlen (name) + 1) ;
191 strcpy (at->attr, name) ;
192 at->first = at->last = NULL ;
193 at->next = *hd ;
194 *hd = at ;
195 return at ;
196 }
197
attr_val_append(struct attrtab * at,char * val)198 static void attr_val_append (struct attrtab *at, char *val)
199 {
200 struct attrvallist *av ;
201
202 av = my_malloc (sizeof *av) ;
203 av->val = my_malloc (strlen (val) + 1) ;
204 strcpy (av->val, val) ;
205 av->next = NULL ;
206 if (at->last != NULL)
207 at->last->next = av ;
208 if (at->first == NULL)
209 at->first = av ;
210 at->last = av ;
211 }
212
213 /* nb of val for attr */
attr_get_nval(struct attrvallist * av)214 static int attr_get_nval (struct attrvallist *av)
215 {
216 int n ;
217
218 n = 0 ;
219 while (av != NULL)
220 {
221 n++ ;
222 av = av->next ;
223 }
224 return n ;
225 }
226
227
228
parse_attr(char * tab[],int ntab,struct attrtab ** hd)229 static void parse_attr (char *tab [], int ntab, struct attrtab **hd)
230 {
231 int i, j ;
232 struct attrtab *at ;
233 char val [MAXLINE], *p ;
234 static struct
235 {
236 char *name ; /* attribute name */
237 int nparam ; /* number of parameters for this attr */
238 } attrtypes [] =
239 {
240 { "type", 1, },
241 { "eq", 1, },
242 { "name", 1, },
243 { "desc", 1, },
244 { "link", 1, },
245 { "stat", 1, },
246 { "encap", 1, },
247 { "net", 1, },
248 { "vlan", 1, },
249 { "allow", 2, },
250 { "addr", 1, },
251 { "instance", 1, },
252 { "model", 1, },
253 { "snmp", 1, },
254 { "incoming", 1, },
255 { "declared", 1, },
256 { "location", 1, },
257 { "radio", 2, },
258 { "ssid", 2, },
259 { "iface", 1, },
260 { "ssidname", 1, },
261 { "mode", 1, },
262 { "native", 1, },
263 { "voice", 1, },
264 { "manual", 1, },
265 { "ipmac", 1, },
266 { "portmac", 1, },
267 { "ifname", 1, },
268 } ;
269
270
271 while (ntab > 0)
272 {
273 for (i = 0 ; i < NTAB (attrtypes) ; i++)
274 {
275 if (strcmp (tab [0], attrtypes [i].name) == 0)
276 {
277 at = attr_get (*hd, tab [0]) ;
278 if (at == NULL)
279 at = attr_append (hd, tab [0]) ;
280
281 ntab-- ; tab++ ;
282
283 if (ntab < attrtypes [i].nparam)
284 {
285 inconsistency ("Not enough values for attribute '%s'", tab [0]) ;
286 exit (1) ;
287 }
288
289 for (j = 0 ; j < attrtypes [i].nparam ; j++)
290 {
291 if (j == 0)
292 p = val ;
293 else
294 *p++ = ' ' ;
295
296 strcpy (p, tab [0]) ;
297 p += strlen (p) ;
298
299 ntab-- ; tab++ ;
300 }
301
302 attr_val_append (at, val) ;
303 break ;
304 }
305 }
306 if (i >= NTAB (attrtypes))
307 {
308 inconsistency ("Unrecognized keyword '%s'", tab [0]) ;
309 exit (1) ;
310 }
311 }
312 }
313
314 /******************************************************************************
315 Process net lists associated to L1 & L2 interfaces
316 ******************************************************************************/
317
process_netlist(struct netlist ** head,struct attrtab * attrtab)318 static void process_netlist (struct netlist **head, struct attrtab *attrtab)
319 {
320 struct attrvallist *av ;
321 struct netlist *nl ;
322
323 *head = NULL ;
324
325 av = attr_get_vallist (attrtab, "net") ;
326 while (av != NULL)
327 {
328 char *addr ;
329 struct network *n ;
330
331 addr = attr_get_val (av) ;
332 n = net_get_p (addr) ;
333
334 /*
335 * First, look for the same network in our list, just in case
336 */
337
338 for (nl = *head ; nl != NULL ; nl = nl->next)
339 if (ip_equal (&nl->net->addr, &n->addr))
340 break ;
341
342 /*
343 * If not found, insert it
344 */
345
346 if (nl == NULL)
347 {
348 nl = mobj_alloc (nlistmobj, 1) ;
349 nl->net = n ;
350 nl->next = *head ;
351 *head = nl ;
352 }
353
354 av = av->next ;
355 }
356 }
357
358 /******************************************************************************
359 Build the initial graph
360 ******************************************************************************/
361
process_L1(struct attrtab * attrtab,struct node * n)362 static void process_L1 (struct attrtab *attrtab, struct node *n)
363 {
364 char *ifname ;
365 char *ifdesc ;
366 char *link ;
367 char *encap ;
368 char *stat ;
369 struct attrvallist *avlr, *avls ;
370
371 ifname = attr_get_val (attr_get_vallist (attrtab, "name")) ;
372 n->u.l1.ifname = symtab_to_name (symtab_get (ifname)) ;
373
374 ifdesc = attr_get_val (attr_get_vallist (attrtab, "desc")) ;
375 ifdesc = symtab_to_name (symtab_get (ifdesc)) ;
376 if (strcmp (ifdesc, "-") == 0) {
377 ifdesc = NULL ;
378 }
379 n->u.l1.ifdesc = ifdesc ;
380
381 link = attr_get_val (attr_get_vallist (attrtab, "link")) ;
382 n->u.l1.link = symtab_to_name (symtab_get (link)) ;
383
384 stat = attr_get_val (attr_get_vallist (attrtab, "stat")) ;
385 stat = symtab_to_name (symtab_get (stat)) ;
386 if (strcmp (stat, "-") == 0) {
387 stat = NULL ;
388 }
389 n->u.l1.stat = stat ;
390
391 encap = attr_get_val (attr_get_vallist (attrtab, "encap")) ;
392 if (strcmp (encap, "disabled") == 0)
393 n->u.l1.l1type = L1T_DISABLED ;
394 else if (strcmp (encap, "trunk") == 0)
395 n->u.l1.l1type = L1T_TRUNK ;
396 else if (strcmp (encap, "ether") == 0)
397 n->u.l1.l1type = L1T_ETHER ;
398 else
399 {
400 inconsistency ("Invalid encap type (%s)", encap) ;
401 exit (1) ;
402 }
403
404 avlr = attr_get_vallist (attrtab, "radio") ;
405 avls = attr_get_vallist (attrtab, "ssid") ;
406 if (avlr != NULL || avls != NULL)
407 {
408 struct radio *r ;
409 char *m = NULL ;
410 char *p, *q ;
411
412 if (avlr == NULL)
413 m = "SSID parameter without radio information on %s/%s" ;
414 if (avls == NULL)
415 m = "Radio parameters without ssid on %s/%s" ;
416 if (m != NULL)
417 {
418 inconsistency (m, n->eq->name, n->u.l1.ifname) ;
419 return ;
420 }
421
422 r = &(n->u.l1.radio) ;
423
424 /* process radio parameters */
425
426 p = attr_get_val (avlr) ;
427 while (isspace (*p))
428 p++ ;
429 /* first word */
430 q = p ;
431 while (! isspace (*p) && *p != '\0')
432 p++ ;
433 if (*p == '\0')
434 {
435 inconsistency ("Too few radio parameters on %s/%s", n->eq->name, n->u.l1.ifname) ;
436 return ;
437 }
438 *p++ = '\0' ;
439 if (strcmp (q, "dfs") == 0)
440 r->channel = CHAN_DFS ;
441 else if (sscanf (q, "%d", &r->channel) != 1)
442 inconsistency ("Invalid radio channel (%s) on %s/%s", q, n->eq->name, n->u.l1.ifname) ;
443 /* second word */
444 while (isspace (*p))
445 p++ ;
446 if (sscanf (p, "%d", &r->power) != 1)
447 inconsistency ("Invalid radio power (%s) on %s/%s", p, n->eq->name, n->u.l1.ifname) ;
448
449 /* process ssid list */
450 while (avls != NULL)
451 {
452 char *ssidname, *ssidmode ;
453 struct ssid *s ;
454
455 ssidmode = ssidname = attr_get_val (avls) ;
456 while (*ssidmode != ' ' && *ssidmode != '\0')
457 ssidmode ++ ;
458 if (*ssidmode == '\0')
459 error (0, "Internal error : no mode found for ssid") ;
460 *ssidmode++ = '\0' ;
461
462 s = create_ssid (ssidname, ssidmode) ;
463 s->next = r->ssid ;
464 r->ssid = s ;
465
466 avls = avls->next ;
467 }
468 }
469 }
470
process_L2(struct attrtab * attrtab,struct node * n)471 static void process_L2 (struct attrtab *attrtab, struct node *n)
472 {
473 char *s ;
474 vlan_t vlan ;
475 char *stat ;
476 char *ifname ;
477 struct attrvallist *av ;
478
479 av = attr_get_vallist (attrtab, "native") ;
480 if (av == NULL)
481 {
482 n->u.l2.native = 0 ;
483 }
484 else
485 {
486 n->u.l2.native = atoi (attr_get_val (av)) ;
487 }
488
489 s = attr_get_val (attr_get_vallist (attrtab, "vlan")) ;
490 vlan = atoi (s) ;
491 if (vlan < 0)
492 {
493 inconsistency ("Invalid vlan-id (%s)", s) ;
494 exit (1) ;
495 }
496 n->u.l2.vlan = vlan ;
497
498 stat = attr_get_val (attr_get_vallist (attrtab, "stat")) ;
499 stat = symtab_to_name (symtab_get (stat)) ;
500 if (strcmp (stat, "-") == 0) {
501 stat = NULL ;
502 }
503 n->u.l2.stat = stat ;
504
505 ifname = attr_get_val (attr_get_vallist (attrtab, "ifname")) ;
506 ifname = symtab_to_name (symtab_get (ifname)) ;
507 if (strcmp (ifname, "-") == 0) {
508 ifname = NULL ;
509 }
510 n->u.l2.ifname = ifname ;
511
512 }
513
process_L3(struct attrtab * attrtab,struct node * n)514 static void process_L3 (struct attrtab *attrtab, struct node *n)
515 {
516 char *addr ;
517 int r ;
518
519 addr = attr_get_val (attr_get_vallist (attrtab, "addr")) ;
520 r = ip_pton (addr, &n->u.l3.addr) ;
521 if (r == 0)
522 {
523 inconsistency ("Invalid address (%s)", addr) ;
524 exit (1) ;
525 }
526 }
527
process_bridge(struct attrtab * attrtab,struct node * n)528 static void process_bridge (struct attrtab *attrtab, struct node *n)
529 {
530 /* nothing to do for bridges */
531 }
532
process_router(struct attrtab * attrtab,struct node * n)533 static void process_router (struct attrtab *attrtab, struct node *n)
534 {
535 char *instance ;
536
537 instance = attr_get_val (attr_get_vallist (attrtab, "instance")) ;
538 n->u.router.name = symtab_to_name (symtab_get (instance)) ;
539 }
540
process_L2pat(struct attrtab * attrtab,struct node * n)541 static void process_L2pat (struct attrtab *attrtab, struct node *n)
542 {
543 struct attrvallist *av ;
544 vlan_t native ;
545
546 av = attr_get_vallist (attrtab, "native") ;
547 if (av != NULL)
548 {
549 if (sscanf (attr_get_val (av), "%d", &native) != 1)
550 {
551 inconsistency ("Unrecognized native vlan (%s)", attr_get_val (av)) ;
552 exit (1) ;
553 }
554 n->u.l2pat.native = native ;
555 }
556 else
557 {
558 n->u.l2pat.native = -1 ;
559 }
560
561 av = attr_get_vallist (attrtab, "allow") ;
562 while (av != NULL)
563 {
564 vlan_t v1, v2 ;
565 struct vlanlist *vl ;
566
567 if (sscanf (attr_get_val (av), "%d %d", &v1, &v2) != 2)
568 {
569 inconsistency ("Unrecognized vlan range (%s)", attr_get_val (av)) ;
570 exit (1) ;
571 }
572
573 vl = mobj_alloc (vlistmobj, 1) ;
574 vl->min = v1 ;
575 vl->max = v2 ;
576 vl->next = n->u.l2pat.allowed ;
577 n->u.l2pat.allowed = vl ;
578
579 av = av->next ;
580 }
581 }
582
process_brpat(struct attrtab * attrtab,struct node * n)583 static void process_brpat (struct attrtab *attrtab, struct node *n)
584 {
585 /* nothing to do for bridge patterns */
586 }
587
588 struct attrcheck
589 {
590 char *attr ;
591 int minoccurr ;
592 int maxoccurr ;
593 } ;
594
check_attr(struct attrtab * attrtab,struct attrcheck ac[])595 static int check_attr (struct attrtab *attrtab, struct attrcheck ac [])
596 {
597 int i ;
598 struct attrvallist *av ;
599 int noc ;
600
601 for (i = 0 ; ac [i].attr != NULL ; i++)
602 {
603 av = attr_get_vallist (attrtab, ac [i].attr) ;
604 if (av == NULL)
605 noc = 0 ;
606 else
607 noc = attr_get_nval (av) ;
608
609 if (noc < ac [i].minoccurr || noc > ac [i].maxoccurr)
610 {
611 inconsistency ("Invalid number (%d) of '%s' values (should be in [%d..%d])",
612 noc, ac [i].attr, ac [i].minoccurr, ac [i].maxoccurr) ;
613 return 0 ;
614 }
615 }
616
617 /*
618 * XXX : we should test that every attribute mentionned for this
619 * node is in the struct attrcheck array.
620 */
621
622 return 1 ;
623 }
624
process_eq(char * tab[0],int ntab)625 static void process_eq (char *tab [0], int ntab)
626 {
627 struct eq *eq ;
628 char *eqname ;
629 char *eqtype ;
630 char *eqmodel ;
631 char *eqsnmp ;
632 char *eqlocation ;
633 int eqmanual ;
634 int eqipmac ;
635 int eqportmac ;
636 struct attrtab *attrtab ; /* head of attribute table */
637 struct attrvallist *av ;
638 static struct attrcheck eqattr [] = {
639 { "type", 1, 1},
640 { "model", 1, 1},
641 { "snmp", 1, 1},
642 { "location", 0, 1},
643 { "manual", 0, 1},
644 { "ipmac", 0, 1},
645 { "portmac", 0, 1},
646 { NULL, 0, 0}
647 } ;
648
649
650 if (ntab < 2)
651 {
652 inconsistency ("Eq declaration has not enough attributes") ;
653 exit (1) ;
654 }
655
656 eqname = tab [1] ;
657 tab += 2 ;
658 ntab -= 2 ;
659
660 /*
661 * Locate proper equipement
662 */
663
664 eq = eq_get (eqname, 0) ;
665
666 /*
667 * Parse all attributes
668 */
669
670 attrtab = attr_init () ;
671 parse_attr (tab, ntab, &attrtab) ;
672
673 if (! check_attr (attrtab, eqattr))
674 {
675 inconsistency ("Incorrect eq attribute list") ;
676 exit (1) ;
677 }
678
679 av = attr_get_vallist (attrtab, "type") ;
680 if (av != NULL)
681 eqtype = attr_get_val (av) ;
682 else
683 {
684 inconsistency ("Should not happen : 'eq %s' without type", eqname) ;
685 exit (1) ;
686 }
687
688 av = attr_get_vallist (attrtab, "model") ;
689 if (av != NULL)
690 eqmodel = attr_get_val (av) ;
691 else
692 {
693 inconsistency ("Should not happen : 'eq %s' without model", eqname) ;
694 exit (1) ;
695 }
696
697 av = attr_get_vallist (attrtab, "snmp") ;
698 if (av != NULL)
699 eqsnmp = attr_get_val (av) ;
700 else
701 {
702 inconsistency ("Should not happen : 'eq %s' without SNMP community", eqname) ;
703 exit (1) ;
704 }
705
706 av = attr_get_vallist (attrtab, "location") ;
707 if (av != NULL)
708 eqlocation = attr_get_val (av) ;
709 else
710 {
711 inconsistency ("Should not happen : 'eq %s' without location", eqname) ;
712 exit (1) ;
713 }
714
715 av = attr_get_vallist (attrtab, "manual") ;
716 eqmanual = ((av == NULL) ? 1 : atoi (attr_get_val (av))) ;
717
718 av = attr_get_vallist (attrtab, "ipmac") ;
719 eqipmac = ((av == NULL) ? 0 : atoi (attr_get_val (av))) ;
720
721 av = attr_get_vallist (attrtab, "portmac") ;
722 eqportmac = ((av == NULL) ? 0 : atoi (attr_get_val (av))) ;
723
724 eq->type = symtab_to_name (symtab_get (eqtype)) ;
725 eq->model = symtab_to_name (symtab_get (eqmodel)) ;
726 if (strcmp (eqsnmp, "-") == 0)
727 eq->snmp = NULL ;
728 else eq->snmp = symtab_to_name (symtab_get (eqsnmp)) ;
729 if (strcmp (eqlocation, "-") == 0)
730 eq->location = NULL ;
731 else eq->location = symtab_to_name (symtab_get (eqlocation)) ;
732 eq->manual = eqmanual ;
733 eq->ipmac = eqipmac ;
734 eq->portmac = eqportmac ;
735
736 attr_close (attrtab) ;
737 }
738
739
740 #define MAXKWBYTYPE 20
741
process_node(char * tab[],int ntab)742 static void process_node (char *tab [], int ntab)
743 {
744 int i ;
745 struct node *n ;
746 char *nodename ;
747 char *nodetype ;
748 struct eq *eq ;
749 struct attrtab *attrtab ; /* head of attribute table */
750 struct attrvallist *av ;
751 static struct
752 {
753 char *type ;
754 enum nodetype nodetype ;
755 void (*fct) (struct attrtab *, struct node *) ;
756 struct attrcheck attr [MAXKWBYTYPE] ;
757 } attrbytype [] =
758 {
759 { "L1" , NT_L1, process_L1, {
760 { "type", 1, 1 },
761 { "eq", 1, 1 },
762 { "name", 1, 1 },
763 { "desc", 1, 1 },
764 { "link", 1, 1 },
765 { "stat", 1, 1 },
766 { "encap", 1, 1 },
767 { "radio", 0, 1 },
768 { "ssid", 0, 1000000 },
769 { "net", 0, 1000000 },
770 { NULL, 0 },
771 },
772 },
773 { "L2" , NT_L2, process_L2, {
774 { "type", 1, 1 },
775 { "eq", 1, 1 },
776 { "vlan", 1, 1 },
777 { "stat", 1, 1 },
778 { "ifname", 1, 1 },
779 { "native", 0, 1 },
780 { NULL, 0 },
781 },
782 },
783 { "L3" , NT_L3, process_L3, {
784 { "type", 1, 1 },
785 { "eq", 1, 1 },
786 { "addr", 1, 1 },
787 { NULL, 0 },
788 },
789 },
790 { "router" , NT_ROUTER, process_router, {
791 { "type", 1, 1 },
792 { "eq", 1, 1 },
793 { "instance", 1, 1 },
794 { NULL, 0 },
795 },
796 },
797 { "bridge" , NT_BRIDGE, process_bridge, {
798 { "type", 1, 1 },
799 { "eq", 1, 1 },
800 { NULL, 0 },
801 },
802 },
803 { "L2pat" , NT_L2PAT, process_L2pat, {
804 { "type", 1, 1 },
805 { "eq", 1, 1 },
806 { "native", 0, 1 },
807 { "allow", 0, 1000000 },
808 { NULL, 0 },
809 },
810 },
811 { "brpat" , NT_BRPAT, process_brpat, {
812 { "type", 1, 1 },
813 { "eq", 1, 1 },
814 { NULL, 0 },
815 },
816 },
817 } ;
818
819
820 if (ntab < 2)
821 {
822 inconsistency ("Node has not enough attributes") ;
823 exit (1) ;
824 }
825
826 nodename = tab [1] ;
827 tab += 2 ;
828 ntab -= 2 ;
829
830 /*
831 * Parse all attributes
832 */
833
834 attrtab = attr_init () ;
835 parse_attr (tab, ntab, &attrtab) ;
836
837 av = attr_get_vallist (attrtab, "type") ;
838 if (av == NULL)
839 {
840 inconsistency ("Node '%s' has no type", nodename) ;
841 exit (1) ;
842 }
843 nodetype = attr_get_val (av) ;
844
845 /*
846 * Specific analysis given the nodetype
847 */
848
849 for (i = 0 ; i < NTAB (attrbytype) ; i++)
850 {
851 if (strcmp (nodetype, attrbytype [i].type) == 0)
852 {
853 if (! check_attr (attrtab, attrbytype [i].attr))
854 {
855 inconsistency ("Incorrect node attribute list") ;
856 exit (1) ;
857 }
858
859 eq = eq_get (attr_get_val (attr_get_vallist (attrtab, "eq")), 0) ;
860
861 n = create_node (nodename, eq, attrbytype [i].nodetype) ;
862 (*attrbytype [i].fct) (attrtab, n) ;
863 break ;
864 }
865 }
866 if (i >= NTAB (attrbytype))
867 {
868 inconsistency ("Unrecognized type '%s' for node '%s'", nodetype, nodename) ;
869 exit (1) ;
870 }
871
872 attr_close (attrtab) ;
873 }
874
process_link(char * tab[],int ntab)875 static void process_link (char *tab [], int ntab)
876 {
877 char *linkname ;
878 char *n1, *n2 ;
879 struct attrtab *attrtab ; /* head of attribute table */
880 struct attrvallist *av ;
881 static struct attrcheck linkattr [] = {
882 { "name", 0, 1},
883 { NULL, 0, 0}
884 } ;
885
886 if (ntab < 3)
887 {
888 inconsistency ("Link has not enough data") ;
889 exit (1) ;
890 }
891
892 n1 = tab [1] ;
893 n2 = tab [2] ;
894 tab += 3 ;
895 ntab -= 3 ;
896
897 /*
898 * Parse all attributes
899 */
900
901 attrtab = attr_init () ;
902 parse_attr (tab, ntab, &attrtab) ;
903
904 if (! check_attr (attrtab, linkattr))
905 {
906 inconsistency ("Incorrect link attribute list") ;
907 exit (1) ;
908 }
909
910 av = attr_get_vallist (attrtab, "name") ;
911 if (av != NULL)
912 linkname = attr_get_val (av) ;
913 else linkname = NULL ;
914
915 (void) create_link (linkname, n1, n2) ;
916 }
917
process_static_routes(char * tab[],int ntab)918 struct route *process_static_routes (char *tab [], int ntab)
919 {
920 struct route *head, *r ;
921
922 if (ntab % 2 != 0)
923 {
924 inconsistency ("Odd number of route entries") ;
925 exit (1) ;
926 }
927 head = NULL ;
928 while (ntab > 0)
929 {
930 r = mobj_alloc (routemobj, 1) ;
931
932 if (! ip_pton (tab [0], &r->net))
933 inconsistency ("Route '%s'->'%s' has a bad address", tab [0], tab [1]) ;
934 if (! ip_pton (tab [1], &r->gw))
935 inconsistency ("Route '%s'->'%s' has a bad gateway", tab [0], tab [1]) ;
936
937 r->next = head ;
938 head = r ;
939
940 tab += 2 ;
941 ntab -= 2 ;
942 }
943 return head ;
944 }
945
process_rnet(char * tab[],int ntab)946 static void process_rnet (char *tab [], int ntab)
947 {
948 struct rnet *n ;
949 struct network *net ;
950 char *vrrpaddr ;
951
952 if (ntab < 8)
953 {
954 inconsistency ("Routed network has not enough data") ;
955 exit (1) ;
956 }
957
958 MOBJ_ALLOC_INSERT (n, rnetmobj) ;
959
960 net = net_get_p (tab [1]) ;
961 if (net == NULL)
962 error (0, "Cannot find a slot for net") ;
963 n->net = net ;
964
965 n->router = check_node (tab [2], tab [1]) ;
966 n->l3 = check_node (tab [3], tab [1]) ;
967 n->l2 = check_node (tab [4], tab [1]) ;
968 n->l1 = check_node (tab [5], tab [1]) ;
969
970 vrrpaddr = tab [6] ;
971 if (strcmp (vrrpaddr, "-") == 0)
972 vrrpaddr = "0.0.0.0/0" ;
973 if (! ip_pton (vrrpaddr, &n->vrrpaddr))
974 inconsistency ("Routed network '%s' has a bad VRRP address (%s)",
975 tab [1], vrrpaddr) ;
976 n->vrrpprio = atoi (tab [7]) ;
977
978 tab += 8 ;
979 ntab -= 8 ;
980 n->routelist = process_static_routes (tab, ntab) ;
981 }
982
process_vlan(char * tab[],int ntab)983 static void process_vlan (char *tab [], int ntab)
984 {
985 int vlanid ;
986 char *id, *desc ;
987 struct attrtab *attrtab ; /* head of attribute table */
988 struct attrvallist *av ;
989 static struct attrcheck vlanattr [] = {
990 { "desc", 1, 1},
991 { "voice", 1, 1},
992 { "net", 0, 100000},
993 { NULL, 0, 0}
994 } ;
995 struct vlan *tabvlan ;
996
997 if (ntab < 2)
998 {
999 inconsistency ("Vlan declaration has not enough attributes") ;
1000 exit (1) ;
1001 }
1002
1003 tabvlan = mobj_data (vlanmobj) ;
1004 vlanid = 0 ;
1005
1006 id = tab [1] ;
1007 if (sscanf (id, "%d", &vlanid) != 1 || vlanid >= MAXVLAN)
1008 inconsistency ("Incorrect vlan-id ('%s')", id) ;
1009
1010 tab += 2 ;
1011 ntab -= 2 ;
1012
1013 /*
1014 * Parse all attributes
1015 */
1016
1017 attrtab = attr_init () ;
1018 parse_attr (tab, ntab, &attrtab) ;
1019
1020 if (! check_attr (attrtab, vlanattr))
1021 {
1022 inconsistency ("Incorrect vlan attribute list") ;
1023 exit (1) ;
1024 }
1025
1026 av = attr_get_vallist (attrtab, "desc") ;
1027 if (av != NULL)
1028 desc = symtab_to_name (symtab_get (attr_get_val (av))) ;
1029 else desc = NULL ;
1030 tabvlan [vlanid].name = desc ;
1031
1032 av = attr_get_vallist (attrtab, "voice") ;
1033 tabvlan [vlanid].voice = (av == NULL) ? 0 : atoi (attr_get_val (av)) ;
1034
1035 process_netlist (&tabvlan [vlanid].netlist, attrtab) ;
1036
1037 attr_close (attrtab) ;
1038 }
1039
process_lvlan(char * tab[],int ntab)1040 static void process_lvlan (char *tab [], int ntab)
1041 {
1042 int vlanid ;
1043 char *id, *eqname, *flag ;
1044 struct eq *eq ;
1045 struct attrtab *attrtab ; /* head of attribute table */
1046 struct attrvallist *av ;
1047 static struct attrcheck lvlanattr [] = {
1048 { "desc", 1, 1},
1049 { "incoming", 0, 1},
1050 { "declared", 0, 1},
1051 { NULL, 0, 0}
1052 } ;
1053 struct vlan *tabvlan ;
1054 struct lvlan *lv ;
1055
1056 if (ntab < 3)
1057 {
1058 inconsistency ("Lvlan declaration has not enough attributes") ;
1059 exit (1) ;
1060 }
1061
1062
1063 eqname = tab [1] ;
1064 id = tab [2] ;
1065 tab += 3 ;
1066 ntab -= 3 ;
1067
1068 /*
1069 * Locate proper equipement
1070 */
1071
1072 eq = eq_get (eqname, 0) ;
1073
1074 /*
1075 * Translate vlan id
1076 */
1077
1078 vlanid = 0 ;
1079 if (sscanf (id, "%d", &vlanid) != 1 || vlanid >= MAXVLAN)
1080 inconsistency ("Incorrect vlan-id ('%s')", id) ;
1081
1082 tabvlan = mobj_data (vlanmobj) ;
1083
1084 /*
1085 * Insert lvlan in vlan table
1086 */
1087
1088 lv = mobj_alloc (lvlanmobj, 1) ;
1089
1090 lv->next = tabvlan [vlanid].lvlan ;
1091 tabvlan [vlanid].lvlan = lv ;
1092
1093 lv->vlanid = vlanid ;
1094 lv->eq = eq ;
1095 lv->name = NULL ;
1096 lv->mark = 0 ;
1097
1098 /*
1099 * Parse all attributes
1100 */
1101
1102 attrtab = attr_init () ;
1103 parse_attr (tab, ntab, &attrtab) ;
1104
1105 if (! check_attr (attrtab, lvlanattr))
1106 {
1107 inconsistency ("Incorrect lvlan attribute list") ;
1108 exit (1) ;
1109 }
1110
1111 av = attr_get_vallist (attrtab, "desc") ;
1112 if (av != NULL)
1113 lv->name = symtab_to_name (symtab_get (attr_get_val (av))) ;
1114
1115 av = attr_get_vallist (attrtab, "incoming") ;
1116 if (av != NULL)
1117 {
1118 flag = attr_get_val (av) ;
1119 if (strcmp (flag, "yes") == 0)
1120 lv->mark |= LVLAN_INCOMING ;
1121 }
1122
1123 av = attr_get_vallist (attrtab, "declared") ;
1124 if (av != NULL)
1125 {
1126 flag = attr_get_val (av) ;
1127 if (strcmp (flag, "yes") == 0)
1128 lv->mark |= LVLAN_DECLARED ;
1129 }
1130
1131 attr_close (attrtab) ;
1132 }
1133
process_ssidprobe(char * tab[0],int ntab)1134 static void process_ssidprobe (char *tab [0], int ntab)
1135 {
1136 char *name ; /* name of probe */
1137 char *eqname ;
1138 struct eq *eq ;
1139 char *ifname ;
1140 struct node *iface ;
1141 char *ssidname ;
1142 struct ssid *ssid ;
1143 char *mode ;
1144 enum ssidprobe_mode m ;
1145 struct ssidprobe *sp ;
1146 struct attrtab *attrtab ; /* head of attribute table */
1147 struct attrvallist *av ;
1148 static struct attrcheck eqattr [] = {
1149 { "eq", 1, 1},
1150 { "iface", 1, 1},
1151 { "ssidname", 1, 1},
1152 { "mode", 1, 1},
1153 { NULL, 0, 0}
1154 } ;
1155
1156
1157 if (ntab < 2)
1158 {
1159 inconsistency ("Ssidprobe declaration has not enough attributes") ;
1160 exit (1) ;
1161 }
1162
1163 name = symtab_to_name (symtab_get (tab [1])) ;
1164 tab += 2 ;
1165 ntab -= 2 ;
1166
1167 /*
1168 * Parse all attributes
1169 */
1170
1171 attrtab = attr_init () ;
1172 parse_attr (tab, ntab, &attrtab) ;
1173
1174 if (! check_attr (attrtab, eqattr))
1175 {
1176 inconsistency ("Incorrect eq attribute list") ;
1177 exit (1) ;
1178 }
1179
1180 av = attr_get_vallist (attrtab, "eq") ;
1181 if (av != NULL)
1182 eqname = attr_get_val (av) ;
1183 else
1184 {
1185 inconsistency ("Should not happen : 'ssidprobe %s' without eq", name) ;
1186 exit (1) ;
1187 }
1188 eq = eq_get (eqname, 0) ;
1189
1190 av = attr_get_vallist (attrtab, "iface") ;
1191 if (av != NULL)
1192 ifname = attr_get_val (av) ;
1193 else
1194 {
1195 inconsistency ("Should not happen : 'ssidprobe %s' without iface", name) ;
1196 exit (1) ;
1197 }
1198 iface = symtab_to_node (symtab_get (ifname)) ;
1199 if (iface == NULL)
1200 {
1201 inconsistency ("Interface '%s' not found for ssidprobe '%s'", ifname, name) ;
1202 exit (1) ;
1203 }
1204 if (iface->eq != eq || iface->nodetype != NT_L1)
1205 {
1206 inconsistency ("Interface '%s' not found on '%s' for ssidprobe '%s'", ifname, eq->name, name) ;
1207 exit (1) ;
1208 }
1209
1210 av = attr_get_vallist (attrtab, "ssidname") ;
1211 if (av != NULL)
1212 ssidname = attr_get_val (av) ;
1213 else
1214 {
1215 inconsistency ("Should not happen : 'ssidprobe %s' without ssidname", name) ;
1216 exit (1) ;
1217 }
1218 ssidname = symtab_to_name (symtab_get (ssidname)) ;
1219 for (ssid = iface->u.l1.radio.ssid ; ssid != NULL ; ssid = ssid->next)
1220 {
1221 if (ssid->name == ssidname)
1222 break ;
1223 }
1224 if (ssid == NULL)
1225 {
1226 inconsistency ("Ssid '%s' not found for ssidprobe '%s'", ssidname, name) ;
1227 exit (1) ;
1228 }
1229
1230 av = attr_get_vallist (attrtab, "mode") ;
1231 if (av != NULL)
1232 mode = attr_get_val (av) ;
1233 else
1234 {
1235 inconsistency ("Should not happen : 'ssidprobe %s' without mode", name) ;
1236 exit (1) ;
1237 }
1238 if (strcmp (mode, "assoc") == 0)
1239 m = SSIDPROBE_ASSOC ;
1240 else if (strcmp (mode, "auth") == 0)
1241 m = SSIDPROBE_AUTH ;
1242 else
1243 {
1244 inconsistency ("Invalid mode '%s' for ssidprobe '%s'", mode, name) ;
1245 exit (1) ;
1246 }
1247
1248 /*
1249 * Object creation
1250 */
1251
1252 MOBJ_ALLOC_INSERT (sp, ssidprobemobj) ;
1253
1254 sp->name = name ;
1255 sp->eq = eq ;
1256 sp->l1 = iface ;
1257 sp->ssid = ssid ;
1258 sp->mode = m ;
1259
1260 attr_close (attrtab) ;
1261 }
1262
1263
1264
1265 /******************************************************************************
1266 The real function of this file
1267 ******************************************************************************/
1268
text_read(FILE * fpin)1269 void text_read (FILE *fpin)
1270 {
1271 char orgline [MAXLINE] ;
1272 char line [MAXLINE] ;
1273 MOBJ *args ; char **argv ;
1274 char *p ;
1275 char *tok ;
1276 int n ;
1277
1278 hashmobj = mobj_init (sizeof (struct symtab *), MOBJ_CONST) ;
1279 symtab_init () ;
1280
1281 symmobj = mobj_init (sizeof (struct symtab ), MOBJ_MALLOC) ;
1282 strmobj = mobj_init (sizeof (char ), MOBJ_MALLOC) ;
1283 nodemobj = mobj_init (sizeof (struct node ), MOBJ_MALLOC) ;
1284 linkmobj = mobj_init (sizeof (struct link ), MOBJ_MALLOC) ;
1285 llistmobj = mobj_init (sizeof (struct linklist ), MOBJ_MALLOC) ;
1286 eqmobj = mobj_init (sizeof (struct eq ), MOBJ_MALLOC) ;
1287 lvlanmobj = mobj_init (sizeof (struct lvlan ), MOBJ_MALLOC) ;
1288 netmobj = mobj_init (sizeof (struct network ), MOBJ_MALLOC) ;
1289 nlistmobj = mobj_init (sizeof (struct netlist ), MOBJ_MALLOC) ;
1290 rnetmobj = mobj_init (sizeof (struct rnet ), MOBJ_MALLOC) ;
1291 routemobj = mobj_init (sizeof (struct route ), MOBJ_MALLOC) ;
1292 vlistmobj = mobj_init (sizeof (struct vlanlist ), MOBJ_MALLOC) ;
1293 ssidmobj = mobj_init (sizeof (struct ssid ), MOBJ_MALLOC) ;
1294 ssidprobemobj = mobj_init (sizeof (struct ssidprobe), MOBJ_MALLOC) ;
1295
1296 vlanmobj = mobj_init (sizeof (struct vlan ), MOBJ_CONST) ;
1297 mobj_alloc (vlanmobj, MAXVLAN) ;
1298
1299 args = mobj_init (sizeof (char *), MOBJ_REALLOC) ;
1300
1301 lineno = 0 ;
1302 while (fgets (line, sizeof line, fpin) != NULL)
1303 {
1304 lineno++ ;
1305 strcpy (orgline, line) ; /* save a copy for later use */
1306
1307 p = strchr (line, '\n') ;
1308 if (p != NULL)
1309 *p = '\0' ;
1310
1311 p = strchr (line, '#') ; /* remove comments */
1312 if (p != NULL)
1313 *p = '\0' ;
1314
1315 /*
1316 * Very simplistic syntax analysis
1317 */
1318
1319 p = line ;
1320
1321 mobj_empty (args) ;
1322 (void) mobj_alloc (args, 1) ; /* last NULL entry */
1323
1324 n = 0 ;
1325 argv = mobj_data (args) ;
1326 argv [n] = NULL ;
1327
1328 while ((tok = strsep (&p, " \t")) != NULL)
1329 if (tok [0] != '\0')
1330 {
1331 (void) mobj_alloc (args, 1) ;
1332 argv = mobj_data (args) ;
1333 argv [n++] = tok ;
1334 argv [n] = NULL ;
1335 }
1336
1337 argv = mobj_data (args) ;
1338
1339 if (argv [0] != NULL)
1340 {
1341 if (strcmp (argv [0], "eq") == 0)
1342 process_eq (argv, n) ;
1343 else if (strcmp (argv [0], "node") == 0)
1344 process_node (argv, n) ;
1345 else if (strcmp (argv [0], "link") == 0)
1346 process_link (argv, n) ;
1347 else if (strcmp (argv [0], "rnet") == 0)
1348 process_rnet (argv, n) ;
1349 else if (strcmp (argv [0], "vlan") == 0)
1350 process_vlan (argv, n) ;
1351 else if (strcmp (argv [0], "lvlan") == 0)
1352 process_lvlan (argv, n) ;
1353 else if (strcmp (argv [0], "ssidprobe") == 0)
1354 process_ssidprobe (argv, n) ;
1355 else
1356 {
1357 inconsistency ("Unknown directive '%s'", argv [0]) ;
1358 exit (1) ;
1359 }
1360 }
1361 else
1362 ; /* ignore it */
1363 }
1364 lineno = -1 ;
1365
1366 mobj_close (args) ;
1367 }
1368