summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/mrt.c578
-rw-r--r--usr.sbin/bgpd/mrt.h72
-rw-r--r--usr.sbin/bgpd/session.c8
3 files changed, 325 insertions, 333 deletions
diff --git a/usr.sbin/bgpd/mrt.c b/usr.sbin/bgpd/mrt.c
index e8cd8be4a56..bacdb0cb628 100644
--- a/usr.sbin/bgpd/mrt.c
+++ b/usr.sbin/bgpd/mrt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.c,v 1.57 2009/03/18 19:45:09 claudio Exp $ */
+/* $OpenBSD: mrt.c,v 1.58 2009/03/19 07:00:06 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -32,15 +32,16 @@
#include "mrt.h"
-static u_int16_t mrt_attr_length(struct rde_aspath *, int);
-static int mrt_attr_dump(void *, u_int16_t, struct rde_aspath *,
+static int mrt_attr_dump(struct buf *, struct rde_aspath *,
struct bgpd_addr *);
static int mrt_dump_entry_mp(struct mrt *, struct prefix *,
u_int16_t, struct rde_peer*);
static int mrt_dump_entry(struct mrt *, struct prefix *,
u_int16_t, struct rde_peer*);
-static int mrt_dump_header(struct buf *, u_int16_t, u_int16_t,
- u_int32_t);
+static int mrt_dump_hdr_se(struct buf **, struct peer *,
+ u_int16_t, u_int16_t, u_int32_t, int);
+static int mrt_dump_hdr_rde(struct buf **, u_int16_t type,
+ u_int16_t, u_int32_t);
static int mrt_open(struct mrt *, time_t);
#define DUMP_BYTE(x, b) \
@@ -48,8 +49,7 @@ static int mrt_open(struct mrt *, time_t);
u_char t = (b); \
if (buf_add((x), &t, sizeof(t)) == -1) { \
log_warnx("mrt_dump1: buf_add error"); \
- buf_free((x)); \
- return (-1); \
+ goto fail; \
} \
} while (0)
@@ -59,8 +59,7 @@ static int mrt_open(struct mrt *, time_t);
t = htons((s)); \
if (buf_add((x), &t, sizeof(t)) == -1) { \
log_warnx("mrt_dump2: buf_add error"); \
- buf_free((x)); \
- return (-1); \
+ goto fail; \
} \
} while (0)
@@ -70,8 +69,7 @@ static int mrt_open(struct mrt *, time_t);
t = htonl((l)); \
if (buf_add((x), &t, sizeof(t)) == -1) { \
log_warnx("mrt_dump3: buf_add error"); \
- buf_free((x)); \
- return (-1); \
+ goto fail; \
} \
} while (0)
@@ -80,325 +78,175 @@ static int mrt_open(struct mrt *, time_t);
u_int32_t t = (l); \
if (buf_add((x), &t, sizeof(t)) == -1) { \
log_warnx("mrt_dump4: buf_add error"); \
- buf_free((x)); \
- return (-1); \
+ goto fail; \
} \
} while (0)
-int
+void
mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen,
- struct peer *peer, struct bgpd_config *bgp)
+ struct peer *peer)
{
struct buf *buf;
- u_int16_t len;
int incoming = 0;
- switch (peer->sa_local.ss_family) {
- case AF_INET:
- len = pkglen + MRT_BGP4MP_IPv4_HEADER_SIZE;
- break;
- case AF_INET6:
- len = pkglen + MRT_BGP4MP_IPv6_HEADER_SIZE;
- break;
- default:
- return (-1);
- }
-
/* get the direction of the message to swap address and AS fields */
if (mrt->type == MRT_ALL_IN || mrt->type == MRT_UPDATE_IN)
incoming = 1;
- if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) {
- log_warnx("mrt_dump_bgp_msg: buf_open error");
- return (-1);
- }
-
- if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
- len) == -1) {
- log_warnx("mrt_dump_bgp_msg: buf_add error");
- return (-1);
- }
-
- if (!incoming)
- DUMP_SHORT(buf, bgp->short_as);
- DUMP_SHORT(buf, peer->short_as);
- if (incoming)
- DUMP_SHORT(buf, bgp->short_as);
- DUMP_SHORT(buf, /* ifindex */ 0);
- switch (peer->sa_local.ss_family) {
- case AF_INET:
- DUMP_SHORT(buf, AFI_IPv4);
- if (!incoming)
- DUMP_NLONG(buf, ((struct sockaddr_in *)
- &peer->sa_local)->sin_addr.s_addr);
- DUMP_NLONG(buf,
- ((struct sockaddr_in *)&peer->sa_remote)->sin_addr.s_addr);
- if (incoming)
- DUMP_NLONG(buf, ((struct sockaddr_in *)
- &peer->sa_local)->sin_addr.s_addr);
- break;
- case AF_INET6:
- DUMP_SHORT(buf, AFI_IPv6);
- if (!incoming)
- if (buf_add(buf, &((struct sockaddr_in6 *)
- &peer->sa_local)->sin6_addr,
- sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_bgp_msg: buf_add error");
- buf_free(buf);
- return (-1);
- }
- if (buf_add(buf,
- &((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr,
- sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_bgp_msg: buf_add error");
- buf_free(buf);
- return (-1);
- }
- if (incoming)
- if (buf_add(buf, &((struct sockaddr_in6 *)
- &peer->sa_local)->sin6_addr,
- sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_bgp_msg: buf_add error");
- buf_free(buf);
- return (-1);
- }
- break;
- }
+ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
+ pkglen, incoming) == -1)
+ return;
if (buf_add(buf, pkg, pkglen) == -1) {
log_warnx("mrt_dump_bgp_msg: buf_add error");
buf_free(buf);
- return (-1);
+ return;
}
buf_close(&mrt->wbuf, buf);
-
- return (len + MRT_HEADER_SIZE);
}
-int
+void
mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state,
- struct peer *peer, struct bgpd_config *bgp)
+ struct peer *peer)
{
struct buf *buf;
- u_int16_t len;
-
- switch (peer->sa_local.ss_family) {
- case AF_INET:
- len = 4 + MRT_BGP4MP_IPv4_HEADER_SIZE;
- break;
- case AF_INET6:
- len = 4 + MRT_BGP4MP_IPv6_HEADER_SIZE;
- break;
- default:
- return (-1);
- }
-
- if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) {
- log_warnx("mrt_dump_bgp_state: buf_open error");
- return (-1);
- }
- if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE,
- len) == -1) {
- log_warnx("mrt_dump_bgp_state: buf_add error");
- return (-1);
- }
-
- DUMP_SHORT(buf, bgp->short_as);
- DUMP_SHORT(buf, peer->short_as);
- DUMP_SHORT(buf, /* ifindex */ 0);
- switch (peer->sa_local.ss_family) {
- case AF_INET:
- DUMP_SHORT(buf, AFI_IPv4);
- DUMP_NLONG(buf,
- ((struct sockaddr_in *)&peer->sa_local)->sin_addr.s_addr);
- DUMP_NLONG(buf,
- ((struct sockaddr_in *)&peer->sa_remote)->sin_addr.s_addr);
- break;
- case AF_INET6:
- DUMP_SHORT(buf, AFI_IPv6);
- if (buf_add(buf,
- &((struct sockaddr_in6 *)&peer->sa_local)->sin6_addr,
- sizeof(struct in6_addr)) == -1 ||
- buf_add(buf,
- &((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr,
- sizeof(struct in6_addr)) == -1) {
- log_warnx("mrt_dump_bgp_msg: buf_add error");
- buf_free(buf);
- return (-1);
- }
- break;
- }
+ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
+ 2 * sizeof(short), 0) == -1)
+ return;
DUMP_SHORT(buf, old_state);
DUMP_SHORT(buf, new_state);
buf_close(&mrt->wbuf, buf);
+ return;
- return (len + MRT_HEADER_SIZE);
-}
-
-static u_int16_t
-mrt_attr_length(struct rde_aspath *a, int oldform)
-{
- u_int16_t alen, plen;
- u_int8_t l;
-
- alen = 4 /* origin */ + 7 /* lpref */;
- if (oldform)
- alen += 7 /* nexthop */;
- plen = aspath_length(a->aspath);
- alen += 2 + plen + (plen > 255 ? 2 : 1);
- if (a->med != 0)
- alen += 7;
-
- for (l = 0; l < a->others_len; l++)
- if (a->others[l] != NULL)
- alen += 2 + a->others[l]->len +
- (a->others[l]->len > 255 ? 2 : 1);
- else
- break;
-
- return alen;
+fail:
+ buf_free(buf);
}
static int
-mrt_attr_dump(void *p, u_int16_t len, struct rde_aspath *a,
- struct bgpd_addr *nexthop)
+mrt_attr_dump(struct buf *buf, struct rde_aspath *a, struct bgpd_addr *nexthop)
{
struct attr *oa;
- u_char *buf = p;
- u_int32_t tmp32;
- int r;
- u_int16_t aslen, wlen = 0;
+ u_char *pdata;
+ u_int32_t tmp;
+ int neednewpath = 0;
+ u_int16_t plen;
u_int8_t l;
/* origin */
- if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_ORIGIN,
- &a->origin, 1)) == -1)
+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN,
+ &a->origin, 1) == -1)
return (-1);
- wlen += r; len -= r;
/* aspath */
- aslen = aspath_length(a->aspath);
- if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_ASPATH,
- aspath_dump(a->aspath), aslen)) == -1)
+ pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen);
+ pdata = aspath_deflate(pdata, &plen, &neednewpath);
+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata, plen) == -1)
return (-1);
- wlen += r; len -= r;
+ free(pdata);
if (nexthop) {
/* nexthop, already network byte order */
- if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN,
- ATTR_NEXTHOP, &nexthop->v4.s_addr, 4)) == -1)
+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_NEXTHOP,
+ &nexthop->v4.s_addr, 4) == -1)
return (-1);
- wlen += r; len -= r;
}
/* MED, non transitive */
if (a->med != 0) {
- tmp32 = htonl(a->med);
- if ((r = attr_write(buf + wlen, len, ATTR_OPTIONAL, ATTR_MED,
- &tmp32, 4)) == -1)
+ tmp = htonl(a->med);
+ if (attr_writebuf(buf, ATTR_OPTIONAL, ATTR_MED, &tmp, 4) == -1)
return (-1);
- wlen += r; len -= r;
}
/* local preference, only valid for ibgp */
- tmp32 = htonl(a->lpref);
- if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_LOCALPREF,
- &tmp32, 4)) == -1)
+ tmp = htonl(a->lpref);
+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_LOCALPREF, &tmp, 4) == -1)
return (-1);
- wlen += r; len -= r;
/* dump all other path attributes without modification */
for (l = 0; l < a->others_len; l++) {
if ((oa = a->others[l]) == NULL)
break;
- if ((r = attr_write(buf + wlen, len, oa->flags, oa->type,
- oa->data, oa->len)) == -1)
+ if (attr_writebuf(buf, oa->flags, oa->type,
+ oa->data, oa->len) == -1)
return (-1);
- wlen += r; len -= r;
}
- return (wlen);
+ if (neednewpath) {
+ pdata = aspath_prepend(a->aspath, rde_local_as(), 0, &plen);
+ if (plen != 0)
+ if (attr_writebuf(buf, ATTR_OPTIONAL|ATTR_TRANSITIVE,
+ ATTR_AS4_PATH, pdata, plen) == -1)
+ return (-1);
+ free(pdata);
+ }
+
+ return (0);
}
static int
mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
struct rde_peer *peer)
{
- struct buf *buf;
+ struct buf *buf, *hbuf = NULL, *h2buf = NULL;
void *bptr;
struct bgpd_addr addr, nexthop, *nh;
- u_int16_t len, attr_len;
+ u_int16_t len;
u_int8_t p_len;
sa_family_t af;
- attr_len = mrt_attr_length(p->aspath, 0);
- p_len = PREFIX_SIZE(p->prefix->prefixlen);
- pt_getaddr(p->prefix, &addr);
-
- af = peer->remote_addr.af == 0 ? addr.af : peer->remote_addr.af;
- switch (af) {
- case AF_INET:
- len = MRT_BGP4MP_IPv4_HEADER_SIZE;
- break;
- case AF_INET6:
- len = MRT_BGP4MP_IPv6_HEADER_SIZE;
- break;
- default:
+ if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) {
+ log_warn("mrt_dump_entry_mp: buf_dynamic");
return (-1);
}
- switch (addr.af) {
- case AF_INET:
- len += MRT_BGP4MP_IPv4_ENTRY_SIZE + p_len + attr_len;
- break;
- case AF_INET6:
- len += MRT_BGP4MP_IPv6_ENTRY_SIZE + p_len + attr_len;
- break;
- default:
- return (-1);
- }
-
- if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) {
- log_warnx("mrt_dump_entry_mp: buf_open error");
- return (-1);
+ if (mrt_attr_dump(buf, p->aspath, NULL) == -1) {
+ log_warnx("mrt_dump_entry_mp: mrt_attr_dump error");
+ goto fail;
}
+ len = buf_size(buf);
- if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY,
- len) == -1) {
- log_warnx("mrt_dump_entry_mp: buf_add error");
- return (-1);
+ if ((h2buf = buf_dynamic(MRT_BGP4MP_IPv4_HEADER_SIZE +
+ MRT_BGP4MP_IPv4_ENTRY_SIZE, MRT_BGP4MP_IPv6_HEADER_SIZE +
+ MRT_BGP4MP_IPv6_ENTRY_SIZE + MRT_BGP4MP_MAX_PREFIXLEN)) == NULL) {
+ log_warn("mrt_dump_entry_mp: buf_dynamic");
+ goto fail;
}
- DUMP_SHORT(buf, rde_local_as());
- DUMP_SHORT(buf, peer->short_as);
- DUMP_SHORT(buf, /* ifindex */ 0);
+ DUMP_SHORT(h2buf, rde_local_as());
+ DUMP_SHORT(h2buf, peer->short_as);
+ DUMP_SHORT(h2buf, /* ifindex */ 0);
+ /* XXX is this for peer self? */
+ af = peer->remote_addr.af == 0 ? p->prefix->af : peer->remote_addr.af;
switch (af) {
case AF_INET:
- DUMP_SHORT(buf, AFI_IPv4);
- DUMP_NLONG(buf, peer->local_v4_addr.v4.s_addr);
- DUMP_NLONG(buf, peer->remote_addr.v4.s_addr);
+ DUMP_SHORT(h2buf, AFI_IPv4);
+ DUMP_NLONG(h2buf, peer->local_v4_addr.v4.s_addr);
+ DUMP_NLONG(h2buf, peer->remote_addr.v4.s_addr);
break;
case AF_INET6:
- DUMP_SHORT(buf, AFI_IPv6);
- if (buf_add(buf, &peer->local_v6_addr.v6,
+ DUMP_SHORT(h2buf, AFI_IPv6);
+ if (buf_add(h2buf, &peer->local_v6_addr.v6,
sizeof(struct in6_addr)) == -1 ||
- buf_add(buf, &peer->remote_addr.v6,
+ buf_add(h2buf, &peer->remote_addr.v6,
sizeof(struct in6_addr)) == -1) {
log_warnx("mrt_dump_entry_mp: buf_add error");
- buf_free(buf);
- return (-1);
+ goto fail;
}
break;
+ default:
+ log_warnx("king bula found new AF %d in mrt_dump_entry_mp", af);
+ goto fail;
}
- DUMP_SHORT(buf, 0); /* view */
- DUMP_SHORT(buf, 1); /* status */
- DUMP_LONG(buf, p->lastchange); /* originated */
+ DUMP_SHORT(h2buf, 0); /* view */
+ DUMP_SHORT(h2buf, 1); /* status */
+ DUMP_LONG(h2buf, p->lastchange); /* originated */
if (p->aspath->nexthop == NULL) {
bzero(&nexthop, sizeof(struct bgpd_addr));
@@ -407,94 +255,74 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
} else
nh = &p->aspath->nexthop->exit_nexthop;
+ pt_getaddr(p->prefix, &addr);
switch (addr.af) {
case AF_INET:
- DUMP_SHORT(buf, AFI_IPv4); /* afi */
- DUMP_BYTE(buf, SAFI_UNICAST); /* safi */
- DUMP_BYTE(buf, 4); /* nhlen */
- DUMP_NLONG(buf, nh->v4.s_addr); /* nexthop */
+ DUMP_SHORT(h2buf, AFI_IPv4); /* afi */
+ DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */
+ DUMP_BYTE(h2buf, 4); /* nhlen */
+ DUMP_NLONG(h2buf, nh->v4.s_addr); /* nexthop */
break;
case AF_INET6:
- DUMP_SHORT(buf, AFI_IPv6); /* afi */
- DUMP_BYTE(buf, SAFI_UNICAST); /* safi */
- DUMP_BYTE(buf, 16); /* nhlen */
- if (buf_add(buf, &nh->v6, sizeof(struct in6_addr)) == -1) {
+ DUMP_SHORT(h2buf, AFI_IPv6); /* afi */
+ DUMP_BYTE(h2buf, SAFI_UNICAST); /* safi */
+ DUMP_BYTE(h2buf, 16); /* nhlen */
+ if (buf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) {
log_warnx("mrt_dump_entry_mp: buf_add error");
- buf_free(buf);
- return (-1);
+ goto fail;
}
break;
+ default:
+ log_warnx("king bula found new AF in mrt_dump_entry_mp");
+ goto fail;
}
- if ((bptr = buf_reserve(buf, p_len)) == NULL) {
+ p_len = PREFIX_SIZE(p->prefix->prefixlen);
+ if ((bptr = buf_reserve(h2buf, p_len)) == NULL) {
log_warnx("mrt_dump_entry_mp: buf_reserve error");
- buf_free(buf);
- return (-1);
+ goto fail;
}
if (prefix_write(bptr, p_len, &addr, p->prefix->prefixlen) == -1) {
log_warnx("mrt_dump_entry_mp: prefix_write error");
- buf_free(buf);
- return (-1);
+ goto fail;
}
- DUMP_SHORT(buf, attr_len);
- if ((bptr = buf_reserve(buf, attr_len)) == NULL) {
- log_warnx("mrt_dump_entry_mp: buf_reserve error");
- buf_free(buf);
- return (-1);
- }
+ DUMP_SHORT(h2buf, len);
+ len += buf_size(h2buf);
- if (mrt_attr_dump(bptr, attr_len, p->aspath, NULL) == -1) {
- log_warnx("mrt_dump_entry_mp: mrt_attr_dump error");
- buf_free(buf);
- return (-1);
- }
+ if (mrt_dump_hdr_rde(&hbuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY,
+ len) == -1)
+ goto fail;
+ buf_close(&mrt->wbuf, hbuf);
+ buf_close(&mrt->wbuf, h2buf);
buf_close(&mrt->wbuf, buf);
return (len + MRT_HEADER_SIZE);
+
+fail:
+ if (hbuf)
+ buf_free(hbuf);
+ if (h2buf);
+ buf_free(h2buf);
+ buf_free(buf);
+ return (-1);
}
static int
mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
struct rde_peer *peer)
{
- struct buf *buf;
- void *bptr;
+ struct buf *buf, *hbuf;
struct bgpd_addr addr, *nh;
- u_int16_t len, attr_len;
+ size_t len;
if (p->prefix->af != AF_INET && peer->remote_addr.af == AF_INET)
- /* only for true IPv4 */
+ /* only able to dump IPv4 */
return (0);
- attr_len = mrt_attr_length(p->aspath, 1);
- len = MRT_DUMP_HEADER_SIZE + attr_len;
- pt_getaddr(p->prefix, &addr);
-
- if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) {
- log_warnx("mrt_dump_entry: buf_open error");
- return (-1);
- }
-
- if (mrt_dump_header(buf, MSG_TABLE_DUMP, AFI_IPv4, len) == -1) {
- log_warnx("mrt_dump_entry: buf_add error");
- return (-1);
- }
-
- DUMP_SHORT(buf, 0);
- DUMP_SHORT(buf, snum);
- DUMP_NLONG(buf, addr.v4.s_addr);
- DUMP_BYTE(buf, p->prefix->prefixlen);
- DUMP_BYTE(buf, 1); /* state */
- DUMP_LONG(buf, p->lastchange); /* originated */
- DUMP_NLONG(buf, peer->remote_addr.v4.s_addr);
- DUMP_SHORT(buf, peer->short_as);
-
- DUMP_SHORT(buf, attr_len);
- if ((bptr = buf_reserve(buf, attr_len)) == NULL) {
- log_warnx("mrt_dump_entry: buf_reserve error");
- buf_free(buf);
+ if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) {
+ log_warnx("mrt_dump_entry: buf_dynamic");
return (-1);
}
@@ -504,15 +332,40 @@ 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(bptr, attr_len, p->aspath, nh) == -1) {
+ if (mrt_attr_dump(buf, p->aspath, nh) == -1) {
log_warnx("mrt_dump_entry: mrt_attr_dump error");
buf_free(buf);
return (-1);
}
+ len = buf_size(buf);
+ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, AFI_IPv4, len) == -1) {
+ buf_free(buf);
+ return (-1);
+ }
+
+ DUMP_SHORT(hbuf, 0);
+ DUMP_SHORT(hbuf, snum);
+
+ pt_getaddr(p->prefix, &addr);
+ DUMP_NLONG(hbuf, addr.v4.s_addr);
+ DUMP_BYTE(hbuf, p->prefix->prefixlen);
+
+ DUMP_BYTE(hbuf, 1); /* state */
+ DUMP_LONG(hbuf, p->lastchange); /* originated */
+ DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr);
+ DUMP_SHORT(hbuf, peer->short_as);
+ DUMP_SHORT(hbuf, len);
+
+ buf_close(&mrt->wbuf, hbuf);
buf_close(&mrt->wbuf, buf);
return (len + MRT_HEADER_SIZE);
+
+fail:
+ buf_free(hbuf);
+ buf_free(buf);
+ return (-1);
}
static u_int16_t sequencenum = 0;
@@ -548,19 +401,142 @@ mrt_dump_upcall(struct pt_entry *pt, void *ptr)
}
static int
-mrt_dump_header(struct buf *buf, u_int16_t type, u_int16_t subtype,
- u_int32_t len)
+mrt_dump_hdr_se(struct buf ** bp, struct peer *peer, u_int16_t type,
+ u_int16_t subtype, u_int32_t len, int swap)
{
- time_t now;
+ time_t now;
+
+ if ((*bp = buf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE +
+ MRT_BGP4MP_AS4_IPv6_HEADER_SIZE + len)) == NULL) {
+ log_warnx("mrt_dump_hdr_se: buf_open error");
+ return (-1);
+ }
now = time(NULL);
- DUMP_LONG(buf, now);
- DUMP_SHORT(buf, type);
- DUMP_SHORT(buf, subtype);
- DUMP_LONG(buf, len);
+ DUMP_LONG(*bp, now);
+ DUMP_SHORT(*bp, type);
+ DUMP_SHORT(*bp, subtype);
+
+ switch (peer->sa_local.ss_family) {
+ case AF_INET:
+ if (subtype == BGP4MP_STATE_CHANGE_AS4 ||
+ subtype == BGP4MP_MESSAGE_AS4)
+ len += MRT_BGP4MP_AS4_IPv4_HEADER_SIZE;
+ else
+ len += MRT_BGP4MP_IPv4_HEADER_SIZE;
+ break;
+ case AF_INET6:
+ if (subtype == BGP4MP_STATE_CHANGE_AS4 ||
+ subtype == BGP4MP_MESSAGE_AS4)
+ len += MRT_BGP4MP_AS4_IPv6_HEADER_SIZE;
+ else
+ len += MRT_BGP4MP_IPv6_HEADER_SIZE;
+ break;
+ case 0:
+ goto fail;
+ default:
+ log_warnx("king bula found new AF in mrt_dump_hdr_se");
+ goto fail;
+ }
+
+ DUMP_LONG(*bp, len);
+
+ if (subtype == BGP4MP_STATE_CHANGE_AS4 ||
+ subtype == BGP4MP_MESSAGE_AS4) {
+ if (!swap)
+ DUMP_LONG(*bp, peer->conf.local_as);
+ DUMP_LONG(*bp, peer->conf.remote_as);
+ if (swap)
+ DUMP_LONG(*bp, peer->conf.local_as);
+ } else {
+ if (!swap)
+ DUMP_SHORT(*bp, peer->conf.local_short_as);
+ DUMP_SHORT(*bp, peer->short_as);
+ if (swap)
+ DUMP_SHORT(*bp, peer->conf.local_short_as);
+ }
+
+ DUMP_SHORT(*bp, /* ifindex */ 0);
+
+ switch (peer->sa_local.ss_family) {
+ case AF_INET:
+ DUMP_SHORT(*bp, AFI_IPv4);
+ if (!swap)
+ DUMP_NLONG(*bp, ((struct sockaddr_in *)
+ &peer->sa_local)->sin_addr.s_addr);
+ DUMP_NLONG(*bp,
+ ((struct sockaddr_in *)&peer->sa_remote)->sin_addr.s_addr);
+ if (swap)
+ DUMP_NLONG(*bp, ((struct sockaddr_in *)
+ &peer->sa_local)->sin_addr.s_addr);
+ break;
+ case AF_INET6:
+ DUMP_SHORT(*bp, AFI_IPv6);
+ if (!swap)
+ if (buf_add(*bp, &((struct sockaddr_in6 *)
+ &peer->sa_local)->sin6_addr,
+ sizeof(struct in6_addr)) == -1) {
+ log_warnx("mrt_dump_hdr_se: buf_add error");
+ goto fail;
+ }
+ if (buf_add(*bp,
+ &((struct sockaddr_in6 *)&peer->sa_remote)->sin6_addr,
+ sizeof(struct in6_addr)) == -1) {
+ log_warnx("mrt_dump_hdr_se: buf_add error");
+ goto fail;
+ }
+ if (swap)
+ if (buf_add(*bp, &((struct sockaddr_in6 *)
+ &peer->sa_local)->sin6_addr,
+ sizeof(struct in6_addr)) == -1) {
+ log_warnx("mrt_dump_hdr_se: buf_add error");
+ goto fail;
+ }
+ break;
+ }
return (0);
+
+fail:
+ buf_free(*bp);
+ return (-1);
+}
+
+static int
+mrt_dump_hdr_rde(struct buf **bp, u_int16_t type, u_int16_t subtype,
+ u_int32_t len)
+{
+ time_t now;
+
+ if ((*bp = buf_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");
+ return (-1);
+ }
+
+ now = time(NULL);
+ DUMP_LONG(*bp, now);
+ DUMP_SHORT(*bp, type);
+ DUMP_SHORT(*bp, subtype);
+
+ switch (type) {
+ case MSG_TABLE_DUMP:
+ DUMP_LONG(*bp, MRT_DUMP_HEADER_SIZE + len);
+ break;
+ case MSG_PROTOCOL_BGP4MP:
+ DUMP_LONG(*bp, len);
+ break;
+ default:
+ log_warnx("mrt_dump_hdr_rde: unsupported type");
+ goto fail;
+ }
+ return (0);
+
+fail:
+ buf_free(*bp);
+ return (-1);
}
void
diff --git a/usr.sbin/bgpd/mrt.h b/usr.sbin/bgpd/mrt.h
index 2998c18cbec..6a6bc805987 100644
--- a/usr.sbin/bgpd/mrt.h
+++ b/usr.sbin/bgpd/mrt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.h,v 1.18 2009/03/13 06:25:04 claudio Exp $ */
+/* $OpenBSD: mrt.h,v 1.19 2009/03/19 07:00:07 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -20,12 +20,10 @@
#include "bgpd.h"
-/* In cases of failure wait at least MRT_MIN_RETRY. */
-#define MRT_MIN_RETRY 300
-
/*
- * MRT binary packet format as used by zebra.
+ * MRT binary packet format
* For more info see:
+ * draft-ietf-grow-mrt-04.txt, "MRT routing information export format"
* http://www.quagga.net/docs/docs-multi/Packet-Binary-Dump-Format.html
*/
@@ -38,24 +36,33 @@
* +--------+--------+--------+--------+
* | length | length of packet excluding this header
* +--------+--------+--------+--------+
+ *
+ * ET types include an additional 32bit microsecond field comming after the
+ * length field.
*/
#define MRT_HEADER_SIZE 12
enum MRT_MSG_TYPES {
- MSG_NULL,
+ MSG_NULL, /* 0 empty msg (deprecated) */
MSG_START, /* 1 sender is starting up */
- MSG_DIE, /* 2 receiver should shut down */
+ MSG_DIE, /* 2 receiver should shut down (deprecated) */
MSG_I_AM_DEAD, /* 3 sender is shutting down */
- MSG_PEER_DOWN, /* 4 sender's peer is down */
- MSG_PROTOCOL_BGP, /* 5 msg is a BGP packet */
+ MSG_PEER_DOWN, /* 4 sender's peer is down (deprecated) */
+ MSG_PROTOCOL_BGP, /* 5 msg is a BGP packet (deprecated) */
MSG_PROTOCOL_RIP, /* 6 msg is a RIP packet */
- MSG_PROTOCOL_IDRP, /* 7 msg is an IDRP packet */
+ MSG_PROTOCOL_IDRP, /* 7 msg is an IDRP packet (deprecated) */
MSG_PROTOCOL_RIPNG, /* 8 msg is a RIPNG packet */
- MSG_PROTOCOL_BGP4PLUS, /* 9 msg is a BGP4+ packet */
- MSG_PROTOCOL_BGP4PLUS1, /* 10 msg is a BGP4+ (draft 01) packet */
+ MSG_PROTOCOL_BGP4PLUS, /* 9 msg is a BGP4+ packet (deprecated) */
+ MSG_PROTOCOL_BGP4PLUS1, /* 10 msg is a BGP4+ (draft 01) (deprecated) */
MSG_PROTOCOL_OSPF, /* 11 msg is an OSPF packet */
MSG_TABLE_DUMP, /* 12 routing table dump */
- MSG_PROTOCOL_BGP4MP=16 /* 16 zebras own packet format */
+ MSG_TABLE_DUMP_V2, /* 13 routing table dump */
+ MSG_PROTOCOL_BGP4MP=16, /* 16 zebras own packet format */
+ MSG_PROTOCOL_BGP4MP_ET=17,
+ MSG_PROTOCOL_ISIS=32, /* 32 msg is a ISIS package */
+ MSG_PROTOCOL_ISIS_ET=33,
+ MSG_PROTOCOL_OSPFV3=48, /* 48 msg is a OSPFv3 package */
+ MSG_PROTOCOL_OSPFV3_ET=49
};
/*
@@ -64,15 +71,20 @@ enum MRT_MSG_TYPES {
* In most cases this is the format to choose to dump updates et al.
*/
enum MRT_BGP4MP_TYPES {
- BGP4MP_STATE_CHANGE=0, /* state change */
- BGP4MP_MESSAGE=1, /* bgp message */
- BGP4MP_ENTRY=2, /* table dumps */
- BGP4MP_SNAPSHOT=3
+ BGP4MP_STATE_CHANGE, /* state change */
+ BGP4MP_MESSAGE, /* bgp message */
+ BGP4MP_ENTRY, /* table dumps (deprecated) */
+ BGP4MP_SNAPSHOT, /* file name for dump (deprecated) */
+ BGP4MP_STATE_CHANGE_AS4,
+ BGP4MP_MESSAGE_AS4 /* same as BGP4MP_MESSAGE with 4byte AS */
};
/* size of the BGP4MP headers without payload */
#define MRT_BGP4MP_IPv4_HEADER_SIZE 16
#define MRT_BGP4MP_IPv6_HEADER_SIZE 40
+/* 4-byte AS variants of the previous */
+#define MRT_BGP4MP_AS4_IPv4_HEADER_SIZE 20
+#define MRT_BGP4MP_AS4_IPv6_HEADER_SIZE 44
/* If the type is PROTOCOL_BGP4MP and the subtype is either BGP4MP_STATE_CHANGE
* or BGP4MP_MESSAGE the message consists of a common header plus the payload.
@@ -110,6 +122,7 @@ enum MRT_BGP4MP_TYPES {
*/
#define MRT_BGP4MP_IPv4_ENTRY_SIZE 18
#define MRT_BGP4MP_IPv6_ENTRY_SIZE 30
+#define MRT_BGP4MP_MAX_PREFIXLEN 17
/*
* The "new" table dump format consists of messages of type PROTOCOL_BGP4MP
* and subtype BGP4MP_ENTRY.
@@ -151,9 +164,9 @@ enum MRT_BGP4MP_TYPES {
* +--------+--------+--------+--------+
* | prefix |
* +--------+--------+--------+--------+
- * | plen | status | originated
+ * | plen | status | originated time
* +--------+--------+--------+--------+
- * originated | peer_ip
+ * originated time | peer_ip
* +--------+--------+--------+--------+
* peer_ip | peer_as |
* +--------+--------+--------+--------+
@@ -166,8 +179,7 @@ enum MRT_BGP4MP_TYPES {
*
*
* View is normaly 0 and seqnum just a simple counter for this dump.
- * The status seems to be 1 by default but probably something to indicate
- * the status of a prefix would be more useful.
+ * The status field is unused and should be set to 1.
*/
/* size of the dump header until attr_len */
@@ -186,10 +198,14 @@ enum MRT_BGP_TYPES {
and announcements) */
MSG_BGP_PREF_UPDATE, /* tlv preferences followed by raw update */
MSG_BGP_STATE_CHANGE, /* state change */
- MSG_BGP_SYNC
+ MSG_BGP_SYNC, /* file name for a table dump */
+ MSG_BGP_OPEN, /* BGP open messages */
+ MSG_BGP_NOTIFY, /* BGP notify messages */
+ MSG_BGP_KEEPALIVE /* BGP keepalives */
};
-/* if type MSG_PROTOCOL_BGP and subtype MSG_BGP_UPDATE
+/* if type MSG_PROTOCOL_BGP and subtype MSG_BGP_UPDATE, MSG_BGP_OPEN,
+ * MSG_BGP_NOTIFY or MSG_BGP_KEEPALIVE
*
* +--------+--------+--------+--------+
* | source_as | source_ip
@@ -225,7 +241,7 @@ enum MRT_BGP_TYPES {
/*
* if type MSG_PROTOCOL_BGP and subtype MSG_BGP_SYNC OR
* if type MSG_PROTOCOL_BGP4MP and subtype BGP4MP_SNAPSHOT
- * What is this for?
+ * *DEPRECATED*
*
* +--------+--------+--------+--------+
* | view | filename
@@ -279,10 +295,10 @@ struct prefix;
struct pt_entry;
/* prototypes */
-int mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t,
- struct peer *, struct bgpd_config *);
-int mrt_dump_state(struct mrt *, u_int16_t, u_int16_t,
- struct peer *, struct bgpd_config *);
+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 *);
void mrt_clear_seq(void);
void mrt_dump_upcall(struct pt_entry *, void *);
void mrt_write(struct mrt *);
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index a1e9647bf86..fdeb2111e20 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.288 2009/03/18 19:49:31 claudio Exp $ */
+/* $OpenBSD: session.c,v 1.289 2009/03/19 07:00:07 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -964,7 +964,7 @@ change_state(struct peer *peer, enum session_state state,
if ((mrt->peer_id == 0 && mrt->group_id == 0) ||
mrt->peer_id == peer->conf.id || (mrt->group_id != 0 &&
mrt->group_id == peer->conf.groupid))
- mrt_dump_state(mrt, peer->state, state, peer, conf);
+ mrt_dump_state(mrt, peer->state, state, peer);
}
peer->prev_state = peer->state;
peer->state = state;
@@ -1318,7 +1318,7 @@ session_sendmsg(struct bgp_msg *msg, struct peer *p)
if ((mrt->peer_id == 0 && mrt->group_id == 0) ||
mrt->peer_id == p->conf.id || (mrt->group_id == 0 &&
mrt->group_id == p->conf.groupid))
- mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p, conf);
+ mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p);
}
if (buf_close(&p->wbuf, msg->buf) == -1) {
@@ -1807,7 +1807,7 @@ parse_header(struct peer *peer, u_char *data, u_int16_t *len, u_int8_t *type)
if ((mrt->peer_id == 0 && mrt->group_id == 0) ||
mrt->peer_id == peer->conf.id || (mrt->group_id != 0 &&
mrt->group_id == peer->conf.groupid))
- mrt_dump_bgp_msg(mrt, data, *len, peer, conf);
+ mrt_dump_bgp_msg(mrt, data, *len, peer);
}
return (0);
}