summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/bgpd.813
-rw-r--r--usr.sbin/bgpd/bgpd.conf.518
-rw-r--r--usr.sbin/bgpd/mrt.c309
-rw-r--r--usr.sbin/bgpd/mrt.h106
-rw-r--r--usr.sbin/bgpd/parse.y6
-rw-r--r--usr.sbin/bgpd/printconf.c13
-rw-r--r--usr.sbin/bgpd/rde.c9
-rw-r--r--usr.sbin/bgpd/rde.h4
-rw-r--r--usr.sbin/bgpd/rde_rib.c27
9 files changed, 438 insertions, 67 deletions
diff --git a/usr.sbin/bgpd/bgpd.8 b/usr.sbin/bgpd/bgpd.8
index c74b7268ba5..b5d41f282c6 100644
--- a/usr.sbin/bgpd/bgpd.8
+++ b/usr.sbin/bgpd/bgpd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpd.8,v 1.39 2010/10/15 07:45:32 claudio Exp $
+.\" $OpenBSD: bgpd.8,v 1.40 2011/09/17 16:29:44 claudio Exp $
.\"
.\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 15 2010 $
+.Dd $Mdocdate: September 17 2011 $
.Dt BGPD 8
.Os
.Sh NAME
@@ -212,9 +212,14 @@ control socket
.%D April 2009
.Re
.Rs
-.%R draft-ietf-idr-fsm-subcode-00
+.%R draft-ietf-idr-fsm-subcode-02
.%T "Subcodes for BGP Finite State Machine Error"
-.%D September 2010
+.%D August 2011
+.Re
+.Rs
+.%R draft-ietf-grow-mrt-17
+.%T "MRT routing information export format"
+.%D August 2011
.Re
.Sh HISTORY
The
diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5
index 5b8be1627cd..c3454ccd18c 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.115 2011/06/23 20:35:22 sthen Exp $
+.\" $OpenBSD: bgpd.conf.5,v 1.116 2011/09/17 16:29:44 claudio Exp $
.\"
.\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
.\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: June 23 2011 $
+.Dd $Mdocdate: September 17 2011 $
.Dt BGPD.CONF 5
.Os
.Sh NAME
@@ -149,7 +149,7 @@ The default is 120 seconds.
.It Xo
.Ic dump
.Op Ic rib Ar name
-.Pq Ic table Ns | Ns Ic table-mp
+.Pq Ic table Ns | Ns Ic table-mp Ns | Ns Ic table-v2
.Ar file Op Ar timeout
.Xc
.It Xo
@@ -161,17 +161,21 @@ The default is 120 seconds.
Dump the RIB, a.k.a. the
.Em routing information base ,
and all BGP messages in Multi-threaded Routing Toolkit (MRT) format.
-Dumping the RIB is normally an expensive operation,
-but it should not influence the session handling.
It is possible to dump alternate RIB with the use of
.Ar name .
.Pp
For example, the following will dump the entire table to the
.Xr strftime 3 Ns -expanded
filename.
-The
+Only the
+.Ic table-v2
+format is able to dump a multi-protocol RIB correctly.
+Both
+.Ic table
+and
.Ic table-mp
-format is multi-protocol capable but often not supported by 3rd-party tools.
+formats are more or less limited when handling multi-protocol entries and
+are only left around to support 3rd party tools not handling the new format.
The timeout is optional:
.Bd -literal -offset indent
dump table "/tmp/rib-dump-%H%M" 300
diff --git a/usr.sbin/bgpd/mrt.c b/usr.sbin/bgpd/mrt.c
index d2bfe6475d8..d83325252ff 100644
--- a/usr.sbin/bgpd/mrt.c
+++ b/usr.sbin/bgpd/mrt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.c,v 1.70 2010/09/02 14:03:21 sobrado Exp $ */
+/* $OpenBSD: mrt.c,v 1.71 2011/09/17 16:29:44 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -32,10 +32,12 @@
#include "mrt.h"
-int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct bgpd_addr *);
+int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct bgpd_addr *, int);
int mrt_dump_entry_mp(struct mrt *, struct prefix *, u_int16_t,
struct rde_peer*);
int mrt_dump_entry(struct mrt *, struct prefix *, u_int16_t, struct rde_peer*);
+int mrt_dump_entry_v2(struct mrt *, struct rib_entry *, u_int32_t);
+int mrt_dump_peer(struct ibuf *, struct rde_peer *);
int mrt_dump_hdr_se(struct ibuf **, struct peer *, u_int16_t, u_int16_t,
u_int32_t, int);
int mrt_dump_hdr_rde(struct ibuf **, u_int16_t type, u_int16_t, u_int32_t);
@@ -45,7 +47,7 @@ int mrt_open(struct mrt *, time_t);
do { \
u_char t = (b); \
if (ibuf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump1: ibuf_add error"); \
+ log_warn("mrt_dump1: ibuf_add error"); \
goto fail; \
} \
} while (0)
@@ -55,7 +57,7 @@ int mrt_open(struct mrt *, time_t);
u_int16_t t; \
t = htons((s)); \
if (ibuf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump2: ibuf_add error"); \
+ log_warn("mrt_dump2: ibuf_add error"); \
goto fail; \
} \
} while (0)
@@ -65,7 +67,7 @@ int mrt_open(struct mrt *, time_t);
u_int32_t t; \
t = htonl((l)); \
if (ibuf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump3: ibuf_add error"); \
+ log_warn("mrt_dump3: ibuf_add error"); \
goto fail; \
} \
} while (0)
@@ -74,7 +76,7 @@ int mrt_open(struct mrt *, time_t);
do { \
u_int32_t t = (l); \
if (ibuf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump4: ibuf_add error"); \
+ log_warn("mrt_dump4: ibuf_add error"); \
goto fail; \
} \
} while (0)
@@ -99,7 +101,7 @@ mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen,
return;
if (ibuf_add(buf, pkg, pkglen) == -1) {
- log_warnx("mrt_dump_bgp_msg: buf_add error");
+ log_warn("mrt_dump_bgp_msg: buf_add error");
ibuf_free(buf);
return;
}
@@ -132,14 +134,15 @@ fail:
}
int
-mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop)
+mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop,
+ int v2)
{
struct attr *oa;
u_char *pdata;
u_int32_t tmp;
int neednewpath = 0;
u_int16_t plen, afi;
- u_int8_t l, mpattr[21];
+ u_int8_t l, safi;
/* origin */
if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN,
@@ -148,7 +151,8 @@ mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop)
/* aspath */
pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen);
- pdata = aspath_deflate(pdata, &plen, &neednewpath);
+ if (!v2)
+ pdata = aspath_deflate(pdata, &plen, &neednewpath);
if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata,
plen) == -1) {
free(pdata);
@@ -170,7 +174,7 @@ mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop)
return (-1);
}
- /* local preference, only valid for ibgp */
+ /* local preference */
tmp = htonl(a->lpref);
if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_LOCALPREF, &tmp, 4) == -1)
return (-1);
@@ -185,16 +189,40 @@ mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop)
}
if (nexthop && nexthop->aid != AID_INET) {
- if (aid2afi(nexthop->aid, &afi, &mpattr[2]))
+ struct ibuf *nhbuf;
+
+ if ((nhbuf = ibuf_dynamic(0, UCHAR_MAX)) == NULL)
return (-1);
- afi = htons(afi);
- memcpy(mpattr, &afi, sizeof(afi));
- mpattr[3] = sizeof(struct in6_addr);
- memcpy(&mpattr[4], &nexthop->v6, sizeof(struct in6_addr));
- mpattr[20] = 0; /* Reserved must be 0 */
+ if (!v2) {
+ if (aid2afi(nexthop->aid, &afi, &safi))
+ return (-1);
+ DUMP_SHORT(nhbuf, afi);
+ DUMP_BYTE(nhbuf, safi);
+ }
+ switch (nexthop->aid) {
+ case AID_INET6:
+ DUMP_BYTE(nhbuf, sizeof(struct in6_addr));
+ if (ibuf_add(nhbuf, &nexthop->v6,
+ sizeof(struct in6_addr)) == -1) {
+ }
+ break;
+ case AID_VPN_IPv4:
+ DUMP_BYTE(nhbuf, sizeof(u_int64_t) +
+ sizeof(struct in_addr));
+ DUMP_NLONG(nhbuf, 0); /* set RD to 0 */
+ DUMP_NLONG(nhbuf, 0);
+ DUMP_NLONG(nhbuf, nexthop->v4.s_addr);
+ break;
+ }
+ if (!v2)
+ DUMP_BYTE(nhbuf, 0);
if (attr_writebuf(buf, ATTR_OPTIONAL, ATTR_MP_REACH_NLRI,
- mpattr, sizeof(mpattr)) == -1)
+ nhbuf->buf, ibuf_size(nhbuf)) == -1) {
+fail:
+ ibuf_free(nhbuf);
return (-1);
+ }
+ ibuf_free(nhbuf);
}
if (neednewpath) {
@@ -216,10 +244,8 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
struct rde_peer *peer)
{
struct ibuf *buf, *hbuf = NULL, *h2buf = NULL;
- void *bptr;
struct bgpd_addr addr, nexthop, *nh;
u_int16_t len;
- u_int8_t p_len;
u_int8_t aid;
if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
@@ -227,7 +253,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
return (-1);
}
- if (mrt_attr_dump(buf, p->aspath, NULL) == -1) {
+ if (mrt_attr_dump(buf, p->aspath, NULL, 0) == -1) {
log_warnx("mrt_dump_entry_mp: mrt_attr_dump error");
goto fail;
}
@@ -259,7 +285,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
sizeof(struct in6_addr)) == -1 ||
ibuf_add(h2buf, &peer->remote_addr.v6,
sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_entry_mp: buf_add error");
+ log_warn("mrt_dump_entry_mp: buf_add error");
goto fail;
}
break;
@@ -292,7 +318,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */
DUMP_BYTE(h2buf, 16); /* nhlen */
if (ibuf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_entry_mp: buf_add error");
+ log_warn("mrt_dump_entry_mp: buf_add error");
goto fail;
}
break;
@@ -301,13 +327,8 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
goto fail;
}
- p_len = PREFIX_SIZE(p->prefix->prefixlen);
- if ((bptr = ibuf_reserve(h2buf, p_len)) == NULL) {
- log_warnx("mrt_dump_entry_mp: buf_reserve error");
- goto fail;
- }
- if (prefix_write(bptr, p_len, &addr, p->prefix->prefixlen) == -1) {
- log_warnx("mrt_dump_entry_mp: prefix_write error");
+ if (prefix_writebuf(h2buf, &addr, p->prefix->prefixlen) == -1) {
+ log_warn("mrt_dump_entry_mp: prefix_writebuf error");
goto fail;
}
@@ -349,7 +370,7 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
return (0);
if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
- log_warnx("mrt_dump_entry: buf_dynamic");
+ log_warn("mrt_dump_entry: buf_dynamic");
return (-1);
}
@@ -359,7 +380,7 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
nh = &addr;
} else
nh = &p->aspath->nexthop->exit_nexthop;
- if (mrt_attr_dump(buf, p->aspath, nh) == -1) {
+ if (mrt_attr_dump(buf, p->aspath, nh, 0) == -1) {
log_warnx("mrt_dump_entry: mrt_attr_dump error");
ibuf_free(buf);
return (-1);
@@ -381,7 +402,7 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
break;
case AID_INET6:
if (ibuf_add(hbuf, &addr.v6, sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_entry: buf_add error");
+ log_warn("mrt_dump_entry: buf_add error");
goto fail;
}
break;
@@ -397,7 +418,7 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
case AID_INET6:
if (ibuf_add(hbuf, &peer->remote_addr.v6,
sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_entry: buf_add error");
+ log_warn("mrt_dump_entry: buf_add error");
goto fail;
}
break;
@@ -416,12 +437,214 @@ fail:
return (-1);
}
+int
+mrt_dump_entry_v2(struct mrt *mrt, struct rib_entry *re, u_int32_t snum)
+{
+ struct ibuf *buf, *hbuf = NULL;
+ struct prefix *p;
+ struct bgpd_addr addr;
+ size_t len, off;
+ u_int16_t subtype, nump;
+
+ switch (re->prefix->aid) {
+ case AID_INET:
+ subtype = MRT_DUMP_V2_RIB_IPV4_UNICAST;
+ break;
+ case AID_INET6:
+ subtype = MRT_DUMP_V2_RIB_IPV6_UNICAST;
+ break;
+ default:
+ subtype = MRT_DUMP_V2_RIB_GENERIC;
+ break;
+ }
+
+ if ((buf = ibuf_dynamic(0, UINT_MAX)) == NULL) {
+ log_warn("mrt_dump_entry: buf_dynamic");
+ return (-1);
+ }
+
+ DUMP_LONG(buf, snum);
+ pt_getaddr(re->prefix, &addr);
+ if (subtype == MRT_DUMP_V2_RIB_GENERIC) {
+ u_int16_t afi;
+ u_int8_t safi;
+
+ aid2afi(re->prefix->aid, &afi, &safi);
+ DUMP_SHORT(buf, afi);
+ DUMP_BYTE(buf, safi);
+ }
+ if (prefix_writebuf(buf, &addr, re->prefix->prefixlen) == -1) {
+ log_warn("mrt_dump_entry_mp: prefix_writebuf error");
+ goto fail;
+ }
+
+ off = ibuf_size(buf);
+ if (ibuf_reserve(buf, sizeof(nump)) == NULL) {
+ log_warn("mrt_dump_v2_hdr: buf_reserve error");
+ goto fail;
+ }
+ nump = 0;
+ LIST_FOREACH(p, &re->prefix_h, rib_l) {
+ struct bgpd_addr *nh;
+ struct ibuf *tbuf;
+
+ if (p->aspath->nexthop == NULL) {
+ bzero(&addr, sizeof(struct bgpd_addr));
+ addr.aid = p->prefix->aid;
+ nh = &addr;
+ } else
+ nh = &p->aspath->nexthop->exit_nexthop;
+
+ DUMP_SHORT(buf, p->aspath->peer->mrt_idx);
+ DUMP_LONG(buf, p->lastchange); /* originated */
+
+ if ((tbuf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
+ log_warn("mrt_dump_entry_v2: buf_dynamic");
+ return (-1);
+ }
+ if (mrt_attr_dump(tbuf, p->aspath, nh, 1) == -1) {
+ log_warnx("mrt_dump_entry_v2: mrt_attr_dump error");
+ ibuf_free(buf);
+ return (-1);
+ }
+ len = ibuf_size(tbuf);
+ DUMP_SHORT(buf, (u_int16_t)len);
+ if (ibuf_add(buf, tbuf->buf, ibuf_size(tbuf)) == -1) {
+ log_warn("mrt_dump_entry_v2: ibuf_add error");
+ ibuf_free(tbuf);
+ return (-1);
+ }
+ ibuf_free(tbuf);
+ nump++;
+ }
+ nump = htons(nump);
+ memcpy(ibuf_seek(buf, off, sizeof(nump)), &nump, sizeof(nump));
+
+ len = ibuf_size(buf);
+ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2, subtype, len) == -1) {
+ ibuf_free(buf);
+ return (-1);
+ }
+
+ ibuf_close(&mrt->wbuf, hbuf);
+ ibuf_close(&mrt->wbuf, buf);
+
+ return (0);
+fail:
+ if (hbuf)
+ ibuf_free(hbuf);
+ ibuf_free(buf);
+ return (-1);
+}
+
+int
+mrt_dump_v2_hdr(struct mrt *mrt, struct bgpd_config *conf,
+ struct rde_peer_head *ph)
+{
+ struct rde_peer *peer;
+ struct ibuf *buf, *hbuf = NULL;
+ size_t len, off;
+ u_int16_t nlen, nump;
+
+ if ((buf = ibuf_dynamic(0, UINT_MAX)) == NULL) {
+ log_warn("mrt_dump_v2_hdr: buf_dynamic");
+ return (-1);
+ }
+
+ DUMP_NLONG(buf, conf->bgpid);
+ nlen = strlen(mrt->rib);
+ if (nlen > 0)
+ nlen += 1;
+ DUMP_SHORT(buf, nlen);
+ if (ibuf_add(buf, mrt->rib, nlen) == -1) {
+ log_warn("mrt_dump_v2_hdr: buf_add error");
+ goto fail;
+ }
+
+ off = ibuf_size(buf);
+ if (ibuf_reserve(buf, sizeof(nump)) == NULL) {
+ log_warn("mrt_dump_v2_hdr: buf_reserve error");
+ goto fail;
+ }
+ nump = 0;
+ LIST_FOREACH(peer, ph, peer_l) {
+ peer->mrt_idx = nump;
+ if (mrt_dump_peer(buf, peer) == -1)
+ goto fail;
+ nump++;
+ }
+ nump = htons(nump);
+ memcpy(ibuf_seek(buf, off, sizeof(nump)), &nump, sizeof(nump));
+
+ len = ibuf_size(buf);
+ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP_V2,
+ MRT_DUMP_V2_PEER_INDEX_TABLE, len) == -1)
+ goto fail;
+
+ ibuf_close(&mrt->wbuf, hbuf);
+ ibuf_close(&mrt->wbuf, buf);
+
+ return (0);
+fail:
+ if (hbuf)
+ ibuf_free(hbuf);
+ ibuf_free(buf);
+ return (-1);
+}
+
+int
+mrt_dump_peer(struct ibuf *buf, struct rde_peer *peer)
+{
+ u_int8_t type = 0;
+
+ if (peer->capa.as4byte)
+ type |= MRT_DUMP_V2_PEER_BIT_A;
+ if (peer->remote_addr.aid == AID_INET6)
+ type |= MRT_DUMP_V2_PEER_BIT_I;
+
+ DUMP_BYTE(buf, type);
+ DUMP_LONG(buf, peer->remote_bgpid);
+
+ switch (peer->remote_addr.aid) {
+ case AID_INET:
+ DUMP_NLONG(buf, peer->remote_addr.v4.s_addr);
+ break;
+ case AID_INET6:
+ if (ibuf_add(buf, &peer->remote_addr.v6,
+ sizeof(struct in6_addr)) == -1) {
+ log_warn("mrt_dump_peer: buf_add error");
+ goto fail;
+ }
+ break;
+ case AID_UNSPEC: /* XXX special handling for peer_self? */
+ DUMP_NLONG(buf, 0);
+ break;
+ default:
+ log_warnx("king bula found new AF in mrt_dump_entry_mp");
+ goto fail;
+ }
+
+ if (peer->capa.as4byte)
+ DUMP_LONG(buf, peer->conf.remote_as);
+ else
+ DUMP_SHORT(buf, peer->short_as);
+
+ return (0);
+fail:
+ return (-1);
+}
+
void
mrt_dump_upcall(struct rib_entry *re, void *ptr)
{
struct mrt *mrtbuf = ptr;
struct prefix *p;
+ if (mrtbuf->type == MRT_TABLE_DUMP_V2) {
+ mrt_dump_entry_v2(mrtbuf, re, mrtbuf->seqnum++);
+ return;
+ }
+
/*
* dump all prefixes even the inactive ones. That is the way zebra
* dumps the table so we do the same. If only the active route should
@@ -453,7 +676,7 @@ mrt_dump_hdr_se(struct ibuf ** bp, struct peer *peer, u_int16_t type,
if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE +
MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + len)) == NULL) {
- log_warnx("mrt_dump_hdr_se: buf_open error");
+ log_warn("mrt_dump_hdr_se: buf_open error");
return (-1);
}
@@ -522,20 +745,20 @@ mrt_dump_hdr_se(struct ibuf ** bp, struct peer *peer, u_int16_t type,
if (ibuf_add(*bp, &((struct sockaddr_in6 *)
&peer->sa_local)->sin6_addr,
sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_hdr_se: buf_add error");
+ log_warn("mrt_dump_hdr_se: buf_add error");
goto fail;
}
if (ibuf_add(*bp,
&((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr,
sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_hdr_se: buf_add error");
+ log_warn("mrt_dump_hdr_se: buf_add error");
goto fail;
}
if (swap)
if (ibuf_add(*bp, &((struct sockaddr_in6 *)
&peer->sa_local)->sin6_addr,
sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_hdr_se: buf_add error");
+ log_warn("mrt_dump_hdr_se: buf_add error");
goto fail;
}
break;
@@ -557,7 +780,7 @@ mrt_dump_hdr_rde(struct ibuf **bp, u_int16_t type, u_int16_t subtype,
if ((*bp = ibuf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE +
MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + MRT_BGP4MP_IPv6_ENTRY_SIZE)) ==
NULL) {
- log_warnx("mrt_dump_hdr_rde: buf_dynamic error");
+ log_warn("mrt_dump_hdr_rde: buf_dynamic error");
return (-1);
}
@@ -579,6 +802,7 @@ mrt_dump_hdr_rde(struct ibuf **bp, u_int16_t type, u_int16_t subtype,
DUMP_LONG(*bp, len);
break;
case MSG_PROTOCOL_BGP4MP:
+ case MSG_TABLE_DUMP_V2:
DUMP_LONG(*bp, len);
break;
default:
@@ -650,7 +874,8 @@ mrt_open(struct mrt *mrt, time_t now)
else
type = IMSG_MRT_REOPEN;
- if (mrt->type == MRT_TABLE_DUMP || mrt->type == MRT_TABLE_DUMP_MP)
+ if (mrt->type == MRT_TABLE_DUMP || mrt->type == MRT_TABLE_DUMP_MP ||
+ mrt->type == MRT_TABLE_DUMP_V2)
i = 0;
if (imsg_compose(mrt_imsgbuf[i], type, 0, 0, fd,
@@ -719,7 +944,9 @@ mrt_handler(struct mrt_head *mrt)
LIST_FOREACH(m, mrt, entry) {
if (m->state == MRT_STATE_RUNNING &&
(MRT2MC(m)->ReopenTimerInterval != 0 ||
- m->type == MRT_TABLE_DUMP)) {
+ m->type == MRT_TABLE_DUMP ||
+ m->type == MRT_TABLE_DUMP_MP ||
+ m->type == MRT_TABLE_DUMP_V2)) {
if (mrt_open(m, now) == -1)
continue;
MRT2MC(m)->ReopenTimer =
diff --git a/usr.sbin/bgpd/mrt.h b/usr.sbin/bgpd/mrt.h
index bb9af163b80..352b65c2ad2 100644
--- a/usr.sbin/bgpd/mrt.h
+++ b/usr.sbin/bgpd/mrt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.h,v 1.28 2011/09/16 15:44:42 claudio Exp $ */
+/* $OpenBSD: mrt.h,v 1.29 2011/09/17 16:29:44 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -104,6 +104,7 @@ enum MRT_BGP4MP_TYPES {
*
* The source_ip and dest_ip are dependant of the afi type. For IPv6 source_ip
* and dest_ip are both 16 bytes long.
+ * For the AS4 types the source_as and dest_as numbers are both 4 bytes long.
*
* Payload of a BGP4MP_STATE_CHANGE packet:
*
@@ -155,6 +156,98 @@ enum MRT_BGP4MP_TYPES {
*/
/*
+ * New MRT dump format MSG_TABLE_DUMP_V2, the dump is implemented with
+ * sub-tables for peers and NLRI entries just use the index into the peer
+ * table.
+ */
+enum MRT_DUMP_V2_TYPES {
+ MRT_DUMP_V2_PEER_INDEX_TABLE=1,
+ MRT_DUMP_V2_RIB_IPV4_UNICAST=2,
+ MRT_DUMP_V2_RIB_IPV4_MULTICAST=3,
+ MRT_DUMP_V2_RIB_IPV6_UNICAST=4,
+ MRT_DUMP_V2_RIB_IPV6_MULTICAST=5,
+ MRT_DUMP_V2_RIB_GENERIC=6
+};
+
+/*
+ * Format of the MRT_DUMP_V2_PEER_INDEX_TABLE:
+ * If there is no view_name, view_name_len must be set to 0
+ *
+ * +--------+--------+--------+--------+
+ * | collector_bgp_id |
+ * +--------+--------+--------+--------+
+ * | view_name_len | view_name
+ * +--------+--------+--------+--------+
+ * view_name (variable) ... |
+ * +--------+--------+--------+--------+
+ * | peer_count | peer_entries
+ * +--------+--------+--------+--------+
+ * peer_entries (variable) ...
+ * +--------+--------+--------+--------+
+ *
+ * The format of a peer_entry is the following:
+ *
+ * +--------+
+ * | type |
+ * +--------+--------+--------+--------+
+ * | peer_bgp_id |
+ * +--------+--------+--------+--------+
+ * | peer_ip_addr (variable) |
+ * +--------+--------+--------+--------+
+ * | peer_as (variable) |
+ * +--------+--------+--------+--------+
+ *
+ * The message is packed a bit strangely. The type byte defines what size
+ * the peer addr and peer AS have.
+ * The position of a peer in the PEER_INDEX_TABLE is used as the index for
+ * the other messages.
+ */
+#define MRT_DUMP_V2_PEER_BIT_I 0x1 /* set for IPv6 addrs */
+#define MRT_DUMP_V2_PEER_BIT_A 0x2 /* set for 32 bits AS number */
+
+/*
+ * AFI/SAFI specific RIB Subtypes are special to save a few bytes.
+ *
+ * +--------+--------+--------+--------+
+ * | seq_num |
+ * +--------+--------+--------+--------+
+ * | plen | prefix (variable)
+ * +--------+--------+--------+--------+
+ * | #entry | rib entries (variable)
+ * +--------+--------+--------+--------+
+ *
+ * The RIB_GENERIC subtype is needed for the less common AFI/SAFI pairs
+ *
+ * +--------+--------+--------+--------+
+ * | seq_num |
+ * +--------+--------+--------+--------+
+ * | AFI | SAFI | NLRI
+ * +--------+--------+--------+--------+
+ * NLRI (variable) ...
+ * +--------+--------+--------+--------+
+ * | #entry | rib entries (variable)
+ * +--------+--------+--------+--------+
+ */
+
+/*
+ * The RIB entries have the following form.
+ *
+ * +--------+--------+
+ * | peer index |
+ * +--------+--------+--------+--------+
+ * | originated_time |
+ * +--------+--------+--------+--------+
+ * | attr_len | bgp_attrs
+ * +--------+--------+--------+--------+
+ * bgp_attrs (variable) ...
+ * +--------+--------+--------+--------+
+ *
+ * Some BGP path attributes need special encoding:
+ * - the AS_PATH attribute MUST be encoded as 4-Byte AS
+ * - the MP_REACH_NLRI only consists of the nexthop len and nexthop address
+ */
+
+/*
* Format for routing table dumps in "old" mrt format.
* Type MSG_TABLE_DUMP and subtype is AFI_IPv4 (1) for IPv4 and AFI_IPv6 (2)
* for IPv6. In the IPv6 case prefix and peer_ip are both 16 bytes long.
@@ -171,7 +264,7 @@ enum MRT_BGP4MP_TYPES {
* peer_ip | peer_as |
* +--------+--------+--------+--------+
* | attr_len | bgp attributes
- * +--------+--------+--------+--------+
+
* bgp attributes, attr_len bytes long
* +--------+--------+--------+--------+
* ... |
@@ -225,7 +318,7 @@ enum MRT_BGP_TYPES {
*/
/*
- * For subtype MSG_BGP_STATECHANGE (for all BGP types or just for the
+ * For subtype MSG_BGP_STATE_CHANGE (for all BGP types or just for the
* MSG_PROTOCOL_BGP4PLUS case? Unclear.)
*
* +--------+--------+--------+--------+
@@ -236,7 +329,7 @@ enum MRT_BGP_TYPES {
* | new_state |
* +--------+--------+
*
- * State are defined in RFC 1771/4271.
+ * States are defined in RFC 1771/4271.
*/
/*
@@ -258,6 +351,7 @@ enum mrt_type {
MRT_NONE,
MRT_TABLE_DUMP,
MRT_TABLE_DUMP_MP,
+ MRT_TABLE_DUMP_V2,
MRT_ALL_IN,
MRT_ALL_OUT,
MRT_UPDATE_IN,
@@ -293,6 +387,8 @@ struct mrt_config {
#define MRT2MC(x) ((struct mrt_config *)(x))
#define MRT_MAX_TIMEOUT 7200
+struct bgpd_config;
+struct rde_peer_head;
struct peer;
struct prefix;
struct rib_entry;
@@ -302,6 +398,8 @@ void mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t,
struct peer *);
void mrt_dump_state(struct mrt *, u_int16_t, u_int16_t,
struct peer *);
+int mrt_dump_v2_hdr(struct mrt *, struct bgpd_config *,
+ struct rde_peer_head *);
void mrt_clear_seq(void);
void mrt_dump_upcall(struct rib_entry *, void *);
void mrt_done(void *);
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 75798d892f4..6939faaaee6 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.259 2011/05/01 12:56:04 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.260 2011/09/17 16:29:44 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -449,6 +449,8 @@ conf_main : AS as4number {
action = MRT_TABLE_DUMP;
else if (!strcmp($2, "table-mp"))
action = MRT_TABLE_DUMP_MP;
+ else if (!strcmp($2, "table-v2"))
+ action = MRT_TABLE_DUMP_V2;
else {
yyerror("unknown mrt dump type");
free($2);
@@ -476,6 +478,8 @@ conf_main : AS as4number {
action = MRT_TABLE_DUMP;
else if (!strcmp($4, "table-mp"))
action = MRT_TABLE_DUMP_MP;
+ else if (!strcmp($4, "table-v2"))
+ action = MRT_TABLE_DUMP_V2;
else {
yyerror("unknown mrt dump type");
free($3);
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index 76d260b548d..6599761c638 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.85 2010/12/31 21:22:42 guenther Exp $ */
+/* $OpenBSD: printconf.c,v 1.86 2011/09/17 16:29:44 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -604,6 +604,8 @@ mrt_type(enum mrt_type t)
return "table";
case MRT_TABLE_DUMP_MP:
return "table-mp";
+ case MRT_TABLE_DUMP_V2:
+ return "table-v2";
case MRT_ALL_IN:
return "all in";
case MRT_ALL_OUT:
@@ -632,13 +634,12 @@ print_mrt(u_int32_t pid, u_int32_t gid, const char *prep, const char *prep2)
printf("%s%sdump ", prep, prep2);
if (m->rib[0])
printf("rib %s ", m->rib);
+ printf("%s \"%s\"", mrt_type(m->type),
+ MRT2MC(m)->name);
if (MRT2MC(m)->ReopenTimerInterval == 0)
- printf("%s %s\n", mrt_type(m->type),
- MRT2MC(m)->name);
+ printf("\n");
else
- printf("%s %s %d\n", mrt_type(m->type),
- MRT2MC(m)->name,
- MRT2MC(m)->ReopenTimerInterval);
+ printf(" %d\n", MRT2MC(m)->ReopenTimerInterval);
}
}
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 288a7913a67..5efa9bef765 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.308 2011/07/09 02:51:18 henning Exp $ */
+/* $OpenBSD: rde.c,v 1.309 2011/09/17 16:29:44 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -820,7 +820,8 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
log_warnx("expected to receive fd for mrt dump "
"but didn't receive any");
else if (xmrt.type == MRT_TABLE_DUMP ||
- xmrt.type == MRT_TABLE_DUMP_MP) {
+ xmrt.type == MRT_TABLE_DUMP_MP ||
+ xmrt.type == MRT_TABLE_DUMP_V2) {
rde_dump_mrt_new(&xmrt, imsg.hdr.pid, fd);
} else
close(fd);
@@ -2336,6 +2337,10 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t pid, int fd)
free(ctx);
return;
}
+
+ if (ctx->mrt.type == MRT_TABLE_DUMP_V2)
+ mrt_dump_v2_hdr(&ctx->mrt, conf, &peerlist);
+
ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS;
ctx->ribctx.ctx_rib = &ribs[id];
ctx->ribctx.ctx_upcall = mrt_dump_upcall;
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index d2a594b9696..853fbfb6f23 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.138 2010/11/18 12:18:31 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.139 2011/09/17 16:29:44 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -72,6 +72,7 @@ struct rde_peer {
enum peer_state state;
u_int16_t ribid;
u_int16_t short_as;
+ u_int16_t mrt_idx;
u_int8_t reconf_in; /* in filter changed */
u_int8_t reconf_out; /* out filter changed */
u_int8_t reconf_rib; /* rib changed */
@@ -401,6 +402,7 @@ void prefix_move(struct rde_aspath *, struct prefix *);
int prefix_remove(struct rib *, struct rde_peer *,
struct bgpd_addr *, int, u_int32_t);
int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t);
+int prefix_writebuf(struct ibuf *, struct bgpd_addr *, u_int8_t);
struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *,
u_int32_t);
void prefix_updateall(struct rde_aspath *, enum nexthop_state,
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index fcbfac9e218..a7297ca6004 100644
--- a/usr.sbin/bgpd/rde_rib.c
+++ b/usr.sbin/bgpd/rde_rib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.128 2011/01/14 20:07:00 henning Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.129 2011/09/17 16:29:44 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -856,6 +856,31 @@ prefix_write(u_char *buf, int len, struct bgpd_addr *prefix, u_int8_t plen)
}
}
+int
+prefix_writebuf(struct ibuf *buf, struct bgpd_addr *prefix, u_int8_t plen)
+{
+ int totlen;
+ void *bptr;
+
+ switch (prefix->aid) {
+ case AID_INET:
+ case AID_INET6:
+ totlen = PREFIX_SIZE(plen);
+ break;
+ case AID_VPN_IPv4:
+ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) +
+ prefix->vpn4.labellen;
+ default:
+ return (-1);
+ }
+
+ if ((bptr = ibuf_reserve(buf, totlen)) == NULL)
+ return (-1);
+ if (prefix_write(bptr, totlen, prefix, plen) == -1)
+ return (-1);
+ return (0);
+}
+
/*
* Searches in the prefix list of specified pt_entry for a prefix entry
* belonging to the peer peer. Returns NULL if no match found.