diff options
-rw-r--r-- | usr.sbin/bgpd/mrt.c | 578 | ||||
-rw-r--r-- | usr.sbin/bgpd/mrt.h | 72 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 8 |
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); } |