diff --git a/nest/config.Y b/nest/config.Y index bb1328cc..0c653211 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -9,12 +9,11 @@ CF_HDR static struct proto_config *this_proto; +static struct iface_patt *this_ipatt; #include "nest/rt-dev.h" #include "nest/password.h" -void rt_dev_add_iface(char *); - CF_DECLS CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) @@ -102,18 +101,23 @@ rtable: } ; +/* Interface patterns */ + +iface_patt: + TEXT { this_ipatt->pattern = $1; this_ipatt->prefix = IPA_NONE; this_ipatt->pxlen = 0; } + | IPA pxlen { this_ipatt->pattern = NULL; this_ipatt->prefix = $1; this_ipatt->pxlen = $2; } + | TEXT IPA pxlen { this_ipatt->pattern = $1; this_ipatt->prefix = $2; this_ipatt->pxlen = $3; } + ; + /* Direct device route protocol */ CF_ADDTO(proto, dev_proto '}') dev_proto_start: proto_start DIRECT { struct rt_dev_config *p = proto_config_new(&proto_device, sizeof(struct rt_dev_config)); - struct iface_patt *k = cfg_alloc(sizeof(struct iface_patt)); this_proto = &p->c; p->c.preference = DEF_PREF_DIRECT; init_list(&p->iface_list); - k->pattern = "*"; - add_tail(&p->iface_list, &k->n); } ; @@ -123,15 +127,26 @@ dev_proto: | dev_proto dev_iface_list ';' ; -dev_iface_list: - INTERFACE TEXT { - /* FIXME: Beware of obscure semantics. */ - init_list(&((struct rt_dev_config *) this_proto)->iface_list); - rt_dev_add_iface($2); +dev_iface_entry_init: + /* EMPTY */ { + struct rt_dev_config *p = (void *) this_proto; + struct iface_patt *k = cfg_allocz(sizeof(struct iface_patt)); + add_tail(&p->iface_list, &k->n); + this_ipatt = k; } - | dev_iface_list ',' TEXT { rt_dev_add_iface($3); } ; +dev_iface_entry: + dev_iface_entry_init iface_patt + ; + +dev_iface_list: + INTERFACE dev_iface_entry + | dev_iface_list ',' dev_iface_entry + ; + +/* Password lists */ + password_begin: PASSWORD TEXT { last_password_item = cfg_alloc(sizeof (struct password_item)); @@ -162,14 +177,4 @@ password_list: CF_CODE -void -rt_dev_add_iface(char *n) -{ - struct rt_dev_config *p = (void *) this_proto; - struct iface_patt *k = cfg_alloc(sizeof(struct iface_patt)); - - k->pattern = cfg_strdup(n); - add_tail(&p->iface_list, &k->n); -} - CF_END diff --git a/nest/iface.c b/nest/iface.c index 19ed7fbd..3a5d9c6b 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -588,13 +588,19 @@ iface_patt_match(list *l, struct iface *i) { char *t = p->pattern; int ok = 1; - if (*t == '-') + if (t) { - t++; - ok = 0; + if (*t == '-') + { + t++; + ok = 0; + } + if (!patmatch(t, i->name)) + continue; } - if (patmatch(t, i->name)) - return ok ? p : NULL; + if (!i->addr || !ipa_in_net(i->addr->ip, p->prefix, p->pxlen)) + continue; + return ok ? p : NULL; } return NULL; } @@ -608,7 +614,10 @@ iface_patts_equal(list *a, list *b, int (*comp)(struct iface_patt *, struct ifac y = HEAD(*b); while (x->n.next && y->n.next) { - if (strcmp(x->pattern, y->pattern) || comp && !comp(x, y)) + if (strcmp(x->pattern, y->pattern) || + !ipa_equal(x->prefix, y->prefix) || + x->pxlen != y->pxlen || + comp && !comp(x, y)) return 0; x = (void *) x->n.next; y = (void *) y->n.next; diff --git a/nest/iface.h b/nest/iface.h index 1d26e7b8..9f3a2395 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -122,13 +122,10 @@ void neigh_prune(void); struct iface_patt { node n; byte *pattern; /* Interface name pattern */ + ip_addr prefix; /* Interface prefix */ + int pxlen; - /* Protocol-specific data follow, but keep them like this: - struct rip_iface_patt { - struct iface_patt i; - whatever you (need); - } - */ + /* Protocol-specific data follow after this structure */ }; struct iface_patt *iface_patt_match(list *, struct iface *); diff --git a/nest/rt-dev.c b/nest/rt-dev.c index 63548fc7..c07b5de6 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -23,7 +23,9 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad) { struct rt_dev_config *P = (void *) p->cf; - if (!iface_patt_match(&P->iface_list, ad->iface)) + if (!EMPTY_LIST(P->iface_list) && + !iface_patt_match(&P->iface_list, ad->iface)) + /* Empty list is automagically treated as "*" */ return; if (c & IF_CHANGE_DOWN) { diff --git a/proto/rip/config.Y b/proto/rip/config.Y index 7443c44f..8590e57f 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -17,10 +17,8 @@ CF_HDR #include "proto/rip/rip.h" #include "nest/iface.h" -void rip_dev_add_iface(char *); -struct rip_patt *rip_get_iface(void); - #define RIP_CFG ((struct rip_proto_config *) this_proto) +#define RIP_IPATT ((struct rip_patt *) this_ipatt) CF_DECLS @@ -58,7 +56,6 @@ rip_auth: | NONE { $$=AT_NONE; } ; -/* FIXME FIXME this corrupts memory */ rip_mode: BROADCAST { $$=IM_BROADCAST; } | QUIET { $$=IM_QUIET; } @@ -67,14 +64,8 @@ rip_mode: ; rip_iface_item: - | METRIC expr { - struct rip_patt *k = rip_get_iface(); - k->metric = $2; - } - | MODE rip_mode { - struct rip_patt *k = rip_get_iface(); - k->mode |= $2; - } + | METRIC expr { RIP_IPATT->metric = $2; } + | MODE rip_mode { RIP_IPATT->mode |= $2; } ; rip_iface_opts: @@ -82,32 +73,26 @@ rip_iface_opts: | rip_iface_opts rip_iface_item ';' ; -rip_iface_empty: /* EMPTY */ | rip_iface_opts '}' ; +rip_iface_opt_list: /* EMPTY */ | rip_iface_opts '}' ; + +rip_iface_init: + /* EMPTY */ { + struct rip_patt *k = cfg_allocz(sizeof(struct rip_patt)); + k->metric = 1; + add_tail(&RIP_CFG->iface_list, &k->i.n); + this_ipatt = &k->i; + } + ; + +rip_iface: + rip_iface_init iface_patt rip_iface_opt_list + ; rip_iface_list: - INTERFACE TEXT rip_iface_empty { rip_dev_add_iface($2); } - | dev_iface_list ',' TEXT rip_iface_empty { rip_dev_add_iface($3); } + INTERFACE rip_iface + | rip_iface_list ',' rip_iface ; CF_CODE -void -rip_dev_add_iface(char *n) -{ - struct rip_patt *k = cfg_allocz(sizeof(struct rip_patt)); - k->metric = 1; - k->i.pattern = cfg_strdup(n); - add_tail(&RIP_CFG->iface_list, &k->i.n); -} - -struct rip_patt * -rip_get_iface(void) -{ - struct rip_patt *k = TAIL(RIP_CFG->iface_list); - if (!k) - cf_error( "This cannot happen" ); - return k; -} - - CF_END