]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pim6sd/cfparse.y
This commit was generated by cvs2svn to compensate for changes in r75937,
[FreeBSD/FreeBSD.git] / usr.sbin / pim6sd / cfparse.y
1 /*
2  * Copyright (C) 1999 WIDE Project.
3  * All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  * 
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 %{
32 #include <sys/types.h>
33
34 #include <netinet/in.h>
35
36 #include <arpa/inet.h>
37
38 #include <string.h>
39 #include <syslog.h>
40
41 #include "defs.h"
42 #include "rp.h"
43 #include "vif.h"
44
45 #include "var.h"
46 #include "vmbuf.h"
47 #include "cfparse.h"
48 #include "debug.h"
49 #include "pimd.h"
50 #include "timer.h"
51 #include "inet6.h"
52
53 #define set_param(var,val,p) \
54         do {\
55                 if ((var) != -1) {\
56                         yywarn("%s doubly defined(ignore %d)", (p), (val));\
57                 }\
58                 else {\
59                         (var) = val;\
60                 }\
61         } while(0)
62
63 struct in6_prefix {
64         struct in6_addr paddr;
65         int plen;
66 };
67
68 struct attr_list {
69         struct attr_list *next;
70         int type;
71         union {
72                 unsigned int flags;
73                 double number;
74                 struct in6_prefix prefix;
75         }attru;
76 };
77
78 enum {IFA_FLAG, IFA_PREFERENCE, IFA_METRIC, RPA_PRIORITY, RPA_TIME,
79       BSRA_PRIORITY, BSRA_TIME, BSRA_MASKLEN, IN6_PREFIX, THRESA_RATE,
80       THRESA_INTERVAL};
81
82 static int strict;              /* flag if the grammer check is strict */
83 static struct attr_list *rp_attr, *bsr_attr, *grp_prefix, *regthres_attr,
84         *datathres_attr;
85 static char *cand_rp_ifname, *cand_bsr_ifname;
86 static int srcmetric, srcpref, helloperiod, jpperiod, granularity,
87         datatimo, regsuptimo, probetime, asserttimo;
88 static double helloperiod_coef, jpperiod_coef;
89
90 static int debugonly;
91
92 extern int yylex __P((void));
93 %}
94
95 %union {
96         unsigned long num;
97         double fl;
98         vchar_t val;
99         struct attr_list *attr;
100 }
101
102 %token EOS
103 %token LOGGING LOGLEV NOLOGLEV
104 %token YES NO
105 %token REVERSELOOKUP
106 %token PHYINT IFNAME DISABLE PREFERENCE METRIC NOLISTENER
107 %token GRPPFX
108 %token CANDRP CANDBSR TIME PRIORITY MASKLEN
109 %token NUMBER STRING SLASH
110 %token REGTHRES DATATHRES RATE INTERVAL
111 %token SRCMETRIC SRCPREF HELLOPERIOD GRANULARITY JPPERIOD
112 %token DATATIME REGSUPTIME PROBETIME ASSERTTIME
113
114 %type <num> LOGLEV NOLOGLEV
115 %type <fl> NUMBER
116 %type <val> STRING IFNAME
117 %type <attr> if_attributes rp_substatement rp_attributes
118 %type <attr> bsr_substatement bsr_attributes thres_attributes
119
120 %%
121 statements:
122                 /* empty */
123         |       statements statement
124         ;
125
126 statement:
127                 logging_statement
128         |       reverselookup_statement
129         |       phyint_statement
130         |       candrp_statement
131         |       candbsr_statement
132         |       grppfx_statement
133         |       regthres_statement
134         |       datathres_statement
135         |       param_statement
136         ;
137
138 /* logging */
139 logging_statement:
140         LOGGING log_specs EOS
141         ;
142
143 log_specs:
144                 /* empty */
145         |       log_specs LOGLEV {debug |= $2;}
146         |       log_specs NOLOGLEV {debug &= ~($2);}
147         ;
148
149 /* reverselookup */
150 reverselookup_statement:
151                 REVERSELOOKUP YES EOS { numerichost = FALSE; }
152         |       REVERSELOOKUP NO EOS { numerichost = TRUE; }
153         ;
154
155 /* phyint */
156 phyint_statement:
157         PHYINT IFNAME if_attributes EOS {
158                 struct uvif *v;
159
160                 v = find_vif($2.v);
161                 free($2.v);     /* XXX */
162                 if (v == NULL) {
163                         yywarn("unknown interface: %s", $2.v);
164                         free_attr_list($3);
165                         if (strict)
166                                 return(-1);
167                 }
168                 else {
169                         struct attr_list *p;
170
171                         for (p = (struct attr_list *)v->config_attr;
172                              p && p->next; p = p->next)
173                                 ;
174                         if (p)
175                                 p->next = (void *)$3;
176                         else
177                                 v->config_attr = (void *)$3;
178                 }
179         }
180         ;
181
182 if_attributes:
183                 { $$ = NULL; }
184         |       if_attributes DISABLE
185                 {
186                         if (($$ = add_attribute_flag($1, IFA_FLAG,
187                                                      VIFF_DISABLED)) == NULL)
188                                 return(-1);
189                 }
190         |       if_attributes NOLISTENER
191                 {
192                         if (($$ = add_attribute_flag($1, IFA_FLAG,
193                                                      VIFF_NOLISTENER)) == NULL)
194                                 return(-1);
195                 }
196         |       if_attributes PREFERENCE NUMBER
197                 {
198                         if (($$ = add_attribute_num($1, IFA_PREFERENCE, $3))
199                             == NULL)
200                                 return(-1);
201                 }
202         |       if_attributes METRIC NUMBER
203                 {
204                         if (($$ = add_attribute_num($1, IFA_METRIC, $3))
205                             == NULL)
206                                 return(-1);
207                 }
208         ;
209
210 /* cand_rp */
211 candrp_statement:
212         CANDRP rp_substatement EOS {
213                 if (cand_rp_flag == TRUE) {
214                         yywarn("cand_rp doubly defined");
215                         free_attr_list($2);
216                         if (strict)
217                                 return(-1);
218                 }
219                 else {
220                         cand_rp_flag = TRUE;
221                         rp_attr = $2;
222                 }
223         }
224         ;
225 /* XXX: intermediate rule to avoid shift-reduce conflict */
226 rp_substatement:
227                 IFNAME rp_attributes
228                 {
229                         if (cand_rp_ifname) {
230                                 yywarn("ifname for cand_rp doubly defined");
231                                 if (strict)
232                                         return(-1);
233                         }
234                         else
235                                 cand_rp_ifname = $1.v;
236                         $$ = $2;
237                 }
238         |       rp_attributes
239         ;
240 rp_attributes:
241                 { $$ = NULL; }
242         |       rp_attributes PRIORITY NUMBER
243                 {
244                         if (($$ = add_attribute_num($1, RPA_PRIORITY, $3))
245                             == NULL)
246                                 return(-1);
247                 }
248         |       rp_attributes TIME NUMBER
249                 {
250                         if (($$ = add_attribute_num($1, RPA_TIME, $3))
251                             == NULL)
252                                 return(-1);
253                 }
254         ;
255
256 /* cand_bootstrap_router */
257 candbsr_statement:
258         CANDBSR bsr_substatement  EOS {
259                 if (cand_bsr_flag == TRUE) {
260                         yywarn("cand_bsr doubly defined");
261                         free_attr_list($2);
262                         if (strict)
263                                 return(-1);
264                 }
265                 else {
266                         cand_bsr_flag = TRUE;
267                         bsr_attr = $2;
268                 }
269         }
270         ;
271 /* XXX: intermediate rule to avoid shift-reduce conflict */
272 bsr_substatement:
273                 IFNAME bsr_attributes
274                 {
275                         if (cand_bsr_ifname) {
276                                 yywarn("ifname for cand_bsr doubly defined");
277                                 if (strict)
278                                         return(-1);
279                         }
280                         else
281                                 cand_bsr_ifname = $1.v;
282                         $$ = $2;
283                 }
284         |       bsr_attributes
285         ;
286
287 bsr_attributes:
288                 { $$ = NULL; }
289         |       bsr_attributes PRIORITY NUMBER
290                 {
291                         if (($$ = add_attribute_num($1, BSRA_PRIORITY, $3))
292                             == NULL)
293                                 return(-1);
294                 }
295         |       bsr_attributes TIME NUMBER
296                 {
297                         if (($$ = add_attribute_num($1, BSRA_TIME, $3))
298                             == NULL)
299                                 return(-1);
300                 }
301         |       bsr_attributes MASKLEN NUMBER
302                 {
303                         int masklen = $3;
304
305                         if (masklen < 0 || masklen > 128)
306                                 yywarn("invalid mask length: %d (ignored)",
307                                        masklen);
308                         else if (($$ = add_attribute_num($1, BSRA_MASKLEN,
309                                                          masklen))
310                                  == NULL)
311                                 return(-1);
312                 }
313         ;
314
315 /* group_prefix <group-addr>/<prefix_len> */
316 grppfx_statement:
317         GRPPFX STRING SLASH NUMBER EOS {
318                 struct in6_prefix prefix;
319                 int prefixok = 1;
320
321                 if (inet_pton(AF_INET6, $2.v, &prefix.paddr) != 1) {
322                         yywarn("invalid IPv6 address: %s (ignored)", $2);
323                         prefixok = 0;
324                 }
325                 free($2.v);     /* XXX: which was allocated dynamically */
326
327                 prefix.plen = $4;
328                 if (prefix.plen < 0 || prefix.plen > 128) {
329                         yywarn("invalid prefix length: %d (ignored)",
330                                prefix.plen);
331                         prefixok = 0;
332                 }
333                 if (IN6_IS_ADDR_MC_NODELOCAL(&prefix.paddr) ||
334                     IN6_IS_ADDR_MC_LINKLOCAL(&prefix.paddr)) {
335                         yywarn("group prefix (%s/%d) has a narrow scope "
336                                "(ignored)",
337                                inet6_fmt(&prefix.paddr), prefix.plen);
338                         prefixok = 0;
339                 }
340
341                 if (prefixok) {
342                         struct attr_list *new;
343
344                         if ((new = malloc(sizeof(*new))) == NULL) {
345                                 yyerror("malloc failed");
346                                 return(NULL);
347                         }
348                         memset(new, 0, sizeof(*new));
349
350                         new->type = IN6_PREFIX;
351                         new->attru.prefix = prefix;
352                         new->next = grp_prefix;
353  
354                         grp_prefix = new;
355                 }
356         }
357         ;
358
359 /*
360  * switch_register_threshold [rate <number> interval <number>]
361  * Operation: reads and assigns the switch to the spt threshold
362  * due to registers for the router, if used as RP.
363  * Maybe extended to support different thresholds for different
364  * groups(prefixes).
365  */
366 regthres_statement:
367         REGTHRES thres_attributes EOS {
368                 if (regthres_attr) {
369                         yywarn("switch_register_threshold doubly defined");
370                         free_attr_list($2);
371                         if (strict)
372                                 return(-1);
373                 }
374                 else
375                         regthres_attr = $2;
376         }
377         ;
378
379 thres_attributes:
380                 { $$ = NULL; }
381         |       thres_attributes RATE NUMBER
382                 {
383                         if (($$ = add_attribute_num($1, THRESA_RATE, $3))
384                             == NULL)
385                                 return(-1);
386                 }
387         |       thres_attributes INTERVAL NUMBER
388                 {
389                         if (($$ = add_attribute_num($1, THRESA_INTERVAL, $3))
390                             == NULL)
391                                 return(-1);
392                 }
393
394 /*  
395  * switch_data_threshold [rate <number> interval <number>]
396  * Operation: reads and assigns the switch to the spt threshold due to
397  * data packets, if used as DR.
398  */
399 datathres_statement:
400         DATATHRES thres_attributes EOS {
401                 if (datathres_attr) {
402                         yywarn("switch_data_threshold doubly defined");
403                         free_attr_list($2);
404                         if (strict)
405                                 return(-1);
406                 }
407                 else
408                         datathres_attr = $2;
409         }
410         ;
411
412 param_statement:
413                 SRCMETRIC NUMBER EOS
414                 {
415                         set_param(srcmetric, $2, "default_source_metric");
416                 }
417         |       SRCPREF NUMBER EOS
418                 {
419                         set_param(srcpref, $2, "default_source_preference");
420                 }
421         |       HELLOPERIOD NUMBER EOS
422                 {
423                         set_param(helloperiod, $2, "hello_period");
424                 }
425         |       HELLOPERIOD NUMBER NUMBER EOS
426                 {
427                         set_param(helloperiod, $2, "hello_period");
428                         set_param(helloperiod_coef, $3, "hello_period(coef)");
429                 }
430         |       JPPERIOD NUMBER EOS
431                 {
432                         set_param(jpperiod, $2, "join_prune_period");
433                 }
434         |       JPPERIOD NUMBER NUMBER EOS
435                 {
436                         set_param(jpperiod, $2, "join_prune_period");
437                         set_param(jpperiod_coef, $3, "join_prune_period(coef)");
438                 }
439         |       GRANULARITY NUMBER EOS
440                 {
441                         set_param(granularity, $2, "granularity");
442                 }
443         |       DATATIME NUMBER EOS
444                 {
445                         set_param(datatimo, $2, "data_timeout");
446                 }
447         |       REGSUPTIME NUMBER EOS
448                 {
449                         set_param(regsuptimo, $2, "register_suppression_timeout");
450                 }
451         |       PROBETIME NUMBER EOS
452                 {
453                         set_param(probetime, $2, "probe_time");
454                 }
455         |       ASSERTTIME NUMBER EOS
456                 {
457                         set_param(asserttimo, $2, "assert_timeout");
458                 }
459         ;
460 %%
461
462 static struct attr_list *add_attribute_flag __P((struct attr_list *, int,
463         unsigned int));
464 static struct attr_list *add_attribute_num __P((struct attr_list *, int,
465         double));
466 static void free_attr_list __P((struct attr_list *));
467 static int param_config __P((void));
468 static int phyint_config __P((void));
469 static int rp_config __P((void));
470 static int bsr_config __P((void));
471 static int grp_prefix_config __P((void));
472 static int regthres_config __P((void));
473 static int datathres_config __P((void));
474
475 static struct attr_list *
476 add_attribute_flag(list, type, flag)
477         struct attr_list *list;
478         int type;
479         unsigned int flag;
480 {
481         struct attr_list *p;
482         
483         if ((p = malloc(sizeof(*p))) == NULL) {
484                 yyerror("malloc failed");
485                 return(NULL);
486         }
487         memset((void *)p, 0, sizeof(*p));
488         p->type = type;
489         p->attru.flags = flag;
490         p->next = list;
491
492         return(p);
493 }
494
495 /* XXX: too many dup code... */
496 static struct attr_list *
497 add_attribute_num(list, type, num)
498         struct attr_list *list;
499         int type;
500         double num;
501 {
502         struct attr_list *p;
503         
504         if ((p = malloc(sizeof(*p))) == NULL) {
505                 yyerror("malloc failed");
506                 return(NULL);
507         }
508         memset((void *)p, 0, sizeof(*p));
509         p->type = type;
510         p->attru.number = num;
511         p->next = list;
512
513         return(p);
514 }
515
516 static void
517 free_attr_list(list)
518         struct attr_list *list;
519 {
520         struct attr_list *p, *next;
521
522         for(p = list; p; p = next) {
523                 next = p->next;
524                 free(p);
525         }
526 }
527
528 static int
529 param_config()
530 {
531         struct uvif *v;
532         vifi_t vifi;
533
534         /* at first, set the default values to all the undefined variables */
535         if (srcmetric == -1) srcmetric = DEFAULT_LOCAL_METRIC;
536         if (srcpref == -1) srcpref = DEFAULT_LOCAL_PREF;
537         if (helloperiod == -1) helloperiod = PIM_TIMER_HELLO_PERIOD;
538         if (helloperiod_coef == -1) helloperiod_coef = 3.5;
539         if (jpperiod == -1) jpperiod = PIM_JOIN_PRUNE_PERIOD;
540         if (jpperiod_coef == -1) jpperiod_coef = 3.5;
541         if (granularity == -1) granularity = DEFAULT_TIMER_INTERVAL;
542         if (datatimo == -1) datatimo = PIM_DATA_TIMEOUT;
543         if (regsuptimo == -1) regsuptimo = PIM_REGISTER_SUPPRESSION_TIMEOUT;
544         if (probetime == -1) probetime = PIM_REGISTER_PROBE_TIME;
545         if (asserttimo == -1) asserttimo = PIM_ASSERT_TIMEOUT;
546
547         /* set protocol parameters using the configuration variables */
548         for (vifi = 0, v = uvifs; vifi < MAXVIFS; ++vifi, ++v) {
549                 v->uv_local_metric = srcmetric;
550                 v->uv_local_pref = srcpref;
551         }
552         pim_hello_period = helloperiod;
553         pim_hello_holdtime = helloperiod * helloperiod_coef;
554         pim_join_prune_period = jpperiod;
555         pim_join_prune_holdtime = jpperiod * jpperiod_coef;
556         timer_interval = granularity;
557         pim_data_timeout = datatimo;
558         pim_register_suppression_timeout = regsuptimo;
559         pim_register_probe_time = probetime;
560         pim_assert_timeout = asserttimo;
561
562         IF_DEBUG(DEBUG_PIM_HELLO) {
563                 log(LOG_DEBUG, 0, "pim_hello_period set to: %u",
564                     pim_hello_period);
565                 log(LOG_DEBUG, 0, "pim_hello_holdtime set to: %u",
566                     pim_hello_holdtime);
567         }
568
569         IF_DEBUG(DEBUG_PIM_JOIN_PRUNE) {
570                 log(LOG_DEBUG,0 , "pim_join_prune_period set to: %u",
571                     pim_join_prune_period);
572                 log(LOG_DEBUG, 0, "pim_join_prune_holdtime set to: %u",
573                     pim_join_prune_holdtime);
574         }
575         IF_DEBUG(DEBUG_TIMER) {
576                 log(LOG_DEBUG,0 , "timer interval set to: %u", timer_interval);
577         }
578         IF_DEBUG(DEBUG_PIM_TIMER) {
579                 log(LOG_DEBUG,0 , "PIM data timeout set to: %u",
580                     pim_data_timeout);
581         }
582         IF_DEBUG(DEBUG_PIM_REGISTER) {
583                 log(LOG_DEBUG, 0,
584                     "PIM register suppression timeout set to: %u",
585                     pim_register_suppression_timeout);
586                 log(LOG_DEBUG, 0, "PIM register probe time set to: %u",
587                     pim_register_probe_time);
588         }
589         IF_DEBUG(DEBUG_PIM_ASSERT) {
590                 log(LOG_DEBUG, 0,
591                     "PIM assert timeout set to: %u",
592                     pim_assert_timeout);
593         }
594         return(0);
595 }
596
597 static int
598 phyint_config()
599 {
600         struct uvif *v;
601         vifi_t vifi;
602         struct attr_list *al;
603         
604         for (vifi = 0, v = uvifs; vifi < numvifs ; ++vifi , ++v) {
605                 for (al = (struct attr_list *)v->config_attr; al; al = al->next) {
606                         switch(al->type) {
607                         case IFA_FLAG:
608                                 v->uv_flags |= al->attru.flags;
609                                 break;
610                         case IFA_PREFERENCE:
611                                 if (al->attru.number < 1 ||
612                                     al->attru.number > 255)
613                                         yywarn("invalid phyint preference(%d)",
614                                                (int)al->attru.number);
615                                 else {
616                                         v->uv_local_pref = al->attru.number;
617                                         IF_DEBUG(DEBUG_ASSERT)
618                                                 log(LOG_DEBUG, 0,
619                                                     "default localpref for %s "
620                                                     "is %d",
621                                                     v->uv_name,
622                                                     v->uv_local_pref);
623                                 }
624                                 break;
625                         case IFA_METRIC:
626                                 if (al->attru.number < 1 ||
627                                     al->attru.number > 1024)
628                                         yywarn("invalid metric(%d)",
629                                                al->attru.number);
630                                 else {
631                                         v->uv_metric = al->attru.number;
632                                         IF_DEBUG(DEBUG_ASSERT)
633                                                 log(LOG_DEBUG, 0,
634                                                     "default local metric for %s "
635                                                     "is %d",
636                                                     v->uv_name,
637                                                     v->uv_metric);
638                                 }
639                                 break;
640                         }
641                 }
642         }
643
644         return(0);
645 }
646
647 static int
648 rp_config()
649 {
650         struct sockaddr_in6 *sa6_rp = NULL;
651         struct attr_list *al;
652         u_int8 *data_ptr;
653
654         /* initialization by default values */
655         my_cand_rp_adv_period = PIM_DEFAULT_CAND_RP_ADV_PERIOD;
656         my_cand_rp_priority = PIM_DEFAULT_CAND_RP_PRIORITY;
657
658         if (cand_rp_ifname) {
659                 sa6_rp = local_iface(cand_rp_ifname);
660                 if (!sa6_rp)
661                         log(LOG_WARNING, 0,
662                             "cand_rp '%s' is not configured. "
663                             "take the max local address the router..",
664                             cand_rp_ifname);
665         }
666
667         for (al = rp_attr; al; al = al->next) {
668                 switch(al->type) {
669                 case RPA_PRIORITY:
670                         if (al->attru.number < 0)
671                                 my_cand_rp_priority =
672                                         PIM_DEFAULT_CAND_RP_PRIORITY;
673                         else
674                                 my_cand_rp_priority = al->attru.number;
675                         break;
676                 case RPA_TIME:
677                         if (al->attru.number < 10)
678                                 my_cand_rp_adv_period = 10;
679                         else if (al->attru.number > PIM_DEFAULT_CAND_RP_ADV_PERIOD)
680                                 my_cand_rp_adv_period =
681                                         PIM_DEFAULT_CAND_RP_ADV_PERIOD;
682                         else
683                                 my_cand_rp_adv_period = al->attru.number;
684                         break;
685                 default:
686                         yywarn("unknown attribute(%d) for RP", al->type);
687                         break;
688                 }
689         }
690
691         if (!sa6_rp)
692                 sa6_rp = max_global_address(); /* this MUST suceed */
693         my_cand_rp_address = *sa6_rp;
694
695         /*
696          * initialize related parameters
697          */
698
699         /*
700          * Note that sizeof(pim6_enocd_uni_addr_t) might be larger than
701          * the length of the Encoded-Unicast-address field(18 byte) due to
702          * some padding put in the compiler. However, it doesn't matter
703          * since we use the space just as a buffer(i.e not as the message).
704          */
705         cand_rp_adv_message.buffer = (u_int8 *)malloc(4 +
706                                                       sizeof(pim6_encod_uni_addr_t) +
707                                                       255*sizeof(pim6_encod_grp_addr_t));
708         if(cand_rp_adv_message.buffer == NULL)
709                 log(LOG_ERR, 0, "Candrpadv Buffer allocation");
710
711         cand_rp_adv_message.prefix_cnt_ptr = cand_rp_adv_message.buffer;
712
713         /*
714          * By default, if no group_prefix configured, then prefix_cnt == 0
715          * implies group_prefix = ff00::/8 and masklen = 8.
716          */
717         *cand_rp_adv_message.prefix_cnt_ptr = 0;
718         cand_rp_adv_message.insert_data_ptr = cand_rp_adv_message.buffer;
719
720         /* TODO: XXX: HARDCODING!!! */
721         cand_rp_adv_message.insert_data_ptr += (4 + 18);
722         cand_rp_adv_message.message_size =
723                 cand_rp_adv_message.insert_data_ptr - cand_rp_adv_message.buffer;
724
725         my_cand_rp_holdtime = 2.5 * my_cand_rp_adv_period;
726
727         /* TODO: HARDCODING! */
728         data_ptr = cand_rp_adv_message.buffer + 1;      /* WARNING */
729         PUT_BYTE(my_cand_rp_priority,data_ptr);
730         PUT_HOSTSHORT(my_cand_rp_holdtime, data_ptr);
731         PUT_EUADDR6(my_cand_rp_address.sin6_addr,data_ptr);
732         IF_DEBUG(DEBUG_PIM_CAND_RP) {
733                 log(LOG_DEBUG, 0,
734                     "Local Cand-RP address is : %s",
735                     inet6_fmt(&my_cand_rp_address.sin6_addr));
736                 log(LOG_DEBUG, 0,
737                     "Local Cand-RP priority is : %u",my_cand_rp_priority);
738                 log(LOG_DEBUG, 0,
739                     "Local Cand-RP advertisement period is : %u sec.",
740                     my_cand_rp_adv_period);
741         }
742
743         return(0);
744 }
745
746 static int
747 bsr_config()
748 {
749         struct sockaddr_in6 *sa6_bsr = NULL;
750         struct attr_list *al;
751         int my_bsr_hash_masklen;
752
753         /* initialization by default values */
754         my_bsr_period = PIM_DEFAULT_BOOTSTRAP_PERIOD;
755         my_bsr_priority = PIM_DEFAULT_BSR_PRIORITY;
756         my_bsr_hash_masklen = RP_DEFAULT_IPV6_HASHMASKLEN;
757
758         if (cand_bsr_ifname) {
759                 sa6_bsr = local_iface(cand_bsr_ifname);
760                 if (!sa6_bsr)
761                         log(LOG_WARNING, 0,
762                             "bsr '%s' is not configured. "
763                             "take the max local address the router..",
764                             cand_bsr_ifname);
765         }
766
767         for (al = bsr_attr; al; al = al->next) {
768                 switch(al->type) {
769                 case BSRA_PRIORITY:
770                         if (al->attru.number >= 0)
771                                 my_bsr_priority = al->attru.number;
772                         break;
773                 case BSRA_MASKLEN:
774                         /* validation has been done. */
775                         my_bsr_hash_masklen = al->attru.number;
776                         break;
777                 case BSRA_TIME:
778                         if (al->attru.number < 10)
779                                 my_bsr_period = 10;
780                         else if (al->attru.number > PIM_DEFAULT_BOOTSTRAP_PERIOD)
781                                 my_bsr_period =
782                                         PIM_DEFAULT_BOOTSTRAP_PERIOD;
783                         else
784                                 my_bsr_period = al->attru.number;
785                         break;
786                 default:
787                         yywarn("unknown attribute(%d) for BSR", al->type);
788                         break;
789                 }
790         }
791
792         if (!sa6_bsr)
793                 sa6_bsr = max_global_address(); /* this MUST suceed */
794         my_bsr_address = *sa6_bsr;
795         MASKLEN_TO_MASK6(my_bsr_hash_masklen, my_bsr_hash_mask);
796
797         IF_DEBUG(DEBUG_PIM_BOOTSTRAP) {
798                 log(LOG_DEBUG, 0, "Local BSR address: %s",
799                     inet6_fmt(&my_bsr_address.sin6_addr));
800                 log(LOG_DEBUG, 0, "Local BSR priority : %u", my_bsr_priority);
801                 log(LOG_DEBUG, 0, "Local BSR period is : %u sec.",
802                     my_bsr_period);
803                 log(LOG_DEBUG, 0, "Local BSR hash mask length: %d",
804                     my_bsr_hash_masklen);
805         }
806
807         return(0);
808 }
809
810 static int
811 grp_prefix_config()
812 {
813         struct attr_list *pl;
814
815         if (cand_rp_flag != TRUE) {
816                 log(LOG_WARNING, 0,
817                     "group_prefix was specified without cand_rp(ignored)");
818                 return(0);
819         }
820
821         for (pl = grp_prefix; pl; pl = pl->next) {
822                 if (!IN6_IS_ADDR_MULTICAST(&pl->attru.prefix.paddr)) {
823                         log(LOG_WARNING, 0,
824                             "Config error: %s is not a mulicast address(ignored)",
825                             inet6_fmt(&pl->attru.prefix.paddr));
826                         continue;
827                 }
828
829                 if (!(~(*cand_rp_adv_message.prefix_cnt_ptr))) {
830                         log(LOG_WARNING, 0,
831                             "Too many group_prefix configured. Truncating...");
832                         break;
833                 }
834
835                 /* validation for plen has almost done */
836                 if (pl->attru.prefix.plen < PIM_GROUP_PREFIX_DEFAULT_MASKLEN)
837                         pl->attru.prefix.plen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN;
838
839                 PUT_EGADDR6(pl->attru.prefix.paddr,
840                             (u_int8)pl->attru.prefix.plen, 0,
841                             cand_rp_adv_message.insert_data_ptr);
842                 (*cand_rp_adv_message.prefix_cnt_ptr)++;
843         }
844
845         /* finally, adjust the data size */
846         cand_rp_adv_message.message_size =
847                 cand_rp_adv_message.insert_data_ptr - cand_rp_adv_message.buffer;
848
849         return(0);
850 }
851
852 static int
853 regthres_config()
854 {
855         struct attr_list *al;
856         int rate = -1;
857         int interval = -1;
858
859         if (cand_rp_flag != TRUE) {
860                 log(LOG_WARNING, 0,
861                     "register_threshold was specified without cand_rp");
862         }
863
864         for (al = regthres_attr; al; al = al->next) {
865                 switch(al->type) {
866                 case THRESA_RATE:
867                         if (al->attru.number < 0)
868                                 yywarn("invalid regthres rate: %d(ignored)",
869                                        al->attru.number);
870                         else if (rate != -1)
871                                 yywarn("regthres rate is doubly defined(ignored)");
872                         else
873                                 rate = al->attru.number;
874                         break;
875                 case THRESA_INTERVAL:
876                         if (al->attru.number < 0)
877                                 yywarn("invalid regthres interval: %d(ignored)",
878                                        al->attru.number);
879                         else if (interval != -1)
880                                 yywarn("regthres interval is doubly defined(ignored)");
881                         else
882                                 interval = al->attru.number;
883                         break;
884                 default:
885                         yywarn("unknown attribute(%d) for regthres", al->type);
886                         break;
887                 }
888         }
889
890         /* set default values if not specified */
891         if (rate == -1)
892                 rate = PIM_DEFAULT_REG_RATE;
893         if (interval == -1)
894                 interval = PIM_DEFAULT_REG_RATE_INTERVAL;
895
896         pim_reg_rate_bytes = (rate * interval ) /10;
897         pim_reg_rate_check_interval = interval;
898
899         return(0);
900 }
901
902 static int
903 datathres_config()
904 {
905         struct attr_list *al;
906         int rate = -1;
907         int interval = -1;
908
909         for (al = datathres_attr; al; al = al->next) {
910                 switch(al->type) {
911                 case THRESA_RATE:
912                         if (al->attru.number < 0)
913                                 yywarn("invalid datathres rate: %d(ignored)",
914                                        al->attru.number);
915                         else if (rate != -1)
916                                 yywarn("datathres rate is doubly defined(ignored)");
917                         else
918                                 rate = al->attru.number;
919                         break;
920                 case THRESA_INTERVAL:
921                         if (al->attru.number < 0)
922                                 yywarn("invalid datathres interval: %d(ignored)",
923                                        al->attru.number);
924                         else if (interval != -1)
925                                 yywarn("datathres interval is doubly defined(ignored)");
926                         else
927                                 interval = al->attru.number;
928                         break;
929                 default:
930                         yywarn("unknown attribute(%d) for datathres", al->type);
931                         break;
932                 }
933         }
934
935         /* set default values if not specified */
936         if (rate == -1)
937                 rate = PIM_DEFAULT_DATA_RATE;
938         if (interval == -1)
939                 interval = PIM_DEFAULT_DATA_RATE_INTERVAL;
940
941         pim_data_rate_bytes = (rate * interval ) /10;
942         pim_data_rate_check_interval = interval;
943
944         return(0);
945 }
946
947 int
948 cf_post_config()
949 {
950         struct uvif *v;
951         vifi_t vifi;
952
953         if (debugonly)
954                 goto cleanup;
955
956         param_config();         /* must be called before phyint_conifg() */
957
958         phyint_config();
959
960         if (cand_bsr_flag == TRUE)
961                 bsr_config();
962
963         if (cand_rp_flag == TRUE)
964                 rp_config();
965
966         if (grp_prefix)         /* this must be called after rp_config() */
967                 grp_prefix_config();
968
969         if (cand_rp_flag == TRUE)
970                 regthres_config();
971
972         datathres_config();
973
974         IF_DEBUG(DEBUG_SWITCH) {
975                 log(LOG_DEBUG, 0, "reg_rate_limit set to %u (bits/s)",
976                     pim_reg_rate_bytes);
977                 log(LOG_DEBUG, 0, "reg_rate_interval set to  %u s.",
978                     pim_reg_rate_check_interval);
979                 log(LOG_DEBUG, 0, "data_rate_limit set to %u (bits/s)",
980                     pim_data_rate_bytes);
981                 log(LOG_DEBUG, 0, "data_rate_interval set to %u s.",
982                     pim_data_rate_check_interval);
983         }
984
985   cleanup:
986         /* cleanup temporary variables */
987         if (cand_rp_ifname) free(cand_rp_ifname);
988         if (cand_bsr_ifname) free(cand_bsr_ifname);
989         if (rp_attr) free_attr_list(rp_attr);
990         if (bsr_attr) free_attr_list(bsr_attr);
991         if (grp_prefix) free_attr_list(grp_prefix);
992         if (regthres_attr) free_attr_list(regthres_attr);
993         if (datathres_attr) free_attr_list(datathres_attr);
994         for (vifi = 0, v = uvifs; vifi < numvifs ; ++vifi , ++v)
995                 free_attr_list((struct attr_list *)v->config_attr);
996
997         return(0);
998 }
999
1000 /* initialize all the temporary variables */
1001 void
1002 cf_init(s, d)
1003 {
1004         struct uvif *v;
1005         vifi_t vifi;
1006
1007         strict = s;
1008         debugonly = d;
1009
1010         debug = 0;
1011
1012         rp_attr = bsr_attr = grp_prefix = regthres_attr = datathres_attr = NULL;
1013
1014         cand_rp_ifname = cand_bsr_ifname = NULL;
1015
1016         srcmetric = srcpref = helloperiod = jpperiod = jpperiod_coef
1017                 = granularity = datatimo = regsuptimo = probetime
1018                 = asserttimo = -1;
1019         helloperiod_coef = jpperiod_coef = -1;
1020
1021         for (vifi = 0, v = uvifs; vifi < numvifs ; ++vifi , ++v)
1022                 v->config_attr = NULL;
1023 }