diff options
author | 2004-08-13 14:03:20 +0000 | |
---|---|---|
committer | 2004-08-13 14:03:20 +0000 | |
commit | dfafe578696b99cf3273c4c5f4a6152a71131fcb (patch) | |
tree | 1a845b22b1a09a72dfb33dd353e451b481494f6b | |
parent | Cleanup the code, will need rework (diff) | |
download | wireguard-openbsd-dfafe578696b99cf3273c4c5f4a6152a71131fcb.tar.xz wireguard-openbsd-dfafe578696b99cf3273c4c5f4a6152a71131fcb.zip |
Fix minor issues with IPv6 dumps and add a function for dumping the RIB table
protocol independent. This new dump format is not (yet) supported by the
mrtd route_btoa tool. OK henning@
-rw-r--r-- | usr.sbin/bgpd/bgpd.conf.5 | 11 | ||||
-rw-r--r-- | usr.sbin/bgpd/mrt.c | 200 | ||||
-rw-r--r-- | usr.sbin/bgpd/mrt.h | 14 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 22 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 6 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 20 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 23 |
8 files changed, 246 insertions, 54 deletions
diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index 8d26b8c0e5e..d5e8ee078eb 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.34 2004/08/09 16:29:18 jaredy Exp $ +.\" $OpenBSD: bgpd.conf.5,v 1.35 2004/08/13 14:03:20 claudio Exp $ .\" .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -104,7 +104,11 @@ AS 65001 .Pp sets the local AS to 65001. .Pp -.It Ic dump table Ar file Op Ar timeout +.It Xo +.Ic dump +.Pq Ic table Ns \&| Ns Ic table-mp +.Ar file Op Ar timeout +.Xc .It Xo .Ic dump .Pq Ic all Ns \&| Ns Ic updates @@ -121,6 +125,9 @@ Excessive dumping may result in delayed update processing. For example, the following will dump the entire table to the .Xr strftime 3 Ns -expanded filename. +The +.Ic table-mp +format is multi-protocol capable but often not supported by 3rd-party tools. 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 17347d1e5df..f214782554e 100644 --- a/usr.sbin/bgpd/mrt.c +++ b/usr.sbin/bgpd/mrt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.c,v 1.43 2004/08/11 16:48:45 claudio Exp $ */ +/* $OpenBSD: mrt.c,v 1.44 2004/08/13 14:03:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -32,11 +32,13 @@ #include "mrt.h" -static u_int16_t mrt_attr_length(struct rde_aspath *); +static u_int16_t mrt_attr_length(struct rde_aspath *, int); static int mrt_attr_dump(void *, u_int16_t, 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 peer_config *); + 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_open(struct mrt *, time_t); @@ -90,7 +92,16 @@ mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen, struct buf *buf; u_int16_t len; - len = pkglen + MRT_BGP4MP_HEADER_SIZE; + 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); + } if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) { log_warnx("mrt_dump_bgp_msg: buf_open error"); @@ -148,7 +159,16 @@ mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state, struct buf *buf; u_int16_t len; - len = 4 + MRT_BGP4MP_HEADER_SIZE; + 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"); @@ -197,12 +217,14 @@ mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state, } static u_int16_t -mrt_attr_length(struct rde_aspath *a) +mrt_attr_length(struct rde_aspath *a, int oldform) { struct attr *oa; u_int16_t alen, plen; - alen = 4 /* origin */ + 7 /* nexthop */ + 7 /* lpref */; + 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) @@ -237,11 +259,13 @@ mrt_attr_dump(void *p, u_int16_t len, struct rde_aspath *a, return (-1); wlen += r; len -= r; - /* nexthop, already network byte order */ - if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN, ATTR_NEXTHOP, - &nexthop->v4.s_addr, 4)) == -1) - return (-1); - wlen += r; len -= r; + 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) + return (-1); + wlen += r; len -= r; + } /* MED, non transitive */ if (a->med != 0) { @@ -271,15 +295,151 @@ mrt_attr_dump(void *p, u_int16_t len, struct rde_aspath *a, } static int +mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, + struct rde_peer *peer) +{ + struct buf *buf; + void *bptr; + struct bgpd_addr addr, nexthop, *nh; + u_int16_t len, attr_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: + 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_IPv4_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_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY, + len) == -1) { + log_warnx("mrt_dump_entry_mp: buf_add error"); + return (-1); + } + + DUMP_SHORT(buf, rde_local_as()); + DUMP_SHORT(buf, peer->conf.remote_as); + DUMP_SHORT(buf, /* ifindex */ 0); + + switch (af) { + case AF_INET: + DUMP_SHORT(buf, AFI_IPv4); + DUMP_NLONG(buf, peer->local_addr.v4.s_addr); + DUMP_NLONG(buf, peer->remote_addr.v4.s_addr); + break; + case AF_INET6: + DUMP_SHORT(buf, AFI_IPv6); + if (buf_add(buf, &peer->local_addr.v6, + sizeof(struct in6_addr)) == -1 || + buf_add(buf, &peer->remote_addr.v6, + sizeof(struct in6_addr)) == -1) { + log_warnx("mrt_dump_entry_mp: buf_add error"); + buf_free(buf); + return (-1); + } + break; + } + + DUMP_SHORT(buf, 0); /* view */ + DUMP_SHORT(buf, 1); /* status */ + DUMP_LONG(buf, p->lastchange); /* originated */ + + if (p->aspath->nexthop == NULL) { + bzero(&nexthop, sizeof(struct bgpd_addr)); + nexthop.af = addr.af; + nh = &nexthop; + } else + nh = &p->aspath->nexthop->exit_nexthop; + + 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 */ + 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) { + log_warnx("mrt_dump_entry_mp: buf_add error"); + buf_free(buf); + return (-1); + } + break; + } + + if ((bptr = buf_reserve(buf, p_len)) == NULL) { + log_warnx("mrt_dump_entry_mpbuf_reserve error"); + buf_free(buf); + return (-1); + } + if (prefix_write(bptr, p_len, &addr, p->prefix->prefixlen) == -1) { + log_warnx("mrt_dump_entry_mpprefix_write error"); + buf_free(buf); + return (-1); + } + + DUMP_SHORT(buf, attr_len); + if ((bptr = buf_reserve(buf, attr_len)) == NULL) { + log_warnx("mrt_dump_entry_mpbuf_reserve error"); + buf_free(buf); + return (-1); + } + + if (mrt_attr_dump(bptr, attr_len, p->aspath, NULL) == -1) { + log_warnx("mrt_dump_entry_mpmrt_attr_dump error"); + buf_free(buf); + return (-1); + } + + TAILQ_INSERT_TAIL(&mrt->bufs, buf, entry); + mrt->queued++; + + return (len + MRT_HEADER_SIZE); +} + +static int mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, - struct peer_config *peer) + struct rde_peer *peer) { struct buf *buf; void *bptr; struct bgpd_addr addr, *nh; u_int16_t len, attr_len; - attr_len = mrt_attr_length(p->aspath); + if (p->prefix->af != AF_INET && peer->remote_addr.af == AF_INET) + /* only for true IPv4 */ + return (0); + + attr_len = mrt_attr_length(p->aspath, 1); len = MRT_DUMP_HEADER_SIZE + attr_len; pt_getaddr(p->prefix, &addr); @@ -289,7 +449,7 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, } if (mrt_dump_header(buf, MSG_TABLE_DUMP, AFI_IPv4, len) == -1) { - log_warnx("mrt_dump_bgp_msg: buf_add error"); + log_warnx("mrt_dump_entry: buf_add error"); return (-1); } @@ -300,9 +460,9 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, DUMP_BYTE(buf, 1); /* state */ DUMP_LONG(buf, p->lastchange); /* originated */ DUMP_NLONG(buf, peer->remote_addr.v4.s_addr); - DUMP_SHORT(buf, peer->remote_as); - DUMP_SHORT(buf, attr_len); + DUMP_SHORT(buf, peer->conf.remote_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); @@ -347,8 +507,10 @@ mrt_dump_upcall(struct pt_entry *pt, void *ptr) * be dumped p should be set to p = pt->active. */ LIST_FOREACH(p, &pt->prefix_h, prefix_l) - mrt_dump_entry(mrtbuf, p, sequencenum++, - &p->peer->conf); + if (mrtbuf->type == MRT_TABLE_DUMP) + mrt_dump_entry(mrtbuf, p, sequencenum++, p->peer); + else + mrt_dump_entry_mp(mrtbuf, p, sequencenum++, p->peer); } static int diff --git a/usr.sbin/bgpd/mrt.h b/usr.sbin/bgpd/mrt.h index 1f4942b18fa..8c48653ca31 100644 --- a/usr.sbin/bgpd/mrt.h +++ b/usr.sbin/bgpd/mrt.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.h,v 1.14 2004/08/11 16:48:45 claudio Exp $ */ +/* $OpenBSD: mrt.h,v 1.15 2004/08/13 14:03:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -40,7 +40,7 @@ * +--------+--------+--------+--------+ * | type | subtype | * +--------+--------+--------+--------+ - * | length | length of packet including header + * | length | length of packet excluding this header * +--------+--------+--------+--------+ */ #define MRT_HEADER_SIZE 12 @@ -75,7 +75,8 @@ enum MRT_BGP4MP_TYPES { }; /* size of the BGP4MP headers without payload */ -#define MRT_BGP4MP_HEADER_SIZE 16 +#define MRT_BGP4MP_IPv4_HEADER_SIZE 16 +#define MRT_BGP4MP_IPv6_HEADER_SIZE 40 /* 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. @@ -108,6 +109,12 @@ enum MRT_BGP4MP_TYPES { */ /* + * size of the BGP4MP entries without variable stuff. + * All until nexthop plus attr_len, not included plen, prefix and bgp attrs. + */ +#define MRT_BGP4MP_IPv4_ENTRY_SIZE 18 +#define MRT_BGP4MP_IPv6_ENTRY_SIZE 30 +/* * The "new" table dump format consists of messages of type PROTOCOL_BGP4MP * and subtype BGP4MP_ENTRY. * @@ -237,6 +244,7 @@ enum MRT_BGP_TYPES { enum mrt_type { MRT_NONE, MRT_TABLE_DUMP, + MRT_TABLE_DUMP_MP, MRT_ALL_IN, MRT_ALL_OUT, MRT_UPDATE_IN, diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index a1c02b09478..7c98357000f 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.132 2004/08/10 13:02:08 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.133 2004/08/13 14:03:20 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -139,7 +139,7 @@ typedef struct { %token GROUP NEIGHBOR NETWORK %token REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX ANNOUNCE %token ENFORCE NEIGHBORAS CAPABILITIES REFLECTOR -%token DUMP TABLE IN OUT +%token DUMP IN OUT %token LOG ROUTECOLL %token TCP MD5SIG PASSWORD KEY %token ALLOW DENY MATCH @@ -326,8 +326,21 @@ conf_main : AS asnumber { TAILQ_INSERT_TAIL(netconf, n, entry); } - | DUMP TABLE STRING optnumber { - if (add_mrtconfig(MRT_TABLE_DUMP, $3, $4, NULL) == -1) { + | DUMP STRING STRING optnumber { + int action; + + if (!strcmp($2, "table")) + action = MRT_TABLE_DUMP; + else if (!strcmp($2, "table-mp")) + action = MRT_TABLE_DUMP_MP; + else { + yyerror("unknown mrt dump type"); + free($2); + free($3); + YYERROR; + } + free($2); + if (add_mrtconfig(action, $3, $4, NULL) == -1) { free($3); YYERROR; } @@ -1252,7 +1265,6 @@ lookup(char *s) { "set", SET}, { "source-AS", SOURCEAS}, { "spi", SPI}, - { "table", TABLE}, { "tcp", TCP}, { "to", TO}, { "transit-AS", TRANSITAS} diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 0309f85e373..f0642e7f056 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.26 2004/08/10 13:02:08 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.27 2004/08/13 14:03:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -334,9 +334,11 @@ mrt_type(enum mrt_type t) { switch (t) { case MRT_NONE: - return "unfluffy MRT"; + break; case MRT_TABLE_DUMP: return "table"; + case MRT_TABLE_DUMP_MP: + return "table-mp"; case MRT_ALL_IN: return "all in"; case MRT_ALL_OUT: diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 855564b6fa6..8db89dba774 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.54 2004/08/12 10:24:16 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.55 2004/08/13 14:03:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -295,12 +295,14 @@ struct rde_aspath *path_copy(struct rde_aspath *); struct rde_aspath *path_get(void); void path_put(struct rde_aspath *); +#define PREFIX_SIZE(x) (((x) + 7) / 8 + 1) int prefix_compare(const struct bgpd_addr *, const struct bgpd_addr *, int); struct prefix *prefix_get(struct rde_peer *, struct bgpd_addr *, int); struct pt_entry *prefix_add(struct rde_aspath *, struct bgpd_addr *, int); struct pt_entry *prefix_move(struct rde_aspath *, struct prefix *); void prefix_remove(struct rde_peer *, struct bgpd_addr *, int); +int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t); struct prefix *prefix_bypeer(struct pt_entry *, struct rde_peer *); void prefix_updateall(struct rde_aspath *, enum nexthop_state); void prefix_destroy(struct prefix *); diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 77cbc89fbd9..f3f00a7668e 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.57 2004/08/12 10:24:16 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.58 2004/08/13 14:03:20 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -489,6 +489,24 @@ prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen) path_destroy(asp); } +/* dump a prefix into specified buffer */ +int +prefix_write(u_char *buf, int len, struct bgpd_addr *prefix, u_int8_t plen) +{ + int totlen; + + if (prefix->af != AF_INET) + return (-1); + + totlen = PREFIX_SIZE(plen); + + if (totlen > len) + return (-1); + *buf++ = plen; + memcpy(buf, &prefix->ba, totlen - 1); + return (totlen); +} + /* * Searches in the prefix list of specified pt_entry for a prefix entry * belonging to the peer peer. Returns NULL if no match found. diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index f561c62fffb..3af16ff7059 100644 --- a/usr.sbin/bgpd/rde_update.c +++ b/usr.sbin/bgpd/rde_update.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_update.c,v 1.28 2004/08/10 12:57:18 claudio Exp $ */ +/* $OpenBSD: rde_update.c,v 1.29 2004/08/13 14:03:20 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -26,8 +26,6 @@ int up_generate_attr(struct rde_peer *, struct update_attr *, struct rde_aspath *); -int up_set_prefix(u_char *, int, struct bgpd_addr *, u_int8_t); - /* update stuff. */ struct update_prefix { @@ -707,23 +705,6 @@ up_generate_attr(struct rde_peer *peer, struct update_attr *upa, return (wlen); } -int -up_set_prefix(u_char *buf, int len, struct bgpd_addr *prefix, u_int8_t plen) -{ - int totlen; - - if (prefix->af != AF_INET) - return (-1); - - totlen = (plen + 7) / 8 + 1; - - if (totlen > len) - return (-1); - *buf++ = plen; - memcpy(buf, &prefix->v4.s_addr, totlen - 1); - return (totlen); -} - #define MIN_PREFIX_LEN 5 /* 1 byte prefix length + 4 bytes addr */ int up_dump_prefix(u_char *buf, int len, struct uplist_prefix *prefix_head, @@ -733,7 +714,7 @@ up_dump_prefix(u_char *buf, int len, struct uplist_prefix *prefix_head, int r, wpos = 0; while ((upp = TAILQ_FIRST(prefix_head)) != NULL) { - if ((r = up_set_prefix(buf + wpos, len - wpos, + if ((r = prefix_write(buf + wpos, len - wpos, &upp->prefix, upp->prefixlen)) == -1) break; wpos += r; |