diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2005-04-28 13:54:46 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2005-04-28 13:54:46 +0000 |
commit | 934b54fb57ccdabbc5621556f361d6f264d7781c (patch) | |
tree | e1a8b7bd3a70362a1cf5ecca2a3c517b5db28e41 | |
parent | 0038c3369dd66655dd155902da4283ca84dc9f36 (diff) |
Support for "network connected" and "network static" -- announce all
directly connected respectively all static routes. The list is auto-
matically adjusted as soon as a route changes.
OK henning@
-rw-r--r-- | usr.sbin/bgpd/bgpd.c | 51 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.conf.5 | 10 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 11 | ||||
-rw-r--r-- | usr.sbin/bgpd/kroute.c | 113 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 23 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 17 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 12 |
7 files changed, 223 insertions, 14 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c index 96cef6f54b0..0d198ba0b9e 100644 --- a/usr.sbin/bgpd/bgpd.c +++ b/usr.sbin/bgpd/bgpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.c,v 1.116 2005/03/30 11:23:15 henning Exp $ */ +/* $OpenBSD: bgpd.c,v 1.117 2005/04/28 13:54:45 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -47,6 +47,9 @@ int reconfigure(char *, struct bgpd_config *, struct mrt_head *, int dispatch_imsg(struct imsgbuf *, int); int rfd = -1; +int cflags = 0; +struct filter_set_head *connectset; +struct filter_set_head *staticset; volatile sig_atomic_t mrtdump = 0; volatile sig_atomic_t quit = 0; volatile sig_atomic_t reconfig = 0; @@ -165,6 +168,9 @@ main(int argc, char *argv[]) fprintf(stderr, "configuration OK\n"); exit(0); } + cflags = conf.flags; + connectset = &conf.connectset; + staticset = &conf.staticset; if (geteuid()) errx(1, "need root privileges"); @@ -416,6 +422,10 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, return (-1); } + cflags = conf->flags; + connectset = &conf->connectset; + staticset = &conf->staticset; + prepare_listeners(conf); if (imsg_compose(ibuf_se, IMSG_RECONF_CONF, 0, 0, -1, @@ -444,6 +454,10 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, TAILQ_REMOVE(&net_l, n, entry); free(n); } + /* redistribute list needs to be reloaded too */ + if (kr_redist_reload() == -1) + return (-1); + while ((r = TAILQ_FIRST(rules_l)) != NULL) { if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1, r, sizeof(struct filter_rule)) == -1) @@ -628,3 +642,38 @@ send_imsg_session(int type, pid_t pid, void *data, u_int16_t datalen) { imsg_compose(ibuf_se, type, 0, pid, -1, data, datalen); } + +int +bgpd_redistribute(int type, struct kroute *kr) +{ + struct network_config net; + struct filter_set_head *h; + + if ((cflags & BGPD_FLAG_REDIST_CONNECTED) && (kr->flags & F_CONNECTED)) + h = connectset; + else if ((cflags & BGPD_FLAG_REDIST_STATIC) && (kr->flags & F_STATIC)) + h = staticset; + else + return (0); + + bzero(&net, sizeof(net)); + net.prefix.af = AF_INET; + net.prefix.v4.s_addr = kr->prefix.s_addr; + net.prefixlen = kr->prefixlen; + + if (imsg_compose(ibuf_rde, type, 0, 0, -1, &net, + sizeof(struct network_config)) == -1) + return (-1); + + /* networks that get deleted don't need to send the filter set */ + if (type == IMSG_NETWORK_REMOVE) + return (1); + + if (send_filterset(ibuf_rde, h, 0, 0) == -1) + return (-1); + if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) + return (-1); + + return (1); +} + diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index 2845e2f41e8..aac11a82ffb 100644 --- a/usr.sbin/bgpd/bgpd.conf.5 +++ b/usr.sbin/bgpd/bgpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpd.conf.5,v 1.52 2005/04/18 11:19:39 jmc Exp $ +.\" $OpenBSD: bgpd.conf.5,v 1.53 2005/04/28 13:54:45 claudio Exp $ .\" .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -206,7 +206,15 @@ Log received and sent updates. .Ar address Ns Li / Ns Ar prefix .Op Ic set ...\& .Xc +.It Ic network static Op Ic set ...\& +.It Ic network connected Op Ic set ...\& Announce the specified network as belonging to our AS. +If set to +.Ic connected , +routes to directly attached networks will be announced. +If set to +.Ic static , +all static routes will be announced. .Bd -literal -offset indent network 192.168.7.0/24 .Ed diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index d7bdc63af57..5c01b0c142c 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.164 2005/04/26 15:18:22 henning Exp $ */ +/* $OpenBSD: bgpd.h,v 1.165 2005/04/28 13:54:45 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -52,6 +52,8 @@ #define BGPD_FLAG_NO_FIB_UPDATE 0x0001 #define BGPD_FLAG_NO_EVALUATE 0x0002 #define BGPD_FLAG_REFLECTOR 0x0004 +#define BGPD_FLAG_REDIST_STATIC 0x0008 +#define BGPD_FLAG_REDIST_CONNECTED 0x0010 #define BGPD_FLAG_DECISION_MASK 0x0f00 #define BGPD_FLAG_DECISION_ROUTEAGE 0x0100 #define BGPD_FLAG_DECISION_TRANS_AS 0x0200 @@ -127,8 +129,11 @@ struct listen_addr { }; TAILQ_HEAD(listen_addrs, listen_addr); +SIMPLEQ_HEAD(filter_set_head, filter_set); struct bgpd_config { + struct filter_set_head connectset; + struct filter_set_head staticset; struct listen_addrs *listen_addrs; int opts; int flags; @@ -195,8 +200,6 @@ struct capabilities { u_int8_t refresh; /* route refresh, RFC 2918 */ }; -SIMPLEQ_HEAD(filter_set_head, filter_set); - struct peer_config { struct bgpd_addr remote_addr; struct bgpd_addr local_addr; @@ -591,6 +594,7 @@ struct rrefresh { /* bgpd.c */ void send_nexthop_update(struct kroute_nexthop *); void send_imsg_session(int, pid_t, void *, u_int16_t); +int bgpd_redistribute(int, struct kroute *); /* buffer.c */ struct buf *buf_open(size_t); @@ -651,6 +655,7 @@ int kr_nexthop_add(struct bgpd_addr *); void kr_nexthop_delete(struct bgpd_addr *); void kr_show_route(struct imsg *); void kr_ifinfo(char *); +int kr_redist_reload(void); in_addr_t prefixlen2mask(u_int8_t); struct in6_addr *prefixlen2mask6(u_int8_t prefixlen); void inet6applymask(struct in6_addr *, const struct in6_addr *, diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c index daac81ea272..9d29078bcdc 100644 --- a/usr.sbin/bgpd/kroute.c +++ b/usr.sbin/bgpd/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.124 2005/04/28 13:49:12 claudio Exp $ */ +/* $OpenBSD: kroute.c,v 1.125 2005/04/28 13:54:45 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -72,6 +72,7 @@ struct kif_node { struct kif_kr_head kroute_l; }; +int kr_redistribute(int, struct kroute *); int kroute_compare(struct kroute_node *, struct kroute_node *); int kroute6_compare(struct kroute6_node *, struct kroute6_node *); int knexthop_compare(struct knexthop_node *, struct knexthop_node *); @@ -433,6 +434,92 @@ kr_ifinfo(char *ifname) } } +struct redist_node { + LIST_ENTRY(redist_node) entry; + struct kroute *kr; +}; + +LIST_HEAD(, redist_node) redistlist; + +int +kr_redistribute(int type, struct kroute *kr) +{ + struct redist_node *rn; + u_int32_t a; + + if (!(kr->flags & F_KERNEL)) + return (0); + + /* + * We consider the loopback net, multicast and experimental addresses + * as not redistributable. + */ + a = ntohl(kr->prefix.s_addr); + if (IN_MULTICAST(a) || IN_BADCLASS(a) || + (a >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) + return (0); + /* + * Consider networks with nexthop loopback as not redistributable. + */ + if (kr->nexthop.s_addr == htonl(INADDR_LOOPBACK)) + return (0); + + /* + * never allow 0.0.0.0/0 the default route can only be redistributed + * with announce default. + */ + if (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0) + return (0); + + /* Add or delete kr from list ... + * using a linear list to store the redistributed networks will hurt + * as soon as redistribute ospf comes but until the keep it simple. + */ + LIST_FOREACH(rn, &redistlist, entry) + if (rn->kr == kr) + break; + + switch (type) { + case IMSG_NETWORK_ADD: + log_debug("kr_redistribute: ADD %s/%d fl %x", + inet_ntoa(kr->prefix), kr->prefixlen, kr->flags); + if (rn == NULL) { + if ((rn = calloc(1, sizeof(struct redist_node))) == + NULL) { + log_warn("kr_redistribute"); + return (-1); + } + rn->kr = kr; + LIST_INSERT_HEAD(&redistlist, rn, entry); + } + break; + case IMSG_NETWORK_REMOVE: + log_debug("kr_redistribute: DEL %s/%d fl %x", + inet_ntoa(kr->prefix), kr->prefixlen, kr->flags); + if (rn != NULL) { + LIST_REMOVE(rn, entry); + free(rn); + } + break; + default: + errno = EINVAL; + return (-1); + } + + return (bgpd_redistribute(type, kr)); +} + +int +kr_redist_reload(void) +{ + struct redist_node *rn; + + LIST_FOREACH(rn, &redistlist, entry) + if (bgpd_redistribute(IMSG_NETWORK_ADD, rn->kr) == -1) + return (-1); + return (0); +} + /* * RB-tree compare functions */ @@ -544,6 +631,8 @@ kroute_insert(struct kroute_node *kr) if (kr->r.flags & F_CONNECTED) if (kif_kr_insert(kr) == -1) return (-1); + + kr_redistribute(IMSG_NETWORK_ADD, &kr->r); } return (0); } @@ -565,6 +654,9 @@ kroute_remove(struct kroute_node *kr) if (s->kroute == kr) knexthop_validate(s); + if (kr->r.flags & F_KERNEL) + kr_redistribute(IMSG_NETWORK_REMOVE, &kr->r); + if (kr->r.flags & F_CONNECTED) if (kif_kr_remove(kr) == -1) { free(kr); @@ -1335,7 +1427,7 @@ dispatch_rtmsg(void) struct kroute_node *kr; struct in_addr prefix, nexthop; u_int8_t prefixlen; - int flags; + int flags, oflags; u_short ifindex; if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) { @@ -1420,13 +1512,22 @@ dispatch_rtmsg(void) kr->r.nexthop.s_addr = nexthop.s_addr; if (kr->r.flags & F_NEXTHOP) flags |= F_NEXTHOP; - if ((kr->r.flags & F_CONNECTED) && - !(flags & F_CONNECTED)) + oflags = kr->r.flags; + kr->r.flags = flags; + if ((oflags & F_CONNECTED) && + !(flags & F_CONNECTED)) { kif_kr_remove(kr); + kr_redistribute( + IMSG_NETWORK_REMOVE, + &kr->r); + } if ((flags & F_CONNECTED) && - !(kr->r.flags & F_CONNECTED)) + !(oflags & F_CONNECTED)) { kif_kr_insert(kr); - kr->r.flags = flags; + kr_redistribute( + IMSG_NETWORK_ADD, + &kr->r); + } } } else if (rtm->rtm_type == RTM_CHANGE) { log_warnx("change req for %s/%u: not " diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index dff6c9ae9a7..3b0ac5f6a18 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.161 2005/04/17 16:41:21 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.162 2005/04/28 13:54:45 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -150,6 +150,7 @@ typedef struct { %token ALLOW DENY MATCH %token QUICK %token FROM TO ANY +%token CONNECTED STATIC %token PREFIX PREFIXLEN SOURCEAS TRANSITAS COMMUNITY %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY %token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT @@ -343,6 +344,24 @@ conf_main : AS asnumber { TAILQ_INSERT_TAIL(netconf, n, entry); } + | NETWORK STATIC filter_set { + conf->flags |= BGPD_FLAG_REDIST_STATIC; + if ($3 == NULL || SIMPLEQ_EMPTY($3)) + SIMPLEQ_INIT(&conf->staticset); + else + memcpy(&conf->staticset, $3, + sizeof(conf->staticset)); + free($3); + } + | NETWORK CONNECTED filter_set { + conf->flags |= BGPD_FLAG_REDIST_CONNECTED; + if ($3 == NULL || SIMPLEQ_EMPTY($3)) + SIMPLEQ_INIT(&conf->connectset); + else + memcpy(&conf->connectset, $3, + sizeof(conf->connectset)); + free($3); + } | DUMP STRING STRING optnumber { int action; @@ -1393,6 +1412,7 @@ lookup(char *s) { "blackhole", BLACKHOLE}, { "capabilities", CAPABILITIES}, { "community", COMMUNITY}, + { "connected", CONNECTED}, { "deny", DENY}, { "depend", DEPEND}, { "descr", DESCR}, @@ -1444,6 +1464,7 @@ lookup(char *s) { "set", SET}, { "source-as", SOURCEAS}, { "spi", SPI}, + { "static", STATIC}, { "tcp", TCP}, { "to", TO}, { "transit-as", TRANSITAS}, diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 38142517e14..dc61d881ccf 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.40 2005/04/18 11:00:42 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.41 2005/04/28 13:54:45 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -165,6 +165,21 @@ print_mainconf(struct bgpd_config *conf) TAILQ_FOREACH(la, conf->listen_addrs, entry) printf("listen on %s\n", log_sockaddr((struct sockaddr *)&la->sa)); + + if (conf->flags & BGPD_FLAG_REDIST_CONNECTED) { + printf("network connected"); + if (!SIMPLEQ_EMPTY(&conf->connectset)) + printf(" "); + print_set(&conf->connectset); + printf("\n"); + } + if (conf->flags & BGPD_FLAG_REDIST_STATIC) { + printf("network static"); + if (!SIMPLEQ_EMPTY(&conf->staticset)) + printf(" "); + print_set(&conf->staticset); + printf("\n"); + } } void diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 73a1c05952b..28f83a64509 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.157 2005/04/16 19:10:59 cloder Exp $ */ +/* $OpenBSD: rde.c,v 1.158 2005/04/28 13:54:45 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -486,6 +486,16 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf) parent_set = NULL; network_add(&netconf_p, 1); break; + case IMSG_NETWORK_REMOVE: + if (imsg.hdr.len - IMSG_HEADER_SIZE != + sizeof(struct network_config)) { + log_warnx("rde_dispatch: wrong imsg len"); + break; + } + memcpy(&netconf_p, imsg.data, sizeof(netconf_p)); + SIMPLEQ_INIT(&netconf_p.attrset); + network_delete(&netconf_p, 1); + break; case IMSG_RECONF_FILTER: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct filter_rule)) |