summaryrefslogtreecommitdiffstats
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/config.Y52
-rw-r--r--nest/iface.c67
-rw-r--r--nest/iface.h14
-rw-r--r--nest/rt-dev.c2
4 files changed, 98 insertions, 37 deletions
diff --git a/nest/config.Y b/nest/config.Y
index e843777..1d2f015 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 157a977..01f2581 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 e37f952..f884dd9 100644
--- a/nest/iface.h
+++ b/nest/iface.h
@@ -116,16 +116,22 @@ void neigh_init(struct pool *);
* Interface Pattern Lists
*/
-struct iface_patt {
+struct iface_patt_node {
node n;
- byte *pattern; /* Interface name pattern */
- ip_addr prefix; /* Interface prefix */
+ int positive;
+ byte *pattern;
+ ip_addr prefix;
int pxlen;
+};
+
+struct iface_patt {
+ node n;
+ 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 269346d..348bcc2 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)