diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2012-05-27 18:52:08 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2012-05-27 18:52:08 +0000 |
commit | 6d2dfda18c9d1cfb00ff832aa663711ad744a864 (patch) | |
tree | 82b047f66b90d6888b4caa78a26828c8d7c2cd9d /usr.sbin/bgpd | |
parent | 4a7df4608e07bbe1a65a6b0008521846a55d2c06 (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.h | 20 | ||||
-rw-r--r-- | usr.sbin/bgpd/control.c | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/kroute.c | 8 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 108 |
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); |