summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2012-05-27 18:52:08 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2012-05-27 18:52:08 +0000
commit6d2dfda18c9d1cfb00ff832aa663711ad744a864 (patch)
tree82b047f66b90d6888b4caa78a26828c8d7c2cd9d /usr.sbin/bgpd
parent4a7df4608e07bbe1a65a6b0008521846a55d2c06 (diff)
Extend the network code to allow attributes to be passed in with prefixes.
In the end this will allow anyone to use MRT table dumps to load prefixes into a bgpd instance. For example you can download the RIPE dumps and load full-feeds onto your laptop until the poor thing dies. OK henning@ sthen@
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.h20
-rw-r--r--usr.sbin/bgpd/control.c4
-rw-r--r--usr.sbin/bgpd/kroute.c8
-rw-r--r--usr.sbin/bgpd/rde.c108
4 files changed, 120 insertions, 20 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index c674ec32a4a..68b599ade5c 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.269 2012/04/12 17:31:05 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.270 2012/05/27 18:52:07 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -302,16 +302,18 @@ struct peer_config {
enum network_type {
NETWORK_DEFAULT,
NETWORK_STATIC,
- NETWORK_CONNECTED
+ NETWORK_CONNECTED,
+ NETWORK_MRTCLONE
};
struct network_config {
- struct bgpd_addr prefix;
- struct filter_set_head attrset;
- u_int rtableid;
- enum network_type type;
- u_int8_t prefixlen;
- u_int8_t old; /* used for reloading */
+ struct bgpd_addr prefix;
+ struct filter_set_head attrset;
+ struct rde_aspath *asp;
+ u_int rtableid;
+ enum network_type type;
+ u_int8_t prefixlen;
+ u_int8_t old; /* used for reloading */
};
TAILQ_HEAD(network_head, network);
@@ -349,6 +351,8 @@ enum imsg_type {
IMSG_CTL_LOG_VERBOSE,
IMSG_CTL_SHOW_FIB_TABLES,
IMSG_NETWORK_ADD,
+ IMSG_NETWORK_ASPATH,
+ IMSG_NETWORK_ATTR,
IMSG_NETWORK_REMOVE,
IMSG_NETWORK_FLUSH,
IMSG_NETWORK_DONE,
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
index 84fa4ce92aa..b6b1d9ffb0e 100644
--- a/usr.sbin/bgpd/control.c
+++ b/usr.sbin/bgpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.71 2012/04/12 17:26:09 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.72 2012/05/27 18:52:07 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -434,6 +434,8 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
break;
case IMSG_NETWORK_ADD:
+ case IMSG_NETWORK_ASPATH:
+ case IMSG_NETWORK_ATTR:
case IMSG_NETWORK_REMOVE:
case IMSG_NETWORK_FLUSH:
case IMSG_NETWORK_DONE:
diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c
index 666f437624b..b65609d83c9 100644
--- a/usr.sbin/bgpd/kroute.c
+++ b/usr.sbin/bgpd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.188 2011/05/01 12:56:04 claudio Exp $ */
+/* $OpenBSD: kroute.c,v 1.189 2012/05/27 18:52:07 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -1083,6 +1083,9 @@ kr_net_match(struct ktable *kt, struct kroute *kr)
if (kr->flags & F_CONNECTED)
return (xn);
break;
+ case NETWORK_MRTCLONE:
+ /* can not happen */
+ break;
}
}
return (NULL);
@@ -1112,6 +1115,9 @@ kr_net_match6(struct ktable *kt, struct kroute6 *kr6)
if (kr6->flags & F_CONNECTED)
return (xn);
break;
+ case NETWORK_MRTCLONE:
+ /* can not happen */
+ break;
}
}
return (NULL);
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 309d9c1e899..cd1eb5c3c9a 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.315 2012/05/22 20:38:17 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.316 2012/05/27 18:52:07 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -51,6 +51,7 @@ void rde_update_withdraw(struct rde_peer *, struct bgpd_addr *,
u_int8_t);
int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *,
struct rde_aspath *, struct mpattr *);
+int rde_attr_add(struct rde_aspath *, u_char *, u_int16_t);
u_int8_t rde_attr_missing(struct rde_aspath *, int, u_int16_t);
int rde_get_mp_nexthop(u_char *, u_int16_t, u_int8_t,
struct rde_aspath *);
@@ -357,13 +358,17 @@ rde_dispatch_imsg_session(struct imsgbuf *ibuf)
struct imsg imsg;
struct peer p;
struct peer_config pconf;
- struct rde_peer *peer;
struct session_up sup;
+ struct ctl_show_rib csr;
struct ctl_show_rib_request req;
+ struct rde_peer *peer;
+ struct rde_aspath *asp;
struct filter_set *s;
struct nexthop *nh;
+ u_int8_t *asdata;
ssize_t n;
int verbose;
+ u_int16_t len;
u_int8_t aid;
if ((n = imsg_read(ibuf)) == -1)
@@ -422,6 +427,47 @@ rde_dispatch_imsg_session(struct imsgbuf *ibuf)
TAILQ_INIT(&netconf_s.attrset);
session_set = &netconf_s.attrset;
break;
+ case IMSG_NETWORK_ASPATH:
+ if (imsg.hdr.len - IMSG_HEADER_SIZE <
+ sizeof(struct ctl_show_rib)) {
+ log_warnx("rde_dispatch: wrong imsg len");
+ bzero(&netconf_s, sizeof(netconf_s));
+ break;
+ }
+ asdata = imsg.data;
+ asdata += sizeof(struct ctl_show_rib);
+ memcpy(&csr, imsg.data, sizeof(csr));
+ if (csr.aspath_len + sizeof(csr) > imsg.hdr.len -
+ IMSG_HEADER_SIZE) {
+ log_warnx("rde_dispatch: wrong aspath len");
+ bzero(&netconf_s, sizeof(netconf_s));
+ break;
+ }
+ asp = path_get();
+ asp->lpref = csr.local_pref;
+ asp->med = csr.med;
+ asp->flags = csr.flags;
+ asp->origin = csr.origin;
+ asp->flags |= F_PREFIX_ANNOUNCED | F_ANN_DYNAMIC;
+ asp->aspath = aspath_get(asdata, csr.aspath_len);
+ netconf_s.asp = asp;
+ break;
+ case IMSG_NETWORK_ATTR:
+ if (imsg.hdr.len <= IMSG_HEADER_SIZE) {
+ log_warnx("rde_dispatch: wrong imsg len");
+ break;
+ }
+ /* parse path attributes */
+ len = imsg.hdr.len - IMSG_HEADER_SIZE;
+ asp = netconf_s.asp;
+ if (rde_attr_add(asp, imsg.data, len) == -1) {
+ log_warnx("rde_dispatch: bad network "
+ "attribute");
+ path_put(asp);
+ bzero(&netconf_s, sizeof(netconf_s));
+ break;
+ }
+ break;
case IMSG_NETWORK_DONE:
if (imsg.hdr.len != IMSG_HEADER_SIZE) {
log_warnx("rde_dispatch: wrong imsg len");
@@ -439,6 +485,9 @@ rde_dispatch_imsg_session(struct imsgbuf *ibuf)
goto badnet;
network_add(&netconf_s, 0);
break;
+ case 0:
+ /* something failed beforehands */
+ break;
default:
badnet:
log_warnx("rde_dispatch: bad network");
@@ -1665,6 +1714,42 @@ bad_list:
return (plen);
}
+
+int
+rde_attr_add(struct rde_aspath *a, u_char *p, u_int16_t len)
+{
+ u_int16_t attr_len;
+ u_int16_t plen = 0;
+ u_int8_t flags;
+ u_int8_t type;
+ u_int8_t tmp8;
+
+ if (a == NULL) /* no aspath, nothing to do */
+ return (0);
+ if (len < 3)
+ return (-1);
+
+ UPD_READ(&flags, p, plen, 1);
+ UPD_READ(&type, p, plen, 1);
+
+ if (flags & ATTR_EXTLEN) {
+ if (len - plen < 2)
+ return (-1);
+ UPD_READ(&attr_len, p, plen, 2);
+ attr_len = ntohs(attr_len);
+ } else {
+ UPD_READ(&tmp8, p, plen, 1);
+ attr_len = tmp8;
+ }
+
+ if (len - plen < attr_len)
+ return (-1);
+
+ if (attr_optadd(a, flags, type, p, attr_len) == -1)
+ return (-1);
+ return (0);
+}
+
#undef UPD_READ
#undef CHECK_FLAGS
@@ -1728,7 +1813,7 @@ rde_get_mp_nexthop(u_char *data, u_int16_t len, u_int8_t aid,
/*
* Neither RFC4364 nor RFC3107 specify the format of the
* nexthop in an explicit way. The quality of RFC went down
- * the toilet the larger the the number got.
+ * the toilet the larger the number got.
* RFC4364 is very confusing about VPN-IPv4 address and the
* VPN-IPv4 prefix that carries also a MPLS label.
* So the nexthop is a 12-byte address with a 64bit RD and
@@ -3233,15 +3318,18 @@ network_add(struct network_config *nc, int flagstatic)
}
}
- asp = path_get();
- asp->aspath = aspath_get(NULL, 0);
- asp->origin = ORIGIN_IGP;
- asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
- F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
- /* the nexthop is unset unless a default set overrides it */
+ if (nc->type == NETWORK_MRTCLONE) {
+ asp = nc->asp;
+ } else {
+ asp = path_get();
+ asp->aspath = aspath_get(NULL, 0);
+ asp->origin = ORIGIN_IGP;
+ asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH |
+ F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED;
+ /* the nexthop is unset unless a default set overrides it */
+ }
if (!flagstatic)
asp->flags |= F_ANN_DYNAMIC;
-
rde_apply_set(asp, &nc->attrset, nc->prefix.aid, peerself, peerself);
if (vpnset)
rde_apply_set(asp, vpnset, nc->prefix.aid, peerself, peerself);