summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/rde.c53
-rw-r--r--usr.sbin/bgpd/rde.h9
-rw-r--r--usr.sbin/bgpd/rde_filter.c19
-rw-r--r--usr.sbin/bgpd/rde_rib.c17
-rw-r--r--usr.sbin/bgpd/rde_update.c46
5 files changed, 80 insertions, 64 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 6f7cc7017ae..00498b8765b 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.190 2006/01/05 16:00:07 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.191 2006/01/12 14:05:13 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -827,14 +827,9 @@ rde_update_dispatch(struct imsg *imsg)
return (-1);
}
- /*
- * We need to copy attrs before calling the filter because
- * the filter may change the attributes.
- */
- fasp = path_copy(asp);
/* input filter */
- if (rde_filter(rules_l, peer, fasp, &prefix, prefixlen, peer,
- DIR_IN) == ACTION_DENY) {
+ if (rde_filter(&fasp, rules_l, peer, asp, &prefix, prefixlen,
+ peer, DIR_IN) == ACTION_DENY) {
path_put(fasp);
continue;
}
@@ -850,9 +845,16 @@ rde_update_dispatch(struct imsg *imsg)
return (-1);
}
- rde_update_log("update", peer, &asp->nexthop->exit_nexthop,
+ if (fasp == NULL)
+ fasp = asp;
+
+ rde_update_log("update", peer, &fasp->nexthop->exit_nexthop,
&prefix, prefixlen);
path_update(peer, fasp, &prefix, prefixlen);
+
+ /* free modified aspath */
+ if (fasp != asp)
+ path_put(fasp);
}
/* add MP_REACH_NLRI if available */
@@ -912,10 +914,10 @@ rde_update_dispatch(struct imsg *imsg)
mpp += pos;
mplen -= pos;
- fasp = path_copy(asp);
/* input filter */
- if (rde_filter(rules_l, peer, fasp, &prefix,
- prefixlen, peer, DIR_IN) == ACTION_DENY) {
+ if (rde_filter(&fasp, rules_l, peer, asp,
+ &prefix, prefixlen, peer, DIR_IN) ==
+ ACTION_DENY) {
path_put(fasp);
continue;
}
@@ -932,10 +934,17 @@ rde_update_dispatch(struct imsg *imsg)
return (-1);
}
+ if (fasp == NULL)
+ fasp = asp;
+
rde_update_log("update", peer,
&asp->nexthop->exit_nexthop,
&prefix, prefixlen);
path_update(peer, fasp, &prefix, prefixlen);
+
+ /* free modified aspath */
+ if (fasp != asp)
+ path_put(fasp);
}
break;
default:
@@ -1686,14 +1695,12 @@ rde_softreconfig_out(struct pt_entry *pt, void *ptr)
if (up_test_update(peer, p) != 1)
continue;
- /* copy attributes for output filter */
- oasp = path_copy(p->aspath);
- nasp = path_copy(p->aspath);
-
- oa = rde_filter(rules_l, peer, oasp, &addr, pt->prefixlen,
- p->aspath->peer, DIR_OUT);
- na = rde_filter(newrules, peer, nasp, &addr, pt->prefixlen,
- p->aspath->peer, DIR_OUT);
+ oa = rde_filter(&oasp, rules_l, peer, p->aspath, &addr,
+ pt->prefixlen, p->aspath->peer, DIR_OUT);
+ na = rde_filter(&nasp, newrules, peer, p->aspath, &addr,
+ pt->prefixlen, p->aspath->peer, DIR_OUT);
+ oasp = oasp != NULL ? oasp : p->aspath;
+ nasp = nasp != NULL ? nasp : p->aspath;
if (oa == ACTION_DENY && na == ACTION_DENY)
/* nothing todo */
@@ -1716,8 +1723,10 @@ rde_softreconfig_out(struct pt_entry *pt, void *ptr)
}
done:
- path_put(oasp);
- path_put(nasp);
+ if (oasp != p->aspath)
+ path_put(oasp);
+ if (nasp != p->aspath)
+ path_put(nasp);
}
}
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index ae049bdee7a..b40a897718a 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.81 2006/01/10 16:11:12 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.82 2006/01/12 14:05:13 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -355,9 +355,10 @@ void pt_dump(void (*)(struct pt_entry *, void *), void *,
sa_family_t);
/* rde_filter.c */
-enum filter_actions rde_filter(struct filter_head *, struct rde_peer *,
- struct rde_aspath *, struct bgpd_addr *, u_int8_t,
- struct rde_peer *, enum directions);
+enum filter_actions rde_filter(struct rde_aspath **, struct filter_head *,
+ struct rde_peer *, struct rde_aspath *,
+ struct bgpd_addr *, u_int8_t, struct rde_peer *,
+ enum directions);
void rde_apply_set(struct rde_aspath *, struct filter_set_head *,
sa_family_t, struct rde_peer *, enum directions);
int rde_filter_community(struct rde_aspath *, int, int);
diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c
index 1225307b196..1013e7e3aef 100644
--- a/usr.sbin/bgpd/rde_filter.c
+++ b/usr.sbin/bgpd/rde_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_filter.c,v 1.40 2006/01/10 16:11:12 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.41 2006/01/12 14:05:13 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -30,13 +30,16 @@ int rde_filter_match(struct filter_rule *, struct rde_aspath *,
int filterset_equal(struct filter_set_head *, struct filter_set_head *);
enum filter_actions
-rde_filter(struct filter_head *rules, struct rde_peer *peer,
- struct rde_aspath *asp, struct bgpd_addr *prefix, u_int8_t prefixlen,
- struct rde_peer *from, enum directions dir)
+rde_filter(struct rde_aspath **new, struct filter_head *rules,
+ struct rde_peer *peer, struct rde_aspath *asp, struct bgpd_addr *prefix,
+ u_int8_t prefixlen, struct rde_peer *from, enum directions dir)
{
struct filter_rule *f;
enum filter_actions action = ACTION_ALLOW; /* default allow */
+ if (new != NULL)
+ *new = NULL;
+
TAILQ_FOREACH(f, rules, entry) {
if (dir != f->dir)
continue;
@@ -47,9 +50,13 @@ rde_filter(struct filter_head *rules, struct rde_peer *peer,
f->peer.peerid != peer->conf.id)
continue;
if (rde_filter_match(f, asp, prefix, prefixlen)) {
- if (asp != NULL)
- rde_apply_set(asp, &f->set, prefix->af,
+ if (asp != NULL && new != NULL) {
+ /* asp may get modified so create a copy */
+ if (*new == NULL)
+ *new = path_copy(asp);
+ rde_apply_set(*new, &f->set, prefix->af,
from, dir);
+ }
if (f->action != ACTION_NONE)
action = f->action;
if (f->quick)
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index a06200c728d..41548ef65b4 100644
--- a/usr.sbin/bgpd/rde_rib.c
+++ b/usr.sbin/bgpd/rde_rib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.76 2006/01/09 16:00:48 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.77 2006/01/12 14:05:13 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -86,8 +86,6 @@ path_update(struct rde_peer *peer, struct rde_aspath *nasp,
if ((p = prefix_get(peer, prefix, prefixlen)) != NULL) {
if (path_compare(nasp, p->aspath) == 0) {
- /* already registered */
- path_put(nasp);
/* update last change */
p->lastchange = time(NULL);
return;
@@ -100,12 +98,10 @@ path_update(struct rde_peer *peer, struct rde_aspath *nasp,
* already in the RIB.
*/
if ((asp = path_lookup(nasp, peer)) == NULL) {
- /* path not available, link new */
- path_link(nasp, peer);
- asp = nasp;
- } else
- /* path found, new aspath no longer needed */
- path_put(nasp);
+ /* path not available, create and link new one */
+ asp = path_copy(nasp);
+ path_link(asp, peer);
+ }
/* if the prefix was found move it else add it to the aspath */
if (p != NULL)
@@ -299,6 +295,9 @@ path_get(void)
void
path_put(struct rde_aspath *asp)
{
+ if (asp == NULL)
+ return;
+
if (asp->flags & F_ATTR_LINKED)
fatalx("path_put: linked object");
diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c
index e9606c96803..9593430bd64 100644
--- a/usr.sbin/bgpd/rde_update.c
+++ b/usr.sbin/bgpd/rde_update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_update.c,v 1.47 2006/01/05 16:00:07 claudio Exp $ */
+/* $OpenBSD: rde_update.c,v 1.48 2006/01/12 14:05:13 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -400,7 +400,7 @@ void
up_generate_updates(struct filter_head *rules, struct rde_peer *peer,
struct prefix *new, struct prefix *old)
{
- struct rde_aspath *fasp;
+ struct rde_aspath *asp;
struct bgpd_addr addr;
if (peer->state != PEER_UP)
@@ -411,16 +411,11 @@ up_generate_updates(struct filter_head *rules, struct rde_peer *peer,
if (up_test_update(peer, old) != 1)
return;
- /* copy attributes for output filter */
- fasp = path_copy(old->aspath);
-
pt_getaddr(old->prefix, &addr);
- if (rde_filter(rules, peer, fasp, &addr, old->prefix->prefixlen,
- old->aspath->peer, DIR_OUT) == ACTION_DENY) {
- path_put(fasp);
+ if (rde_filter(NULL, rules, peer, old->aspath, &addr,
+ old->prefix->prefixlen, old->aspath->peer, DIR_OUT) ==
+ ACTION_DENY)
return;
- }
- path_put(fasp);
/* withdraw prefix */
up_generate(peer, NULL, &addr, old->prefix->prefixlen);
@@ -435,22 +430,22 @@ up_generate_updates(struct filter_head *rules, struct rde_peer *peer,
return;
}
- /* copy attributes for output filter */
- fasp = path_copy(new->aspath);
-
pt_getaddr(new->prefix, &addr);
- if (rde_filter(rules, peer, fasp, &addr, new->prefix->prefixlen,
- new->aspath->peer, DIR_OUT) == ACTION_DENY) {
- path_put(fasp);
+ if (rde_filter(&asp, rules, peer, new->aspath, &addr,
+ new->prefix->prefixlen, new->aspath->peer, DIR_OUT) ==
+ ACTION_DENY) {
+ path_put(asp);
up_generate_updates(rules, peer, NULL, old);
return;
}
/* generate update */
- up_generate(peer, fasp, &addr, new->prefix->prefixlen);
-
- /* no longer needed */
- path_put(fasp);
+ if (asp != NULL) {
+ up_generate(peer, asp, &addr, new->prefix->prefixlen);
+ path_put(asp);
+ } else
+ up_generate(peer, new->aspath, &addr,
+ new->prefix->prefixlen);
}
}
@@ -459,7 +454,7 @@ void
up_generate_default(struct filter_head *rules, struct rde_peer *peer,
sa_family_t af)
{
- struct rde_aspath *asp;
+ struct rde_aspath *asp, *fasp;
struct bgpd_addr addr;
if (peer->capa_received.mp_v4 == SAFI_NONE &&
@@ -486,16 +481,21 @@ up_generate_default(struct filter_head *rules, struct rde_peer *peer,
bzero(&addr, sizeof(addr));
addr.af = af;
- if (rde_filter(rules, peer, asp, &addr, 0, NULL, DIR_OUT) ==
+ if (rde_filter(&fasp, rules, peer, asp, &addr, 0, NULL, DIR_OUT) ==
ACTION_DENY) {
+ path_put(fasp);
path_put(asp);
return;
}
/* generate update */
- up_generate(peer, asp, &addr, 0);
+ if (fasp != NULL)
+ up_generate(peer, fasp, &addr, 0);
+ else
+ up_generate(peer, asp, &addr, 0);
/* no longer needed */
+ path_put(fasp);
path_put(asp);
}