"Fossies" - the Fresh Open Source Software Archive

Member "mrouted-3.9.8/cfparse.y" (1 Jan 2017, 18981 Bytes) of package /linux/misc/mrouted-3.9.8.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bison source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "cfparse.y": 3.9.7_vs_3.9.8.

    1 %{
    2 /*
    3  * Configuration file parser for mrouted.
    4  *
    5  * Written by Bill Fenner, NRL, 1994
    6  *
    7  * cfparse.y,v 3.8.4.30 1998/03/01 01:48:58 fenner Exp
    8  */
    9 #include <stdio.h>
   10 #include <stdarg.h>
   11 #include "defs.h"
   12 #include <netdb.h>
   13 #include <ifaddrs.h>
   14 
   15 /*
   16  * Local function declarations
   17  */
   18 static void     fatal(const char *fmt, ...)
   19     __attribute__((__format__ (printf, 1, 2)))
   20     __attribute__((__nonnull__ (1)));
   21 static void     warn(const char *fmt, ...)
   22     __attribute__((__format__ (printf, 1, 2)))
   23     __attribute__((__nonnull__ (1)));
   24 static void     yyerror(char *s);
   25 static char *       next_word(void);
   26 static int      yylex(void);
   27 static uint32_t     valid_if(char *s);
   28 static const char * ifconfaddr(uint32_t a);
   29 int         yyparse(void);
   30 
   31 static FILE *f;
   32 
   33 char *configfilename = _PATH_MROUTED_CONF;
   34 
   35 extern int cache_lifetime;
   36 extern int prune_lifetime;
   37 
   38 int allow_black_holes = 0;
   39 
   40 static int lineno;
   41 
   42 static struct uvif *v;
   43 
   44 static int order, state;
   45 static int noflood = 0;
   46 static int rexmit = VIFF_REXMIT_PRUNES;
   47 
   48 struct addrmask {
   49     uint32_t addr;
   50     int mask;
   51 };
   52 
   53 struct boundnam {
   54     char        *name;
   55     struct addrmask  bound;
   56 };
   57 
   58 #define MAXBOUNDS 20
   59 
   60 struct boundnam boundlist[MAXBOUNDS];   /* Max. of 20 named boundaries */
   61 int numbounds = 0;          /* Number of named boundaries */
   62 
   63 %}
   64 
   65 %union
   66 {
   67     int num;
   68     char *ptr;
   69     struct addrmask addrmask;
   70     uint32_t addr;
   71     struct vf_element *filterelem;
   72 };
   73 
   74 %token CACHE_LIFETIME PRUNE_LIFETIME PRUNING BLACK_HOLE NOFLOOD
   75 %token PHYINT TUNNEL NAME
   76 %token DISABLE ENABLE IGMPV1 SRCRT BESIDE
   77 %token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET ADVERT_METRIC
   78 %token FILTER ACCEPT DENY EXACT BIDIR REXMIT_PRUNES REXMIT_PRUNES2
   79 %token PASSIVE ALLOW_NONPRUNERS
   80 %token NOTRANSIT BLASTER FORCE_LEAF
   81 %token PRUNE_LIFETIME2 NOFLOOD2
   82 %token SYSNAM SYSCONTACT SYSVERSION SYSLOCATION
   83 %token <num> BOOLEAN
   84 %token <num> NUMBER
   85 %token <ptr> STRING
   86 %token <addrmask> ADDRMASK
   87 %token <addr> ADDR
   88 
   89 %type <addr> interface addrname
   90 %type <addrmask> bound boundary addrmask
   91 %type <filterelem> filter filtlist filtelement filtelem
   92 
   93 %start conf
   94 
   95 %%
   96 
   97 conf    : stmts
   98     ;
   99 
  100 stmts   : /* Empty */
  101     | stmts stmt
  102     ;
  103 
  104 stmt    : error
  105     | PHYINT interface
  106     {
  107         vifi_t vifi;
  108 
  109         state++;
  110 
  111         if (order)
  112         fatal("phyints must appear before tunnels");
  113 
  114         for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
  115         if (!(v->uv_flags & VIFF_TUNNEL) && $2 == v->uv_lcl_addr)
  116             break;
  117         }
  118 
  119         if (vifi == numvifs && !missingok)
  120         fatal("%s is not a configured interface", inet_fmt($2, s1, sizeof(s1)));
  121         if (vifi == numvifs)
  122         warn("%s is not a configured interface, continuing", inet_fmt($2, s1, sizeof(s1)));
  123     }
  124     ifmods
  125     | TUNNEL interface addrname
  126     {
  127         const char *ifname;
  128         struct ifreq ffr;
  129         vifi_t vifi;
  130 
  131         order++;
  132 
  133         ifname = ifconfaddr($2);
  134         if (ifname == 0)
  135         fatal("Tunnel local address %s is not mine", inet_fmt($2, s1, sizeof(s1)));
  136 
  137         if (((ntohl($2) & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
  138         fatal("Tunnel local address %s is a loopback address", inet_fmt($2, s1, sizeof(s1)));
  139 
  140         if (ifconfaddr($3) != NULL)
  141         fatal("Tunnel remote address %s is one of mine", inet_fmt($3, s1, sizeof(s1)));
  142 
  143         for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
  144         if (v->uv_flags & VIFF_TUNNEL) {
  145             if ($3 == v->uv_rmt_addr)
  146             fatal("Duplicate tunnel to %s",
  147                   inet_fmt($3, s1, sizeof(s1)));
  148         } else if (!(v->uv_flags & VIFF_DISABLED)) {
  149             if (($3 & v->uv_subnetmask) == v->uv_subnet)
  150             fatal("Unnecessary tunnel to %s, same subnet as vif %d (%s)",
  151                   inet_fmt($3, s1, sizeof(s1)), vifi, v->uv_name);
  152         }
  153         }
  154 
  155         if (numvifs == MAXVIFS)
  156         fatal("too many vifs");
  157 
  158         strlcpy(ffr.ifr_name, ifname, sizeof(ffr.ifr_name));
  159         if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ffr)<0)
  160         fatal("ioctl SIOCGIFFLAGS on %s", ffr.ifr_name);
  161 
  162         v = &uvifs[numvifs];
  163         zero_vif(v, 1);
  164         v->uv_flags = VIFF_TUNNEL | rexmit | noflood;
  165         v->uv_flags |= VIFF_OTUNNEL; /*XXX*/
  166         v->uv_lcl_addr  = $2;
  167         v->uv_rmt_addr  = $3;
  168         v->uv_dst_addr  = $3;
  169         strlcpy(v->uv_name, ffr.ifr_name, sizeof(v->uv_name));
  170 
  171         if (!(ffr.ifr_flags & IFF_UP)) {
  172         v->uv_flags |= VIFF_DOWN;
  173         vifs_down = TRUE;
  174         }
  175     }
  176     tunnelmods
  177     {
  178         if (!(v->uv_flags & VIFF_OTUNNEL))
  179         init_ipip_on_vif(v);
  180 
  181         logit(LOG_INFO, 0, "installing tunnel from %s to %s as vif #%u - rate=%d",
  182           inet_fmt($2, s1, sizeof(s1)), inet_fmt($3, s2, sizeof(s2)),
  183           numvifs, v->uv_rate_limit);
  184 
  185         ++numvifs;
  186 
  187     }
  188     | CACHE_LIFETIME NUMBER
  189     {
  190         if ($2 < MIN_CACHE_LIFETIME)
  191         warn("cache_lifetime %d must be at least %d", $2, MIN_CACHE_LIFETIME);
  192         else
  193         cache_lifetime = $2;
  194     }
  195     | PRUNE_LIFETIME NUMBER
  196     {
  197         if ($2 < MIN_PRUNE_LIFETIME)
  198         warn("prune_lifetime %d must be at least %d", $2, MIN_PRUNE_LIFETIME);
  199         else
  200         prune_lifetime = $2;
  201     }
  202     | PRUNING BOOLEAN
  203     {
  204         if ($2 != 1)
  205         warn("Disabling pruning is no longer supported");
  206     }
  207     | BLACK_HOLE
  208     {
  209 #ifdef ALLOW_BLACK_HOLES
  210         allow_black_holes = 1;
  211 #endif
  212     }
  213     /*
  214      * Turn off initial flooding (until subordinateness is learned
  215      * via route exchange) on all phyints and set the default for
  216      * all further tunnels.
  217      */
  218     | NOFLOOD
  219     {
  220         vifi_t vifi;
  221 
  222         noflood = VIFF_NOFLOOD;
  223         for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v)
  224         v->uv_flags |= VIFF_NOFLOOD;
  225     }
  226     /*
  227      * Turn on prune retransmission on all interfaces.
  228      * Tunnels default to retransmitting, so this just
  229      * needs to turn on phyints.
  230      */
  231     | REXMIT_PRUNES
  232     {
  233         vifi_t vifi;
  234 
  235         for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v)
  236         v->uv_flags |= VIFF_REXMIT_PRUNES;
  237     }
  238     /*
  239      * If true, do as above.  If false, no need to turn
  240      * it off for phyints since they default to not
  241      * rexmit; need to set flag to not rexmit on tunnels.
  242      */
  243     | REXMIT_PRUNES BOOLEAN
  244     {
  245         if ($2) {
  246         vifi_t vifi;
  247 
  248         for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v)
  249             v->uv_flags |= VIFF_REXMIT_PRUNES;
  250         } else {
  251         rexmit = 0;
  252         }
  253     }
  254     | NAME STRING boundary
  255     {
  256         size_t len = strlen($2) + 1;
  257         if (numbounds >= MAXBOUNDS) {
  258         fatal("Too many named boundaries (max %d)", MAXBOUNDS);
  259         }
  260 
  261         boundlist[numbounds].name = malloc(len);
  262         strlcpy(boundlist[numbounds].name, $2, len);
  263         boundlist[numbounds++].bound = $3;
  264     }
  265     | SYSNAM STRING
  266     {
  267         /* Removed SNMP support */
  268     }
  269     | SYSCONTACT STRING
  270     {
  271         /* Removed SNMP support */
  272     }
  273         | SYSVERSION STRING
  274     {
  275         /* Removed SNMP support */
  276     }
  277     | SYSLOCATION STRING
  278     {
  279         /* Removed SNMP support */
  280     }
  281     ;
  282 
  283 tunnelmods  : /* empty */
  284     | tunnelmods tunnelmod
  285     ;
  286 
  287 tunnelmod   : mod
  288     | BESIDE
  289     {
  290         v->uv_flags |= VIFF_OTUNNEL;
  291     }
  292     | BESIDE BOOLEAN
  293     {
  294         if ($2)
  295         v->uv_flags |= VIFF_OTUNNEL;
  296         else
  297         v->uv_flags &= ~VIFF_OTUNNEL;
  298     }
  299     | SRCRT
  300     {
  301         fatal("Source-route tunnels not supported");
  302     }
  303     ;
  304 
  305 ifmods  : /* empty */
  306     | ifmods ifmod
  307     ;
  308 
  309 ifmod   : mod
  310     | DISABLE       { v->uv_flags |= VIFF_DISABLED; }
  311     | ENABLE        { v->uv_flags &= ~VIFF_DISABLED; }
  312     | IGMPV1        { v->uv_flags |= VIFF_IGMPV1; }
  313     | NETMASK addrname
  314     {
  315         uint32_t subnet, mask;
  316 
  317         mask = $2;
  318         subnet = v->uv_lcl_addr & mask;
  319         if (!inet_valid_subnet(subnet, mask))
  320         fatal("Invalid netmask");
  321         v->uv_subnet = subnet;
  322         v->uv_subnetmask = mask;
  323         v->uv_subnetbcast = subnet | ~mask;
  324     }
  325     | NETMASK
  326     {
  327         warn("Expected address after netmask keyword, ignored");
  328     }
  329     | ALTNET addrmask
  330     {
  331         struct phaddr *ph;
  332 
  333         ph = malloc(sizeof(struct phaddr));
  334         if (!ph) {
  335         fatal("Failed allocating memory for 'struct phaddr'");
  336         return 0;
  337         }
  338 
  339         if ($2.mask) {
  340         VAL_TO_MASK(ph->pa_subnetmask, $2.mask);
  341         } else {
  342         ph->pa_subnetmask = v->uv_subnetmask;
  343         }
  344 
  345         ph->pa_subnet = $2.addr & ph->pa_subnetmask;
  346         ph->pa_subnetbcast = ph->pa_subnet | ~ph->pa_subnetmask;
  347 
  348         if ($2.addr & ~ph->pa_subnetmask)
  349         warn("Extra subnet %s/%d has host bits set",
  350              inet_fmt($2.addr, s1, sizeof(s1)), $2.mask);
  351 
  352         ph->pa_next = v->uv_addrs;
  353         v->uv_addrs = ph;
  354     }
  355     | ALTNET
  356     {
  357         warn("Expected address after altnet keyword, ignored");
  358     }
  359     | FORCE_LEAF
  360     {
  361         v->uv_flags |= VIFF_FORCE_LEAF;
  362     }
  363     | FORCE_LEAF BOOLEAN
  364     {
  365         if ($2)
  366         v->uv_flags |= VIFF_FORCE_LEAF;
  367         else
  368         v->uv_flags &= ~VIFF_FORCE_LEAF;
  369     }
  370     ;
  371 
  372 mod : THRESHOLD NUMBER
  373     {
  374         if ($2 < 1 || $2 > 255)
  375         fatal("Invalid threshold %d",$2);
  376         v->uv_threshold = $2;
  377     }
  378     | THRESHOLD
  379     {
  380         warn("Expected number after threshold keyword, ignored");
  381     }
  382     | METRIC NUMBER
  383     {
  384         if ($2 < 1 || $2 > UNREACHABLE)
  385         fatal("Invalid metric %d",$2);
  386         v->uv_metric = $2;
  387     }
  388     | METRIC
  389     {
  390         warn("Expected number after metric keyword, ignored");
  391     }
  392     | ADVERT_METRIC NUMBER
  393     {
  394         if ($2 < 0 || $2 > UNREACHABLE - 1)
  395         fatal("Invalid advert_metric %d", $2);
  396         v->uv_admetric = $2;
  397     }
  398     | ADVERT_METRIC
  399     {
  400         warn("Expected number after advert_metric keyword, ignored");
  401     }
  402     | RATE_LIMIT NUMBER
  403     {
  404         if ($2 > MAX_RATE_LIMIT)
  405         fatal("Invalid rate_limit %d",$2);
  406         v->uv_rate_limit = $2;
  407     }
  408     | RATE_LIMIT
  409     {
  410         warn("Expected number after rate_limit keyword, ignored");
  411     }
  412     | BOUNDARY bound
  413     {
  414         struct vif_acl *v_acl;
  415 
  416         v_acl = malloc(sizeof(struct vif_acl));
  417         if (!v_acl) {
  418         fatal("Failed allocating memory for 'struct vif_acl'");
  419         return 0;
  420         }
  421 
  422         VAL_TO_MASK(v_acl->acl_mask, $2.mask);
  423         v_acl->acl_addr = $2.addr & v_acl->acl_mask;
  424         if ($2.addr & ~v_acl->acl_mask)
  425         warn("Boundary spec %s/%d has host bits set",
  426              inet_fmt($2.addr, s1, sizeof(s1)), $2.mask);
  427         v_acl->acl_next = v->uv_acl;
  428         v->uv_acl = v_acl;
  429     }
  430     | BOUNDARY
  431     {
  432         warn("Expected boundary spec after boundary keyword, ignored");
  433     }
  434     | REXMIT_PRUNES2
  435     {
  436         v->uv_flags |= VIFF_REXMIT_PRUNES;
  437     }
  438     | REXMIT_PRUNES2 BOOLEAN
  439     {
  440         if ($2)
  441         v->uv_flags |= VIFF_REXMIT_PRUNES;
  442         else
  443         v->uv_flags &= ~VIFF_REXMIT_PRUNES;
  444     }
  445     | PASSIVE
  446     {
  447         v->uv_flags |= VIFF_PASSIVE;
  448     }
  449     | NOFLOOD2
  450     {
  451         v->uv_flags |= VIFF_NOFLOOD;
  452     }
  453     | NOTRANSIT
  454     {
  455         v->uv_flags |= VIFF_NOTRANSIT;
  456     }
  457     | BLASTER
  458     {
  459         v->uv_flags |= VIFF_BLASTER;
  460         blaster_alloc(v - uvifs);
  461     }
  462     | ALLOW_NONPRUNERS
  463     {
  464             v->uv_flags |= VIFF_ALLOW_NONPRUNERS;
  465     }
  466     | PRUNE_LIFETIME2 NUMBER
  467     {
  468         if ($2 < MIN_PRUNE_LIFETIME)
  469         warn("prune_lifetime %d must be at least %d", $2, MIN_PRUNE_LIFETIME);
  470         else
  471         v->uv_prune_lifetime = $2;
  472     }
  473     | ACCEPT filter
  474     {
  475         if (v->uv_filter == NULL) {
  476         struct vif_filter *v_filter;
  477 
  478         v_filter = malloc(sizeof(struct vif_filter));
  479         if (!v_filter) {
  480             fatal("Failed allocating memory for 'struct vif_filter'");
  481             return 0;
  482         }
  483 
  484         v_filter->vf_flags = 0;
  485         v_filter->vf_type = VFT_ACCEPT;
  486         v_filter->vf_filter = $2;
  487         v->uv_filter = v_filter;
  488         } else if (v->uv_filter->vf_type != VFT_ACCEPT) {
  489         fatal("Cannot accept and deny");
  490         } else {
  491         struct vf_element *p;
  492 
  493         p = v->uv_filter->vf_filter;
  494         while (p->vfe_next)
  495             p = p->vfe_next;
  496         p->vfe_next = $2;
  497         }
  498     }
  499     | ACCEPT
  500     {
  501         warn("Expected filter spec after accept keyword, ignored");
  502     }
  503     | DENY filter
  504     {
  505         if (!v->uv_filter) {
  506         struct vif_filter *v_filter;
  507 
  508         v_filter = malloc(sizeof(struct vif_filter));
  509         if (!v_filter) {
  510             fatal("Failed allocating memory for 'struct vif_filter'");
  511             return 0;
  512         }
  513 
  514         v_filter->vf_flags = 0;
  515         v_filter->vf_type = VFT_DENY;
  516         v_filter->vf_filter = $2;
  517         v->uv_filter = v_filter;
  518         } else if (v->uv_filter->vf_type != VFT_DENY) {
  519         fatal("Cannot accept and deny");
  520         } else {
  521         struct vf_element *p;
  522 
  523         p = v->uv_filter->vf_filter;
  524         while (p->vfe_next)
  525             p = p->vfe_next;
  526         p->vfe_next = $2;
  527         }
  528     }
  529     | DENY
  530     {
  531         warn("Expected filter spec after deny keyword, ignored");
  532     }
  533     | BIDIR
  534     {
  535         if (!v->uv_filter) {
  536         fatal("bidir goes after filters");
  537         return 0;   /* Never reached */
  538         }
  539         v->uv_filter->vf_flags |= VFF_BIDIR;
  540     }
  541     ;
  542 
  543 interface: ADDR
  544     {
  545         $$ = $1;
  546     }
  547     | STRING
  548     {
  549         $$ = valid_if($1);
  550         if ($$ == 0 && !missingok)
  551         fatal("Invalid interface name %s",$1);
  552     }
  553     ;
  554 
  555 addrname: ADDR
  556     {
  557         $$ = $1;
  558     }
  559     | STRING
  560     {
  561         struct hostent *hp;
  562 
  563         if ((hp = gethostbyname($1)) == NULL || hp->h_length != sizeof($$)) {
  564         fatal("No such host %s", $1);
  565         return 0;   /* Never reached */
  566         }
  567 
  568         if (hp->h_addr_list[1])
  569         fatal("Hostname %s does not %s", $1, "map to a unique address");
  570 
  571         memmove (&$$, hp->h_addr_list[0], hp->h_length);
  572     }
  573 
  574 bound   : boundary
  575     {
  576         $$ = $1;
  577     }
  578     | STRING
  579     {
  580         int i;
  581 
  582         for (i=0; i < numbounds; i++) {
  583         if (!strcmp(boundlist[i].name, $1)) {
  584             $$ = boundlist[i].bound;
  585             break;
  586         }
  587         }
  588 
  589         if (i == numbounds)
  590         fatal("Invalid boundary name %s",$1);
  591     }
  592     ;
  593 
  594 boundary: ADDRMASK
  595     {
  596 #ifdef ALLOW_BLACK_HOLES
  597         if (!allow_black_holes)
  598 #endif
  599         if ((ntohl($1.addr) & 0xff000000) != 0xef000000) {
  600             fatal("Boundaries must be 239.x.x.x, not %s/%d",
  601               inet_fmt($1.addr, s1, sizeof(s1)), $1.mask);
  602         }
  603         $$ = $1;
  604     }
  605     ;
  606 
  607 addrmask: ADDRMASK      { $$ = $1; }
  608     | ADDR          { $$.addr = $1; $$.mask = 0; }
  609     ;
  610 
  611 filter  : filtlist      { $$ = $1; }
  612     | STRING        { fatal("named filters no implemented yet"); }
  613     ;
  614 
  615 filtlist : filtelement      { $$ = $1; }
  616     | filtelement filtlist  { $1->vfe_next = $2; $$ = $1; }
  617     ;
  618 
  619 filtelement : filtelem      { $$ = $1; }
  620     | filtelem EXACT    { $1->vfe_flags |= VFEF_EXACT; $$ = $1; }
  621     ;
  622 
  623 filtelem : ADDRMASK
  624     {
  625         struct vf_element *vfe;
  626 
  627         vfe = malloc(sizeof(struct vf_element));
  628         if (!vfe) {
  629         fatal("Failed allocating memory for 'struct vf_element'");
  630         return 0;
  631         }
  632 
  633         vfe->vfe_addr = $1.addr;
  634         VAL_TO_MASK(vfe->vfe_mask, $1.mask);
  635         vfe->vfe_flags = 0;
  636         vfe->vfe_next = NULL;
  637 
  638         $$ = vfe;
  639     }
  640 %%
  641 static void fatal(const char *fmt, ...)
  642 {
  643     va_list ap;
  644     char buf[MAXHOSTNAMELEN + 100];
  645 
  646     va_start(ap, fmt);
  647     vsnprintf(buf, sizeof(buf), fmt, ap);
  648     va_end(ap);
  649 
  650     logit(LOG_ERR, 0, "%s: %s near line %d", configfilename, buf, lineno);
  651 }
  652 
  653 static void warn(const char *fmt, ...)
  654 {
  655     va_list ap;
  656     char buf[200];
  657 
  658     va_start(ap, fmt);
  659     vsnprintf(buf, sizeof(buf), fmt, ap);
  660     va_end(ap);
  661 
  662     logit(LOG_WARNING, 0, "%s: %s near line %d", configfilename, buf, lineno);
  663 }
  664 
  665 static void yyerror(char *s)
  666 {
  667     logit(LOG_ERR, 0, "%s: %s near line %d", configfilename, s, lineno);
  668 }
  669 
  670 static char *next_word(void)
  671 {
  672     static char buf[1024];
  673     static char *p=NULL;
  674     char *q;
  675 
  676     while (1) {
  677         if (!p || !*p) {
  678             lineno++;
  679             if (fgets(buf, sizeof(buf), f) == NULL)
  680                 return NULL;
  681             p = buf;
  682         }
  683 
  684         while (*p && (*p == ' ' || *p == '\t')) /* skip whitespace */
  685             p++;
  686 
  687         if (*p == '#') {
  688             p = NULL;       /* skip comments */
  689             continue;
  690         }
  691 
  692         q = p;
  693         while (*p && *p != ' ' && *p != '\t' && *p != '\n')
  694             p++;        /* find next whitespace */
  695         *p++ = '\0';    /* null-terminate string */
  696 
  697         if (!*q) {
  698             p = NULL;
  699             continue;   /* if 0-length string, read another line */
  700         }
  701 
  702         return q;
  703     }
  704 }
  705 
  706 /*
  707  * List of keywords.  Must have an empty record at the end to terminate
  708  * list.  If a second value is specified, the first is used at the beginning
  709  * of the file and the second is used while parsing interfaces (e.g. after
  710  * the first "phyint" or "tunnel" keyword).
  711  */
  712 static struct keyword {
  713     char    *word;
  714     int val1;
  715     int val2;
  716 } words[] = {
  717     { "cache_lifetime", CACHE_LIFETIME, 0 },
  718     { "prune_lifetime", PRUNE_LIFETIME, PRUNE_LIFETIME2 },
  719     { "pruning",        PRUNING, 0 },
  720     { "phyint",     PHYINT, 0 },
  721     { "tunnel",     TUNNEL, 0 },
  722     { "disable",        DISABLE, 0 },
  723     { "enable",     ENABLE, 0 },
  724     { "metric",     METRIC, 0 },
  725     { "advert_metric",  ADVERT_METRIC, 0 },
  726     { "threshold",      THRESHOLD, 0 },
  727     { "rate_limit",     RATE_LIMIT, 0 },
  728     { "force_leaf",     FORCE_LEAF, 0 },
  729     { "srcrt",      SRCRT, 0 },
  730     { "sourceroute",    SRCRT, 0 },
  731     { "boundary",       BOUNDARY, 0 },
  732     { "netmask",        NETMASK, 0 },
  733     { "igmpv1",     IGMPV1, 0 },
  734     { "altnet",     ALTNET, 0 },
  735     { "name",       NAME, 0 },
  736     { "accept",     ACCEPT, 0 },
  737     { "deny",       DENY, 0 },
  738     { "exact",      EXACT, 0 },
  739     { "bidir",      BIDIR, 0 },
  740     { "allow_nonpruners",   ALLOW_NONPRUNERS, 0 },
  741 #ifdef ALLOW_BLACK_HOLES
  742     { "allow_black_holes",  BLACK_HOLE, 0 },
  743 #endif
  744     { "noflood",        NOFLOOD, NOFLOOD2 },
  745     { "notransit",      NOTRANSIT, 0 },
  746     { "blaster",        BLASTER, 0 },
  747     { "rexmit_prunes",  REXMIT_PRUNES, REXMIT_PRUNES2 },
  748     { "passive",        PASSIVE, 0 },
  749     { "beside",     BESIDE, 0 },
  750 #if 0 /* Removed SNMP support */
  751     { "sysName",        SYSNAM, 0 },
  752     { "sysContact",     SYSCONTACT, 0 },
  753     { "sysVersion",     SYSVERSION, 0 },
  754     { "sysLocation",    SYSLOCATION, 0 },
  755 #endif
  756     { NULL,         0, 0 }
  757 };
  758 
  759 
  760 static int yylex(void)
  761 {
  762     uint32_t addr, n;
  763     char *q;
  764     struct keyword *w;
  765 
  766     if ((q = next_word()) == NULL) {
  767         return 0;
  768     }
  769 
  770     for (w = words; w->word; w++)
  771         if (!strcmp(q, w->word))
  772             return (state && w->val2) ? w->val2 : w->val1;
  773 
  774     if (!strcmp(q,"on") || !strcmp(q,"yes")) {
  775         yylval.num = 1;
  776         return BOOLEAN;
  777     }
  778 
  779     if (!strcmp(q,"off") || !strcmp(q,"no")) {
  780         yylval.num = 0;
  781         return BOOLEAN;
  782     }
  783 
  784     if (!strcmp(q,"default")) {
  785         yylval.addrmask.mask = 0;
  786         yylval.addrmask.addr = 0;
  787         return ADDRMASK;
  788     }
  789 
  790     if (sscanf(q,"%[.0-9]/%u%c",s1,&n,s2) == 2) {
  791         if ((addr = inet_parse(s1,1)) != 0xffffffff) {
  792             yylval.addrmask.mask = n;
  793             yylval.addrmask.addr = addr;
  794             return ADDRMASK;
  795         }
  796         /* fall through to returning STRING */
  797     }
  798 
  799     if (sscanf(q,"%[.0-9]%c",s1,s2) == 1) {
  800         if ((addr = inet_parse(s1,4)) != 0xffffffff &&
  801             inet_valid_host(addr)) { 
  802             yylval.addr = addr;
  803             return ADDR;
  804         }
  805     }
  806 
  807     if (sscanf(q,"0x%8x%c", &n, s1) == 1) {
  808         yylval.addr = n;
  809         return ADDR;
  810     }
  811 
  812     if (sscanf(q,"%u%c",&n,s1) == 1) {
  813         yylval.num = n;
  814         return NUMBER;
  815     }
  816 
  817     yylval.ptr = q;
  818 
  819     return STRING;
  820 }
  821 
  822 void config_vifs_from_file(void)
  823 {
  824     order = 0;
  825     state = 0;
  826     numbounds = 0;
  827     lineno = 0;
  828 
  829     if ((f = fopen(configfilename, "r")) == NULL) {
  830         if (errno != ENOENT)
  831             logit(LOG_ERR, errno, "Cannot open %s", configfilename);
  832         return;
  833     }
  834 
  835     yyparse();
  836 
  837     fclose(f);
  838 }
  839 
  840 static uint32_t valid_if(char *s)
  841 {
  842     vifi_t vifi;
  843     struct uvif *v;
  844 
  845     for (vifi=0, v=uvifs; vifi<numvifs; vifi++, v++) {
  846         if (!strcmp(v->uv_name, s))
  847             return v->uv_lcl_addr;
  848     }
  849 
  850     return 0;
  851 }
  852 
  853 static const char *ifconfaddr(uint32_t a)
  854 {
  855     static char ifname[IFNAMSIZ];
  856     struct ifaddrs *ifap, *ifa;
  857 
  858     if (getifaddrs(&ifap) != 0)
  859     return NULL;
  860 
  861     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  862     if (ifa->ifa_addr &&
  863         ifa->ifa_addr->sa_family == AF_INET &&
  864         ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == a) {
  865         strlcpy(ifname, ifa->ifa_name, sizeof(ifname));
  866         freeifaddrs(ifap);
  867 
  868         return ifname;
  869     }
  870     }
  871 
  872     freeifaddrs(ifap);
  873 
  874     return NULL;
  875 }
  876 
  877 /**
  878  * Local Variables:
  879  *  version-control: t
  880  *  indent-tabs-mode: t
  881  *  c-file-style: "ellemtel"
  882  *  c-basic-offset: 4
  883  * End:
  884  */