diff options
-rw-r--r-- | usr.sbin/bgpd/rde.c | 78 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 12 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 12 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 17 |
4 files changed, 87 insertions, 32 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index d2dcd3559ca..14eda22d516 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.176 2005/11/01 14:37:16 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.177 2005/11/01 15:21:54 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -65,6 +65,7 @@ void rde_dump_upcall(struct pt_entry *, void *); void rde_dump_as(struct filter_as *, pid_t); void rde_dump_prefix_upcall(struct pt_entry *, void *); void rde_dump_prefix(struct ctl_show_rib_prefix *, pid_t); +void rde_softreconfig_out(struct pt_entry *, void *); void rde_up_dump_upcall(struct pt_entry *, void *); void rde_update_queue_runner(void); void rde_update6_queue_runner(void); @@ -520,7 +521,8 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf) nconf = NULL; parent_set = NULL; prefix_network_clean(&peerself, reloadtime); - /* soft reconfig out */ + + pt_dump(rde_softreconfig_out, NULL, AF_UNSPEC); while ((r = TAILQ_FIRST(rules_l)) != NULL) { TAILQ_REMOVE(rules_l, r, entry); filterset_free(&r->set); @@ -706,7 +708,7 @@ rde_update_dispatch(struct imsg *imsg) } /* input filter */ - if (rde_filter(peer, NULL, &prefix, prefixlen, peer, + if (rde_filter(rules_l, peer, NULL, &prefix, prefixlen, peer, DIR_IN) == ACTION_DENY) continue; @@ -762,8 +764,8 @@ rde_update_dispatch(struct imsg *imsg) mplen -= pos; /* input filter */ - if (rde_filter(peer, NULL, &prefix, prefixlen, - peer, DIR_IN) == ACTION_DENY) + if (rde_filter(rules_l, peer, NULL, &prefix, + prefixlen, peer, DIR_IN) == ACTION_DENY) continue; rde_update_log("withdraw", peer, NULL, @@ -827,7 +829,7 @@ rde_update_dispatch(struct imsg *imsg) */ fasp = path_copy(asp); /* input filter */ - if (rde_filter(peer, fasp, &prefix, prefixlen, peer, + if (rde_filter(rules_l, peer, fasp, &prefix, prefixlen, peer, DIR_IN) == ACTION_DENY) { path_put(fasp); continue; @@ -908,8 +910,8 @@ rde_update_dispatch(struct imsg *imsg) fasp = path_copy(asp); /* input filter */ - if (rde_filter(peer, fasp, &prefix, prefixlen, - peer, DIR_IN) == ACTION_DENY) { + if (rde_filter(rules_l, peer, fasp, &prefix, + prefixlen, peer, DIR_IN) == ACTION_DENY) { path_put(fasp); continue; } @@ -1777,13 +1779,65 @@ rde_send_nexthop(struct bgpd_addr *next, int valid) u_char queue_buf[4096]; void +rde_softreconfig_out(struct pt_entry *pt, void *ptr) +{ + struct prefix *p = pt->active; + struct rde_peer *peer; + struct rde_aspath *oasp, *nasp; + enum filter_actions oa, na; + struct bgpd_addr addr; + + if (p == NULL) + return; + + pt_getaddr(pt, &addr); + LIST_FOREACH(peer, &peerlist, peer_l) { + 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->peer, DIR_OUT); + na = rde_filter(newrules, peer, nasp, &addr, pt->prefixlen, + p->peer, DIR_OUT); + + if (oa == ACTION_DENY && na == ACTION_DENY) + /* nothing todo */ + goto done; + if (oa == ACTION_DENY && na == ACTION_ALLOW) { + /* send update */ + up_generate(peer, nasp, &addr, pt->prefixlen); + goto done; + } + if (oa == ACTION_ALLOW && na == ACTION_DENY) { + /* send withdraw */ + up_generate(peer, NULL, &addr, pt->prefixlen); + goto done; + } + if (oa == ACTION_ALLOW && na == ACTION_ALLOW) { + if (path_compare(nasp, oasp) == 0) + goto done; + /* send update */ + up_generate(peer, nasp, &addr, pt->prefixlen); + } + +done: + path_put(oasp); + path_put(nasp); + } +} + +void rde_up_dump_upcall(struct pt_entry *pt, void *ptr) { struct rde_peer *peer = ptr; if (pt->active == NULL) return; - up_generate_updates(peer, pt->active, NULL); + up_generate_updates(rules_l, peer, pt->active, NULL); } void @@ -1803,7 +1857,7 @@ rde_generate_updates(struct prefix *new, struct prefix *old) LIST_FOREACH(peer, &peerlist, peer_l) { if (peer->state != PEER_UP) continue; - up_generate_updates(peer, new, old); + up_generate_updates(rules_l, peer, new, old); } } @@ -2150,7 +2204,7 @@ peer_dump(u_int32_t id, u_int16_t afi, u_int8_t safi) safi == SAFI_BOTH) { if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) - up_generate_default(peer, AF_INET); + up_generate_default(rules_l, peer, AF_INET); else pt_dump(rde_up_dump_upcall, peer, AF_INET); } @@ -2159,7 +2213,7 @@ peer_dump(u_int32_t id, u_int16_t afi, u_int8_t safi) safi == SAFI_BOTH) { if (peer->conf.announce_type == ANNOUNCE_DEFAULT_ROUTE) - up_generate_default(peer, AF_INET6); + up_generate_default(rules_l, peer, AF_INET6); else pt_dump(rde_up_dump_upcall, peer, AF_INET6); } diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index b9fd7b8a41a..7e4988bc3ed 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.71 2005/11/01 14:37:16 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.72 2005/11/01 15:21:54 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -331,9 +331,10 @@ void up_down(struct rde_peer *); int up_test_update(struct rde_peer *, struct prefix *); int up_generate(struct rde_peer *, struct rde_aspath *, struct bgpd_addr *, u_int8_t); -void up_generate_updates(struct rde_peer *, +void up_generate_updates(struct filter_head *, struct rde_peer *, struct prefix *, struct prefix *); -void up_generate_default(struct rde_peer *, sa_family_t); +void up_generate_default(struct filter_head *, struct rde_peer *, + sa_family_t); int up_dump_prefix(u_char *, int, struct uplist_prefix *, struct rde_peer *); int up_dump_attrnlri(u_char *, int, struct rde_peer *); @@ -353,8 +354,9 @@ void pt_dump(void (*)(struct pt_entry *, void *), void *, sa_family_t); /* rde_filter.c */ -enum filter_actions rde_filter(struct rde_peer *, struct rde_aspath *, - struct bgpd_addr *, u_int8_t, struct rde_peer *, enum directions); +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); 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 9d197c7f19a..b238eb40da9 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.35 2005/11/01 10:58:29 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.36 2005/11/01 15:21:54 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -24,20 +24,18 @@ #include "bgpd.h" #include "rde.h" -extern struct filter_head *rules_l; /* XXX ugly */ - int rde_filter_match(struct filter_rule *, struct rde_aspath *, struct bgpd_addr *, u_int8_t); enum filter_actions -rde_filter(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 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 */ - TAILQ_FOREACH(f, rules_l, entry) { + TAILQ_FOREACH(f, rules, entry) { if (dir != f->dir) continue; if (f->peer.groupid != 0 && diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index 86b21cb8b16..5703cdee03e 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.42 2005/11/01 14:37:16 claudio Exp $ */ +/* $OpenBSD: rde_update.c,v 1.43 2005/11/01 15:21:54 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -394,7 +394,7 @@ up_generate(struct rde_peer *peer, struct rde_aspath *asp, } void -up_generate_updates(struct rde_peer *peer, +up_generate_updates(struct filter_head *rules, struct rde_peer *peer, struct prefix *new, struct prefix *old) { struct rde_aspath *fasp; @@ -412,7 +412,7 @@ up_generate_updates(struct rde_peer *peer, fasp = path_copy(old->aspath); pt_getaddr(old->prefix, &addr); - if (rde_filter(peer, fasp, &addr, old->prefix->prefixlen, + if (rde_filter(rules, peer, fasp, &addr, old->prefix->prefixlen, old->peer, DIR_OUT) == ACTION_DENY) { path_put(fasp); return; @@ -426,7 +426,7 @@ up_generate_updates(struct rde_peer *peer, case 1: break; case 0: - up_generate_updates(peer, NULL, old); + up_generate_updates(rules, peer, NULL, old); return; case -1: return; @@ -436,10 +436,10 @@ up_generate_updates(struct rde_peer *peer, fasp = path_copy(new->aspath); pt_getaddr(new->prefix, &addr); - if (rde_filter(peer, fasp, &addr, new->prefix->prefixlen, + if (rde_filter(rules, peer, fasp, &addr, new->prefix->prefixlen, new->peer, DIR_OUT) == ACTION_DENY) { path_put(fasp); - up_generate_updates(peer, NULL, old); + up_generate_updates(rules, peer, NULL, old); return; } @@ -453,7 +453,8 @@ up_generate_updates(struct rde_peer *peer, /* send a default route to the specified peer */ void -up_generate_default(struct rde_peer *peer, sa_family_t af) +up_generate_default(struct filter_head *rules, struct rde_peer *peer, + sa_family_t af) { struct rde_aspath *asp; struct bgpd_addr addr; @@ -482,7 +483,7 @@ up_generate_default(struct rde_peer *peer, sa_family_t af) bzero(&addr, sizeof(addr)); addr.af = af; - if (rde_filter(peer, asp, &addr, 0, NULL, DIR_OUT) == + if (rde_filter(rules, peer, asp, &addr, 0, NULL, DIR_OUT) == ACTION_DENY) { path_put(asp); return; |