From 20e94fb85b7097b57089e3912475ac881fd5528d Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Wed, 6 May 2009 22:02:45 +0200 Subject: [PATCH] A change in OSPF and RIP interface patterns. Allows to add more interface patterns to one common 'options' section like: interface "eth3", "eth4" { options common to eth3 and eth4 }; Also removes undocumented and unnecessary ability to specify more interface patterns with different 'options' sections: interface "eth3" { options ... }, "eth4" { options ... }; --- nest/config.Y | 52 ++++++++++++++++++++++++----------- nest/iface.c | 67 ++++++++++++++++++++++++++++++++++----------- nest/iface.h | 14 +++++++--- nest/rt-dev.c | 2 +- proto/ospf/config.Y | 15 ++++------ proto/ospf/iface.c | 2 +- proto/ospf/ospf.c | 4 +-- proto/rip/config.Y | 25 ++++++++--------- proto/rip/rip.c | 4 +-- 9 files changed, 121 insertions(+), 64 deletions(-) diff --git a/nest/config.Y b/nest/config.Y index e8437770..1d2f0150 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -18,6 +18,7 @@ CF_DEFINES static struct proto_config *this_proto; static struct iface_patt *this_ipatt; +static struct iface_patt_node *this_ipn; static list *this_p_list; static struct password_item *this_p_item; static int password_id; @@ -146,12 +147,36 @@ debug_default: /* Interface patterns */ -iface_patt: - TEXT { this_ipatt->pattern = $1; this_ipatt->prefix = IPA_NONE; this_ipatt->pxlen = 0; } - | prefix { this_ipatt->pattern = NULL; this_ipatt->prefix = $1.addr; this_ipatt->pxlen = $1.len; } - | TEXT prefix { this_ipatt->pattern = $1; this_ipatt->prefix = $2.addr; this_ipatt->pxlen = $2.len; } +iface_patt_node_init: + /* EMPTY */ { + struct iface_patt_node *ipn = cfg_allocz(sizeof(struct iface_patt_node)); + add_tail(&this_ipatt->ipn_list, NODE ipn); + this_ipn = ipn; + } ; +iface_patt_node_body: + TEXT { this_ipn->pattern = $1; this_ipn->prefix = IPA_NONE; this_ipn->pxlen = 0; } + | prefix { this_ipn->pattern = NULL; this_ipn->prefix = $1.addr; this_ipn->pxlen = $1.len; } + | TEXT prefix { this_ipn->pattern = $1; this_ipn->prefix = $2.addr; this_ipn->pxlen = $2.len; } + ; + +iface_negate: + { this_ipn->positive = 1; } + | '-' { this_ipn->positive = 0; } + ; + +iface_patt_node: + iface_patt_node_init iface_negate iface_patt_node_body + ; + + +iface_patt_list: + iface_patt_node + | iface_patt_list ',' iface_patt_node + ; + + /* Direct device route protocol */ CF_ADDTO(proto, dev_proto '}') @@ -167,25 +192,20 @@ dev_proto_start: proto_start DIRECT { dev_proto: dev_proto_start proto_name '{' | dev_proto proto_item ';' - | dev_proto dev_iface_list ';' + | dev_proto dev_iface_patt ';' ; -dev_iface_entry_init: +dev_iface_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; + this_ipatt = cfg_allocz(sizeof(struct iface_patt)); + add_tail(&p->iface_list, NODE this_ipatt); + init_list(&this_ipatt->ipn_list); } ; -dev_iface_entry: - dev_iface_entry_init iface_patt - ; - -dev_iface_list: - INTERFACE dev_iface_entry - | dev_iface_list ',' dev_iface_entry +dev_iface_patt: + INTERFACE dev_iface_init iface_patt_list ; /* Debug flags */ diff --git a/nest/iface.c b/nest/iface.c index 157a977a..01f25810 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -543,32 +543,72 @@ if_init(void) * Interface Pattern Lists */ -struct iface_patt * -iface_patt_match(list *l, struct iface *i) +static int +iface_patt_match(struct iface_patt *ifp, struct iface *i) { - struct iface_patt *p; + struct iface_patt_node *p; - WALK_LIST(p, *l) + WALK_LIST(p, ifp->ipn_list) { char *t = p->pattern; - int ok = 1; + int pos = p->positive; + if (t) { if (*t == '-') { t++; - ok = 0; + pos = !pos; } + if (!patmatch(t, i->name)) continue; } - if (!i->addr || !ipa_in_net(i->addr->ip, p->prefix, p->pxlen)) - continue; - return ok ? p : NULL; + + if (p->pxlen) + if (!i->addr || !ipa_in_net(i->addr->ip, p->prefix, p->pxlen)) + continue; + + return pos; } + + return 0; +} + +struct iface_patt * +iface_patt_find(list *l, struct iface *i) +{ + struct iface_patt *p; + + WALK_LIST(p, *l) + if (iface_patt_match(p, i)) + return p; + return NULL; } +static int +iface_plists_equal(struct iface_patt *pa, struct iface_patt *pb) +{ + struct iface_patt_node *x, *y; + + x = HEAD(pa->ipn_list); + y = HEAD(pb->ipn_list); + while (x->n.next && y->n.next) + { + if ((x->positive != y->positive) || + (!x->pattern && y->pattern) || /* This nasty lines where written by me... :-( Feela */ + (!y->pattern && x->pattern) || + ((x->pattern != y->pattern) && strcmp(x->pattern, y->pattern)) || + !ipa_equal(x->prefix, y->prefix) || + (x->pxlen != y->pxlen)) + return 0; + x = (void *) x->n.next; + y = (void *) y->n.next; + } + return (!x->n.next && !y->n.next); +} + int iface_patts_equal(list *a, list *b, int (*comp)(struct iface_patt *, struct iface_patt *)) { @@ -578,13 +618,8 @@ 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 ((!x->pattern && y->pattern) || /* This nasty lines where written by me... :-( Feela */ - (!y->pattern && x->pattern) || - (!(x->pattern==y->pattern) && - strcmp(x->pattern, y->pattern)) || - !ipa_equal(x->prefix, y->prefix) || - x->pxlen != y->pxlen || - comp && !comp(x, y)) + if (!iface_plists_equal(x, y) || + (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 e37f9522..f884dd90 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -116,16 +116,22 @@ void neigh_init(struct pool *); * Interface Pattern Lists */ +struct iface_patt_node { + node n; + int positive; + byte *pattern; + ip_addr prefix; + int pxlen; +}; + struct iface_patt { node n; - byte *pattern; /* Interface name pattern */ - ip_addr prefix; /* Interface prefix */ - int pxlen; + list ipn_list; /* A list of struct iface_patt_node */ /* Protocol-specific data follow after this structure */ }; -struct iface_patt *iface_patt_match(list *, struct iface *); +struct iface_patt *iface_patt_find(list *, struct iface *); int iface_patts_equal(list *, list *, int (*)(struct iface_patt *, struct iface_patt *)); #endif diff --git a/nest/rt-dev.c b/nest/rt-dev.c index 269346de..348bcc2e 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -30,7 +30,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad) struct rt_dev_config *P = (void *) p->cf; if (!EMPTY_LIST(P->iface_list) && - !iface_patt_match(&P->iface_list, ad->iface)) + !iface_patt_find(&P->iface_list, ad->iface)) /* Empty list is automagically treated as "*" */ return; if (c & IF_CHANGE_DOWN) diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index bfe2d9c8..7f7d6a31 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -13,9 +13,9 @@ CF_HDR CF_DEFINES #define OSPF_CFG ((struct ospf_config *) this_proto) -static struct ospf_area_config *this_area; -static struct iface_patt *this_ipatt; #define OSPF_PATT ((struct ospf_iface_patt *) this_ipatt) + +static struct ospf_area_config *this_area; static struct nbma_node *this_nbma; static struct area_net_config *this_pref; @@ -90,7 +90,7 @@ ospf_area_item: STUB COST expr { this_area->stub = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); } | STUB bool {if($2) { if(!this_area->stub) this_area->stub=DEFAULT_STUB_COST;}else{ this_area->stub=0;}} | NETWORKS '{' pref_list '}' - | INTERFACE ospf_iface_list + | INTERFACE ospf_iface | ospf_vlink ; @@ -122,6 +122,7 @@ ospf_vlink_start: VIRTUAL LINK idval if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone"); this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); add_tail(&this_area->vlink_list, NODE this_ipatt); + init_list(&this_ipatt->ipn_list); OSPF_PATT->vid = $3; OSPF_PATT->cost = COST_D; OSPF_PATT->helloint = HELLOINT_D; @@ -222,6 +223,7 @@ ospf_iface_start: { this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); add_tail(&this_area->patt_list, NODE this_ipatt); + init_list(&this_ipatt->ipn_list); OSPF_PATT->cost = COST_D; OSPF_PATT->helloint = HELLOINT_D; OSPF_PATT->pollint = POLLINT_D; @@ -251,12 +253,7 @@ ospf_iface_opt_list: ; ospf_iface: - ospf_iface_start iface_patt ospf_iface_opt_list { finish_iface_config(OSPF_PATT); } - ; - -ospf_iface_list: - ospf_iface - | ospf_iface_list ',' ospf_iface + ospf_iface_start iface_patt_list ospf_iface_opt_list { finish_iface_config(OSPF_PATT); } ; opttext: diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index a4c97413..5162f9f0 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -550,7 +550,7 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface) WALK_LIST(ac, c->area_list) { if (ip = (struct ospf_iface_patt *) - iface_patt_match(&ac->patt_list, iface)) + iface_patt_find(&ac->patt_list, iface)) break; } diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 1eae3762..0cab1d7b 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -634,11 +634,11 @@ ospf_reconfigure(struct proto *p, struct proto_config *c) WALK_LIST(ifa, po->iface_list) { if (oldip = (struct ospf_iface_patt *) - iface_patt_match(&oldac->patt_list, ifa->iface)) + iface_patt_find(&oldac->patt_list, ifa->iface)) { /* Now reconfigure interface */ if (!(newip = (struct ospf_iface_patt *) - iface_patt_match(&newac->patt_list, ifa->iface))) + iface_patt_find(&newac->patt_list, ifa->iface))) return 0; /* HELLO TIMER */ diff --git a/proto/rip/config.Y b/proto/rip/config.Y index f1ae43cb..9a11069e 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -55,7 +55,7 @@ rip_cfg: | rip_cfg HONOR ALWAYS ';' { RIP_CFG->honor = HO_ALWAYS; } | rip_cfg HONOR NEIGHBOR ';' { RIP_CFG->honor = HO_NEIGHBOR; } | rip_cfg HONOR NEVER ';' { RIP_CFG->honor = HO_NEVER; } - | rip_cfg rip_iface_list ';' + | rip_cfg INTERFACE rip_iface ';' ; rip_auth: @@ -64,6 +64,7 @@ rip_auth: | NONE { $$=AT_NONE; } ; + rip_mode: BROADCAST { $$=IM_BROADCAST; } | MULTICAST { $$=0; } @@ -78,28 +79,26 @@ rip_iface_item: ; rip_iface_opts: - '{' + /* empty */ | rip_iface_opts rip_iface_item ';' ; -rip_iface_opt_list: /* 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; + this_ipatt = cfg_allocz(sizeof(struct rip_patt)); + add_tail(&RIP_CFG->iface_list, NODE this_ipatt); + init_list(&this_ipatt->ipn_list); + RIP_IPATT->metric = 1; } ; rip_iface: - rip_iface_init iface_patt rip_iface_opt_list - ; - -rip_iface_list: - INTERFACE rip_iface - | rip_iface_list ',' rip_iface + rip_iface_init iface_patt_list rip_iface_opt_list ; CF_ADDTO(dynamic_attr, RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_RIP_METRIC); }) diff --git a/proto/rip/rip.c b/proto/rip/rip.c index b5a4cc36..12cc8783 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -742,7 +742,7 @@ rip_real_if_add(struct object_lock *lock) struct iface *iface = lock->iface; struct proto *p = lock->data; struct rip_interface *rif; - struct iface_patt *k = iface_patt_match(&P_CF->iface_list, iface); + struct iface_patt *k = iface_patt_find(&P_CF->iface_list, iface); if (!k) bug("This can not happen! It existed few seconds ago!" ); @@ -771,7 +771,7 @@ rip_if_notify(struct proto *p, unsigned c, struct iface *iface) } } if (c & IF_CHANGE_UP) { - struct iface_patt *k = iface_patt_match(&P_CF->iface_list, iface); + struct iface_patt *k = iface_patt_find(&P_CF->iface_list, iface); struct object_lock *lock; struct rip_patt *PATT = (struct rip_patt *) k;