Annotation of embedaddon/mrouted/cfparse.y, revision 1.1.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>