diff options
-rw-r--r-- | usr.sbin/bgpd/rde.c | 53 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 9 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 19 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 17 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 46 |
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); } |