summaryrefslogtreecommitdiffstats
path: root/usr.sbin/mrouted/cfparse.y
diff options
context:
space:
mode:
authorfenner <fenner@FreeBSD.org>1999-01-20 07:55:57 +0000
committerfenner <fenner@FreeBSD.org>1999-01-20 07:55:57 +0000
commitcdafdeb1c3a36e7c0b59fd4f6f0b90b3b1cc27f8 (patch)
treeccf540c94528b6508bed4892f971ca6ff14c68a7 /usr.sbin/mrouted/cfparse.y
parent1de14dda19dab2b943562326a3d97281534dc709 (diff)
downloadFreeBSD-src-cdafdeb1c3a36e7c0b59fd4f6f0b90b3b1cc27f8.zip
FreeBSD-src-cdafdeb1c3a36e7c0b59fd4f6f0b90b3b1cc27f8.tar.gz
Merge conflicts from 3.9-beta3+IOS12. The conflicts were huge; cvs's
merge algorithm failed on several files, and the translation of the mrouted man page to mdoc didn't help...
Diffstat (limited to 'usr.sbin/mrouted/cfparse.y')
-rw-r--r--usr.sbin/mrouted/cfparse.y441
1 files changed, 358 insertions, 83 deletions
diff --git a/usr.sbin/mrouted/cfparse.y b/usr.sbin/mrouted/cfparse.y
index e5a1dc9..14e206e 100644
--- a/usr.sbin/mrouted/cfparse.y
+++ b/usr.sbin/mrouted/cfparse.y
@@ -4,7 +4,8 @@
*
* Written by Bill Fenner, NRL, 1994
*
- * $Id: cfparse.y,v 1.7 1997/02/22 16:06:48 peter Exp $
+ * $Id: cfparse.y,v 1.8 1998/06/09 05:01:27 imp Exp $
+ * cfparse.y,v 3.8.4.30 1998/03/01 01:48:58 fenner Exp
*/
#include <stdio.h>
#ifdef __STDC__
@@ -29,19 +30,23 @@ int yyparse __P((void));
static FILE *f;
-extern int udp_socket;
char *configfilename = _PATH_MROUTED_CONF;
extern int cache_lifetime;
-extern int max_prune_lifetime;
+extern int prune_lifetime;
+
+/* imported from config.c, with slight memory leak */
+extern struct ifconf ifc;
+
+int allow_black_holes = 0;
static int lineno;
-static struct ifreq ifbuf[32];
-static struct ifconf ifc;
static struct uvif *v;
-static int order;
+static int order, state;
+static int noflood = 0;
+static int rexmit = VIFF_REXMIT_PRUNES;
struct addrmask {
u_int32 addr;
@@ -66,12 +71,17 @@ int numbounds = 0; /* Number of named boundaries */
char *ptr;
struct addrmask addrmask;
u_int32 addr;
+ struct vf_element *filterelem;
};
-%token CACHE_LIFETIME PRUNING
+%token CACHE_LIFETIME PRUNE_LIFETIME PRUNING BLACK_HOLE NOFLOOD
%token PHYINT TUNNEL NAME
-%token DISABLE IGMPV1 SRCRT
+%token DISABLE IGMPV1 SRCRT BESIDE
%token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET ADVERT_METRIC
+%token FILTER ACCEPT DENY EXACT BIDIR REXMIT_PRUNES REXMIT_PRUNES2
+%token PASSIVE ALLOW_NONPRUNERS
+%token NOTRANSIT BLASTER FORCE_LEAF
+%token PRUNE_LIFETIME2 NOFLOOD2
%token SYSNAM SYSCONTACT SYSVERSION SYSLOCATION
%token <num> BOOLEAN
%token <num> NUMBER
@@ -81,6 +91,7 @@ int numbounds = 0; /* Number of named boundaries */
%type <addr> interface addrname
%type <addrmask> bound boundary addrmask
+%type <filterelem> filter filtlist filtelement filtelem
%start conf
@@ -98,6 +109,8 @@ stmt : error
vifi_t vifi;
+ state++;
+
if (order)
fatal("phyints must appear before tunnels");
@@ -127,12 +140,9 @@ stmt : error
fatal("Tunnel local address %s is not mine",
inet_fmt($2, s1));
- strncpy(ffr.ifr_name, ifr->ifr_name, IFNAMSIZ);
- ffr.ifr_name[IFNAMSIZ-1]='\0';
- if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ffr)<0)
- fatal("ioctl SIOCGIFFLAGS on %s",ffr.ifr_name);
- if (ffr.ifr_flags & IFF_LOOPBACK)
- fatal("Tunnel local address %s is a loopback interface",
+ if (((ntohl($2) & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) ==
+ IN_LOOPBACKNET)
+ fatal("Tunnel local address %s is a loopback address",
inet_fmt($2, s1));
if (ifconfaddr(&ifc, $3) != 0)
@@ -148,30 +158,26 @@ stmt : error
inet_fmt($3, s1));
} else if (!(v->uv_flags & VIFF_DISABLED)) {
if (($3 & v->uv_subnetmask) == v->uv_subnet)
- fatal("Unnecessary tunnel to %s",
- inet_fmt($3,s1));
+ fatal("Unnecessary tunnel to %s, same subnet as vif %d (%s)",
+ inet_fmt($3,s1), vifi, v->uv_name);
}
if (numvifs == MAXVIFS)
fatal("too many vifs");
+ strncpy(ffr.ifr_name, ifr->ifr_name, IFNAMSIZ);
+ if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ffr)<0)
+ fatal("ioctl SIOCGIFFLAGS on %s", ffr.ifr_name);
+
v = &uvifs[numvifs];
- v->uv_flags = VIFF_TUNNEL;
- v->uv_metric = DEFAULT_METRIC;
- v->uv_admetric = 0;
- v->uv_rate_limit= DEFAULT_TUN_RATE_LIMIT;
- v->uv_threshold = DEFAULT_THRESHOLD;
+ zero_vif(v, 1);
+ v->uv_flags = VIFF_TUNNEL | rexmit | noflood;
+ v->uv_flags |= VIFF_OTUNNEL; /*XXX*/
v->uv_lcl_addr = $2;
v->uv_rmt_addr = $3;
- v->uv_subnet = 0;
- v->uv_subnetmask= 0;
- v->uv_subnetbcast= 0;
+ v->uv_dst_addr = $3;
strncpy(v->uv_name, ffr.ifr_name, IFNAMSIZ);
v->uv_name[IFNAMSIZ-1]='\0';
- v->uv_groups = NULL;
- v->uv_neighbors = NULL;
- v->uv_acl = NULL;
- v->uv_addrs = NULL;
if (!(ffr.ifr_flags & IFF_UP)) {
v->uv_flags |= VIFF_DOWN;
@@ -180,17 +186,101 @@ stmt : error
}
tunnelmods
{
- log(LOG_INFO, 0,
- "installing tunnel from %s to %s as vif #%u - rate=%d",
- inet_fmt($2, s1), inet_fmt($3, s2),
- numvifs, v->uv_rate_limit);
- ++numvifs;
+ if (!(v->uv_flags & VIFF_OTUNNEL)) {
+ init_ipip_on_vif(v);
+ }
+
+ log(LOG_INFO, 0,
+ "installing tunnel from %s to %s as vif #%u - rate=%d",
+ inet_fmt($2, s1), inet_fmt($3, s2),
+ numvifs, v->uv_rate_limit);
+
+ ++numvifs;
+
}
- | PRUNING BOOLEAN { pruning = $2; }
- | CACHE_LIFETIME NUMBER { cache_lifetime = $2;
- max_prune_lifetime = cache_lifetime * 2;
+ | CACHE_LIFETIME NUMBER {
+
+ if ($2 < MIN_CACHE_LIFETIME) {
+ warn("cache_lifetime %d must be at least %d",
+ $2, MIN_CACHE_LIFETIME);
+ } else {
+ cache_lifetime = $2;
+ }
+
+ }
+ | PRUNE_LIFETIME NUMBER {
+
+ if ($2 < MIN_PRUNE_LIFETIME) {
+ warn("prune_lifetime %d must be at least %d",
+ $2, MIN_PRUNE_LIFETIME);
+ } else {
+ prune_lifetime = $2;
+ }
+
+ }
+ | PRUNING BOOLEAN {
+
+ if ($2 != 1) {
+ warn("Disabling pruning is no longer supported");
+ }
+
+ }
+ | BLACK_HOLE {
+#ifdef ALLOW_BLACK_HOLES
+ allow_black_holes = 1;
+#endif
+ }
+ /*
+ * Turn off initial flooding (until subordinateness is learned
+ * via route exchange) on all phyints and set the default for
+ * all further tunnels.
+ */
+ | NOFLOOD {
+
+ vifi_t vifi;
+
+ noflood = VIFF_NOFLOOD;
+ for (vifi = 0, v = uvifs;
+ vifi < numvifs;
+ ++vifi, ++v)
+ v->uv_flags |= VIFF_NOFLOOD;
+
}
+ /*
+ * Turn on prune retransmission on all interfaces.
+ * Tunnels default to retransmitting, so this just
+ * needs to turn on phyints.
+ */
+ | REXMIT_PRUNES {
+
+ vifi_t vifi;
+
+ for (vifi = 0, v = uvifs;
+ vifi < numvifs;
+ ++vifi, ++v)
+ v->uv_flags |= VIFF_REXMIT_PRUNES;
+
+ }
+ /*
+ * If true, do as above. If false, no need to turn
+ * it off for phyints since they default to not
+ * rexmit; need to set flag to not rexmit on tunnels.
+ */
+ | REXMIT_PRUNES BOOLEAN {
+
+ if ($2) {
+ vifi_t vifi;
+
+ for (vifi = 0, v = uvifs;
+ vifi < numvifs;
+ ++vifi, ++v)
+ v->uv_flags |= VIFF_REXMIT_PRUNES;
+ } else {
+ rexmit = 0;
+ }
+
+ }
| NAME STRING boundary { if (numbounds >= MAXBOUNDS) {
fatal("Too many named boundaries (max %d)", MAXBOUNDS);
}
@@ -226,6 +316,16 @@ tunnelmods : /* empty */
;
tunnelmod : mod
+ | BESIDE { v->uv_flags |= VIFF_OTUNNEL; }
+ | BESIDE BOOLEAN {
+
+ if ($2) {
+ v->uv_flags |= VIFF_OTUNNEL;
+ } else {
+ v->uv_flags &= ~VIFF_OTUNNEL;
+ }
+
+ }
| SRCRT { fatal("Source-route tunnels not supported"); }
;
@@ -277,6 +377,20 @@ ifmod : mod
warn("Expected address after altnet keyword, ignored");
}
+ | FORCE_LEAF {
+
+ v->uv_flags |= VIFF_FORCE_LEAF;
+
+ }
+ | FORCE_LEAF BOOLEAN {
+
+ if ($2) {
+ v->uv_flags |= VIFF_FORCE_LEAF;
+ } else {
+ v->uv_flags &= ~VIFF_FORCE_LEAF;
+ }
+
+ }
;
mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
@@ -336,6 +450,122 @@ mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
warn("Expected boundary spec after boundary keyword, ignored");
}
+ | REXMIT_PRUNES2 {
+
+ v->uv_flags |= VIFF_REXMIT_PRUNES;
+
+ }
+ | REXMIT_PRUNES2 BOOLEAN {
+
+ if ($2) {
+ v->uv_flags |= VIFF_REXMIT_PRUNES;
+ } else {
+ v->uv_flags &= ~VIFF_REXMIT_PRUNES;
+ }
+
+ }
+ | PASSIVE {
+
+ v->uv_flags |= VIFF_PASSIVE;
+
+ }
+ | NOFLOOD2 {
+
+ v->uv_flags |= VIFF_NOFLOOD;
+
+ }
+ | NOTRANSIT {
+
+ v->uv_flags |= VIFF_NOTRANSIT;
+
+ }
+ | BLASTER {
+
+ v->uv_flags |= VIFF_BLASTER;
+ blaster_alloc(v - uvifs);
+
+ }
+ | ALLOW_NONPRUNERS {
+
+ v->uv_flags |= VIFF_ALLOW_NONPRUNERS;
+
+ }
+ | PRUNE_LIFETIME2 NUMBER {
+
+ if ($2 < MIN_PRUNE_LIFETIME) {
+ warn("prune_lifetime %d must be at least %d",
+ $2, MIN_PRUNE_LIFETIME);
+ } else {
+ v->uv_prune_lifetime = $2;
+ }
+
+ }
+ | ACCEPT filter {
+
+ if (v->uv_filter == NULL) {
+ struct vif_filter *v_filter;
+
+ v_filter = (struct vif_filter *)malloc(sizeof(struct vif_filter));
+ if (v_filter == NULL)
+ fatal("out of memory");
+ v_filter->vf_flags = 0;
+ v_filter->vf_type = VFT_ACCEPT;
+ v_filter->vf_filter = $2;
+ v->uv_filter = v_filter;
+ } else if (v->uv_filter->vf_type != VFT_ACCEPT) {
+ fatal("can't accept and deny");
+ } else {
+ struct vf_element *p;
+
+ p = v->uv_filter->vf_filter;
+ while (p->vfe_next)
+ p = p->vfe_next;
+ p->vfe_next = $2;
+ }
+
+ }
+ | ACCEPT {
+
+ warn("Expected filter spec after accept keyword, ignored");
+
+ }
+ | DENY filter {
+
+ if (v->uv_filter == NULL) {
+ struct vif_filter *v_filter;
+
+ v_filter = (struct vif_filter *)malloc(sizeof(struct vif_filter));
+ if (v_filter == NULL)
+ fatal("out of memory");
+ v_filter->vf_flags = 0;
+ v_filter->vf_type = VFT_DENY;
+ v_filter->vf_filter = $2;
+ v->uv_filter = v_filter;
+ } else if (v->uv_filter->vf_type != VFT_DENY) {
+ fatal("can't accept and deny");
+ } else {
+ struct vf_element *p;
+
+ p = v->uv_filter->vf_filter;
+ while (p->vfe_next)
+ p = p->vfe_next;
+ p->vfe_next = $2;
+ }
+
+ }
+ | DENY {
+
+ warn("Expected filter spec after deny keyword, ignored");
+
+ }
+ | BIDIR {
+
+ if (v->uv_filter == NULL) {
+ fatal("bidir goes after filters");
+ }
+ v->uv_filter->vf_flags |= VFF_BIDIR;
+
+ }
;
interface : ADDR { $$ = $1; }
@@ -378,6 +608,9 @@ bound : boundary { $$ = $1; }
boundary : ADDRMASK {
+#ifdef ALLOW_BLACK_HOLES
+ if (!allow_black_holes)
+#endif
if ((ntohl($1.addr) & 0xff000000) != 0xef000000) {
fatal("Boundaries must be 239.x.x.x, not %s/%d",
inet_fmt($1.addr, s1), $1.mask);
@@ -390,6 +623,35 @@ boundary : ADDRMASK {
addrmask : ADDRMASK { $$ = $1; }
| ADDR { $$.addr = $1; $$.mask = 0; }
;
+
+filter : filtlist { $$ = $1; }
+ | STRING { fatal("named filters no implemented yet"); }
+ ;
+
+filtlist : filtelement { $$ = $1; }
+ | filtelement filtlist { $1->vfe_next = $2; $$ = $1; }
+ ;
+
+filtelement : filtelem { $$ = $1; }
+ | filtelem EXACT { $1->vfe_flags |= VFEF_EXACT; $$ = $1; }
+ ;
+
+filtelem : ADDRMASK {
+
+ struct vf_element *vfe;
+
+ vfe = (struct vf_element *)malloc(sizeof(struct vf_element));
+ if (vfe == NULL)
+ fatal("out of memory");
+
+ vfe->vfe_addr = $1.addr;
+ VAL_TO_MASK(vfe->vfe_mask, $1.mask);
+ vfe->vfe_flags = 0;
+ vfe->vfe_next = NULL;
+
+ $$ = vfe;
+
+ }
%%
#ifdef __STDC__
static void
@@ -455,7 +717,6 @@ next_word()
{
static char buf[1024];
static char *p=NULL;
- extern FILE *f;
char *q;
while (1) {
@@ -494,47 +755,75 @@ next_word()
}
}
+/*
+ * List of keywords. Must have an empty record at the end to terminate
+ * list. If a second value is specified, the first is used at the beginning
+ * of the file and the second is used while parsing interfaces (e.g. after
+ * the first "phyint" or "tunnel" keyword).
+ */
+static struct keyword {
+ char *word;
+ int val1;
+ int val2;
+} words[] = {
+ { "cache_lifetime", CACHE_LIFETIME },
+ { "prune_lifetime", PRUNE_LIFETIME, PRUNE_LIFETIME2 },
+ { "pruning", PRUNING },
+ { "phyint", PHYINT },
+ { "tunnel", TUNNEL },
+ { "disable", DISABLE },
+ { "metric", METRIC },
+ { "advert_metric", ADVERT_METRIC },
+ { "threshold", THRESHOLD },
+ { "rate_limit", RATE_LIMIT },
+ { "force_leaf", FORCE_LEAF },
+ { "srcrt", SRCRT },
+ { "sourceroute", SRCRT },
+ { "boundary", BOUNDARY },
+ { "netmask", NETMASK },
+ { "igmpv1", IGMPV1 },
+ { "altnet", ALTNET },
+ { "name", NAME },
+ { "accept", ACCEPT },
+ { "deny", DENY },
+ { "exact", EXACT },
+ { "bidir", BIDIR },
+ { "allow_nonpruners", ALLOW_NONPRUNERS },
+#ifdef ALLOW_BLACK_HOLES
+ { "allow_black_holes", BLACK_HOLE },
+#endif
+ { "noflood", NOFLOOD, NOFLOOD2},
+ { "notransit", NOTRANSIT },
+ { "blaster", BLASTER },
+ { "rexmit_prunes", REXMIT_PRUNES, REXMIT_PRUNES2 },
+ { "passive", PASSIVE },
+ { "beside", BESIDE },
+#ifdef SNMP
+ { "sysName", SYSNAM },
+ { "sysContact", SYSCONTACT },
+ { "sysVersion", SYSVERSION },
+ { "sysLocation", SYSLOCATION },
+#endif
+ { NULL, 0 }
+};
+
+
static int
yylex()
{
int n;
u_int32 addr;
char *q;
+ struct keyword *w;
if ((q = next_word()) == NULL) {
return 0;
}
- if (!strcmp(q,"cache_lifetime"))
- return CACHE_LIFETIME;
- if (!strcmp(q,"pruning"))
- return PRUNING;
- if (!strcmp(q,"phyint"))
- return PHYINT;
- if (!strcmp(q,"tunnel"))
- return TUNNEL;
- if (!strcmp(q,"disable"))
- return DISABLE;
- if (!strcmp(q,"metric"))
- return METRIC;
- if (!strcmp(q,"advert_metric"))
- return ADVERT_METRIC;
- if (!strcmp(q,"threshold"))
- return THRESHOLD;
- if (!strcmp(q,"rate_limit"))
- return RATE_LIMIT;
- if (!strcmp(q,"srcrt") || !strcmp(q,"sourceroute"))
- return SRCRT;
- if (!strcmp(q,"boundary"))
- return BOUNDARY;
- if (!strcmp(q,"netmask"))
- return NETMASK;
- if (!strcmp(q,"igmpv1"))
- return IGMPV1;
- if (!strcmp(q,"altnet"))
- return ALTNET;
- if (!strcmp(q,"name"))
- return NAME;
+ for (w = words; w->word; w++)
+ if (!strcmp(q, w->word))
+ return (state && w->val2) ? w->val2 : w->val1;
+
if (!strcmp(q,"on") || !strcmp(q,"yes")) {
yylval.num = 1;
return BOOLEAN;
@@ -572,14 +861,6 @@ yylex()
return NUMBER;
}
#ifdef SNMP
- if (!strcmp(q,"sysName"))
- return SYSNAM;
- if (!strcmp(q,"sysContact"))
- return SYSCONTACT;
- if (!strcmp(q,"sysVersion"))
- return SYSVERSION;
- if (!strcmp(q,"sysLocation"))
- return SYSLOCATION;
if (*q=='"') {
if (q[ strlen(q)-1 ]=='"')
q[ strlen(q)-1 ]='\0'; /* trash trailing quote */
@@ -594,9 +875,8 @@ yylex()
void
config_vifs_from_file()
{
- extern FILE *f;
-
order = 0;
+ state = 0;
numbounds = 0;
lineno = 0;
@@ -606,11 +886,6 @@ config_vifs_from_file()
return;
}
- ifc.ifc_buf = (char *)ifbuf;
- ifc.ifc_len = sizeof(ifbuf);
- if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0)
- log(LOG_ERR, errno, "ioctl SIOCGIFCONF");
-
yyparse();
fclose(f);
@@ -643,7 +918,7 @@ ifconfaddr(ifcp, a)
if (ifrp->ifr_addr.sa_family == AF_INET &&
((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr == a)
return (ifrp);
-#if (defined(BSD) && (BSD >= 199006))
+#ifdef HAVE_SA_LEN
n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
if (n < sizeof(*ifrp))
++ifrp;
OpenPOWER on IntegriCloud