summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2005-04-28 13:54:46 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2005-04-28 13:54:46 +0000
commit934b54fb57ccdabbc5621556f361d6f264d7781c (patch)
treee1a8b7bd3a70362a1cf5ecca2a3c517b5db28e41
parent0038c3369dd66655dd155902da4283ca84dc9f36 (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.c51
-rw-r--r--usr.sbin/bgpd/bgpd.conf.510
-rw-r--r--usr.sbin/bgpd/bgpd.h11
-rw-r--r--usr.sbin/bgpd/kroute.c113
-rw-r--r--usr.sbin/bgpd/parse.y23
-rw-r--r--usr.sbin/bgpd/printconf.c17
-rw-r--r--usr.sbin/bgpd/rde.c12
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))