File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mrouted / cfparse.y
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:10:48 2012 UTC (12 years, 3 months ago) by misho
Branches: mrouted, MAIN
CVS tags: v3_9_6p0, v3_9_6, v3_9_5, HEAD
mrouted

    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>