diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-07-30 14:44:31 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-07-30 14:44:31 +0000 |
commit | 6f31625bc9c9324e216ae595bf936070a14ed0ad (patch) | |
tree | c9ea2d93a187ad06df2e36ddb687f3d2a5e42fe1 /usr.sbin/bgpd | |
parent | 306decf1e1aa0fee1e041fd60f3ddb4b1b3ec1ef (diff) |
Add new announce type "default-route" which will only announce the default
route to the specified neighbor. Idea and OK henning@
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 3 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 7 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 3 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 95 |
5 files changed, 94 insertions, 19 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index ed27696b4c2..1c01fcdecbe 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.136 2004/07/27 15:26:45 henning Exp $ */ +/* $OpenBSD: bgpd.h,v 1.137 2004/07/30 14:44:30 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -146,6 +146,7 @@ enum announce_type { ANNOUNCE_UNDEF, ANNOUNCE_SELF, ANNOUNCE_NONE, + ANNOUNCE_DEFAULT_ROUTE, ANNOUNCE_ALL }; diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 6214224936f..0947501c2e7 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.127 2004/07/28 17:05:08 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.128 2004/07/30 14:44:30 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -537,6 +537,9 @@ peeropts : REMOTEAS asnumber { curpeer->conf.announce_type = ANNOUNCE_NONE; else if (!strcmp($2, "all")) curpeer->conf.announce_type = ANNOUNCE_ALL; + else if (!strcmp($2, "default-route")) + curpeer->conf.announce_type = + ANNOUNCE_DEFAULT_ROUTE; else { free($2); YYERROR; diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 247bd52b400..54499d1ac62 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.129 2004/07/29 17:05:13 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.130 2004/07/30 14:44:30 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -1432,6 +1432,11 @@ peer_dump(u_int32_t id, u_int16_t afi, u_int8_t safi) if (afi == AFI_ALL || afi == AFI_IPv4) if (safi == SAFI_ALL || safi == SAFI_UNICAST || safi == SAFI_BOTH) { + if (peer->conf.announce_type == + ANNOUNCE_DEFAULT_ROUTE) { + up_generate_default(peer, AF_INET); + return; + } pt_dump(up_dump_upcall, peer, AF_INET); return; } diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index edee7b77d54..370c169c9ef 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.46 2004/07/28 16:02:14 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.47 2004/07/30 14:44:30 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -315,6 +315,7 @@ void up_init(struct rde_peer *); void up_down(struct rde_peer *); void up_generate_updates(struct rde_peer *, struct prefix *, struct prefix *); +void up_generate_default(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 *); diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index 5a712d28498..e44648a443e 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.23 2004/07/13 17:57:20 jaredy Exp $ */ +/* $OpenBSD: rde_update.c,v 1.24 2004/07/30 14:44:30 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -233,12 +233,6 @@ up_generate_updates(struct rde_peer *peer, if (peer->state != PEER_UP) return; - /* - * Filtering should be hooked up here. - * With filtering the decision if withdraw, update or nothing - * needs to be done on a per peer basis -- actually per filter - * set. - */ if (new == NULL || new->aspath->nexthop == NULL || new->aspath->nexthop->state != NEXTHOP_REACH) { @@ -261,7 +255,7 @@ up_generate_updates(struct rde_peer *peer, if (old->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) { /* - * redistribution rules: + * route reflector redistribution rules: * 1. if announce is set -> announce * 2. old non-client, new non-client -> no * 3. old client, new non-client -> yes @@ -280,6 +274,7 @@ up_generate_updates(struct rde_peer *peer, switch (peer->conf.announce_type) { case ANNOUNCE_UNDEF: case ANNOUNCE_NONE: + case ANNOUNCE_DEFAULT_ROUTE: return; case ANNOUNCE_ALL: break; @@ -306,7 +301,7 @@ up_generate_updates(struct rde_peer *peer, /* * don't send messages back to originator - * XXX this is not specified in the RFC but seems logical. + * NOTE this is not specified in the RFC but seems logical. */ if ((atr = attr_optget(&old->aspath->flags, ATTR_ORIGINATOR_ID)) != NULL) { @@ -330,7 +325,7 @@ up_generate_updates(struct rde_peer *peer, /* withdraw prefix */ p = calloc(1, sizeof(struct update_prefix)); if (p == NULL) - fatal("up_queue_update"); + fatal("up_generate_updates"); p->prefix = addr; p->prefixlen = old->prefix->prefixlen; @@ -356,7 +351,7 @@ up_generate_updates(struct rde_peer *peer, if (new->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) { /* - * redistribution rules: + * route reflector redistribution rules: * 1. if announce is set -> announce * 2. old non-client, new non-client -> no * 3. old client, new non-client -> yes @@ -377,7 +372,11 @@ up_generate_updates(struct rde_peer *peer, switch (peer->conf.announce_type) { case ANNOUNCE_UNDEF: case ANNOUNCE_NONE: - up_generate_updates(peer, NULL, old); + case ANNOUNCE_DEFAULT_ROUTE: + /* + * no need to withdraw old prefix as this will be + * filtered out to. + */ return; case ANNOUNCE_ALL: break; @@ -423,7 +422,7 @@ up_generate_updates(struct rde_peer *peer, /* * don't send messages back to originator - * XXX this is not specified in the RFC but seems logical. + * NOTE this is not specified in the RFC but seems logical. */ if ((atr = attr_optget(&new->aspath->flags, ATTR_ORIGINATOR_ID)) != NULL) { @@ -438,11 +437,11 @@ up_generate_updates(struct rde_peer *peer, /* generate update */ p = calloc(1, sizeof(struct update_prefix)); if (p == NULL) - fatal("up_queue_update"); + fatal("up_generate_updates"); a = calloc(1, sizeof(struct update_attr)); if (a == NULL) - fatal("up_queue_update"); + fatal("up_generate_updates"); if (up_generate_attr(peer, a, &attrs, new->aspath->nexthop) == -1) { @@ -468,6 +467,72 @@ up_generate_updates(struct rde_peer *peer, } } +void +up_generate_default(struct rde_peer *peer, sa_family_t af) +{ + struct update_attr *a; + struct update_prefix *p; + struct attr_flags attrs; + struct bgpd_addr addr; + struct nexthop nexthop; + + bzero(&attrs, sizeof(attrs)); + bzero(&addr, sizeof(addr)); + bzero(&nexthop, sizeof(nexthop)); + + attrs.aspath = aspath_create(NULL, 0); + attrs.nexthop.s_addr = INADDR_ANY; + /* med = 0 */ + attrs.lpref = DEFAULT_LPREF; + attrs.origin = ORIGIN_IGP; + TAILQ_INIT(&attrs.others); + + nexthop.state = NEXTHOP_REACH; + nexthop.flags = NEXTHOP_ANNOUNCE; + nexthop.exit_nexthop.af = af; + nexthop.true_nexthop.af = af; + + /* apply default overrides. Not yet possible */ + + /* filter as usual */ + addr.af = AF_INET; + if (rde_filter(peer, &attrs, &addr, 0, DIR_OUT) == ACTION_DENY) { + attr_free(&attrs); + return; + } + + /* generate update */ + p = calloc(1, sizeof(struct update_prefix)); + if (p == NULL) + fatal("up_generate_default"); + + a = calloc(1, sizeof(struct update_attr)); + if (a == NULL) + fatal("up_generate_default"); + + if (up_generate_attr(peer, a, &attrs, &nexthop) == -1) { + log_warnx("generation of bgp path attributes failed"); + free(a); + free(p); + return; + } + + /* + * use aspath_hash as attr_hash, this may be unoptimal + * but currently I don't care. + */ + a->attr_hash = aspath_hash(attrs.aspath); + p->prefix = addr; + p->prefixlen = 0; /* default route */ + + /* no longer needed */ + attr_free(&attrs); + + if (up_add(peer, p, a) == -1) + log_warnx("queuing update failed."); + +} + u_char up_attr_buf[4096]; int |