Annotation of embedaddon/mrouted/cfparse.y, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>