1
0
mirror of https://git.FreeBSD.org/ports.git synced 2025-01-06 06:30:19 +00:00

net/openbgpd: revert upgrade from 6.5p0 to 5.2.20121209

- openbgpd version 6.5p0 was the "portable" version, which specifically
  does *not* support kernel routing updates.
- Therefore this is only suitable for route servers/collectors, not
  for production use in routers. This significantly violates POLA :)

PR:		213445
Submitted by:	Oliver H <oliver@watershed.co.uk>
This commit is contained in:
Kurt Jaeger 2019-06-03 20:08:36 +00:00
parent 21a86ae3be
commit 713c2289b8
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=503421
61 changed files with 24467 additions and 38 deletions

View File

@ -1,9 +1,13 @@
# $FreeBSD$
PORTNAME= openbgpd
PORTVERSION= 6.5p0
PORTVERSION= 5.2.20121209
PORTREVISION= 3
PORTEPOCH= 1
CATEGORIES= net
MASTER_SITES= OPENBSD/OpenBGPD
DISTNAME= ${PORTNAME}-4.6
DIST_SUBDIR= ${PORTNAME}
MAINTAINER= hrs@FreeBSD.org
COMMENT= Free implementation of the Border Gateway Protocol, Version 4
@ -11,21 +15,27 @@ COMMENT= Free implementation of the Border Gateway Protocol, Version 4
LICENSE= ISCL
LICENSE_FILE= ${FILESDIR}/COPYING
USES= autoreconf libtool uidfix
CONFLICTS= zebra-[0-9]* quagga-[0-9]*
USES= tar:tgz uidfix
USE_RC_SUBR= ${PORTNAME}
GNU_CONFIGURE= yes
NO_WRKSUBDIR= yes
PLIST_FILES= sbin/bgpctl sbin/bgpd man/man5/bgpd.conf.5.gz \
man/man8/bgpctl.8.gz man/man8/bgpd.8.gz
SUB_FILES= pkg-message
USERS= _bgpd
GROUPS= _bgpd
CONFLICTS= zebra-[0-9]* quagga-[0-9]*
OPTIONS_DEFINE= IPV6LLPEER
OPTIONS_DEFAULT= IPV6LLPEER
IPV6LLPEER_DESC= Support nexthop using IPv6 link-local address
OPTIONS_DEFINE= IPV6LLPEER
OPTIONS_DEFAULT=IPV6LLPEER
IPV6LLPEER_DESC=Support nexthop using IPv6 link-local address
IPV6LLPEER_MAKE_ARGS= -DIPV6_LINKLOCAL_PEER
post-patch:
@${REINPLACE_CMD} -e "s|%%PREFIX%%|${PREFIX}|g" \
${WRKSRC}/bgpd/bgpd.8 \
${WRKSRC}/bgpd/bgpd.conf.5 \
${WRKSRC}/bgpctl/bgpctl.8
.include <bsd.port.mk>

View File

@ -1,3 +1,3 @@
TIMESTAMP = 1556692508
SHA256 (openbgpd-6.5p0.tar.gz) = 20c1a40bafcbbea60c4ecc6dd2e87fcba6847bfad62739b705a3806b6b442a56
SIZE (openbgpd-6.5p0.tar.gz) = 677691
SHA256 (openbgpd/openbgpd-4.6.tgz) = d9a0a3542e5ec744889ca12871f01aa1d86f12844e093010f37d0601796e15cf
SIZE (openbgpd/openbgpd-4.6.tgz) = 168197

View File

@ -0,0 +1,12 @@
Index: Makefile
===================================================================
RCS file: Makefile
diff -N Makefile
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Makefile 30 Jun 2009 07:07:55 -0000 1.2
@@ -0,0 +1,5 @@
+# $hrs: openbgpd/Makefile,v 1.2 2009/06/30 07:07:55 hrs Exp $
+
+SUBDIR= bgpd bgpctl
+
+.include <bsd.subdir.mk>

View File

@ -1,20 +0,0 @@
--- Makefile.am.orig 2019-05-01 11:22:14 UTC
+++ Makefile.am
@@ -19,13 +19,14 @@
EXTRA_DIST = README.md VERSION bgpd.conf
install-data-hook:
- @if [ ! -d "$(DESTDIR)$(localstatedir)/run" ]; then \
+ if [ ! -d "$(DESTDIR)$(localstatedir)/run" ]; then \
$(INSTALL) -m 755 -d "$(DESTDIR)$(localstatedir)/run"; \
fi
- @if [ ! -d "$(DESTDIR)$(sysconfdir)" ]; then \
+ if [ ! -d "$(DESTDIR)$(sysconfdir)" ]; then \
$(INSTALL) -m 755 -d "$(DESTDIR)$(sysconfdir)"; \
fi
- @if [ ! -f "$(DESTDIR)$(sysconfdir)/bgpd.conf" ]; then \
+ $(INSTALL) -m 644 "$(srcdir)/bgpd.conf" "$(DESTDIR)$(sysconfdir)/bgpd.conf.sample"; \
+ if [ ! -f "$(DESTDIR)$(sysconfdir)/bgpd.conf" ]; then \
$(INSTALL) -m 644 "$(srcdir)/bgpd.conf" "$(DESTDIR)$(sysconfdir)/bgpd.conf"; \
else \
echo; \

View File

@ -0,0 +1,12 @@
Index: Makefile.inc
===================================================================
RCS file: Makefile.inc
diff -N Makefile.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Makefile.inc 16 May 2014 01:06:14 -0000 1.5
@@ -0,0 +1,5 @@
+# $hrs: openbgpd/Makefile.inc,v 1.5 2014/05/16 01:06:14 hrs Exp $
+
+PREFIX?= /usr/local
+BINDIR?= ${PREFIX}/sbin
+MANDIR?= ${PREFIX}/man/man

View File

@ -0,0 +1,31 @@
Index: bgpctl/Makefile
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -p -r1.1.1.1 -r1.4
--- bgpctl/Makefile 30 Jun 2009 05:46:15 -0000 1.1.1.1
+++ bgpctl/Makefile 13 Oct 2012 18:35:56 -0000 1.4
@@ -1,17 +1,18 @@
# $OpenBSD: Makefile,v 1.10 2007/12/20 17:08:48 henning Exp $
-.PATH: ${.CURDIR}/../bgpd
+.PATH: ${.CURDIR}/../bgpd ${.CURDIR}/../openbsd-compat
PROG= bgpctl
-SRCS= bgpctl.c parser.c buffer.c imsg.c util.c timer.c
+SRCS= bgpctl.c parser.c util.c timer.c
SRCS+= irrfilter.c whois.c irr_asset.c irr_prefix.c irr_output.c
-SRCS+= irr_parser.c
+SRCS+= irr_parser.c mrtparser.c
+SRCS+= fmt_scaled.c imsg.c imsg-buffer.c
CFLAGS+= -Wall
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+= -Wsign-compare
-CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../bgpd
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../bgpd -I${.CURDIR}/../openbsd-compat
MAN= bgpctl.8
LDADD= -lutil
DPADD+= ${LIBUTIL}

View File

@ -0,0 +1,287 @@
Index: bgpctl/bgpctl.8
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/bgpctl.8,v
retrieving revision 1.1.1.6
retrieving revision 1.6
diff -u -p -r1.1.1.6 -r1.6
--- bgpctl/bgpctl.8 14 Feb 2010 20:20:13 -0000 1.1.1.6
+++ bgpctl/bgpctl.8 13 Oct 2012 18:35:56 -0000 1.6
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpctl.8,v 1.49 2009/06/06 06:11:17 claudio Exp $
+.\" $OpenBSD: bgpctl.8,v 1.59 2012/05/27 20:49:42 jmc Exp $
.\"
.\" Copyright (c) 2003 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: June 6 2009 $
+.Dd $Mdocdate: May 27 2012 $
.Dt BGPCTL 8
.Os
.Sh NAME
@@ -32,8 +32,7 @@ The
program controls the
.Xr bgpd 8
daemon.
-Commands to switch between displays may be abbreviated to the
-minimum unambiguous prefix; for example,
+Commands may be abbreviated to the minimum unambiguous prefix; for example,
.Cm s s
for
.Cm show summary .
@@ -53,11 +52,19 @@ to communicate with
.Pp
The commands are as follows:
.Bl -tag -width xxxxxx
-.It Cm fib couple
-Insert the learned routes into the Forwarding Information Base
+.It Xo
+.Cm fib
+.Op Cm table Ar number
+.Cm couple
+.Xc
+Insert the learned routes into the specified Forwarding Information Base
a.k.a. the kernel routing table.
-.It Cm fib decouple
-Remove the learned routes from the Forwarding Information Base
+.It Xo
+.Cm fib
+.Op Cm table Ar number
+.Cm decouple
+.Xc
+Remove the learned routes from the specified Forwarding Information Base
a.k.a. the kernel routing table.
.It Xo
.Cm irrfilter
@@ -79,7 +86,15 @@ The options are as follows:
Use
.Ar directory
to write the filter files to.
+.It Fl 4
+Fetch only IPv4 prefixes from the registry.
+.It Fl 6
+Fetch only IPv6 prefixes from the registry.
.El
+.It Cm log brief
+Disable verbose debug logging.
+.It Cm log verbose
+Enable verbose debug logging.
.It Cm neighbor Ar peer Cm up
Take the BGP session to the specified neighbor up.
.Ar peer
@@ -98,12 +113,21 @@ Note that the neighbor is not obliged to
all, even if it announced the route refresh capability.
.Ar peer
may be the neighbor's address or description.
-.It Cm network add Ar prefix
+.It Cm network add Ar prefix Op Ar arguments
Add the specified prefix to the list of announced networks.
+It is possible to set various path attributes with additional
+.Ar arguments .
.It Cm network delete Ar prefix
Remove the specified prefix from the list of announced networks.
.It Cm network flush
Remove all dynamically added prefixes from the list of announced networks.
+.It Cm network mrt file Ar file filter
+Import networks from an MRT table dump for debugging purposes.
+.Ar filter
+can be specified similarly to the
+.Ar show mrt
+command.
+Only networks matching the filter will be imported.
.It Cm network show Ar family
Show all announced networks.
.Ar family ,
@@ -122,7 +146,7 @@ view of the Forwarding Information Base.
can be an IP address, in which case the route to this address is shown,
or a flag:
.Pp
-.Bl -tag -width connected -compact
+.Bl -tag -width tableXnumber -compact
.It Cm connected
Show only connected routes.
.It Cm static
@@ -133,9 +157,81 @@ Show only routes originating from
itself.
.It Cm nexthop
Show only routes required to reach a BGP nexthop.
+.It Cm inet
+Show only IPv4 routes.
+.It Cm inet6
+Show only IPv6 routes.
+.It Cm table Ar number
+Show the routing table with ID
+.Ar number
+instead of the default routing table with ID 0.
.El
.It Cm show interfaces
Show the interface states.
+.It Xo
+.Cm show mrt
+.Op Ar options
+.Ar filter
+.Xc
+Show routes from an MRT table dump file.
+.Ar filter
+can be an IP address, a CIDR prefix, an AS filter, a combination or nothing:
+.Pp
+.Bl -tag -width "address/len all" -compact
+.It Ar address
+Show best matching route for address.
+.It Ar address Ns Li / Ns Ar len
+Show RIB entry for this CIDR prefix.
+.It Xo
+.Ar address Ns Li / Ns Ar len
+.Cm all
+.Xc
+Show all entries in the specified range.
+.\".It Ar address/len Cm longer-prefixes
+.It Cm as Ar as
+Show all entries with
+.Ar as
+anywhere in the AS path.
+.It Cm empty-as
+Show all entries that are internal routes with no AS's in the AS path.
+.It Cm neighbor Ar ip
+Show only entries from the specified peer.
+.It Cm peer-as Ar as
+Show all entries with
+.Ar as
+as leftmost AS.
+.It Cm source-as Ar as
+Show all entries with
+.Ar as
+as rightmost AS.
+.It Cm transit-as Ar as
+Show all entries with
+.Ar as
+anywhere but rightmost.
+.El
+.Pp
+Additionally, the following
+.Ar options
+are defined:
+.Pp
+.Bl -tag -width "file name" -compact
+.It Cm detail
+Show more detailed output for matching routes.
+.It Ar family
+Limit the output to the given address family.
+.It Cm file Ar name
+Read the MRT dump from file
+.Ar name
+instead of using stdin.
+.El
+.Pp
+Multiple options and filters can be used at the same time.
+.It Cm show summary
+Show a list of all neighbors, including information about the session state
+and message counters.
+.It Cm show summary terse
+Show a list of all neighbors, including information about the session state,
+in a terse format.
.It Cm show neighbor Ar peer modifier
Show detailed information about the neighbor identified by
.Ar peer ,
@@ -183,33 +279,33 @@ Show all entries in the specified range.
Show all entries with
.Ar as
anywhere in the AS path.
-.It Cm source-as Ar as
-Show all entries with
-.Ar as
-as rightmost AS.
-.It Cm transit-as Ar as
-Show all entries with
-.Ar as
-anywhere but rightmost.
-.It Cm peer-as Ar as
-Show all entries with
-.Ar as
-as leftmost AS.
-.It Cm empty-as
-Show all entries that are internal routes with no AS's in the AS path.
.It Cm community Ar community
Show all entries with community
.Ar community .
+.It Cm empty-as
+Show all entries that are internal routes with no AS's in the AS path.
+.It Cm memory
+Show RIB memory statistics.
.It Cm neighbor Ar peer
Show only entries from the specified peer.
-.It Cm table Ar rib
-Show only entries from the specified RIB table.
+.It Cm peer-as Ar as
+Show all entries with
+.Ar as
+as leftmost AS.
+.It Cm source-as Ar as
+Show all entries with
+.Ar as
+as rightmost AS.
.It Cm summary
This is the same as the
.Ic show summary
command.
-.It Cm memory
-Show RIB memory statistics.
+.It Cm table Ar rib
+Show only entries from the specified RIB table.
+.It Cm transit-as Ar as
+Show all entries with
+.Ar as
+anywhere but rightmost.
.El
.Pp
Additionally, the following
@@ -217,8 +313,10 @@ Additionally, the following
are defined:
.Pp
.Bl -tag -width "detail" -compact
+.It Cm selected
+Show only selected routes.
.It Cm detail
-Show more detailed output for matched routes.
+Show more detailed output for matching routes.
.It Ar family
Limit the output to the given address family.
.It Cm in
@@ -243,10 +341,12 @@ and message counters.
.It Cm show summary terse
Show a list of all neighbors, including information about the session state,
in a terse format.
+.It Cm show tables
+Show a list of all currently loaded fib routing tables.
.El
.Sh FILES
.Bl -tag -width "/var/run/bgpd.sockXXX" -compact
-.It Pa /etc/bgpd.conf
+.It Pa %%PREFIX%%/etc/bgpd.conf
default
.Xr bgpd 8
configuration file
@@ -260,10 +360,19 @@ control socket
.Xr bgpd 8 ,
.Xr bgplg 8 ,
.Xr bgplgsh 8
+.Sh STANDARDS
.Rs
-.%R RFC 2622
-.%T "Routing Policy Specification Language (RPSL)"
+.%A C. Alaettinoglu
+.%A C. Villamizar
+.%A E. Gerich
+.%A D. Kessens
+.%A D. Meyer
+.%A T. Bates
+.%A D. Karrenberg
+.%A M. Terpstra
.%D June 1999
+.%R RFC 2622
+.%T Routing Policy Specification Language (RPSL)
.Re
.Sh HISTORY
The

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
Index: bgpctl/irr_asset.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_asset.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.2 -r1.1.1.3
--- bgpctl/irr_asset.c 9 Jul 2009 16:49:55 -0000 1.1.1.2
+++ bgpctl/irr_asset.c 13 Oct 2012 18:22:52 -0000 1.1.1.3
@@ -1,4 +1,4 @@
-/* $OpenBSD: irr_asset.c,v 1.8 2009/04/14 21:10:54 jj Exp $ */
+/* $OpenBSD: irr_asset.c,v 1.7 2007/03/31 12:46:55 henning Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>

View File

@ -0,0 +1,14 @@
Index: bgpctl/irr_output.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_output.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.1 -r1.1.1.2
--- bgpctl/irr_output.c 30 Jun 2009 05:46:15 -0000 1.1.1.1
+++ bgpctl/irr_output.c 13 Oct 2012 18:22:52 -0000 1.1.1.2
@@ -1,4 +1,4 @@
-/* $OpenBSD: irr_output.c,v 1.13 2007/03/05 17:28:21 henning Exp $ */
+/* $OpenBSD: irr_output.c,v 1.12 2007/03/05 15:02:05 henning Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>

View File

@ -0,0 +1,48 @@
Index: bgpctl/irr_parser.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_parser.c,v
retrieving revision 1.1.1.5
retrieving revision 1.5
diff -u -p -r1.1.1.5 -r1.5
--- bgpctl/irr_parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.5
+++ bgpctl/irr_parser.c 13 Oct 2012 18:35:56 -0000 1.5
@@ -1,4 +1,4 @@
-/* $OpenBSD: irr_parser.c,v 1.8 2007/03/05 22:34:08 henning Exp $ */
+/* $OpenBSD: irr_parser.c,v 1.9 2009/09/08 15:40:25 claudio Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -81,6 +81,7 @@ parse_response(FILE *f, enum qtype qtype
return (-1);
break;
case QTYPE_ROUTE:
+ case QTYPE_ROUTE6:
if ((n = parse_route(key, val)) == -1)
return (-1);
break;
@@ -281,7 +282,7 @@ parse_policy(char *key, char *val)
!isdigit(tok[2]))
errx(1, "peering spec \"%s\": format "
"error, AS expected", tok);
- pi->peer_as = strtonum(tok + 2, 1, USHRT_MAX,
+ pi->peer_as = strtonum(tok + 2, 1, UINT_MAX,
&errstr);
if (errstr)
errx(1, "peering spec \"%s\": format "
@@ -407,11 +408,13 @@ parse_asset(char *key, char *val)
int
parse_route(char *key, char *val)
{
- if (strcmp(key, "route")) /* ignore everything else */
+ if (strcmp(key, "route") && strcmp(key, "route6"))
+ /* ignore everything else */
return (0);
- /* route is single-value, but seen trailing , in the wild */
- if (strlen(val) > 0 && val[strlen(val) - 1] == ',')
+ /* route is single-value, but seen trailing , and \r in the wild */
+ if (strlen(val) > 0 && (val[strlen(val) - 1] == ',' ||
+ val[strlen(val) - 1] == '\r'))
val[strlen(val) - 1] = '\0';
return (prefixset_addmember(val));

View File

@ -0,0 +1,157 @@
Index: bgpctl/irr_prefix.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_prefix.c,v
retrieving revision 1.1.1.5
retrieving revision 1.1.1.8
diff -u -p -r1.1.1.5 -r1.1.1.8
--- bgpctl/irr_prefix.c 14 Feb 2010 20:20:14 -0000 1.1.1.5
+++ bgpctl/irr_prefix.c 13 Oct 2012 18:22:52 -0000 1.1.1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: irr_prefix.c,v 1.15 2007/05/27 18:54:25 henning Exp $ */
+/* $OpenBSD: irr_prefix.c,v 1.17 2009/09/08 16:11:36 sthen Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -29,6 +29,7 @@
#include <arpa/inet.h>
#include "irrfilter.h"
+#include "bgpd.h"
void prefixset_aggregate(struct prefix_set *);
int prefix_aggregate(struct irr_prefix *, const struct irr_prefix *);
@@ -63,7 +64,11 @@ prefixset_get(char *as)
fflush(stdout);
}
curpfxs = pfxs;
- if (whois(as, QTYPE_ROUTE) == -1)
+ if ((irrflags & F_IPV4) && whois(as, QTYPE_ROUTE) == -1)
+ errx(1, "whois error, prefixset_get %s", as);
+ if ((irrflags & F_IPV6) && whois(as, QTYPE_ROUTE6) == -1)
+ errx(1, "whois error, prefixset_get %s", as);
+ if (whois(as, QTYPE_ROUTE6) == -1)
errx(1, "whois error, prefixset_get %s", as);
curpfxs = NULL;
if (irrverbose >= 3)
@@ -80,9 +85,11 @@ prefixset_addmember(char *s)
void *p;
u_int i;
struct irr_prefix *pfx;
- int len;
+ int len, ret;
+ char *slash;
+ const char *errstr;
- if (strchr(s, '/') == NULL) {
+ if ((slash = strchr(s, '/')) == NULL) {
fprintf(stderr, "%s: prefix %s does not have the len "
"specified, ignoring\n", curpfxs->as, s);
return (0);
@@ -92,17 +99,26 @@ prefixset_addmember(char *s)
err(1, "prefixset_addmember calloc");
if ((len = inet_net_pton(AF_INET, s, &pfx->addr.in,
- sizeof(pfx->addr.in))) == -1) {
- if (errno == ENOENT) {
- fprintf(stderr, "%s: prefix \"%s\": parse error\n",
+ sizeof(pfx->addr.in))) != -1) {
+ pfx->af = AF_INET;
+ } else {
+ len = strtonum(slash + 1, 0, 128, &errstr);
+ if (errstr)
+ errx(1, "prefixset_addmember %s prefix %s: prefixlen "
+ "is %s", curpfxs->as, s, errstr);
+ *slash = '\0';
+
+ if ((ret = inet_pton(AF_INET6, s, &pfx->addr.in6)) == -1)
+ err(1, "prefixset_addmember %s prefix \"%s\"",
curpfxs->as, s);
+ else if (ret == 0) {
+ fprintf(stderr, "prefixset_addmember %s prefix \"%s\": "
+ "No matching address family found", curpfxs->as, s);
+ free(pfx);
return (0);
- } else
- err(1, "prefixset_addmember %s inet_net_pton \"%s\"",
- curpfxs->as, s);
+ }
+ pfx->af = AF_INET6;
}
-
- pfx->af = AF_INET;
pfx->len = pfx->maxlen = len;
/* yes, there are dupes... e. g. from multiple sources */
@@ -175,24 +191,47 @@ prefixset_aggregate(struct prefix_set *p
int
prefix_aggregate(struct irr_prefix *a, const struct irr_prefix *b)
{
- in_addr_t mask;
+ in_addr_t mask;
+ struct in6_addr ma;
+ struct in6_addr mb;
if (a->len == 0)
return (1);
- mask = htonl(0xffffffff << (32 - a->len));
+ if (a->af != b->af)
+ /* We cannot aggregate addresses of different families. */
+ return (0);
- if ((a->addr.in.s_addr & mask) == (b->addr.in.s_addr & mask))
- return (1);
+ if (a->af == AF_INET) {
+ mask = htonl(prefixlen2mask(a->len));
+ if ((a->addr.in.s_addr & mask) == (b->addr.in.s_addr & mask))
+ return (1);
+ } else if (a->af == AF_INET6) {
+ inet6applymask(&ma, &a->addr.in6, a->len);
+ inet6applymask(&mb, &b->addr.in6, a->len);
+ if (IN6_ARE_ADDR_EQUAL(&ma, &mb))
+ return (1);
+ }
- /* see wether we can fold them in one */
+ /* see whether we can fold them in one */
if (a->len == b->len && a->len > 1) {
- mask = htonl(0xffffffff << (32 - (a->len - 1)));
- if ((a->addr.in.s_addr & mask) ==
- (b->addr.in.s_addr & mask)) {
- a->len--;
- a->addr.in.s_addr &= mask;
- return (1);
+ if (a->af == AF_INET) {
+ mask = htonl(prefixlen2mask(a->len - 1));
+ if ((a->addr.in.s_addr & mask) ==
+ (b->addr.in.s_addr & mask)) {
+ a->len--;
+ a->addr.in.s_addr &= mask;
+ return (1);
+ }
+ } else if (a->af == AF_INET6) {
+ inet6applymask(&ma, &a->addr.in6, a->len - 1);
+ inet6applymask(&mb, &b->addr.in6, a->len - 1);
+
+ if (IN6_ARE_ADDR_EQUAL(&ma, &mb)) {
+ a->len--;
+ memcpy(&a->addr.in6, &ma, sizeof(ma));
+ return (1);
+ }
}
}
@@ -219,6 +258,13 @@ irr_prefix_cmp(const void *a, const void
if (ntohl(pa->addr.in.s_addr) >
ntohl(pb->addr.in.s_addr))
return (1);
+ } else if (pa->af == AF_INET6) {
+ for (r = 0; r < 16; r++) {
+ if (pa->addr.in6.s6_addr[r] < pb->addr.in6.s6_addr[r])
+ return (-1);
+ if (pa->addr.in6.s6_addr[r] > pb->addr.in6.s6_addr[r])
+ return (1);
+ }
} else
errx(1, "irr_prefix_cmp unknown af %u", pa->af);

View File

@ -0,0 +1,24 @@
Index: bgpctl/irrfilter.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -p -r1.1.1.1 -r1.3
--- bgpctl/irrfilter.c 30 Jun 2009 05:46:15 -0000 1.1.1.1
+++ bgpctl/irrfilter.c 13 Oct 2012 18:35:56 -0000 1.3
@@ -1,4 +1,4 @@
-/* $OpenBSD: irrfilter.c,v 1.4 2007/05/28 23:31:53 henning Exp $ */
+/* $OpenBSD: irrfilter.c,v 1.3 2007/03/06 16:45:34 henning Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -15,6 +15,9 @@
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#if defined(__FreeBSD__) /* compat */
+#include "openbsd-compat.h"
+#endif /* defined(__FreeBSD__) */
#include <sys/types.h>
#include <sys/param.h>

View File

@ -0,0 +1,59 @@
Index: bgpctl/irrfilter.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irrfilter.h,v
retrieving revision 1.1.1.5
retrieving revision 1.4
diff -u -p -r1.1.1.5 -r1.4
--- bgpctl/irrfilter.h 14 Feb 2010 20:20:14 -0000 1.1.1.5
+++ bgpctl/irrfilter.h 13 Oct 2012 18:35:56 -0000 1.4
@@ -1,4 +1,4 @@
-/* $OpenBSD: irrfilter.h,v 1.7 2007/03/06 16:45:34 henning Exp $ */
+/* $OpenBSD: irrfilter.h,v 1.8 2009/09/08 15:40:25 claudio Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -16,11 +16,17 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#if defined(__FreeBSD__) /* compat */
+#include "openbsd-compat.h"
+#endif /* defined(__FreeBSD__) */
+
#include <sys/queue.h>
#include <sys/tree.h>
#include <netinet/in.h>
#define F_IMPORTONLY 0x01 /* skip export: items */
+#define F_IPV4 0x02 /* use IPv4 items */
+#define F_IPV6 0x04 /* use IPv6 items */
int irrflags;
int irrverbose;
@@ -37,7 +43,7 @@ struct policy_item {
char *action;
char *filter;
enum pdir dir;
- u_int16_t peer_as;
+ u_int32_t peer_as;
};
TAILQ_HEAD(policy_head, policy_item);
@@ -55,7 +61,8 @@ enum qtype {
QTYPE_NONE,
QTYPE_OWNAS,
QTYPE_ASSET,
- QTYPE_ROUTE
+ QTYPE_ROUTE,
+ QTYPE_ROUTE6
};
struct as_set {
@@ -72,6 +79,7 @@ struct as_set {
struct irr_prefix {
union {
struct in_addr in;
+ struct in6_addr in6;
} addr;
sa_family_t af;
u_int8_t len;

View File

@ -0,0 +1,977 @@
Index: bgpctl/mrtparser.c
===================================================================
RCS file: bgpctl/mrtparser.c
diff -N bgpctl/mrtparser.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ bgpctl/mrtparser.c 13 Oct 2012 18:22:53 -0000 1.1.1.1
@@ -0,0 +1,970 @@
+/* $OpenBSD: mrtparser.c,v 1.2 2012/03/06 07:52:32 claudio Exp $ */
+/*
+ * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mrt.h"
+#include "mrtparser.h"
+
+void *mrt_read_msg(int, struct mrt_hdr *);
+size_t mrt_read_buf(int, void *, size_t);
+
+struct mrt_peer *mrt_parse_v2_peer(struct mrt_hdr *, void *);
+struct mrt_rib *mrt_parse_v2_rib(struct mrt_hdr *, void *);
+int mrt_parse_dump(struct mrt_hdr *, void *, struct mrt_peer **,
+ struct mrt_rib **);
+int mrt_parse_dump_mp(struct mrt_hdr *, void *, struct mrt_peer **,
+ struct mrt_rib **);
+int mrt_extract_attr(struct mrt_rib_entry *, u_char *, int, sa_family_t,
+ int);
+
+void mrt_free_peers(struct mrt_peer *);
+void mrt_free_rib(struct mrt_rib *);
+void mrt_free_bgp_state(struct mrt_bgp_state *);
+void mrt_free_bgp_msg(struct mrt_bgp_msg *);
+
+u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *);
+int mrt_extract_addr(void *, u_int, union mrt_addr *, sa_family_t);
+
+void *
+mrt_read_msg(int fd, struct mrt_hdr *hdr)
+{
+ void *buf;
+
+ bzero(hdr, sizeof(*hdr));
+ if (mrt_read_buf(fd, hdr, sizeof(*hdr)) != sizeof(*hdr))
+ return (NULL);
+
+ if ((buf = malloc(ntohl(hdr->length))) == NULL)
+ err(1, "malloc(%d)", hdr->length);
+
+ if (mrt_read_buf(fd, buf, ntohl(hdr->length)) != ntohl(hdr->length)) {
+ free(buf);
+ return (NULL);
+ }
+ return (buf);
+}
+
+size_t
+mrt_read_buf(int fd, void *buf, size_t len)
+{
+ char *b = buf;
+ ssize_t n;
+
+ while (len > 0) {
+ if ((n = read(fd, b, len)) == -1) {
+ if (errno == EINTR)
+ continue;
+ err(1, "read");
+ }
+ if (n == 0)
+ break;
+ b += n;
+ len -= n;
+ }
+
+ return (b - (char *)buf);
+}
+
+void
+mrt_parse(int fd, struct mrt_parser *p, int verbose)
+{
+ struct mrt_hdr h;
+ struct mrt_peer *pctx = NULL;
+ struct mrt_rib *r;
+ void *msg;
+
+ while ((msg = mrt_read_msg(fd, &h))) {
+ switch (ntohs(h.type)) {
+ case MSG_NULL:
+ case MSG_START:
+ case MSG_DIE:
+ case MSG_I_AM_DEAD:
+ case MSG_PEER_DOWN:
+ case MSG_PROTOCOL_BGP:
+ case MSG_PROTOCOL_IDRP:
+ case MSG_PROTOCOL_BGP4PLUS:
+ case MSG_PROTOCOL_BGP4PLUS1:
+ if (verbose)
+ printf("deprecated MRT type %d\n",
+ ntohs(h.type));
+ break;
+ case MSG_PROTOCOL_RIP:
+ case MSG_PROTOCOL_RIPNG:
+ case MSG_PROTOCOL_OSPF:
+ case MSG_PROTOCOL_ISIS_ET:
+ case MSG_PROTOCOL_ISIS:
+ case MSG_PROTOCOL_OSPFV3_ET:
+ case MSG_PROTOCOL_OSPFV3:
+ if (verbose)
+ printf("unsuported MRT type %d\n",
+ ntohs(h.type));
+ break;
+ case MSG_TABLE_DUMP:
+ switch (ntohs(h.subtype)) {
+ case MRT_DUMP_AFI_IP:
+ case MRT_DUMP_AFI_IPv6:
+ if (p->dump == NULL)
+ break;
+ if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) {
+ p->dump(r, pctx, p->arg);
+ mrt_free_rib(r);
+ }
+ break;
+ default:
+ if (verbose)
+ printf("unknown AFI %d in table dump\n",
+ ntohs(h.subtype));
+ break;
+ }
+ break;
+ case MSG_TABLE_DUMP_V2:
+ switch (ntohs(h.subtype)) {
+ case MRT_DUMP_V2_PEER_INDEX_TABLE:
+ if (p->dump == NULL)
+ break;
+ if (pctx)
+ mrt_free_peers(pctx);
+ pctx = mrt_parse_v2_peer(&h, msg);
+ break;
+ case MRT_DUMP_V2_RIB_IPV4_UNICAST:
+ case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
+ case MRT_DUMP_V2_RIB_IPV6_UNICAST:
+ case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
+ case MRT_DUMP_V2_RIB_GENERIC:
+ if (p->dump == NULL)
+ break;
+ r = mrt_parse_v2_rib(&h, msg);
+ if (r) {
+ p->dump(r, pctx, p->arg);
+ mrt_free_rib(r);
+ }
+ break;
+ default:
+ if (verbose)
+ printf("unhandled BGP4MP subtype %d\n",
+ ntohs(h.subtype));
+ break;
+ }
+ break;
+ case MSG_PROTOCOL_BGP4MP_ET:
+ /* currently just ignore the microsec field */
+ msg = (char *)msg + sizeof(u_int32_t);
+ h.length -= sizeof(u_int32_t);
+ /* FALLTHROUGH */
+ case MSG_PROTOCOL_BGP4MP:
+ switch (ntohs(h.subtype)) {
+ case BGP4MP_STATE_CHANGE:
+ case BGP4MP_STATE_CHANGE_AS4:
+ /* XXX p->state(s, p->arg); */
+ errx(1, "BGP4MP subtype not yet implemented");
+ break;
+ case BGP4MP_MESSAGE:
+ case BGP4MP_MESSAGE_AS4:
+ case BGP4MP_MESSAGE_LOCAL:
+ case BGP4MP_MESSAGE_AS4_LOCAL:
+ /* XXX p->message(m, p->arg); */
+ errx(1, "BGP4MP subtype not yet implemented");
+ break;
+ case BGP4MP_ENTRY:
+ if (p->dump == NULL)
+ break;
+ if (mrt_parse_dump_mp(&h, msg, &pctx, &r) ==
+ 0) {
+ p->dump(r, pctx, p->arg);
+ mrt_free_rib(r);
+ }
+ break;
+ default:
+ if (verbose)
+ printf("unhandled BGP4MP subtype %d\n",
+ ntohs(h.subtype));
+ break;
+ }
+ break;
+ default:
+ if (verbose)
+ printf("unknown MRT type %d\n", ntohs(h.type));
+ break;
+ }
+ free(msg);
+ }
+ if (pctx)
+ mrt_free_peers(pctx);
+}
+
+struct mrt_peer *
+mrt_parse_v2_peer(struct mrt_hdr *hdr, void *msg)
+{
+ struct mrt_peer_entry *peers;
+ struct mrt_peer *p;
+ u_int8_t *b = msg;
+ u_int32_t bid, as4;
+ u_int16_t cnt, i, as2;
+ u_int len = ntohl(hdr->length);
+
+ if (len < 8) /* min msg size */
+ return NULL;
+
+ p = calloc(1, sizeof(struct mrt_peer));
+ if (p == NULL)
+ err(1, "calloc");
+
+ /* collector bgp id */
+ memcpy(&bid, b, sizeof(bid));
+ b += sizeof(bid);
+ len -= sizeof(bid);
+ p->bgp_id = ntohl(bid);
+
+ /* view name length */
+ memcpy(&cnt, b, sizeof(cnt));
+ b += sizeof(cnt);
+ len -= sizeof(cnt);
+ cnt = ntohs(cnt);
+
+ /* view name */
+ if (cnt > len)
+ goto fail;
+ if (cnt != 0) {
+ if ((p->view = malloc(cnt + 1)) == NULL)
+ err(1, "malloc");
+ memcpy(p->view, b, cnt);
+ p->view[cnt] = 0;
+ } else
+ if ((p->view = strdup("")) == NULL)
+ err(1, "strdup");
+ b += cnt;
+ len -= cnt;
+
+ /* peer_count */
+ if (len < sizeof(cnt))
+ goto fail;
+ memcpy(&cnt, b, sizeof(cnt));
+ b += sizeof(cnt);
+ len -= sizeof(cnt);
+ cnt = ntohs(cnt);
+
+ /* peer entries */
+ if ((peers = calloc(cnt, sizeof(struct mrt_peer_entry))) == NULL)
+ err(1, "calloc");
+ for (i = 0; i < cnt; i++) {
+ u_int8_t type;
+
+ if (len < sizeof(u_int8_t) + sizeof(u_int32_t))
+ goto fail;
+ type = *b++;
+ len -= 1;
+ memcpy(&bid, b, sizeof(bid));
+ b += sizeof(bid);
+ len -= sizeof(bid);
+ peers[i].bgp_id = ntohl(bid);
+
+ if (type & MRT_DUMP_V2_PEER_BIT_I) {
+ if (mrt_extract_addr(b, len, &peers[i].addr,
+ AF_INET6) == -1)
+ goto fail;
+ b += sizeof(struct in6_addr);
+ len -= sizeof(struct in6_addr);
+ } else {
+ if (mrt_extract_addr(b, len, &peers[i].addr,
+ AF_INET) == -1)
+ goto fail;
+ b += sizeof(struct in_addr);
+ len -= sizeof(struct in_addr);
+ }
+
+ if (type & MRT_DUMP_V2_PEER_BIT_A) {
+ memcpy(&as4, b, sizeof(as4));
+ b += sizeof(as4);
+ len -= sizeof(as4);
+ as4 = ntohl(as4);
+ } else {
+ memcpy(&as2, b, sizeof(as2));
+ b += sizeof(as2);
+ len -= sizeof(as2);
+ as4 = ntohs(as2);
+ }
+ peers[i].asnum = as4;
+ }
+ p->peers = peers;
+ p->npeers = cnt;
+ return (p);
+fail:
+ mrt_free_peers(p);
+ return (NULL);
+}
+
+struct mrt_rib *
+mrt_parse_v2_rib(struct mrt_hdr *hdr, void *msg)
+{
+ struct mrt_rib_entry *entries;
+ struct mrt_rib *r;
+ u_int8_t *b = msg;
+ u_int len = ntohl(hdr->length);
+ u_int32_t snum;
+ u_int16_t cnt, i;
+ u_int8_t plen;
+
+ if (len < sizeof(snum) + 1)
+ return NULL;
+
+ r = calloc(1, sizeof(struct mrt_rib));
+ if (r == NULL)
+ err(1, "calloc");
+
+ /* seq_num */
+ memcpy(&snum, b, sizeof(snum));
+ b += sizeof(snum);
+ len -= sizeof(snum);
+ r->seqnum = ntohl(snum);
+
+ switch (ntohs(hdr->subtype)) {
+ case MRT_DUMP_V2_RIB_IPV4_UNICAST:
+ case MRT_DUMP_V2_RIB_IPV4_MULTICAST:
+ plen = *b++;
+ len -= 1;
+ if (len < MRT_PREFIX_LEN(plen))
+ goto fail;
+ r->prefix.sin.sin_family = AF_INET;
+ r->prefix.sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&r->prefix.sin.sin_addr, b, MRT_PREFIX_LEN(plen));
+ b += MRT_PREFIX_LEN(plen);
+ len -= MRT_PREFIX_LEN(plen);
+ r->prefixlen = plen;
+ break;
+ case MRT_DUMP_V2_RIB_IPV6_UNICAST:
+ case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
+ plen = *b++;
+ len -= 1;
+ if (len < MRT_PREFIX_LEN(plen))
+ goto fail;
+ r->prefix.sin6.sin6_family = AF_INET6;
+ r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&r->prefix.sin6.sin6_addr, b, MRT_PREFIX_LEN(plen));
+ b += MRT_PREFIX_LEN(plen);
+ len -= MRT_PREFIX_LEN(plen);
+ r->prefixlen = plen;
+ break;
+ case MRT_DUMP_V2_RIB_GENERIC:
+ /* XXX unhandled */
+ errx(1, "MRT_DUMP_V2_RIB_GENERIC subtype not yet implemented");
+ goto fail;
+ }
+
+ /* entries count */
+ if (len < sizeof(cnt))
+ goto fail;
+ memcpy(&cnt, b, sizeof(cnt));
+ b += sizeof(cnt);
+ len -= sizeof(cnt);
+ cnt = ntohs(cnt);
+ r->nentries = cnt;
+
+ /* entries */
+ if ((entries = calloc(cnt, sizeof(struct mrt_rib_entry))) == NULL)
+ err(1, "calloc");
+ for (i = 0; i < cnt; i++) {
+ u_int32_t otm;
+ u_int16_t pix, alen;
+ if (len < 2 * sizeof(u_int16_t) + sizeof(u_int32_t))
+ goto fail;
+ /* peer index */
+ memcpy(&pix, b, sizeof(pix));
+ b += sizeof(pix);
+ len -= sizeof(pix);
+ entries[i].peer_idx = ntohs(pix);
+
+ /* originated */
+ memcpy(&otm, b, sizeof(otm));
+ b += sizeof(otm);
+ len -= sizeof(otm);
+ entries[i].originated = ntohl(otm);
+
+ /* attr_len */
+ memcpy(&alen, b, sizeof(alen));
+ b += sizeof(alen);
+ len -= sizeof(alen);
+ alen = ntohs(alen);
+
+ /* attr */
+ if (len < alen)
+ goto fail;
+ if (mrt_extract_attr(&entries[i], b, alen,
+ r->prefix.sa.sa_family, 1) == -1)
+ goto fail;
+ b += alen;
+ len -= alen;
+ }
+ r->entries = entries;
+ return (r);
+fail:
+ mrt_free_rib(r);
+ return (NULL);
+}
+
+int
+mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
+ struct mrt_rib **rp)
+{
+ struct mrt_peer *p;
+ struct mrt_rib *r;
+ struct mrt_rib_entry *re;
+ u_int8_t *b = msg;
+ u_int len = ntohl(hdr->length);
+ u_int16_t asnum, alen;
+
+ if (*pp == NULL) {
+ *pp = calloc(1, sizeof(struct mrt_peer));
+ if (*pp == NULL)
+ err(1, "calloc");
+ (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry));
+ if ((*pp)->peers == NULL)
+ err(1, "calloc");
+ (*pp)->npeers = 1;
+ }
+ p = *pp;
+
+ *rp = r = calloc(1, sizeof(struct mrt_rib));
+ if (r == NULL)
+ err(1, "calloc");
+ re = calloc(1, sizeof(struct mrt_rib_entry));
+ if (re == NULL)
+ err(1, "calloc");
+ r->nentries = 1;
+ r->entries = re;
+
+ if (len < 2 * sizeof(u_int16_t))
+ goto fail;
+ /* view */
+ b += sizeof(u_int16_t);
+ len -= sizeof(u_int16_t);
+ /* seqnum */
+ memcpy(&r->seqnum, b, sizeof(u_int16_t));
+ b += sizeof(u_int16_t);
+ len -= sizeof(u_int16_t);
+ r->seqnum = ntohs(r->seqnum);
+
+ switch (ntohs(hdr->subtype)) {
+ case MRT_DUMP_AFI_IP:
+ if (mrt_extract_addr(b, len, &r->prefix, AF_INET) == -1)
+ goto fail;
+ b += sizeof(struct in_addr);
+ len -= sizeof(struct in_addr);
+ break;
+ case MRT_DUMP_AFI_IPv6:
+ if (mrt_extract_addr(b, len, &r->prefix, AF_INET6) == -1)
+ goto fail;
+ b += sizeof(struct in6_addr);
+ len -= sizeof(struct in6_addr);
+ break;
+ }
+ if (len < 2 * sizeof(u_int32_t) + 2 * sizeof(u_int16_t) + 2)
+ goto fail;
+ r->prefixlen = *b++;
+ len -= 1;
+ /* status */
+ b += 1;
+ len -= 1;
+ /* originated */
+ memcpy(&re->originated, b, sizeof(u_int32_t));
+ b += sizeof(u_int32_t);
+ len -= sizeof(u_int32_t);
+ re->originated = ntohl(re->originated);
+ /* peer ip */
+ switch (ntohs(hdr->subtype)) {
+ case MRT_DUMP_AFI_IP:
+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1)
+ goto fail;
+ b += sizeof(struct in_addr);
+ len -= sizeof(struct in_addr);
+ break;
+ case MRT_DUMP_AFI_IPv6:
+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1)
+ goto fail;
+ b += sizeof(struct in6_addr);
+ len -= sizeof(struct in6_addr);
+ break;
+ }
+ memcpy(&asnum, b, sizeof(asnum));
+ b += sizeof(asnum);
+ len -= sizeof(asnum);
+ p->peers->asnum = ntohs(asnum);
+
+ memcpy(&alen, b, sizeof(alen));
+ b += sizeof(alen);
+ len -= sizeof(alen);
+ alen = ntohs(alen);
+
+ /* attr */
+ if (len < alen)
+ goto fail;
+ if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1)
+ goto fail;
+ b += alen;
+ len -= alen;
+
+ return (0);
+fail:
+ mrt_free_rib(r);
+ return (-1);
+}
+
+int
+mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
+ struct mrt_rib **rp)
+{
+ struct mrt_peer *p;
+ struct mrt_rib *r;
+ struct mrt_rib_entry *re;
+ u_int8_t *b = msg;
+ u_int len = ntohl(hdr->length);
+ u_int16_t asnum, alen, afi;
+ u_int8_t safi, nhlen;
+ sa_family_t af;
+
+ if (*pp == NULL) {
+ *pp = calloc(1, sizeof(struct mrt_peer));
+ if (*pp == NULL)
+ err(1, "calloc");
+ (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry));
+ if ((*pp)->peers == NULL)
+ err(1, "calloc");
+ (*pp)->npeers = 1;
+ }
+ p = *pp;
+
+ *rp = r = calloc(1, sizeof(struct mrt_rib));
+ if (r == NULL)
+ err(1, "calloc");
+ re = calloc(1, sizeof(struct mrt_rib_entry));
+ if (re == NULL)
+ err(1, "calloc");
+ r->nentries = 1;
+ r->entries = re;
+
+ if (len < 4 * sizeof(u_int16_t))
+ goto fail;
+ /* source AS */
+ b += sizeof(u_int16_t);
+ len -= sizeof(u_int16_t);
+ /* dest AS */
+ memcpy(&asnum, b, sizeof(asnum));
+ b += sizeof(asnum);
+ len -= sizeof(asnum);
+ p->peers->asnum = ntohs(asnum);
+ /* iface index */
+ b += sizeof(u_int16_t);
+ len -= sizeof(u_int16_t);
+ /* afi */
+ memcpy(&afi, b, sizeof(afi));
+ b += sizeof(afi);
+ len -= sizeof(afi);
+ afi = ntohs(afi);
+
+ /* source + dest ip */
+ switch (afi) {
+ case MRT_DUMP_AFI_IP:
+ if (len < 2 * sizeof(struct in_addr))
+ goto fail;
+ /* source IP */
+ b += sizeof(struct in_addr);
+ len -= sizeof(struct in_addr);
+ /* dest IP */
+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1)
+ goto fail;
+ b += sizeof(struct in_addr);
+ len -= sizeof(struct in_addr);
+ break;
+ case MRT_DUMP_AFI_IPv6:
+ if (len < 2 * sizeof(struct in6_addr))
+ goto fail;
+ /* source IP */
+ b += sizeof(struct in6_addr);
+ len -= sizeof(struct in6_addr);
+ /* dest IP */
+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1)
+ goto fail;
+ b += sizeof(struct in6_addr);
+ len -= sizeof(struct in6_addr);
+ break;
+ }
+
+ if (len < 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t))
+ goto fail;
+ /* view + status */
+ b += 2 * sizeof(u_int16_t);
+ len -= 2 * sizeof(u_int16_t);
+ /* originated */
+ memcpy(&re->originated, b, sizeof(u_int32_t));
+ b += sizeof(u_int32_t);
+ len -= sizeof(u_int32_t);
+ re->originated = ntohl(re->originated);
+
+ /* afi */
+ memcpy(&afi, b, sizeof(afi));
+ b += sizeof(afi);
+ len -= sizeof(afi);
+ afi = ntohs(afi);
+
+ /* safi */
+ safi = *b++;
+ len -= 1;
+
+ switch (afi) {
+ case MRT_DUMP_AFI_IP:
+ if (safi == 1 || safi == 2) {
+ af = AF_INET;
+ break;
+ } else if (safi == 128) {
+ af = AF_VPNv4;
+ break;
+ }
+ goto fail;
+ case MRT_DUMP_AFI_IPv6:
+ if (safi != 1 && safi != 2)
+ goto fail;
+ af = AF_INET6;
+ break;
+ default:
+ goto fail;
+ }
+
+ /* nhlen */
+ nhlen = *b++;
+ len -= 1;
+
+ /* nexthop */
+ if (mrt_extract_addr(b, len, &re->nexthop, af) == -1)
+ goto fail;
+ if (len < nhlen)
+ goto fail;
+ b += nhlen;
+ len -= nhlen;
+
+ if (len < 1)
+ goto fail;
+ r->prefixlen = *b++;
+ len -= 1;
+
+ /* prefix */
+ switch (af) {
+ case AF_INET:
+ if (len < MRT_PREFIX_LEN(r->prefixlen))
+ goto fail;
+ r->prefix.sin.sin_family = AF_INET;
+ r->prefix.sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&r->prefix.sin.sin_addr, b,
+ MRT_PREFIX_LEN(r->prefixlen));
+ b += MRT_PREFIX_LEN(r->prefixlen);
+ len -= MRT_PREFIX_LEN(r->prefixlen);
+ break;
+ case AF_INET6:
+ if (len < MRT_PREFIX_LEN(r->prefixlen))
+ goto fail;
+ r->prefix.sin6.sin6_family = AF_INET6;
+ r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&r->prefix.sin6.sin6_addr, b,
+ MRT_PREFIX_LEN(r->prefixlen));
+ b += MRT_PREFIX_LEN(r->prefixlen);
+ len -= MRT_PREFIX_LEN(r->prefixlen);
+ break;
+ case AF_VPNv4:
+ if (len < MRT_PREFIX_LEN(r->prefixlen))
+ goto fail;
+ errx(1, "AF_VPNv4 handling not yet implemented");
+ goto fail;
+ }
+
+ memcpy(&alen, b, sizeof(alen));
+ b += sizeof(alen);
+ len -= sizeof(alen);
+ alen = ntohs(alen);
+
+ /* attr */
+ if (len < alen)
+ goto fail;
+ if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1)
+ goto fail;
+ b += alen;
+ len -= alen;
+
+ return (0);
+fail:
+ mrt_free_rib(r);
+ return (-1);
+}
+
+int
+mrt_extract_attr(struct mrt_rib_entry *re, u_char *a, int alen, sa_family_t af,
+ int as4)
+{
+ struct mrt_attr *ap;
+ u_int32_t tmp;
+ u_int16_t attr_len;
+ u_int8_t type, flags, *attr;
+
+ do {
+ if (alen < 3)
+ return (-1);
+ attr = a;
+ flags = *a++;
+ alen -= 1;
+ type = *a++;
+ alen -= 1;
+
+ if (flags & MRT_ATTR_EXTLEN) {
+ if (alen < 2)
+ return (-1);
+ memcpy(&attr_len, a, sizeof(attr_len));
+ attr_len = ntohs(attr_len);
+ a += sizeof(attr_len);
+ alen -= sizeof(attr_len);
+ } else {
+ attr_len = *a++;
+ alen -= 1;
+ }
+ switch (type) {
+ case MRT_ATTR_ORIGIN:
+ if (attr_len != 1)
+ return (-1);
+ re->origin = *a;
+ break;
+ case MRT_ATTR_ASPATH:
+ if (as4) {
+ re->aspath_len = attr_len;
+ if ((re->aspath = malloc(attr_len)) == NULL)
+ err(1, "malloc");
+ memcpy(re->aspath, a, attr_len);
+ } else {
+ re->aspath = mrt_aspath_inflate(a, attr_len,
+ &re->aspath_len);
+ if (re->aspath == NULL)
+ return (-1);
+ }
+ break;
+ case MRT_ATTR_NEXTHOP:
+ if (attr_len != 4)
+ return (-1);
+ if (af != AF_INET)
+ break;
+ memcpy(&tmp, a, sizeof(tmp));
+ re->nexthop.sin.sin_len = sizeof(struct sockaddr_in);
+ re->nexthop.sin.sin_family = AF_INET;
+ re->nexthop.sin.sin_addr.s_addr = tmp;
+ break;
+ case MRT_ATTR_MED:
+ if (attr_len != 4)
+ return (-1);
+ memcpy(&tmp, a, sizeof(tmp));
+ re->med = ntohl(tmp);
+ break;
+ case MRT_ATTR_LOCALPREF:
+ if (attr_len != 4)
+ return (-1);
+ memcpy(&tmp, a, sizeof(tmp));
+ re->local_pref = ntohl(tmp);
+ break;
+ case MRT_ATTR_MP_REACH_NLRI:
+ /*
+ * XXX horrible hack:
+ * Once again IETF and the real world differ in the
+ * implementation. In short the abbreviated MP_NLRI
+ * hack in the standard is not used in real life.
+ * Detect the two cases by looking at the first byte
+ * of the payload (either the nexthop addr length (RFC)
+ * or the high byte of the AFI (old form)). If the
+ * first byte matches the expected nexthop length it
+ * is expected to be the RFC 6396 encoding.
+ */
+ if (*a != attr_len - 1) {
+ a += 3;
+ alen -= 3;
+ attr_len -= 3;
+ }
+ switch (af) {
+ case AF_INET6:
+ if (attr_len < sizeof(struct in6_addr) + 1)
+ return (-1);
+ re->nexthop.sin6.sin6_len =
+ sizeof(struct sockaddr_in6);
+ re->nexthop.sin6.sin6_family = AF_INET6;
+ memcpy(&re->nexthop.sin6.sin6_addr, a + 1,
+ sizeof(struct in6_addr));
+ break;
+ case AF_VPNv4:
+ if (attr_len < sizeof(u_int64_t) +
+ sizeof(struct in_addr))
+ return (-1);
+ re->nexthop.svpn4.sv_len =
+ sizeof(struct sockaddr_vpn4);
+ re->nexthop.svpn4.sv_family = AF_VPNv4;
+ memcpy(&tmp, a + 1 + sizeof(u_int64_t),
+ sizeof(tmp));
+ re->nexthop.svpn4.sv_addr.s_addr = tmp;
+ break;
+ }
+ break;
+ case MRT_ATTR_AS4PATH:
+ if (!as4) {
+ if (re->aspath)
+ free(re->aspath);
+ re->aspath_len = attr_len;
+ if ((re->aspath = malloc(attr_len)) == NULL)
+ err(1, "malloc");
+ memcpy(re->aspath, a, attr_len);
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ re->nattrs++;
+ if (re->nattrs >= UCHAR_MAX)
+ err(1, "too many attributes");
+ ap = realloc(re->attrs,
+ re->nattrs * sizeof(struct mrt_attr));
+ if (ap == NULL)
+ err(1, "realloc");
+ re->attrs = ap;
+ ap = re->attrs + re->nattrs - 1;
+ ap->attr_len = a + attr_len - attr;
+ if ((ap->attr = malloc(ap->attr_len)) == NULL)
+ err(1, "malloc");
+ memcpy(ap->attr, attr, ap->attr_len);
+ break;
+ }
+ a += attr_len;
+ alen -= attr_len;
+ } while (alen > 0);
+
+ return (0);
+}
+
+void
+mrt_free_peers(struct mrt_peer *p)
+{
+ free(p->peers);
+ free(p->view);
+ free(p);
+}
+
+void
+mrt_free_rib(struct mrt_rib *r)
+{
+ u_int16_t i, j;
+
+ for (i = 0; i < r->nentries && r->entries; i++) {
+ for (j = 0; j < r->entries[i].nattrs; j++)
+ free(r->entries[i].attrs[j].attr);
+ free(r->entries[i].attrs);
+ free(r->entries[i].aspath);
+ }
+
+ free(r->entries);
+ free(r);
+}
+
+void
+mrt_free_bgp_state(struct mrt_bgp_state *s)
+{
+ free(s);
+}
+
+void
+mrt_free_bgp_msg(struct mrt_bgp_msg *m)
+{
+ free(m->msg);
+ free(m);
+}
+
+u_char *
+mrt_aspath_inflate(void *data, u_int16_t len, u_int16_t *newlen)
+{
+ u_int8_t *seg, *nseg, *ndata;
+ u_int16_t seg_size, olen, nlen;
+ u_int8_t seg_len;
+
+ /* first calculate the length of the aspath */
+ seg = data;
+ nlen = 0;
+ for (olen = len; olen > 0; olen -= seg_size, seg += seg_size) {
+ seg_len = seg[1];
+ seg_size = 2 + sizeof(u_int16_t) * seg_len;
+ nlen += 2 + sizeof(u_int32_t) * seg_len;
+
+ if (seg_size > olen)
+ return NULL;
+ }
+
+ *newlen = nlen;
+ if ((ndata = malloc(nlen)) == NULL)
+ err(1, "malloc");
+
+ /* then copy the aspath */
+ seg = data;
+ for (nseg = ndata; nseg < ndata + nlen; ) {
+ *nseg++ = *seg++;
+ *nseg++ = seg_len = *seg++;
+ for (; seg_len > 0; seg_len--) {
+ *nseg++ = 0;
+ *nseg++ = 0;
+ *nseg++ = *seg++;
+ *nseg++ = *seg++;
+ }
+ }
+
+ return (ndata);
+}
+
+int
+mrt_extract_addr(void *msg, u_int len, union mrt_addr *addr, sa_family_t af)
+{
+ u_int8_t *b = msg;
+
+ switch (af) {
+ case AF_INET:
+ if (len < sizeof(struct in_addr))
+ return (-1);
+ addr->sin.sin_family = AF_INET;
+ addr->sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&addr->sin.sin_addr, b, sizeof(struct in_addr));
+ return sizeof(struct in_addr);
+ case AF_INET6:
+ if (len < sizeof(struct in6_addr))
+ return (-1);
+ addr->sin6.sin6_family = AF_INET6;
+ addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&addr->sin6.sin6_addr, b, sizeof(struct in6_addr));
+ return sizeof(struct in6_addr);
+ case AF_VPNv4:
+ if (len < sizeof(u_int64_t) + sizeof(struct in_addr))
+ return (-1);
+ addr->svpn4.sv_len = sizeof(struct sockaddr_vpn4);
+ addr->svpn4.sv_family = AF_VPNv4;
+ memcpy(&addr->svpn4.sv_addr, b + sizeof(u_int64_t),
+ sizeof(struct in_addr));
+ return (sizeof(u_int64_t) + sizeof(struct in_addr));
+ default:
+ return (-1);
+ }
+}

View File

@ -0,0 +1,122 @@
Index: bgpctl/mrtparser.h
===================================================================
RCS file: bgpctl/mrtparser.h
diff -N bgpctl/mrtparser.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ bgpctl/mrtparser.h 13 Oct 2012 18:22:53 -0000 1.1.1.1
@@ -0,0 +1,115 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct sockaddr_vpn4 {
+ u_int8_t sv_len;
+ sa_family_t sv_family;
+ u_int8_t sv_labellen;
+ u_int8_t sv_pad;
+ struct in_addr sv_addr;
+ u_int64_t sv_rd;
+ u_int8_t sv_label[21];
+ u_int8_t sv_pad2[3];
+};
+
+#define AF_VPNv4 250 /* XXX high enough to not cause issues */
+
+union mrt_addr {
+ struct sockaddr_in6 sin6;
+ struct sockaddr_in sin;
+ struct sockaddr_vpn4 svpn4;
+ struct sockaddr sa;
+};
+
+/* data structures for the MSG_TABLE_DUMP_V2 format */
+struct mrt_peer_entry {
+ union mrt_addr addr;
+ u_int32_t bgp_id;
+ u_int32_t asnum;
+};
+
+struct mrt_peer {
+ char *view;
+ struct mrt_peer_entry *peers;
+ u_int32_t bgp_id;
+ u_int16_t npeers;
+};
+
+struct mrt_attr {
+ void *attr;
+ size_t attr_len;
+};
+
+struct mrt_rib_entry {
+ void *aspath;
+ struct mrt_attr *attrs;
+ union mrt_addr nexthop;
+ time_t originated;
+ u_int32_t local_pref;
+ u_int32_t med;
+ u_int16_t peer_idx;
+ u_int16_t aspath_len;
+ u_int16_t nattrs;
+ u_int8_t origin;
+};
+
+struct mrt_rib {
+ struct mrt_rib_entry *entries;
+ union mrt_addr prefix;
+ u_int32_t seqnum;
+ u_int16_t nentries;
+ u_int8_t prefixlen;
+};
+
+/* data structures for the BGP4MP MESSAGE and STATE types */
+struct mrt_bgp_state {
+ union mrt_addr src;
+ union mrt_addr dst;
+ u_int32_t src_as;
+ u_int32_t dst_as;
+ u_int16_t old_state;
+ u_int16_t new_state;
+};
+
+struct mrt_bgp_msg {
+ union mrt_addr src;
+ union mrt_addr dst;
+ u_int32_t src_as;
+ u_int32_t dst_as;
+ u_int16_t msg_len;
+ void *msg;
+};
+
+#define MRT_ATTR_ORIGIN 1
+#define MRT_ATTR_ASPATH 2
+#define MRT_ATTR_NEXTHOP 3
+#define MRT_ATTR_MED 4
+#define MRT_ATTR_LOCALPREF 5
+#define MRT_ATTR_MP_REACH_NLRI 14
+#define MRT_ATTR_AS4PATH 17
+#define MRT_ATTR_EXTLEN 0x10
+
+#define MRT_PREFIX_LEN(x) ((((u_int)x) + 7) / 8)
+
+struct mrt_parser {
+ void (*dump)(struct mrt_rib *, struct mrt_peer *, void *);
+ void (*state)(struct mrt_bgp_state *, void *);
+ void (*message)(struct mrt_bgp_msg *, void *);
+ void *arg;
+};
+
+void mrt_parse(int, struct mrt_parser *, int);

View File

@ -0,0 +1,400 @@
Index: bgpctl/parser.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.c,v
retrieving revision 1.1.1.6
retrieving revision 1.7
diff -u -p -r1.1.1.6 -r1.7
--- bgpctl/parser.c 14 Feb 2010 20:20:14 -0000 1.1.1.6
+++ bgpctl/parser.c 13 Oct 2012 18:35:56 -0000 1.7
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.54 2009/06/12 16:44:02 claudio Exp $ */
+/* $OpenBSD: parser.c,v 1.64 2012/03/27 18:24:11 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -16,11 +16,16 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#if defined(__FreeBSD__) /* compat */
+#include "openbsd-compat.h"
+#endif /* defined(__FreeBSD__) */
+
#include <sys/types.h>
#include <sys/socket.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
#include <stdio.h>
@@ -52,7 +57,9 @@ enum token_type {
PREPSELF,
WEIGHT,
FAMILY,
- GETOPT
+ GETOPT,
+ RTABLE,
+ FILENAME
};
enum getopts {
@@ -72,14 +79,18 @@ static const struct token t_show[];
static const struct token t_show_summary[];
static const struct token t_show_fib[];
static const struct token t_show_rib[];
+static const struct token t_show_mrt[];
+static const struct token t_show_mrt_file[];
static const struct token t_show_rib_neigh[];
+static const struct token t_show_mrt_neigh[];
static const struct token t_show_rib_rib[];
static const struct token t_show_neighbor[];
static const struct token t_show_neighbor_modifiers[];
static const struct token t_fib[];
static const struct token t_neighbor[];
static const struct token t_neighbor_modifiers[];
-static const struct token t_show_as[];
+static const struct token t_show_rib_as[];
+static const struct token t_show_mrt_as[];
static const struct token t_show_prefix[];
static const struct token t_show_ip[];
static const struct token t_show_community[];
@@ -97,6 +108,9 @@ static const struct token t_prepself[];
static const struct token t_weight[];
static const struct token t_irrfilter[];
static const struct token t_irrfilter_opts[];
+static const struct token t_log[];
+static const struct token t_fib_table[];
+static const struct token t_show_fib_table[];
static const struct token t_main[] = {
{ KEYWORD, "reload", RELOAD, NULL},
@@ -105,6 +119,7 @@ static const struct token t_main[] = {
{ KEYWORD, "neighbor", NEIGHBOR, t_neighbor},
{ KEYWORD, "network", NONE, t_network},
{ KEYWORD, "irrfilter", IRRFILTER, t_irrfilter},
+ { KEYWORD, "log", NONE, t_log},
{ ENDTOKEN, "", NONE, NULL}
};
@@ -116,8 +131,10 @@ static const struct token t_show[] = {
{ KEYWORD, "network", NETWORK_SHOW, t_network_show},
{ KEYWORD, "nexthop", SHOW_NEXTHOP, NULL},
{ KEYWORD, "rib", SHOW_RIB, t_show_rib},
+ { KEYWORD, "tables", SHOW_FIB_TABLES, NULL},
{ KEYWORD, "ip", NONE, t_show_ip},
{ KEYWORD, "summary", SHOW_SUMMARY, t_show_summary},
+ { KEYWORD, "mrt", SHOW_MRT, t_show_mrt},
{ ENDTOKEN, "", NONE, NULL}
};
@@ -128,24 +145,26 @@ static const struct token t_show_summary
};
static const struct token t_show_fib[] = {
- { NOTOKEN, "", NONE, NULL},
- { FLAG, "connected", F_CONNECTED, t_show_fib},
- { FLAG, "static", F_STATIC, t_show_fib},
- { FLAG, "bgp", F_BGPD_INSERTED, t_show_fib},
- { FLAG, "nexthop", F_NEXTHOP, t_show_fib},
- { FAMILY, "", NONE, t_show_fib},
- { ADDRESS, "", NONE, NULL},
- { ENDTOKEN, "", NONE, NULL}
+ { NOTOKEN, "", NONE, NULL},
+ { FLAG, "connected", F_CONNECTED, t_show_fib},
+ { FLAG, "static", F_STATIC, t_show_fib},
+ { FLAG, "bgp", F_BGPD_INSERTED, t_show_fib},
+ { FLAG, "nexthop", F_NEXTHOP, t_show_fib},
+ { KEYWORD, "table", NONE, t_show_fib_table},
+ { FAMILY, "", NONE, t_show_fib},
+ { ADDRESS, "", NONE, NULL},
+ { ENDTOKEN, "", NONE, NULL}
};
static const struct token t_show_rib[] = {
{ NOTOKEN, "", NONE, NULL},
- { ASTYPE, "as", AS_ALL, t_show_as},
- { ASTYPE, "source-as", AS_SOURCE, t_show_as},
- { ASTYPE, "transit-as", AS_TRANSIT, t_show_as},
- { ASTYPE, "peer-as", AS_PEER, t_show_as},
+ { ASTYPE, "as", AS_ALL, t_show_rib_as},
+ { ASTYPE, "source-as", AS_SOURCE, t_show_rib_as},
+ { ASTYPE, "transit-as", AS_TRANSIT, t_show_rib_as},
+ { ASTYPE, "peer-as", AS_PEER, t_show_rib_as},
{ ASTYPE, "empty-as", AS_EMPTY, t_show_rib},
{ KEYWORD, "community", NONE, t_show_community},
+ { FLAG, "selected", F_CTL_ACTIVE, t_show_rib},
{ FLAG, "detail", F_CTL_DETAIL, t_show_rib},
{ FLAG, "in", F_CTL_ADJ_IN, t_show_rib},
{ FLAG, "out", F_CTL_ADJ_OUT, t_show_rib},
@@ -158,12 +177,38 @@ static const struct token t_show_rib[] =
{ ENDTOKEN, "", NONE, NULL}
};
+
+static const struct token t_show_mrt[] = {
+ { NOTOKEN, "", NONE, NULL},
+ { ASTYPE, "as", AS_ALL, t_show_mrt_as},
+ { ASTYPE, "source-as", AS_SOURCE, t_show_mrt_as},
+ { ASTYPE, "transit-as", AS_TRANSIT, t_show_mrt_as},
+ { ASTYPE, "peer-as", AS_PEER, t_show_mrt_as},
+ { ASTYPE, "empty-as", AS_EMPTY, t_show_mrt},
+ { FLAG, "detail", F_CTL_DETAIL, t_show_mrt},
+ { KEYWORD, "neighbor", NONE, t_show_mrt_neigh},
+ { KEYWORD, "file", NONE, t_show_mrt_file},
+ { FAMILY, "", NONE, t_show_mrt},
+ { PREFIX, "", NONE, t_show_prefix},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
+static const struct token t_show_mrt_file[] = {
+ { FILENAME, "", NONE, t_show_mrt},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
static const struct token t_show_rib_neigh[] = {
{ PEERADDRESS, "", NONE, t_show_rib},
{ PEERDESC, "", NONE, t_show_rib},
{ ENDTOKEN, "", NONE, NULL}
};
+static const struct token t_show_mrt_neigh[] = {
+ { PEERADDRESS, "", NONE, t_show_mrt},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
static const struct token t_show_rib_rib[] = {
{ RIBNAME, "", NONE, t_show_rib},
{ ENDTOKEN, "", NONE, NULL}
@@ -187,6 +232,7 @@ static const struct token t_show_neighbo
static const struct token t_fib[] = {
{ KEYWORD, "couple", FIB_COUPLE, NULL},
{ KEYWORD, "decouple", FIB_DECOUPLE, NULL},
+ { KEYWORD, "table", NONE, t_fib_table},
{ ENDTOKEN, "", NONE, NULL}
};
@@ -204,11 +250,16 @@ static const struct token t_neighbor_mod
{ ENDTOKEN, "", NONE, NULL}
};
-static const struct token t_show_as[] = {
+static const struct token t_show_rib_as[] = {
{ ASNUM, "", NONE, t_show_rib},
{ ENDTOKEN, "", NONE, NULL}
};
+static const struct token t_show_mrt_as[] = {
+ { ASNUM, "", NONE, t_show_mrt},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
static const struct token t_show_prefix[] = {
{ NOTOKEN, "", NONE, NULL},
{ FLAG, "all", F_LONGER, NULL},
@@ -231,6 +282,7 @@ static const struct token t_network[] =
{ KEYWORD, "delete", NETWORK_REMOVE, t_prefix},
{ KEYWORD, "flush", NETWORK_FLUSH, NULL},
{ KEYWORD, "show", NETWORK_SHOW, t_network_show},
+ { KEYWORD, "mrt", NETWORK_MRT, t_show_mrt},
{ ENDTOKEN, "", NONE, NULL}
};
@@ -311,6 +363,22 @@ static const struct token t_irrfilter_op
{ ENDTOKEN, "", NONE, NULL}
};
+static const struct token t_log[] = {
+ { KEYWORD, "verbose", LOG_VERBOSE, NULL},
+ { KEYWORD, "brief", LOG_BRIEF, NULL},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
+static const struct token t_fib_table[] = {
+ { RTABLE, "", NONE, t_fib},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
+static const struct token t_show_fib_table[] = {
+ { RTABLE, "", NONE, t_show_fib},
+ { ENDTOKEN, "", NONE, NULL}
+};
+
static struct parse_result res;
const struct token *match_token(int *argc, char **argv[],
@@ -404,15 +472,22 @@ match_token(int *argc, char **argv[], co
case FAMILY:
if (word == NULL)
break;
- if (!strcmp(word, "inet") || !strcmp(word, "IPv4")) {
+ if (!strcmp(word, "inet") ||
+ !strcasecmp(word, "IPv4")) {
match++;
t = &table[i];
- res.af = AF_INET;
+ res.aid = AID_INET;
}
- if (!strcmp(word, "inet6") || !strcmp(word, "IPv6")) {
+ if (!strcmp(word, "inet6") ||
+ !strcasecmp(word, "IPv6")) {
match++;
t = &table[i];
- res.af = AF_INET6;
+ res.aid = AID_INET6;
+ }
+ if (!strcasecmp(word, "VPNv4")) {
+ match++;
+ t = &table[i];
+ res.aid = AID_VPN_IPv4;
}
break;
case ADDRESS:
@@ -485,6 +560,7 @@ match_token(int *argc, char **argv[], co
case PREPNBR:
case PREPSELF:
case WEIGHT:
+ case RTABLE:
if (word != NULL && strlen(word) > 0 &&
parse_number(word, &res, table[i].type)) {
match++;
@@ -518,6 +594,23 @@ match_token(int *argc, char **argv[], co
t = &table[i];
}
break;
+ case FILENAME:
+ if (word != NULL && strlen(word) > 0) {
+ if ((res.mrtfd = open(word, O_RDONLY)) == -1) {
+ /*
+ * ignore error if path has no / and
+ * does not exist. In hope to print
+ * usage.
+ */
+ if (errno == ENOENT &&
+ !strchr(word, '/'))
+ break;
+ err(1, "mrt open(%s)", word);
+ }
+ match++;
+ t = &table[i];
+ }
+ break;
case ENDTOKEN:
break;
}
@@ -577,6 +670,9 @@ show_valid_args(const struct token table
case WEIGHT:
fprintf(stderr, " <number>\n");
break;
+ case RTABLE:
+ fprintf(stderr, " <rtableid>\n");
+ break;
case NEXTHOP:
fprintf(stderr, " <address>\n");
break;
@@ -584,11 +680,14 @@ show_valid_args(const struct token table
fprintf(stderr, " <pftable>\n");
break;
case FAMILY:
- fprintf(stderr, " [ inet | inet6 | IPv4 | IPv6 ]\n");
+ fprintf(stderr, " [ inet | inet6 | IPv4 | IPv6 | VPNv4 ]\n");
break;
case GETOPT:
fprintf(stderr, " <options>\n");
break;
+ case FILENAME:
+ fprintf(stderr, " <filename>\n");
+ break;
case ENDTOKEN:
break;
}
@@ -608,7 +707,7 @@ parse_addr(const char *word, struct bgpd
bzero(&ina, sizeof(ina));
if (inet_net_pton(AF_INET, word, &ina, sizeof(ina)) != -1) {
- addr->af = AF_INET;
+ addr->aid = AID_INET;
addr->v4 = ina;
return (1);
}
@@ -618,13 +717,7 @@ parse_addr(const char *word, struct bgpd
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(word, "0", &hints, &r) == 0) {
- addr->af = AF_INET6;
- memcpy(&addr->v6,
- &((struct sockaddr_in6 *)r->ai_addr)->sin6_addr,
- sizeof(addr->v6));
- addr->scope_id =
- ((struct sockaddr_in6 *)r->ai_addr)->sin6_scope_id;
-
+ sa2addr(r->ai_addr, addr);
freeaddrinfo(r);
return (1);
}
@@ -647,7 +740,7 @@ parse_prefix(const char *word, struct bg
if ((p = strrchr(word, '/')) != NULL) {
mask = strtonum(p + 1, 0, 128, &errstr);
if (errstr)
- errx(1, "invalid netmask: %s", errstr);
+ errx(1, "netmask %s", errstr);
if ((ps = malloc(strlen(word) - strlen(p) + 1)) == NULL)
err(1, "parse_prefix: malloc");
@@ -663,15 +756,15 @@ parse_prefix(const char *word, struct bg
if (parse_addr(word, addr) == 0)
return (0);
- switch (addr->af) {
- case AF_INET:
+ switch (addr->aid) {
+ case AID_INET:
if (mask == -1)
mask = 32;
if (mask > 32)
errx(1, "invalid netmask: too large");
addr->v4.s_addr = addr->v4.s_addr & htonl(prefixlen2mask(mask));
break;
- case AF_INET6:
+ case AID_INET6:
if (mask == -1)
mask = 128;
inet6applymask(&addr->v6, &addr->v6, mask);
@@ -706,7 +799,7 @@ parse_asnum(const char *word, u_int32_t
if (errstr)
errx(1, "AS number is %s: %s", errstr, word);
} else {
- uval = strtonum(word, 0, ASNUM_MAX - 1, &errstr);
+ uval = strtonum(word, 0, UINT_MAX, &errstr);
if (errstr)
errx(1, "AS number is %s: %s", errstr, word);
}
@@ -730,6 +823,11 @@ parse_number(const char *word, struct pa
errx(1, "number is %s: %s", errstr, word);
/* number was parseable */
+ if (type == RTABLE) {
+ r->rtableid = uval;
+ return (1);
+ }
+
if ((fs = calloc(1, sizeof(struct filter_set))) == NULL)
err(1, NULL);
switch (type) {
@@ -882,8 +980,14 @@ bgpctl_getopt(int *argc, char **argv[],
int ch;
optind = optreset = 1;
- while ((ch = getopt((*argc) + 1, (*argv) - 1, "o:")) != -1) {
+ while ((ch = getopt((*argc) + 1, (*argv) - 1, "46o:")) != -1) {
switch (ch) {
+ case '4':
+ res.flags = (res.flags | F_IPV4) & ~F_IPV6;
+ break;
+ case '6':
+ res.flags = (res.flags | F_IPV6) & ~F_IPV4;
+ break;
case 'o':
res.irr_outdir = optarg;
break;

View File

@ -0,0 +1,55 @@
Index: bgpctl/parser.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/parser.h,v
retrieving revision 1.1.1.6
retrieving revision 1.1.1.9
diff -u -p -r1.1.1.6 -r1.1.1.9
--- bgpctl/parser.h 14 Feb 2010 20:20:14 -0000 1.1.1.6
+++ bgpctl/parser.h 13 Oct 2012 18:22:53 -0000 1.1.1.9
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.h,v 1.19 2009/06/06 06:05:41 claudio Exp $ */
+/* $OpenBSD: parser.h,v 1.23 2011/09/21 10:37:51 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -29,7 +29,9 @@ enum actions {
SHOW_NEIGHBOR_TIMERS,
SHOW_NEIGHBOR_TERSE,
SHOW_FIB,
+ SHOW_FIB_TABLES,
SHOW_RIB,
+ SHOW_MRT,
SHOW_RIB_MEM,
SHOW_NEXTHOP,
SHOW_INTERFACE,
@@ -37,6 +39,8 @@ enum actions {
FIB,
FIB_COUPLE,
FIB_DECOUPLE,
+ LOG_VERBOSE,
+ LOG_BRIEF,
NEIGHBOR,
NEIGHBOR_UP,
NEIGHBOR_DOWN,
@@ -46,6 +50,7 @@ enum actions {
NETWORK_REMOVE,
NETWORK_FLUSH,
NETWORK_SHOW,
+ NETWORK_MRT,
IRRFILTER
};
@@ -59,9 +64,11 @@ struct parse_result {
char rib[PEER_DESCR_LEN];
char *irr_outdir;
int flags;
- enum actions action;
+ u_int rtableid;
+ enum actions action;
u_int8_t prefixlen;
- sa_family_t af;
+ u_int8_t aid;
+ int mrtfd;
};
__dead void usage(void);

View File

@ -0,0 +1,18 @@
Index: bgpctl/whois.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/whois.c,v
retrieving revision 1.1.1.5
retrieving revision 1.1.1.7
diff -u -p -r1.1.1.5 -r1.1.1.7
--- bgpctl/whois.c 14 Feb 2010 20:20:14 -0000 1.1.1.5
+++ bgpctl/whois.c 13 Oct 2012 18:22:54 -0000 1.1.1.7
@@ -68,7 +68,8 @@ char *qtype_opts[] = {
"",
"-T aut-num",
"-K -T as-set",
- "-K -T route -i origin"
+ "-K -T route -i origin",
+ "-K -T route6 -i origin"
};
char *server = "whois.radb.net";

View File

@ -0,0 +1,30 @@
--- bgpd/Makefile.orig 2013-02-21 19:20:05.000000000 +0000
+++ bgpd/Makefile 2013-02-21 19:20:54.000000000 +0000
@@ -1,15 +1,25 @@
# $OpenBSD: Makefile,v 1.28 2009/06/25 14:14:54 deraadt Exp $
+.PATH: ${.CURDIR}/.. ${.CURDIR}/../openbsd-compat
+
+CONFFILE?= ${PREFIX}/etc/bgpd.conf
+
PROG= bgpd
-SRCS= bgpd.c buffer.c session.c log.c parse.y config.c imsg.c \
+SRCS= bgpd.c session.c log.c parse.y config.c \
rde.c rde_rib.c rde_decide.c rde_prefix.c mrt.c kroute.c \
control.c pfkey.c rde_update.c rde_attr.c printconf.c \
- rde_filter.c pftable.c name2id.c util.c carp.c timer.c
+ rde_filter.c pftable.c name2id.c util.c carp.c timer.c \
+ imsg.c imsg-buffer.c
CFLAGS+= -Wall -I${.CURDIR}
+CFLAGS+= -I${.CURDIR}/../openbsd-compat
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+= -Wsign-compare
+CFLAGS+= -DCONFFILE=\"${CONFFILE}\"
+.if defined(IPV6_LINKLOCAL_PEER)
+CFLAGS+= -DIPV6_LINKLOCAL_PEER
+.endif
YFLAGS=
MAN= bgpd.8 bgpd.conf.5

View File

@ -0,0 +1,348 @@
Index: bgpd/bgpd.8
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.8,v
retrieving revision 1.1.1.8
retrieving revision 1.10
diff -u -p -r1.1.1.8 -r1.10
--- bgpd/bgpd.8 14 Feb 2010 20:19:57 -0000 1.1.1.8
+++ bgpd/bgpd.8 13 Oct 2012 18:36:00 -0000 1.10
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpd.8,v 1.28 2009/01/13 23:01:36 sthen Exp $
+.\" $OpenBSD: bgpd.8,v 1.45 2012/08/24 20:13:03 jmc 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: January 13 2009 $
+.Dd $Mdocdate: August 24 2012 $
.Dt BGPD 8
.Os
.Sh NAME
@@ -24,12 +24,8 @@
.Nm bgpd
.Bk -words
.Op Fl cdnv
-.Oo Xo
-.Fl D Ar macro Ns = Ns Ar value Oc
-.Xc
+.Op Fl D Ar macro Ns = Ns Ar value
.Op Fl f Ar file
-.Op Fl r Ar path
-.Op Fl s Ar path
.Ek
.Sh DESCRIPTION
.Nm
@@ -42,15 +38,106 @@ concerning
with other BGP systems.
.Nm
uses the Border Gateway Protocol, Version 4,
-as described in RFC 1771.
-Please refer to that document for more information about BGP.
+as described in RFC 4271.
+.Pp
+BGP is an exterior gateway protocol using a multiple step decision process
+to find the best path.
+Advanced filtering can be used to influence the route
+decision for traffic engineering.
+The session engine of
+.Nm
+is responsible for maintaining the TCP session with each neighbor.
+Updates are passed to the Route Decision Engine (RDE) where the paths
+are filtered and used to compute a Routing Information Base (RIB).
+The parent process is responsible for keeping the RIB in sync with
+the kernel routing table.
+.Pp
+The route decision process selects the best path by evaluating all paths to
+the same destination.
+The decision process continues to the next step if paths have equal attributes.
+Paths that are less preferred are taken out of consideration until there is
+only one path left.
+.Bl -enum -width 42 -offset bula
+.It
+All paths with errors or loops are not eligible.
+.It
+Paths with an unreachable nexthop are not eligible.
+After this step all remaining paths are valid.
+.It
+The path with the highest
+.Em LOCAL_PREF
+is selected.
+.It
+The path with the shortest
+.Em AS path
+attribute is selected.
+.It
+The
+.Em ORIGIN
+attribute is compared.
+The order is IGP before EGP before incomplete origins.
+.It
+The path with the lowest
+.Em MULTI_EXIT_DISC
+metric is selected.
+Normally, this value is only considered when choosing between multiple
+routes sent by the same neighbouring AS.
+However, if
+.Dq Li rde med compare always
+is set in the configuration, the metric is compared for routes sent by any AS.
+.It
+Comparison of the BGP session type.
+Paths learned over an external (EBGP) session are preferred over those
+learned via an internal (IBGP) session.
+.It
+The path with the lowest local
+.Em weight
+is selected.
+.It
+If
+.Dq Li rde route-age evaluate
+is set then the oldest path is selected.
+.It
+The path coming from the neighbor with the lowest
+.Em BGP ID
+wins.
+If the
+.Em ORIGINATOR_ID
+attribute is present that value will be used in the comparison instead.
+.It
+The path with the shortest
+.Em CLUSTER_LIST
+attribute is selected.
+If it is not present then a length of 0 is used in the comparison.
+.It
+The path coming from the peer with the lowest IP address is selected.
+IPv4 sessions will be preferred over IPv6 ones.
+.It
+In case of locally announced prefixes
+.Nm
+will prefer statically set prefixes over dynamically inserted ones.
+.El
+.Pp
+Attributes set by filters can be used to tip the decision process to prefer
+particular paths over others.
+This can be achieved by changing the
+.Em localpref ,
+.Em med ,
+or
+.Em weight
+attributes.
+AS path prepending or changing the
+.Em med
+or
+.Em origin
+attribute can be used to influencing the routing behaviour on remote systems.
.Pp
.Nm
is usually started at boot time, and can be enabled by
setting the following in
-.Pa /etc/rc.conf.local :
+.Pa /etc/rc.conf :
.Pp
-.Dl bgpd_flags=\&"\&"
+.Dl openbgpd_enable=\&"YES\&"
.Pp
See
.Xr rc 8
@@ -117,25 +204,16 @@ Use
.Ar file
as the configuration file,
instead of the default
-.Pa /etc/bgpd.conf .
+.Pa %%PREFIX%%/etc/bgpd.conf .
.It Fl n
Configtest mode.
Only check the configuration file for validity.
-.It Fl r Ar path
-Open a second, restricted, control socket that
-.Xr bgpctl 8
-can use.
-Only
-.Em show
-requests are allowed on this socket.
-.It Fl s Ar path
-Use an alternate location for the default control socket.
.It Fl v
Produce more verbose output.
.El
.Sh FILES
.Bl -tag -width "/var/run/bgpd.sockXXX" -compact
-.It Pa /etc/bgpd.conf
+.It Pa %%PREFIX%%/etc/bgpd.conf
default
.Nm
configuration file
@@ -149,55 +227,144 @@ control socket
.Xr bgpctl 8 ,
.Xr bgplg 8 ,
.Xr bgplgsh 8
+.Sh STANDARDS
.Rs
-.%R RFC 1771
-.%T "A Border Gateway Protocol 4 (BGP-4)"
-.%D March 1995
-.Re
-.Rs
-.%R RFC 1997
-.%T "BGP Communities Attribute"
+.%A R. Chandra
+.%A P. Traina
+.%A "T. Li"
.%D August 1996
+.%R RFC 1997
+.%T BGP Communities Attribute
.Re
+.Pp
.Rs
-.%R RFC 2385
-.%T "Protection of BGP Sessions via the TCP MD5 Signature Option"
+.%A A. Heffernan
.%D August 1998
+.%R RFC 2385
+.%T Protection of BGP Sessions via the TCP MD5 Signature Option
.Re
+.Pp
.Rs
-.%R RFC 2796
-.%T "BGP Route Reflection - An Alternative to Full Mesh IBGP"
-.%D April 2000
+.%A P. Marques
+.%A F. Dupont
+.%D March 1999
+.%R RFC 2545
+.%T Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing
.Re
+.Pp
.Rs
-.%R RFC 2918
-.%T "Route Refresh Capability for BGP-4"
+.%A E. Chen
.%D September 2000
+.%R RFC 2918
+.%T Route Refresh Capability for BGP-4
.Re
+.Pp
.Rs
-.%R RFC 3392
-.%T "Capabilities Advertisement with BGP-4"
-.%D January 1999
+.%A G. Huston
+.%D April 2004
+.%R RFC 3765
+.%T NOPEER Community for Border Gateway Protocol (BGP) Route Scope Control
.Re
+.Pp
.Rs
-.%R RFC 3682
-.%T "The Generalized TTL Security Mechanism (GTSM)"
-.%D February 2004
+.%A Y. Rekhter
+.%A "T. Li"
+.%A S. Hares
+.%D January 2006
+.%R RFC 4271
+.%T A Border Gateway Protocol 4 (BGP-4)
.Re
+.Pp
.Rs
-.%R RFC 3765
-.%T "NOPEER Community for Border Gateway Protocol"
-.%D April 2004
+.%A S. Sangli
+.%A D. Tappan
+.%A Y. Rekhter
+.%D February 2006
+.%R RFC 4360
+.%T BGP Extended Communities Attribute
.Re
+.Pp
.Rs
-.%R RFC 4760
-.%T "Multiprotocol Extensions for BGP-4"
+.%A E. Rosen
+.%A Y. Rekhter
+.%D February 2006
+.%R RFC 4364
+.%T BGP/MPLS IP Virtual Private Networks (VPNs)
+.Re
+.Pp
+.Rs
+.%A T. Bates
+.%A E. Chen
+.%A R. Chandra
+.%D April 2006
+.%R RFC 4456
+.%T "BGP Route Reflection: An Alternative to Full Mesh Internal BGP (IBGP)"
+.Re
+.Pp
+.Rs
+.%A E. Chen
+.%A V. Gillet
+.%D April 2006
+.%R RFC 4486
+.%T Subcodes for BGP Cease Notification Message
+.Re
+.Pp
+.Rs
+.%A T. Bates
+.%A R. Chandra
+.%A D. Katz
+.%A Y. Rekhter
.%D January 2007
+.%R RFC 4760
+.%T Multiprotocol Extensions for BGP-4
.Re
+.Pp
.Rs
-.%R RFC 4893
-.%T "BGP Support for Four-octet AS Number Space"
+.%A Q. Vohra
+.%A E. Chen
.%D May 2007
+.%R RFC 4893
+.%T BGP Support for Four-octet AS Number Space
+.Re
+.Pp
+.Rs
+.%A V. Gill
+.%A J. Heasley
+.%A D. Meyer
+.%A P. Savola
+.%A C. Pignatoro
+.%D October 2007
+.%R RFC 5082
+.%T The Generalized TTL Security Mechanism (GTSM)
+.Re
+.Pp
+.Rs
+.%A J. Scudder
+.%A R. Chandra
+.%D February 2009
+.%R RFC 5492
+.%T Capabilities Advertisement with BGP-4
+.Re
+.Pp
+.Rs
+.%D April 2009
+.%R draft-ietf-idr-optional-transitive-00
+.%T Error Handling for Optional Transitive BGP Attributes
+.Re
+.Pp
+.Rs
+.%D August 2011
+.%R draft-ietf-grow-mrt-17
+.%T MRT routing information export format
+.Re
+.Pp
+.Rs
+.%A J. Dong
+.%A M. Chen
+.%A A. Suryanarayana
+.%D May 2012
+.%R RFC 6608
+.%T Subcodes for BGP Finite State Machine Error
.Re
.Sh HISTORY
The

View File

@ -0,0 +1,693 @@
Index: bgpd/bgpd.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.c,v
retrieving revision 1.1.1.7
retrieving revision 1.1.1.12
diff -u -p -r1.1.1.7 -r1.1.1.12
--- bgpd/bgpd.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/bgpd.c 8 Dec 2012 10:37:08 -0000 1.1.1.12
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.148 2009/06/07 00:30:23 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.169 2012/09/18 09:45:51 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -32,8 +32,8 @@
#include <string.h>
#include <unistd.h>
-#include "mrt.h"
#include "bgpd.h"
+#include "mrt.h"
#include "session.h"
void sighdlr(int);
@@ -42,23 +42,23 @@ int main(int, char *[]);
int check_child(pid_t, const char *);
int send_filterset(struct imsgbuf *, struct filter_set_head *);
int reconfigure(char *, struct bgpd_config *, struct mrt_head *,
- struct peer **, struct filter_head *);
+ struct peer **);
int dispatch_imsg(struct imsgbuf *, int);
+int control_setup(struct bgpd_config *);
int rfd = -1;
-int cflags = 0;
-struct filter_set_head *connectset;
-struct filter_set_head *connectset6;
-struct filter_set_head *staticset;
-struct filter_set_head *staticset6;
-volatile sig_atomic_t mrtdump = 0;
-volatile sig_atomic_t quit = 0;
-volatile sig_atomic_t sigchld = 0;
-volatile sig_atomic_t reconfig = 0;
-pid_t reconfpid = 0;
+int cflags;
+volatile sig_atomic_t mrtdump;
+volatile sig_atomic_t quit;
+volatile sig_atomic_t sigchld;
+volatile sig_atomic_t reconfig;
+pid_t reconfpid;
+int reconfpending;
struct imsgbuf *ibuf_se;
struct imsgbuf *ibuf_rde;
struct rib_names ribnames = SIMPLEQ_HEAD_INITIALIZER(ribnames);
+char *cname;
+char *rcname;
void
sighdlr(int sig)
@@ -86,8 +86,8 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-cdnv] ", __progname);
- fprintf(stderr, "[-D macro=value] [-f file] [-r path] [-s path]\n");
+ fprintf(stderr, "usage: %s [-cdnv] [-D macro=value] [-f file]\n",
+ __progname);
exit(1);
}
@@ -101,15 +101,10 @@ int
main(int argc, char *argv[])
{
struct bgpd_config conf;
- struct peer *peer_l, *p;
struct mrt_head mrt_l;
- struct network_head net_l;
- struct filter_head *rules_l;
- struct network *net;
- struct filter_rule *r;
+ struct peer *peer_l, *p;
struct mrt *m;
struct listen_addr *la;
- struct rde_rib *rr;
struct pollfd pfd[POLL_MAX];
pid_t io_pid = 0, rde_pid = 0, pid;
char *conffile;
@@ -124,18 +119,13 @@ main(int argc, char *argv[])
bgpd_process = PROC_MAIN;
log_init(1); /* log to stderr until daemonized */
-
- if ((rules_l = calloc(1, sizeof(struct filter_head))) == NULL)
- err(1, NULL);
+ log_verbose(1);
bzero(&conf, sizeof(conf));
LIST_INIT(&mrt_l);
- TAILQ_INIT(&net_l);
- TAILQ_INIT(rules_l);
peer_l = NULL;
- conf.csock = SOCKET_NAME;
- while ((ch = getopt(argc, argv, "cdD:f:nr:s:v")) != -1) {
+ while ((ch = getopt(argc, argv, "cdD:f:nv")) != -1) {
switch (ch) {
case 'c':
conf.opts |= BGPD_OPT_FORCE_DEMOTE;
@@ -158,12 +148,7 @@ main(int argc, char *argv[])
if (conf.opts & BGPD_OPT_VERBOSE)
conf.opts |= BGPD_OPT_VERBOSE2;
conf.opts |= BGPD_OPT_VERBOSE;
- break;
- case 'r':
- conf.rcsock = optarg;
- break;
- case 's':
- conf.csock = optarg;
+ log_verbose(1);
break;
default:
usage();
@@ -176,24 +161,22 @@ main(int argc, char *argv[])
if (argc > 0)
usage();
- if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l, rules_l)) {
- free(rules_l);
- exit(1);
- }
-
if (conf.opts & BGPD_OPT_NOACTION) {
+ struct network_head net_l;
+ struct rdomain_head rdom_l;
+ struct filter_head rules_l;
+
+ if (parse_config(conffile, &conf, &mrt_l, &peer_l, &net_l,
+ &rules_l, &rdom_l))
+ exit(1);
+
if (conf.opts & BGPD_OPT_VERBOSE)
- print_config(&conf, &ribnames, &net_l, peer_l, rules_l,
- &mrt_l);
+ print_config(&conf, &ribnames, &net_l, peer_l, &rules_l,
+ &mrt_l, &rdom_l);
else
fprintf(stderr, "configuration OK\n");
exit(0);
}
- cflags = conf.flags;
- connectset = &conf.connectset;
- staticset = &conf.staticset;
- connectset6 = &conf.connectset6;
- staticset6 = &conf.staticset6;
if (geteuid())
errx(1, "need root privileges");
@@ -202,6 +185,7 @@ main(int argc, char *argv[])
errx(1, "unknown user %s", BGPD_USER);
log_init(debug);
+ log_verbose(conf.opts & BGPD_OPT_VERBOSE);
if (!debug)
daemon(1, 0);
@@ -225,13 +209,9 @@ main(int argc, char *argv[])
session_socket_blockmode(pipe_s2r_c[0], BM_NONBLOCK);
session_socket_blockmode(pipe_s2r_c[1], BM_NONBLOCK);
- prepare_listeners(&conf);
-
/* fork children */
- rde_pid = rde_main(&conf, peer_l, &net_l, rules_l, &mrt_l, &ribnames,
- pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug);
- io_pid = session_main(&conf, peer_l, &net_l, rules_l, &mrt_l, &ribnames,
- pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c);
+ rde_pid = rde_main(pipe_m2r, pipe_s2r, pipe_m2s, pipe_s2r_c, debug);
+ io_pid = session_main(pipe_m2s, pipe_s2r, pipe_m2r, pipe_s2r_c);
setproctitle("parent");
@@ -254,33 +234,12 @@ main(int argc, char *argv[])
imsg_init(ibuf_se, pipe_m2s[0]);
imsg_init(ibuf_rde, pipe_m2r[0]);
mrt_init(ibuf_rde, ibuf_se);
- if ((rfd = kr_init(!(conf.flags & BGPD_FLAG_NO_FIB_UPDATE),
- conf.rtableid)) == -1)
+ if ((rfd = kr_init()) == -1)
quit = 1;
+ quit = reconfigure(conffile, &conf, &mrt_l, &peer_l);
if (pftable_clear_all() != 0)
quit = 1;
- while ((net = TAILQ_FIRST(&net_l)) != NULL) {
- TAILQ_REMOVE(&net_l, net, entry);
- filterset_free(&net->net.attrset);
- free(net);
- }
-
- while ((r = TAILQ_FIRST(rules_l)) != NULL) {
- TAILQ_REMOVE(rules_l, r, entry);
- free(r);
- }
- TAILQ_FOREACH(la, conf.listen_addrs, entry) {
- close(la->fd);
- la->fd = -1;
- }
- while ((rr = SIMPLEQ_FIRST(&ribnames))) {
- SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
- free(rr);
- }
-
- mrt_reconfigure(&mrt_l);
-
while (quit == 0) {
bzero(pfd, sizeof(pfd));
pfd[PFD_PIPE_SESSION].fd = ibuf_se->fd;
@@ -335,15 +294,16 @@ main(int argc, char *argv[])
u_int error;
reconfig = 0;
- log_info("rereading config");
- switch (reconfigure(conffile, &conf, &mrt_l, &peer_l,
- rules_l)) {
+ switch (reconfigure(conffile, &conf, &mrt_l, &peer_l)) {
case -1: /* fatal error */
quit = 1;
break;
case 0: /* all OK */
error = 0;
break;
+ case 2:
+ error = CTL_RES_PENDING;
+ break;
default: /* parse error */
error = CTL_RES_PARSE_ERROR;
break;
@@ -389,13 +349,13 @@ main(int argc, char *argv[])
LIST_REMOVE(m, entry);
free(m);
}
- while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) {
- TAILQ_REMOVE(conf.listen_addrs, la, entry);
- close(la->fd);
- free(la);
- }
+ if (conf.listen_addrs)
+ while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) {
+ TAILQ_REMOVE(conf.listen_addrs, la, entry);
+ close(la->fd);
+ free(la);
+ }
- free(rules_l);
control_cleanup(conf.csock);
control_cleanup(conf.rcsock);
carp_demote_shutdown();
@@ -413,6 +373,8 @@ main(int argc, char *argv[])
free(ibuf_se);
msgbuf_clear(&ibuf_rde->w);
free(ibuf_rde);
+ free(rcname);
+ free(cname);
log_info("Terminating");
return (0);
@@ -452,27 +414,33 @@ send_filterset(struct imsgbuf *i, struct
int
reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
- struct peer **peer_l, struct filter_head *rules_l)
+ struct peer **peer_l)
{
struct network_head net_l;
- struct network *n;
+ struct rdomain_head rdom_l;
+ struct filter_head rules_l;
struct peer *p;
struct filter_rule *r;
struct listen_addr *la;
struct rde_rib *rr;
+ struct rdomain *rd;
- if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, rules_l)) {
+ if (reconfpending) {
+ log_info("previous reload still running");
+ return (2);
+ }
+ reconfpending = 2; /* one per child */
+
+ log_info("rereading config");
+ if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, &rules_l,
+ &rdom_l)) {
log_warnx("config file %s has errors, not reloading",
conffile);
+ reconfpending = 0;
return (1);
}
cflags = conf->flags;
- connectset = &conf->connectset;
- staticset = &conf->staticset;
- connectset6 = &conf->connectset6;
- staticset6 = &conf->staticset6;
-
prepare_listeners(conf);
/* start reconfiguration */
@@ -483,12 +451,6 @@ reconfigure(char *conffile, struct bgpd_
conf, sizeof(struct bgpd_config)) == -1)
return (-1);
- /* send peer list and listeners to the SE */
- for (p = *peer_l; p != NULL; p = p->next)
- if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
- &p->conf, sizeof(struct peer_config)) == -1)
- return (-1);
-
TAILQ_FOREACH(la, conf->listen_addrs, entry) {
if (imsg_compose(ibuf_se, IMSG_RECONF_LISTENER, 0, 0, la->fd,
la, sizeof(struct listen_addr)) == -1)
@@ -496,51 +458,104 @@ reconfigure(char *conffile, struct bgpd_
la->fd = -1;
}
+ if (control_setup(conf) == -1)
+ return (-1);
+
+ /* adjust fib syncing on reload */
+ ktable_preload();
+
/* RIBs for the RDE */
while ((rr = SIMPLEQ_FIRST(&ribnames))) {
SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
+ if (ktable_update(rr->rtableid, rr->name, NULL,
+ rr->flags) == -1) {
+ log_warnx("failed to load rdomain %d",
+ rr->rtableid);
+ return (-1);
+ }
if (imsg_compose(ibuf_rde, IMSG_RECONF_RIB, 0, 0, -1,
rr, sizeof(struct rde_rib)) == -1)
return (-1);
free(rr);
}
- /* networks for the RDE */
- while ((n = TAILQ_FIRST(&net_l)) != NULL) {
- if (imsg_compose(ibuf_rde, IMSG_NETWORK_ADD, 0, 0, -1,
- &n->net, sizeof(struct network_config)) == -1)
- return (-1);
- if (send_filterset(ibuf_rde, &n->net.attrset) == -1)
- return (-1);
- if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1,
- NULL, 0) == -1)
- return (-1);
- TAILQ_REMOVE(&net_l, n, entry);
- filterset_free(&n->net.attrset);
- free(n);
+ /* send peer list and listeners to the SE and RDE */
+ for (p = *peer_l; p != NULL; p = p->next) {
+ if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
+ &p->conf, sizeof(struct peer_config)) == -1)
+ return (-1);
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_PEER, p->conf.id, 0, -1,
+ &p->conf, sizeof(struct peer_config)) == -1)
+ return (-1);
}
- /* redistribute list needs to be reloaded too */
- if (kr_reload() == -1)
+ /* networks go via kroute to the RDE */
+ if (kr_net_reload(0, &net_l))
return (-1);
/* filters for the RDE */
- while ((r = TAILQ_FIRST(rules_l)) != NULL) {
+ while ((r = TAILQ_FIRST(&rules_l)) != NULL) {
+ TAILQ_REMOVE(&rules_l, r, entry);
if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1,
r, sizeof(struct filter_rule)) == -1)
return (-1);
if (send_filterset(ibuf_rde, &r->set) == -1)
return (-1);
- TAILQ_REMOVE(rules_l, r, entry);
filterset_free(&r->set);
free(r);
}
+ while ((rd = SIMPLEQ_FIRST(&rdom_l)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&rdom_l, entry);
+ if (ktable_update(rd->rtableid, rd->descr, rd->ifmpe,
+ rd->flags) == -1) {
+ log_warnx("failed to load rdomain %d",
+ rd->rtableid);
+ return (-1);
+ }
+ /* networks go via kroute to the RDE */
+ if (kr_net_reload(rd->rtableid, &rd->net_l))
+ return (-1);
+
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN, 0, 0, -1,
+ rd, sizeof(*rd)) == -1)
+ return (-1);
+
+ /* export targets */
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_EXPORT, 0, 0,
+ -1, NULL, 0) == -1)
+ return (-1);
+ if (send_filterset(ibuf_rde, &rd->export) == -1)
+ return (-1);
+ filterset_free(&rd->export);
+
+ /* import targets */
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_IMPORT, 0, 0,
+ -1, NULL, 0) == -1)
+ return (-1);
+ if (send_filterset(ibuf_rde, &rd->import) == -1)
+ return (-1);
+ filterset_free(&rd->import);
+
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_RDOMAIN_DONE, 0, 0,
+ -1, NULL, 0) == -1)
+ return (-1);
+
+ free(rd);
+ }
+
/* signal both childs to replace their config */
if (imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1 ||
imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1)
return (-1);
+ /* fix kroute information */
+ ktable_postload();
+
+ /* redistribute list needs to be reloaded too */
+ if (kr_reload() == -1)
+ return (-1);
+
/* mrt changes can be sent out of bound */
mrt_reconfigure(mrt_l);
return (0);
@@ -550,8 +565,8 @@ int
dispatch_imsg(struct imsgbuf *ibuf, int idx)
{
struct imsg imsg;
- int n;
- int rv;
+ ssize_t n;
+ int rv, verbose;
if ((n = imsg_read(ibuf)) == -1)
return (-1);
@@ -573,46 +588,39 @@ dispatch_imsg(struct imsgbuf *ibuf, int
case IMSG_KROUTE_CHANGE:
if (idx != PFD_PIPE_ROUTE)
log_warnx("route request not from RDE");
- else if (kr_change(imsg.data))
+ else if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct kroute_full))
+ log_warnx("wrong imsg len");
+ else if (kr_change(imsg.hdr.peerid, imsg.data))
rv = -1;
break;
case IMSG_KROUTE_DELETE:
if (idx != PFD_PIPE_ROUTE)
log_warnx("route request not from RDE");
- else if (kr_delete(imsg.data))
- rv = -1;
- break;
- case IMSG_KROUTE6_CHANGE:
- if (idx != PFD_PIPE_ROUTE)
- log_warnx("route request not from RDE");
- else if (kr6_change(imsg.data))
- rv = -1;
- break;
- case IMSG_KROUTE6_DELETE:
- if (idx != PFD_PIPE_ROUTE)
- log_warnx("route request not from RDE");
- else if (kr6_delete(imsg.data))
+ else if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct kroute_full))
+ log_warnx("wrong imsg len");
+ else if (kr_delete(imsg.hdr.peerid, imsg.data))
rv = -1;
break;
case IMSG_NEXTHOP_ADD:
if (idx != PFD_PIPE_ROUTE)
log_warnx("nexthop request not from RDE");
- else
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct bgpd_addr))
- log_warnx("wrong imsg len");
- else if (kr_nexthop_add(imsg.data) == -1)
- rv = -1;
+ else if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct bgpd_addr))
+ log_warnx("wrong imsg len");
+ else if (kr_nexthop_add(imsg.hdr.peerid, imsg.data) ==
+ -1)
+ rv = -1;
break;
case IMSG_NEXTHOP_REMOVE:
if (idx != PFD_PIPE_ROUTE)
log_warnx("nexthop request not from RDE");
+ else if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct bgpd_addr))
+ log_warnx("wrong imsg len");
else
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct bgpd_addr))
- log_warnx("wrong imsg len");
- else
- kr_nexthop_delete(imsg.data);
+ kr_nexthop_delete(imsg.hdr.peerid, imsg.data);
break;
case IMSG_PFTABLE_ADD:
if (idx != PFD_PIPE_ROUTE)
@@ -646,26 +654,28 @@ dispatch_imsg(struct imsgbuf *ibuf, int
case IMSG_CTL_RELOAD:
if (idx != PFD_PIPE_SESSION)
log_warnx("reload request not from SE");
- else
+ else {
reconfig = 1;
reconfpid = imsg.hdr.pid;
+ }
break;
case IMSG_CTL_FIB_COUPLE:
if (idx != PFD_PIPE_SESSION)
log_warnx("couple request not from SE");
else
- kr_fib_couple();
+ kr_fib_couple(imsg.hdr.peerid);
break;
case IMSG_CTL_FIB_DECOUPLE:
if (idx != PFD_PIPE_SESSION)
log_warnx("decouple request not from SE");
else
- kr_fib_decouple();
+ kr_fib_decouple(imsg.hdr.peerid);
break;
case IMSG_CTL_KROUTE:
case IMSG_CTL_KROUTE_ADDR:
case IMSG_CTL_SHOW_NEXTHOP:
case IMSG_CTL_SHOW_INTERFACE:
+ case IMSG_CTL_SHOW_FIB_TABLES:
if (idx != PFD_PIPE_SESSION)
log_warnx("kroute request not from SE");
else
@@ -692,6 +702,16 @@ dispatch_imsg(struct imsgbuf *ibuf, int
carp_demote_set(msg->demote_group, msg->level);
}
break;
+ case IMSG_CTL_LOG_VERBOSE:
+ /* already checked by SE */
+ memcpy(&verbose, imsg.data, sizeof(verbose));
+ log_verbose(verbose);
+ break;
+ case IMSG_RECONF_DONE:
+ if (reconfpending == 0)
+ log_warnx("unexpected RECONF_DONE received");
+ reconfpending--;
+ break;
default:
break;
}
@@ -707,7 +727,7 @@ send_nexthop_update(struct kroute_nextho
{
char *gw = NULL;
- if (msg->gateway.af)
+ if (msg->gateway.aid)
if (asprintf(&gw, ": via %s",
log_addr(&msg->gateway)) == -1) {
log_warn("send_nexthop_update");
@@ -717,7 +737,7 @@ send_nexthop_update(struct kroute_nextho
log_info("nexthop %s now %s%s%s", log_addr(&msg->nexthop),
msg->valid ? "valid" : "invalid",
msg->connected ? ": directly connected" : "",
- msg->gateway.af ? gw : "");
+ msg->gateway.aid ? gw : "");
free(gw);
@@ -733,56 +753,20 @@ send_imsg_session(int type, pid_t pid, v
}
int
-bgpd_redistribute(int type, struct kroute *kr, struct kroute6 *kr6)
+send_network(int type, struct network_config *net, struct filter_set_head *h)
{
- struct network_config net;
- struct filter_set_head *h;
-
- if ((cflags & BGPD_FLAG_REDIST_CONNECTED) && kr &&
- (kr->flags & F_CONNECTED))
- h = connectset;
- else if ((cflags & BGPD_FLAG_REDIST_STATIC) && kr &&
- (kr->flags & F_STATIC))
- h = staticset;
- else if ((cflags & BGPD_FLAG_REDIST6_CONNECTED) && kr6 &&
- (kr6->flags & F_CONNECTED))
- h = connectset6;
- else if ((cflags & BGPD_FLAG_REDIST6_STATIC) && kr6 &&
- (kr6->flags & F_STATIC))
- h = staticset6;
- else
- return (0);
-
- bzero(&net, sizeof(net));
- if (kr && kr6)
- fatalx("bgpd_redistribute: unable to redistribute v4 and v6"
- "together");
- if (kr != NULL) {
- net.prefix.af = AF_INET;
- net.prefix.v4.s_addr = kr->prefix.s_addr;
- net.prefixlen = kr->prefixlen;
- }
- if (kr6 != NULL) {
- net.prefix.af = AF_INET6;
- memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr));
- net.prefixlen = kr6->prefixlen;
- }
-
-
- if (imsg_compose(ibuf_rde, type, 0, 0, -1, &net,
+ if (imsg_compose(ibuf_rde, type, 0, 0, -1, net,
sizeof(struct network_config)) == -1)
return (-1);
-
/* networks that get deleted don't need to send the filter set */
if (type == IMSG_NETWORK_REMOVE)
- return (1);
-
+ return (0);
if (send_filterset(ibuf_rde, h) == -1)
return (-1);
if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1)
return (-1);
- return (1);
+ return (0);
}
int
@@ -810,3 +794,45 @@ bgpd_filternexthop(struct kroute *kr, st
return (1);
}
+
+int
+control_setup(struct bgpd_config *conf)
+{
+ int fd, restricted;
+
+ /* control socket is outside chroot */
+ if (!cname || strcmp(cname, conf->csock)) {
+ if (cname) {
+ control_cleanup(cname);
+ free(cname);
+ }
+ if ((cname = strdup(conf->csock)) == NULL)
+ fatal("strdup");
+ if ((fd = control_init(0, cname)) == -1)
+ fatalx("control socket setup failed");
+ restricted = 0;
+ if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
+ &restricted, sizeof(restricted)) == -1)
+ return (-1);
+ }
+ if (!conf->rcsock) {
+ /* remove restricted socket */
+ control_cleanup(rcname);
+ free(rcname);
+ rcname = NULL;
+ } else if (!rcname || strcmp(rcname, conf->rcsock)) {
+ if (rcname) {
+ control_cleanup(rcname);
+ free(rcname);
+ }
+ if ((rcname = strdup(conf->rcsock)) == NULL)
+ fatal("strdup");
+ if ((fd = control_init(1, rcname)) == -1)
+ fatalx("control socket setup failed");
+ restricted = 1;
+ if (imsg_compose(ibuf_se, IMSG_RECONF_CTRL, 0, 0, fd,
+ &restricted, sizeof(restricted)) == -1)
+ return (-1);
+ }
+ return (0);
+}

View File

@ -0,0 +1,746 @@
Index: bgpd/bgpd.conf.5
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.conf.5,v
retrieving revision 1.1.1.7
retrieving revision 1.10
diff -u -p -r1.1.1.7 -r1.10
--- bgpd/bgpd.conf.5 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/bgpd.conf.5 8 Dec 2012 20:17:59 -0000 1.10
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpd.conf.5,v 1.94 2009/06/07 00:31:22 claudio Exp $
+.\" $OpenBSD: bgpd.conf.5,v 1.122 2012/11/13 09:47:20 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 7 2009 $
+.Dd $Mdocdate: November 13 2012 $
.Dt BGPD.CONF 5
.Os
.Sh NAME
@@ -26,11 +26,11 @@
The
.Xr bgpd 8
daemon implements the Border Gateway Protocol version 4 as described
-in RFC 1771.
+in RFC 4271.
.Sh SECTIONS
The
.Nm
-config file is divided into four main sections.
+config file is divided into five main sections.
.Bl -tag -width xxxx
.It Sy Macros
User-defined variables may be defined and used later, simplifying the
@@ -38,6 +38,8 @@ configuration file.
.It Sy Global Configuration
Global settings for
.Xr bgpd 8 .
+.It Sy Routing Domain Configuration
+The definition and properties for BGP MPLS VPNs are set in this section.
.It Sy Neighbors and Groups
.Xr bgpd 8
establishes sessions with
@@ -54,9 +56,16 @@ the sections should be grouped and appea
.Nm
in the order shown above.
.Pp
+The current line can be extended over multiple lines using a backslash
+.Pq Sq \e .
Comments can be put anywhere in the file using a hash mark
.Pq Sq # ,
and extend to the end of the current line.
+Care should be taken when commenting out multi-line text:
+the comment is effective until the end of the entire block.
+.Pp
+Argument names not beginning with a letter, digit, or underscore
+must be quoted.
.Pp
Additional configuration files can be included with the
.Ic include
@@ -66,8 +75,8 @@ include "/etc/bgpd/bgpd-10.0.0.1.filter"
.Ed
.Sh MACROS
Macros can be defined that will later be expanded in context.
-Macro names must start with a letter, and may contain letters, digits
-and underscores.
+Macro names must start with a letter, digit, or underscore,
+and may contain any of those characters.
Macro names may not be reserved words (for example,
.Ic AS ,
.Ic neighbor ,
@@ -93,7 +102,7 @@ Set the local
.Em autonomous system
number to
.Ar as-number .
-If the first AS number is a 4-byte AS it is possible to specifiy a secondary
+If the first AS number is a 4-byte AS it is possible to specify a secondary
2-byte AS number which is used for neighbors which do not support 4-byte AS
numbers.
The default for the secondary AS is 23456.
@@ -143,29 +152,33 @@ 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
.Ic dump
-.Pq Ic all Ns \&| Ns Ic updates
-.Pq Ic in Ns \&| Ns Ic out
+.Pq Ic all Ns | Ns Ic updates
+.Pq Ic in Ns | Ns Ic out
.Ar file Op Ar timeout
.Xc
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
@@ -195,7 +208,7 @@ dump updates out "/tmp/updates-out-%H%M"
.Pp
.It Xo
.Ic fib-update
-.Pq Ic yes Ns \&| Ns Ic no
+.Pq Ic yes Ns | Ns Ic no
.Xc
If set to
.Ic no ,
@@ -242,12 +255,12 @@ Log received and sent updates.
.Xc
.It Xo
.Ic network
-.Pq Ic inet Ns \&| Ns Ic inet6
+.Pq Ic inet Ns | Ns Ic inet6
.Ic static Op Ic set ...\&
.Xc
.It Xo
.Ic network
-.Pq Ic inet Ns \&| Ns Ic inet6
+.Pq Ic inet Ns | Ns Ic inet6
.Ic connected Op Ic set ...\&
.Xc
Announce the specified network as belonging to our AS.
@@ -278,7 +291,7 @@ section.
.Ic nexthop
.Ic qualify
.Ic via
-.Pq Ic bgp Ns \&| Ns Ic default
+.Pq Ic bgp Ns | Ns Ic default
.Xc
If set to
.Ic bgp ,
@@ -295,38 +308,47 @@ daemons like
.Ic rde
.Ic med
.Ic compare
-.Pq Ic always Ns \&| Ns Ic strict
+.Pq Ic always Ns | Ns Ic strict
.Xc
If set to
.Ic always ,
the
-.Em MED
+.Em MULTI_EXIT_DISC
attributes will always be compared.
The default is
.Ic strict ,
-where the
-.Em MED
-is only compared between peers belonging to the same AS.
+where the metric is only compared between peers belonging to the same AS.
.Pp
.It Xo
.Ic rde
.Ic rib Ar name
.Op Ic no Ic evaluate
.Xc
-Creat an additional RIB named
+.It Xo
+.Ic rde
+.Ic rib Ar name
+.Op Ic rtable Ar number
+.Xc
+Create an additional RIB named
.Ar name .
It is possible to disable the decision process per RIB with the
.Ic no Ic evaluate
flag.
+If a
+.Ic rtable
+is specified, routes will be exported to the given kernel routing table.
+Currently the routing table must belong to the default routing domain and
+nexthop verification happens on table 0.
+Routes in the specified table will not be considered for nexthop verification.
.Ic Adj-RIB-In
and
.Ic Loc-RIB
-are created automaticaly and used as default.
+are created automatically and used as default.
.Pp
.It Xo
.Ic rde
.Ic route-age
-.Pq Ic ignore Ns \&| Ns Ic evaluate
+.Pq Ic ignore Ns | Ns Ic evaluate
.Xc
If set to
.Ic evaluate ,
@@ -339,7 +361,7 @@ The default is
.Pp
.It Xo
.Ic route-collector
-.Pq Ic yes Ns \&| Ns Ic no
+.Pq Ic yes Ns | Ns Ic no
.Xc
If set to
.Ic yes ,
@@ -361,13 +383,24 @@ to the local machine.
Work with the given kernel routing table
instead of the default table,
.Ar 0 .
-Note that this table is used for nexthop verification as well.
-Directly connected networks are always taken into account, even though
-their routes live in table 0.
+Note that table 0 is used for nexthop verification.
+Routes in the specified table will not be considered for nexthop verification.
+This is the same as using the following syntax:
+.Bd -literal -offset indent
+rde rib Loc-RIB rtable number
+.Ed
+.Pp
+.It Ic socket Qo Ar path Qc Op Ic restricted
+Set the control socket location to
+.Ar path .
+If
+.Ic restricted
+is specified a restricted control socket will be created.
+By default /var/run/bgpd.sock is used and no restricted socket is created.
.Pp
.It Xo
.Ic transparent-as
-.Pq Ic yes Ns \&| Ns Ic no
+.Pq Ic yes Ns | Ns Ic no
.Xc
If set to
.Ic yes ,
@@ -376,6 +409,110 @@ to EBGP neighbors are not prepended with
The default is
.Ic no .
.El
+.Sh ROUTING DOMAIN CONFIGURATION
+.Xr bgpd 8
+supports the setup and distribution of Virtual Private Networks.
+It is possible to import and export prefixes between routing domains.
+Each routing domain is specified by an
+.Ic rdomain
+section, which allows properties to be set specifically for that rdomain:
+.Bd -literal -offset indent
+rdomain 1 {
+ descr "a rdomain"
+ rd 65002:1
+ import-target rt 65002:42
+ export-target rt 65002:42
+ network 192.168.1/24
+ depend on mpe0
+}
+.Ed
+.Pp
+There are several routing domain properties:
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic depend on Ar interface
+Routes added to the rdomain will use this interface as the outgoing interface.
+Normally this will be an MPLS Provider Edge,
+.Xr mpe 4 ,
+interface that is part of the rdomain.
+Local networks will be announced with the MPLS label specified on the interface.
+.Pp
+.It Ic descr Ar description
+Add a description.
+The description is used when logging but has no further meaning to
+.Xr bgpd 8 .
+.Pp
+.It Ic export-target Ar subtype Ar as-number Ns Li : Ns Ar local
+.It Ic export-target Ar subtype Ar IP Ns Li : Ns Ar local
+Specify an extended community which will be attached to announced networks.
+More than one
+.Ic export-target
+can be specified.
+See also the
+.Sx ATTRIBUTE SET
+section for further information about the encoding.
+The
+.Ar subtype
+should be set to
+.Ar rt
+for best compatibility with other implementations.
+.Pp
+.It Xo
+.Ic fib-update
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic no ,
+do not update the Forwarding Information Base, a.k.a. the kernel
+routing table.
+The default is
+.Ic yes .
+.Pp
+.It Ic import-target Ar subtype Ar as-number Ns Li : Ns Ar local
+.It Ic import-target Ar subtype Ar IP Ns Li : Ns Ar local
+Only prefixes matching one of the specified
+.Ic import-targets
+will be imported into the rdomain.
+More than one
+.Ic import-target
+can be specified.
+See also the
+.Sx ATTRIBUTE SET
+section for further information about the encoding of extended communities.
+The
+.Ar subtype
+should be set to
+.Ar rt
+for best compatibility with other implementations.
+.Pp
+.It Ic network Ar arguments ...
+Define which networks should be exported into this VPN.
+See also the
+.Ic nexthop
+section in
+.Sx GLOBAL CONFIGURATION
+for further information about the arguments.
+.Pp
+.It Ic rd Ar as-number Ns Li : Ns Ar local
+.It Ic rd Ar IP Ns Li : Ns Ar local
+The sole purpose of the Route Distinguisher
+.Ic rd
+is to ensure that possible common prefixes are destinct between VPNs.
+The
+.Ic rd
+is neither used to identify the origin of the prefix nor to control into
+which VPNs the prefix is distributed to.
+The
+.Ar as-number
+or
+.Ar IP
+of a
+.Ic rd
+should be set to a number or IP that was assigned by an appropriate authority.
+Whereas
+.Ar local
+can be chosen by the local operator.
+.El
.Sh NEIGHBORS AND GROUPS
.Xr bgpd 8
establishes TCP connections to other BGP speakers called
@@ -470,21 +607,35 @@ The default for IBGP peers is
.Pp
.It Xo
.Ic announce
-.Pq Ic IPv4 Ns \&| Ns Ic IPv6
-.Pq Ic none Ns \&| Ns Ic unicast
+.Pq Ic IPv4 Ns | Ns Ic IPv6
+.Pq Ic none Ns | Ns Ic unicast Ns | Ns Ic vpn
.Xc
For the given address family, control which subsequent address families
(at the moment, only
.Em none ,
-which disables the announcement of that address family, and
-.Em unicast
-are supported) are announced during the capabilities negotiation.
+which disables the announcement of that address family,
+.Em unicast ,
+and
+.Em vpn ,
+which allows the distribution of BGP MPLS VPNs, are supported) are announced
+during the capabilities negotiation.
Only routes for that address family and subsequent address family will be
announced and processed.
.Pp
.It Xo
+.Ic announce as-4byte
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic no ,
+the 4-byte AS capability is not announced and so native 4-byte AS support is
+disabled.
+The default is
+.Ic yes .
+.Pp
+.It Xo
.Ic announce capabilities
-.Pq Ic yes Ns \&| Ns Ic no
+.Pq Ic yes Ns | Ns Ic no
.Xc
If set to
.Ic no ,
@@ -493,6 +644,29 @@ This can be helpful to connect to old or
The default is
.Ic yes .
.Pp
+.It Xo
+.Ic announce refresh
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic no ,
+the route refresh capability is not announced.
+The default is
+.Ic yes .
+.Pp
+.It Xo
+.Ic announce restart
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic yes ,
+the graceful restart capability is announced.
+Currently only the End-of-RIB marker is supported and announced by the
+.Ic restart
+capability.
+The default is
+.Ic no .
+.Pp
.It Ic demote Ar group
Increase the
.Xr carp 4
@@ -504,7 +678,7 @@ The demotion counter will be increased a
.Xr bgpd 8
starts and decreased
60 seconds after the session went to state
-.Em ESTABLISHED.
+.Em ESTABLISHED .
For neighbors added at runtime, the demotion counter is only increased after
the session has been
.Em ESTABLISHED
@@ -548,8 +722,8 @@ Do not start the session when bgpd comes
.Pp
.It Xo
.Ic dump
-.Pq Ic all Ns \&| Ns Ic updates
-.Pq Ic in Ns \&| Ns Ic out
+.Pq Ic all Ns | Ns Ic updates
+.Pq Ic in Ns | Ns Ic out
.Ar file Op Ar timeout
.Xc
Do a peer specific MRT dump.
@@ -564,7 +738,7 @@ section in
.Pp
.It Xo
.Ic enforce neighbor-as
-.Pq Ic yes Ns \&| Ns Ic no
+.Pq Ic yes Ns | Ns Ic no
.Xc
If set to
.Ic yes ,
@@ -589,10 +763,16 @@ Inherited from the global configuration
Set the minimal acceptable holdtime.
Inherited from the global configuration if not given.
.Pp
+.It Ic interface Ar interface
+Set an interface used for a nexthop with a link-local IPv6 address.
+Note that if this is not specified and a link-local IPv6 address is
+received as nexthop of the peer, it will be marked as invalid and
+ignored.
+.Pp
.It Xo
.Ic ipsec
-.Pq Ic ah Ns \&| Ns Ic esp
-.Pq Ic in Ns \&| Ns Ic out
+.Pq Ic ah Ns | Ns Ic esp
+.Pq Ic in Ns | Ns Ic out
.Ic spi Ar spi-number authspec Op Ar encspec
.Xc
Enable IPsec with static keying.
@@ -627,7 +807,7 @@ Keys must be given in hexadecimal format
.Pp
.It Xo
.Ic ipsec
-.Pq Ic ah Ns \&| Ns Ic esp
+.Pq Ic ah Ns | Ns Ic esp
.Ic ike
.Xc
Enable IPsec with dynamic keying.
@@ -639,11 +819,11 @@ is responsible for managing the session
With
.Xr isakmpd 8 ,
it is sufficient to copy the peer's public key, found in
-.Pa /etc/isakmpd/local.pub ,
+.Pa %%PREFIX%%/etc/isakmpd/private/local.pub ,
to the local machine.
It must be stored in a file
named after the peer's IP address and must be stored in
-.Pa /etc/isakmpd/pubkeys/ipv4/ .
+.Pa %%PREFIX%%/etc/isakmpd/pubkeys/ipv4/ .
The local public key must be copied to the peer in the same way.
As
.Xr bgpd 8
@@ -698,11 +878,11 @@ Do not attempt to actively open a TCP co
.It Ic remote-as Ar as-number
Set the AS number of the remote system.
.Pp
-.It rib .Ar name
+.It Ic rib Ar name
Bind the neighbor to the specified RIB.
.Pp
.It Ic route-reflector Op Ar address
-Act as an RFC 2796
+Act as an RFC 4456
.Em route-reflector
for this neighbor.
An optional cluster ID can be specified; otherwise the BGP ID will be used.
@@ -732,8 +912,8 @@ These sets are rewritten into filter rul
.Pp
.It Xo
.Ic softreconfig
-.Pq Ic in Ns \&| Ns Ic out
-.Pq Ic yes Ns \&| Ns Ic no
+.Pq Ic in Ns | Ns Ic out
+.Pq Ic yes Ns | Ns Ic no
.Xc
Turn soft reconfiguration on or off for the specified direction.
If soft reconfiguration is turned on, filter changes will be applied on
@@ -760,7 +940,7 @@ tcp md5sig key deadbeef
.Pp
.It Xo
.Ic transparent-as
-.Pq Ic yes Ns \&| Ns Ic no
+.Pq Ic yes Ns | Ns Ic no
.Xc
If set to
.Ic yes ,
@@ -772,7 +952,7 @@ setting.
.Pp
.It Xo
.Ic ttl-security
-.Pq Ic yes Ns \&| Ns Ic no
+.Pq Ic yes Ns | Ns Ic no
.Xc
Enable or disable ttl-security.
When enabled,
@@ -849,6 +1029,10 @@ is matched against a part of the
.Em AS path
specified by the
.Ar as-type .
+.Ar as-number
+may be set to
+.Ic neighbor-as ,
+which is expanded to the current neighbor remote AS number.
.Ar as-type
is one of the following operators:
.Pp
@@ -917,7 +1101,32 @@ may be set to
which is expanded to the current neighbor remote AS number.
.Pp
.It Xo
-.Pq Ic from Ns \&| Ns Ic to
+.Ic ext-community
+.Ar subtype Ar as-number Ns Li : Ns Ar local
+.Xc
+.It Xo
+.Ic ext-community
+.Ar subtype Ar IP Ns Li : Ns Ar local
+.Xc
+.It Xo
+.Ic ext-community
+.Ar subtype Ar numvalue
+.Xc
+This rule applies only to
+.Em UPDATES
+where the
+.Em extended community
+path attribute is present and matches.
+Extended Communities are specified by a
+.Ar subtype
+and normally two values, a globally unique part (e.g. the AS number) and a
+local part.
+See also the
+.Sx ATTRIBUTE SET
+section for further information about the encoding.
+.Pp
+.It Xo
+.Pq Ic from Ns | Ns Ic to
.Ar peer
.Xc
This rule applies only to
@@ -945,7 +1154,7 @@ if enclosed in curly brackets:
deny from { 128.251.16.1, 251.128.16.2, group hojo }
.Ed
.Pp
-.It Pq Ic inet Ns \&| Ns Ic inet6
+.It Pq Ic inet Ns | Ns Ic inet6
This rule applies only to routes matching the stated address family.
The address family needs to be set only in rules that use
.Ic prefixlen
@@ -953,6 +1162,37 @@ without specifying a
.Ic prefix
beforehand.
.Pp
+.It Ic max-as-len Ar len
+This rule applies only to
+.Em UPDATES
+where the
+.Em AS path
+has more than
+.Ar len
+elements.
+.Pp
+.It Ic max-as-seq Ar len
+This rule applies only to
+.Em UPDATES
+where a single
+.Em AS number
+is repeated more than
+.Ar len
+times.
+.Pp
+.It Ic nexthop Ar address
+This rule applies only to
+.Em UPDATES
+where the nexthop is equal to
+.Ar address .
+The
+.Ar address
+can be set to
+.Em neighbor
+in which case the nexthop is compared against the address of the neighbor.
+Nexthop filtering is not supported on locally announced networks and one must
+take into consideration previous rules overwriting nexthops.
+.Pp
.It Xo
.Ic prefix
.Ar address Ns Li / Ns Ar len
@@ -1028,6 +1268,12 @@ matches a rule which has the
option set, this rule is considered the last matching rule, and evaluation
of subsequent rules is skipped.
.Pp
+.It Ic rib Ar name
+Apply rule only to the specified RIB.
+This only applies for received updates, so not for rules using the
+.Ar to peer
+parameter.
+.Pp
.It Ic set Ar attribute ...
All matching rules can set the
.Em AS path attributes
@@ -1079,6 +1325,48 @@ Alternately, well-known communities may
or
.Ic NO_PEER .
.Pp
+.It Xo
+.Ic ext-community Op Ar delete
+.Ar subtype Ar as-number Ns Li : Ns Ar local
+.Xc
+.It Xo
+.Ic ext-community Op Ar delete
+.Ar subtype Ar IP Ns Li : Ns Ar local
+.Xc
+.It Xo
+.Ic ext-community Op Ar delete
+.Ar subtype Ar numvalue
+.Xc
+Set or delete the
+.Em Extended Community
+AS path attribute.
+Extended Communities are specified by a
+.Ar subtype
+and normally two values, a globally unique part (e.g. the AS number) and a
+local part.
+The type is selected depending on the encoding of the global part.
+Two-octet AS Specific Extended Communities and Four-octet AS Specific Extended
+Communities are encoded as
+.Ar as-number Ns Li : Ns Ar local .
+Four-octet encoding is used if the
+.Ar as-number
+is bigger then 65535 or if the AS_DOT encoding is used.
+IPv4 Address Specific Extended Communities are encoded as
+.Ar IP Ns Li : Ns Ar local .
+Opaque Extended Communities are encoded with a single numeric value.
+Currently the following subtypes are supported:
+.Bd -literal -offset indent
+rt Route Target
+soo Source of Origin
+odi OSPF Domain Identifier
+ort OSPF Route Type
+ori OSPF Router ID
+bdc BGP Data Collection
+.Ed
+.Pp
+Not all type and subtype value pairs are allowed by IANA and the parser
+will ensure that no invalid combination is created.
+.Pp
.It Ic localpref Ar number
Set the
.Em LOCAL_PREF
@@ -1108,6 +1396,20 @@ otherwise it will be set to
.Ar number .
.Pp
.It Xo
+.Ic origin
+.Sm off
+.Po Ic igp \*(Ba
+.Ic egp \*(Ba
+.Ic incomplete Pc
+.Sm on
+.Xc
+Set the
+.Em ORIGIN
+AS path attribute to mark the source of this
+route as being injected from an igp protocol, an egp protocol
+or being an aggregated route.
+.Pp
+.It Xo
.Ic nexthop
.Sm off
.Po Ar address \*(Ba
@@ -1157,9 +1459,8 @@ times to the
.Em AS path .
.Pp
.It Ic rtlabel Ar label
-Add the prefix with the specified
-.Ar label
-to the kernel routing table.
+Add the prefix to the kernel routing table with the specified
+.Ar label .
.Pp
.It Ic weight Ar number
The
@@ -1181,8 +1482,8 @@ For prefixes with equally long paths, th
is selected.
.El
.Sh FILES
-.Bl -tag -width "/etc/bgpd.conf" -compact
-.It Pa /etc/bgpd.conf
+.Bl -tag -width "%%PREFIX%%/etc/bgpd.conf" -compact
+.It Pa %%PREFIX%%/etc/bgpd.conf
.Xr bgpd 8
configuration file
.El

View File

@ -0,0 +1,872 @@
Index: bgpd/bgpd.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/bgpd.h,v
retrieving revision 1.1.1.8
retrieving revision 1.15
diff -u -p -r1.1.1.8 -r1.15
--- bgpd/bgpd.h 14 Feb 2010 20:19:57 -0000 1.1.1.8
+++ bgpd/bgpd.h 16 May 2014 00:36:26 -0000 1.15
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.241 2009/06/12 16:42:53 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.273 2012/09/18 10:10:00 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
+#include <sys/tree.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -30,11 +31,16 @@
#include <poll.h>
#include <stdarg.h>
-#include <imsg.h>
+#if defined(__FreeBSD__) /* compat */
+#include "openbsd-compat.h"
+#endif /* defined(__FreeBSD__) */
+#include "imsg.h"
#define BGP_VERSION 4
#define BGP_PORT 179
+#ifndef CONFFILE
#define CONFFILE "/etc/bgpd.conf"
+#endif /* !CONFFILE */
#define BGPD_USER "_bgpd"
#define PEER_DESCR_LEN 32
#define PFTABLE_LEN 16
@@ -42,8 +48,6 @@
#define IPSEC_ENC_KEY_LEN 32
#define IPSEC_AUTH_KEY_LEN 20
-#define ASNUM_MAX 0xffffffff
-
#define MAX_PKTSIZE 4096
#define MIN_HOLDTIME 3
#define READ_BUF_SIZE 65535
@@ -55,13 +59,8 @@
#define BGPD_OPT_NOACTION 0x0004
#define BGPD_OPT_FORCE_DEMOTE 0x0008
-#define BGPD_FLAG_NO_FIB_UPDATE 0x0001
#define BGPD_FLAG_NO_EVALUATE 0x0002
#define BGPD_FLAG_REFLECTOR 0x0004
-#define BGPD_FLAG_REDIST_STATIC 0x0008
-#define BGPD_FLAG_REDIST_CONNECTED 0x0010
-#define BGPD_FLAG_REDIST6_STATIC 0x0020
-#define BGPD_FLAG_REDIST6_CONNECTED 0x0040
#define BGPD_FLAG_NEXTHOP_BGP 0x0080
#define BGPD_FLAG_NEXTHOP_DEFAULT 0x1000
#define BGPD_FLAG_DECISION_MASK 0x0f00
@@ -83,9 +82,12 @@
#define F_REJECT 0x0080
#define F_BLACKHOLE 0x0100
#define F_LONGER 0x0200
+#define F_MPLS 0x0400
+#define F_REDISTRIBUTED 0x0800
#define F_CTL_DETAIL 0x1000 /* only used by bgpctl */
#define F_CTL_ADJ_IN 0x2000
#define F_CTL_ADJ_OUT 0x4000
+#define F_CTL_ACTIVE 0x8000
/*
* Limit the number of control messages generated by the RDE and queued in
@@ -109,18 +111,75 @@ enum reconf_action {
RECONF_DELETE
};
+/* Address Family Numbers as per RFC 1700 */
+#define AFI_UNSPEC 0
+#define AFI_IPv4 1
+#define AFI_IPv6 2
+
+/* Subsequent Address Family Identifier as per RFC 4760 */
+#define SAFI_NONE 0
+#define SAFI_UNICAST 1
+#define SAFI_MULTICAST 2
+#define SAFI_MPLS 4
+#define SAFI_MPLSVPN 128
+
+struct aid {
+ u_int16_t afi;
+ sa_family_t af;
+ u_int8_t safi;
+ char *name;
+};
+
+extern const struct aid aid_vals[];
+
+#define AID_UNSPEC 0
+#define AID_INET 1
+#define AID_INET6 2
+#define AID_VPN_IPv4 3
+#define AID_MAX 4
+#define AID_MIN 1 /* skip AID_UNSPEC since that is a dummy */
+
+#define AID_VALS { \
+ /* afi, af, safii, name */ \
+ { AFI_UNSPEC, AF_UNSPEC, SAFI_NONE, "unspec"}, \
+ { AFI_IPv4, AF_INET, SAFI_UNICAST, "IPv4 unicast" }, \
+ { AFI_IPv6, AF_INET6, SAFI_UNICAST, "IPv6 unicast" }, \
+ { AFI_IPv4, AF_INET, SAFI_MPLSVPN, "IPv4 vpn" } \
+}
+
+#define AID_PTSIZE { \
+ 0, \
+ sizeof(struct pt_entry4), \
+ sizeof(struct pt_entry6), \
+ sizeof(struct pt_entry_vpn4) \
+}
+
+struct vpn4_addr {
+ u_int64_t rd;
+ struct in_addr addr;
+ u_int8_t labelstack[21]; /* max that makes sense */
+ u_int8_t labellen;
+ u_int8_t pad1;
+ u_int8_t pad2;
+};
+
+#define BGP_MPLS_BOS 0x01
+
struct bgpd_addr {
- sa_family_t af;
union {
struct in_addr v4;
struct in6_addr v6;
- u_int8_t addr8[16];
- u_int16_t addr16[8];
- u_int32_t addr32[4];
+ struct vpn4_addr vpn4;
+ /* maximum size for a prefix is 256 bits */
+ u_int8_t addr8[32];
+ u_int16_t addr16[16];
+ u_int32_t addr32[8];
} ba; /* 128-bit address */
u_int32_t scope_id; /* iface scope id for v6 */
+ u_int8_t aid;
#define v4 ba.v4
#define v6 ba.v6
+#define vpn4 ba.vpn4
#define addr8 ba.addr8
#define addr16 ba.addr16
#define addr32 ba.addr32
@@ -141,17 +200,12 @@ TAILQ_HEAD(listen_addrs, listen_addr);
TAILQ_HEAD(filter_set_head, filter_set);
struct bgpd_config {
- struct filter_set_head connectset;
- struct filter_set_head connectset6;
- struct filter_set_head staticset;
- struct filter_set_head staticset6;
struct listen_addrs *listen_addrs;
char *csock;
char *rcsock;
int opts;
int flags;
int log;
- u_int rtableid;
u_int32_t bgpid;
u_int32_t clusterid;
u_int32_t as;
@@ -205,12 +259,24 @@ struct peer_auth {
};
struct capabilities {
- u_int8_t mp_v4; /* multiprotocol extensions, RFC 4760 */
- u_int8_t mp_v6;
- u_int8_t refresh; /* route refresh, RFC 2918 */
- u_int8_t restart; /* graceful restart, RFC 4724 */
- u_int8_t as4byte; /* draft-ietf-idr-as4bytes-13 */
-};
+ struct {
+ int16_t timeout; /* graceful restart timeout */
+ int8_t flags[AID_MAX]; /* graceful restart per AID flags */
+ int8_t restart; /* graceful restart, RFC 4724 */
+ } grestart;
+ int8_t mp[AID_MAX]; /* multiprotocol extensions, RFC 4760 */
+ int8_t refresh; /* route refresh, RFC 2918 */
+ int8_t as4byte; /* 4-byte ASnum, RFC 4893 */
+};
+
+#define CAPA_GR_PRESENT 0x01
+#define CAPA_GR_RESTART 0x02
+#define CAPA_GR_FORWARD 0x04
+#define CAPA_GR_RESTARTING 0x08
+
+#define CAPA_GR_TIMEMASK 0x0fff
+#define CAPA_GR_R_FLAG 0x8000
+#define CAPA_GR_F_FLAG 0x80
struct peer_config {
struct bgpd_addr remote_addr;
@@ -237,7 +303,7 @@ struct peer_config {
u_int8_t template;
u_int8_t remote_masklen;
u_int8_t cloned;
- u_int8_t ebgp; /* 1 = ebgp, 0 = ibgp */
+ u_int8_t ebgp; /* 0 = ibgp else ebgp */
u_int8_t distance; /* 1 = direct, >1 = multihop */
u_int8_t passive;
u_int8_t down;
@@ -248,21 +314,33 @@ struct peer_config {
u_int8_t ttlsec; /* TTL security hack */
u_int8_t flags;
u_int8_t pad[3];
+ char lliface[IFNAMSIZ];
};
#define PEERFLAG_TRANS_AS 0x01
+enum network_type {
+ NETWORK_DEFAULT,
+ NETWORK_STATIC,
+ NETWORK_CONNECTED,
+ NETWORK_MRTCLONE
+};
+
struct network_config {
- struct bgpd_addr prefix;
- struct filter_set_head attrset;
- u_int8_t prefixlen;
+ struct bgpd_addr prefix;
+ struct filter_set_head attrset;
+ struct rde_aspath *asp;
+ u_int rtableid;
+ enum network_type type;
+ u_int8_t prefixlen;
+ u_int8_t old; /* used for reloading */
};
TAILQ_HEAD(network_head, network);
struct network {
- struct network_config net;
- TAILQ_ENTRY(network) entry;
+ struct network_config net;
+ TAILQ_ENTRY(network) entry;
};
enum imsg_type {
@@ -276,7 +354,6 @@ enum imsg_type {
IMSG_CTL_NEIGHBOR_CLEAR,
IMSG_CTL_NEIGHBOR_RREFRESH,
IMSG_CTL_KROUTE,
- IMSG_CTL_KROUTE6,
IMSG_CTL_KROUTE_ADDR,
IMSG_CTL_RESULT,
IMSG_CTL_SHOW_NEIGHBOR,
@@ -288,11 +365,14 @@ enum imsg_type {
IMSG_CTL_SHOW_RIB_ATTR,
IMSG_CTL_SHOW_RIB_COMMUNITY,
IMSG_CTL_SHOW_NETWORK,
- IMSG_CTL_SHOW_NETWORK6,
IMSG_CTL_SHOW_RIB_MEM,
IMSG_CTL_SHOW_TERSE,
IMSG_CTL_SHOW_TIMER,
+ IMSG_CTL_LOG_VERBOSE,
+ IMSG_CTL_SHOW_FIB_TABLES,
IMSG_NETWORK_ADD,
+ IMSG_NETWORK_ASPATH,
+ IMSG_NETWORK_ATTR,
IMSG_NETWORK_REMOVE,
IMSG_NETWORK_FLUSH,
IMSG_NETWORK_DONE,
@@ -302,19 +382,25 @@ enum imsg_type {
IMSG_RECONF_PEER,
IMSG_RECONF_FILTER,
IMSG_RECONF_LISTENER,
+ IMSG_RECONF_CTRL,
+ IMSG_RECONF_RDOMAIN,
+ IMSG_RECONF_RDOMAIN_EXPORT,
+ IMSG_RECONF_RDOMAIN_IMPORT,
+ IMSG_RECONF_RDOMAIN_DONE,
IMSG_RECONF_DONE,
IMSG_UPDATE,
IMSG_UPDATE_ERR,
IMSG_SESSION_ADD,
IMSG_SESSION_UP,
IMSG_SESSION_DOWN,
+ IMSG_SESSION_STALE,
+ IMSG_SESSION_FLUSH,
+ IMSG_SESSION_RESTARTED,
IMSG_MRT_OPEN,
IMSG_MRT_REOPEN,
IMSG_MRT_CLOSE,
IMSG_KROUTE_CHANGE,
IMSG_KROUTE_DELETE,
- IMSG_KROUTE6_CHANGE,
- IMSG_KROUTE6_DELETE,
IMSG_NEXTHOP_ADD,
IMSG_NEXTHOP_REMOVE,
IMSG_NEXTHOP_UPDATE,
@@ -337,6 +423,7 @@ enum ctl_results {
CTL_RES_DENIED,
CTL_RES_NOCAP,
CTL_RES_PARSE_ERROR,
+ CTL_RES_PENDING,
CTL_RES_NOMEM
};
@@ -379,9 +466,43 @@ enum suberr_cease {
ERR_CEASE_RSRC_EXHAUST
};
+struct kroute_node;
+struct kroute6_node;
+struct knexthop_node;
+RB_HEAD(kroute_tree, kroute_node);
+RB_HEAD(kroute6_tree, kroute6_node);
+RB_HEAD(knexthop_tree, knexthop_node);
+
+struct ktable {
+ char descr[PEER_DESCR_LEN];
+ char ifmpe[IFNAMSIZ];
+ struct kroute_tree krt;
+ struct kroute6_tree krt6;
+ struct knexthop_tree knt;
+ struct network_head krn;
+ u_int rtableid;
+ u_int nhtableid; /* rdomain id for nexthop lookup */
+ u_int ifindex; /* ifindex of ifmpe */
+ int nhrefcnt; /* refcnt for nexthop table */
+ enum reconf_action state;
+ u_int8_t fib_conf; /* configured FIB sync flag */
+ u_int8_t fib_sync; /* is FIB synced with kernel? */
+};
+
+struct kroute_full {
+ struct bgpd_addr prefix;
+ struct bgpd_addr nexthop;
+ char label[RTLABEL_LEN];
+ u_int16_t flags;
+ u_short ifindex;
+ u_int8_t prefixlen;
+ u_int8_t priority;
+};
+
struct kroute {
struct in_addr prefix;
struct in_addr nexthop;
+ u_int32_t mplslabel;
u_int16_t flags;
u_int16_t labelid;
u_short ifindex;
@@ -400,14 +521,12 @@ struct kroute6 {
};
struct kroute_nexthop {
- union {
- struct kroute kr4;
- struct kroute6 kr6;
- } kr;
struct bgpd_addr nexthop;
struct bgpd_addr gateway;
+ struct bgpd_addr net;
u_int8_t valid;
u_int8_t connected;
+ u_int8_t netlen;
};
struct kif {
@@ -423,8 +542,7 @@ struct kif {
struct session_up {
struct bgpd_addr local_addr;
struct bgpd_addr remote_addr;
- struct capabilities capa_announced;
- struct capabilities capa_received;
+ struct capabilities capa;
u_int32_t remote_bgpid;
u_int16_t short_as;
};
@@ -437,8 +555,13 @@ struct pftable_msg {
struct ctl_show_nexthop {
struct bgpd_addr addr;
- u_int8_t valid;
struct kif kif;
+ union {
+ struct kroute kr4;
+ struct kroute6 kr6;
+ } kr;
+ u_int8_t valid;
+ u_int8_t krvalid;
};
struct ctl_neighbor {
@@ -447,20 +570,11 @@ struct ctl_neighbor {
int show_timers;
};
-struct kroute_label {
- struct kroute kr;
- char label[RTLABEL_LEN];
-};
-
-struct kroute6_label {
- struct kroute6 kr;
- char label[RTLABEL_LEN];
-};
-
-#define F_RIB_ELIGIBLE 0x01
-#define F_RIB_ACTIVE 0x02
-#define F_RIB_INTERNAL 0x04
-#define F_RIB_ANNOUNCE 0x08
+#define F_PREF_ELIGIBLE 0x01
+#define F_PREF_ACTIVE 0x02
+#define F_PREF_INTERNAL 0x04
+#define F_PREF_ANNOUNCE 0x08
+#define F_PREF_STALE 0x10
struct ctl_show_rib {
struct bgpd_addr true_nexthop;
@@ -472,9 +586,7 @@ struct ctl_show_rib {
u_int32_t remote_id;
u_int32_t local_pref;
u_int32_t med;
- u_int32_t prefix_cnt;
- u_int32_t active_cnt;
- u_int32_t rib_cnt;
+ u_int32_t weight;
u_int16_t aspath_len;
u_int16_t flags;
u_int8_t prefixlen;
@@ -482,13 +594,6 @@ struct ctl_show_rib {
/* plus a aspath_len bytes long aspath */
};
-struct ctl_show_rib_prefix {
- struct bgpd_addr prefix;
- time_t lastchange;
- u_int16_t flags;
- u_int8_t prefixlen;
-};
-
enum as_spec {
AS_NONE,
AS_ALL,
@@ -498,16 +603,52 @@ enum as_spec {
AS_EMPTY
};
+enum aslen_spec {
+ ASLEN_NONE,
+ ASLEN_MAX,
+ ASLEN_SEQ
+};
+
struct filter_as {
- enum as_spec type;
u_int32_t as;
+ u_int16_t flags;
+ enum as_spec type;
};
+struct filter_aslen {
+ u_int aslen;
+ enum aslen_spec type;
+};
+
+#define AS_FLAG_NEIGHBORAS 0x01
+
struct filter_community {
- int as;
- int type;
+ int as;
+ int type;
};
+struct filter_extcommunity {
+ u_int16_t flags;
+ u_int8_t type;
+ u_int8_t subtype; /* if extended type */
+ union {
+ struct ext_as {
+ u_int16_t as;
+ u_int32_t val;
+ } ext_as;
+ struct ext_as4 {
+ u_int32_t as4;
+ u_int16_t val;
+ } ext_as4;
+ struct ext_ip {
+ struct in_addr addr;
+ u_int16_t val;
+ } ext_ip;
+ u_int64_t ext_opaq; /* only 48 bits */
+ } data;
+};
+
+
struct ctl_show_rib_request {
char rib[PEER_DESCR_LEN];
struct ctl_neighbor neighbor;
@@ -518,8 +659,8 @@ struct ctl_show_rib_request {
pid_t pid;
u_int16_t flags;
enum imsg_type type;
- sa_family_t af;
u_int8_t prefixlen;
+ u_int8_t aid;
};
enum filter_actions {
@@ -585,6 +726,28 @@ struct filter_peers {
#define EXT_COMMUNITY_OSPF_RTR_TYPE 6 /* RFC 4577 */
#define EXT_COMMUNITY_OSPF_RTR_ID 7 /* RFC 4577 */
#define EXT_COMMUNITY_BGP_COLLECT 8 /* RFC 4384 */
+/* other handy defines */
+#define EXT_COMMUNITY_OPAQUE_MAX 0xffffffffffffULL
+#define EXT_COMMUNITY_FLAG_VALID 0x01
+
+struct ext_comm_pairs {
+ u_int8_t type;
+ u_int8_t subtype;
+ u_int8_t transitive; /* transitive bit needs to be set */
+};
+
+#define IANA_EXT_COMMUNITIES { \
+ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_ROUTE_TGT, 0 }, \
+ { EXT_COMMUNITY_TWO_AS, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \
+ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_OSPF_DOM_ID, 0 }, \
+ { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_BGP_COLLECT, 0 }, \
+ { EXT_COMMUNITY_FOUR_AS, EXT_COMMUNITY_ROUTE_TGT, 0 }, \
+ { EXT_COMMUNITY_FOUR_AS, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \
+ { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_TGT, 0 }, \
+ { EXT_COMMUNITY_IPV4, EXT_CUMMUNITY_ROUTE_ORIG, 0 }, \
+ { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_OSPF_RTR_ID, 0 }, \
+ { EXT_COMMUNITY_OPAQUE, EXT_COMMUNITY_OSPF_RTR_TYPE, 0 } \
+}
struct filter_prefix {
@@ -592,18 +755,28 @@ struct filter_prefix {
u_int8_t len;
};
+struct filter_nexthop {
+ struct bgpd_addr addr;
+ u_int8_t flags;
+#define FILTER_NEXTHOP_ADDR 1
+#define FILTER_NEXTHOP_NEIGHBOR 2
+};
+
struct filter_prefixlen {
enum comp_ops op;
- sa_family_t af;
+ u_int8_t aid;
u_int8_t len_min;
u_int8_t len_max;
};
struct filter_match {
- struct filter_prefix prefix;
- struct filter_prefixlen prefixlen;
- struct filter_as as;
- struct filter_community community;
+ struct filter_prefix prefix;
+ struct filter_prefixlen prefixlen;
+ struct filter_nexthop nexthop;
+ struct filter_as as;
+ struct filter_aslen aslen;
+ struct filter_community community;
+ struct filter_extcommunity ext_community;
};
TAILQ_HEAD(filter_head, filter_rule);
@@ -635,10 +808,13 @@ enum action_types {
ACTION_SET_NEXTHOP_SELF,
ACTION_SET_COMMUNITY,
ACTION_DEL_COMMUNITY,
+ ACTION_SET_EXT_COMMUNITY,
+ ACTION_DEL_EXT_COMMUNITY,
ACTION_PFTABLE,
ACTION_PFTABLE_ID,
ACTION_RTLABEL,
- ACTION_RTLABEL_ID
+ ACTION_RTLABEL_ID,
+ ACTION_SET_ORIGIN
};
struct filter_set {
@@ -650,23 +826,53 @@ struct filter_set {
int32_t relative;
struct bgpd_addr nexthop;
struct filter_community community;
+ struct filter_extcommunity ext_community;
char pftable[PFTABLE_LEN];
char rtlabel[RTLABEL_LEN];
+ u_int8_t origin;
} action;
enum action_types type;
};
-struct rrefresh {
- u_int16_t afi;
- u_int8_t safi;
+struct rdomain {
+ SIMPLEQ_ENTRY(rdomain) entry;
+ char descr[PEER_DESCR_LEN];
+ char ifmpe[IFNAMSIZ];
+ struct filter_set_head import;
+ struct filter_set_head export;
+ struct network_head net_l;
+ u_int64_t rd;
+ u_int rtableid;
+ u_int label;
+ int flags;
};
+SIMPLEQ_HEAD(rdomain_head, rdomain);
+
+struct rde_rib {
+ SIMPLEQ_ENTRY(rde_rib) entry;
+ char name[PEER_DESCR_LEN];
+ u_int rtableid;
+ u_int16_t id;
+ u_int16_t flags;
+};
+SIMPLEQ_HEAD(rib_names, rde_rib);
+extern struct rib_names ribnames;
+
+/* rde_rib flags */
+#define F_RIB_ENTRYLOCK 0x0001
+#define F_RIB_NOEVALUATE 0x0002
+#define F_RIB_NOFIB 0x0004
+#define F_RIB_NOFIBSYNC 0x0008
+#define F_RIB_HASNOFIB (F_RIB_NOFIB | F_RIB_NOEVALUATE)
+
+/* 4-byte magic AS number */
+#define AS_TRANS 23456
struct rde_memstats {
int64_t path_cnt;
int64_t prefix_cnt;
int64_t rib_cnt;
- int64_t pt4_cnt;
- int64_t pt6_cnt;
+ int64_t pt_cnt[AID_MAX];
int64_t nexthop_cnt;
int64_t aspath_cnt;
int64_t aspath_size;
@@ -677,82 +883,117 @@ struct rde_memstats {
int64_t attr_dcnt;
};
-struct rde_rib {
- SIMPLEQ_ENTRY(rde_rib) entry;
- char name[PEER_DESCR_LEN];
- u_int16_t id;
- u_int16_t flags;
+/* macros for IPv6 link-local address */
+#ifdef __KAME__
+#define IN6_LINKLOCAL_IFINDEX(addr) \
+ ((addr).s6_addr[2] << 8 | (addr).s6_addr[3])
+
+#define SET_IN6_LINKLOCAL_IFINDEX(addr, index) \
+ do { \
+ (addr).s6_addr[2] = ((index) >> 8) & 0xff; \
+ (addr).s6_addr[3] = (index) & 0xff; \
+ } while (0)
+#endif
+
+#define MRT_FILE_LEN 512
+#define MRT2MC(x) ((struct mrt_config *)(x))
+#define MRT_MAX_TIMEOUT 7200
+
+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,
+ MRT_UPDATE_OUT
+};
+
+enum mrt_state {
+ MRT_STATE_RUNNING,
+ MRT_STATE_OPEN,
+ MRT_STATE_REOPEN,
+ MRT_STATE_REMOVE
};
-SIMPLEQ_HEAD(rib_names, rde_rib);
-extern struct rib_names ribnames;
-/* Address Family Numbers as per RFC 1700 */
-#define AFI_IPv4 1
-#define AFI_IPv6 2
-#define AFI_ALL 0xffff
-
-/* Subsequent Address Family Identifier as per RFC 4760 */
-#define SAFI_NONE 0x00
-#define SAFI_UNICAST 0x01
-#define SAFI_MULTICAST 0x02
-#define SAFI_ALL 0xff
+struct mrt {
+ char rib[PEER_DESCR_LEN];
+ struct msgbuf wbuf;
+ LIST_ENTRY(mrt) entry;
+ u_int32_t peer_id;
+ u_int32_t group_id;
+ enum mrt_type type;
+ enum mrt_state state;
+ u_int16_t seqnum;
+};
-/* 4-byte magic AS number */
-#define AS_TRANS 23456
+struct mrt_config {
+ struct mrt conf;
+ char name[MRT_FILE_LEN]; /* base file name */
+ char file[MRT_FILE_LEN]; /* actual file name */
+ time_t ReopenTimer;
+ time_t ReopenTimerInterval;
+};
/* prototypes */
/* bgpd.c */
void send_nexthop_update(struct kroute_nexthop *);
void send_imsg_session(int, pid_t, void *, u_int16_t);
-int bgpd_redistribute(int, struct kroute *, struct kroute6 *);
+int send_network(int, struct network_config *,
+ struct filter_set_head *);
int bgpd_filternexthop(struct kroute *, struct kroute6 *);
-/* log.c */
-void log_init(int);
-void vlog(int, const char *, va_list);
-void log_peer_warn(const struct peer_config *, const char *, ...);
-void log_peer_warnx(const struct peer_config *, const char *, ...);
-void log_warn(const char *, ...);
-void log_warnx(const char *, ...);
-void log_info(const char *, ...);
-void log_debug(const char *, ...);
-void fatal(const char *) __dead;
-void fatalx(const char *) __dead;
-
-/* parse.y */
-int cmdline_symset(char *);
+/* control.c */
+void control_cleanup(const char *);
+int control_imsg_relay(struct imsg *);
/* config.c */
int host(const char *, struct bgpd_addr *, u_int8_t *);
/* kroute.c */
-int kr_init(int, u_int);
-int kr_change(struct kroute_label *);
-int kr_delete(struct kroute_label *);
-int kr6_change(struct kroute6_label *);
-int kr6_delete(struct kroute6_label *);
+int kr_init(void);
+int ktable_update(u_int, char *, char *, int);
+void ktable_preload(void);
+void ktable_postload(void);
+int ktable_exists(u_int, u_int *);
+int kr_change(u_int, struct kroute_full *);
+int kr_delete(u_int, struct kroute_full *);
void kr_shutdown(void);
-void kr_fib_couple(void);
-void kr_fib_decouple(void);
+void kr_fib_couple(u_int);
+void kr_fib_decouple(u_int);
int kr_dispatch_msg(void);
-int kr_nexthop_add(struct bgpd_addr *);
-void kr_nexthop_delete(struct bgpd_addr *);
+int kr_nexthop_add(u_int32_t, struct bgpd_addr *);
+void kr_nexthop_delete(u_int32_t, struct bgpd_addr *);
void kr_show_route(struct imsg *);
void kr_ifinfo(char *);
+int kr_net_reload(u_int, struct network_head *);
int kr_reload(void);
struct in6_addr *prefixlen2mask6(u_int8_t prefixlen);
-/* control.c */
-void control_cleanup(const char *);
-int control_imsg_relay(struct imsg *);
+/* log.c */
+void log_init(int);
+void log_verbose(int);
+void vlog(int, const char *, va_list);
+void log_peer_warn(const struct peer_config *, const char *, ...);
+void log_peer_warnx(const struct peer_config *, const char *, ...);
+void log_warn(const char *, ...);
+void log_warnx(const char *, ...);
+void log_info(const char *, ...);
+void log_debug(const char *, ...);
+void fatal(const char *) __dead;
+void fatalx(const char *) __dead;
-/* pftable.c */
-int pftable_exists(const char *);
-int pftable_add(const char *);
-int pftable_clear_all(void);
-int pftable_addr_add(struct pftable_msg *);
-int pftable_addr_remove(struct pftable_msg *);
-int pftable_commit(void);
+/* mrt.c */
+void mrt_clear_seq(void);
+void mrt_write(struct mrt *);
+void mrt_clean(struct mrt *);
+void mrt_init(struct imsgbuf *, struct imsgbuf *);
+int mrt_timeout(struct mrt_head *);
+void mrt_reconfigure(struct mrt_head *);
+void mrt_handler(struct mrt_head *);
+struct mrt *mrt_get(struct mrt_head *, struct mrt *);
+int mrt_mergeconfig(struct mrt_head *, struct mrt_head *);
/* name2id.c */
u_int16_t rib_name2id(const char *);
@@ -768,10 +1009,22 @@ const char *pftable_id2name(u_int16_t);
void pftable_unref(u_int16_t);
void pftable_ref(u_int16_t);
+/* parse.y */
+int cmdline_symset(char *);
+
+/* pftable.c */
+int pftable_exists(const char *);
+int pftable_add(const char *);
+int pftable_clear_all(void);
+int pftable_addr_add(struct pftable_msg *);
+int pftable_addr_remove(struct pftable_msg *);
+int pftable_commit(void);
/* rde_filter.c */
void filterset_free(struct filter_set_head *);
int filterset_cmp(struct filter_set *, struct filter_set *);
+void filterset_move(struct filter_set_head *,
+ struct filter_set_head *);
const char *filterset_name(enum action_types);
/* util.c */
@@ -779,11 +1032,24 @@ const char *log_addr(const struct bgpd_a
const char *log_in6addr(const struct in6_addr *);
const char *log_sockaddr(struct sockaddr *);
const char *log_as(u_int32_t);
+const char *log_rd(u_int64_t);
+const char *log_ext_subtype(u_int8_t);
int aspath_snprint(char *, size_t, void *, u_int16_t);
int aspath_asprint(char **, void *, u_int16_t);
size_t aspath_strlen(void *, u_int16_t);
+int aspath_match(void *, u_int16_t, enum as_spec, u_int32_t);
+u_int32_t aspath_extract(const void *, int);
+int prefix_compare(const struct bgpd_addr *,
+ const struct bgpd_addr *, int);
in_addr_t prefixlen2mask(u_int8_t);
void inet6applymask(struct in6_addr *, const struct in6_addr *,
int);
+const char *aid2str(u_int8_t);
+int aid2afi(u_int8_t, u_int16_t *, u_int8_t *);
+int afi2aid(u_int16_t, u_int8_t, u_int8_t *);
+sa_family_t aid2af(u_int8_t);
+int af2aid(sa_family_t, u_int8_t, u_int8_t *);
+struct sockaddr *addr2sa(struct bgpd_addr *, u_int16_t);
+void sa2addr(struct sockaddr *, struct bgpd_addr *);
#endif /* __BGPD_H__ */

View File

@ -0,0 +1,104 @@
Index: bgpd/buffer.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/buffer.c,v
retrieving revision 1.1.1.7
retrieving revision 1.3
diff -u -p -r1.1.1.7 -r1.3
--- bgpd/buffer.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/buffer.c 8 Dec 2012 20:17:59 -0000 1.3
@@ -1,4 +1,4 @@
-/* $OpenBSD: buffer.c,v 1.43 2009/06/06 06:33:15 eric Exp $ */
+/* $OpenBSD: buffer.c,v 1.44 2009/07/23 18:58:42 eric Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -144,7 +144,7 @@ int
buf_write(struct msgbuf *msgbuf)
{
struct iovec iov[IOV_MAX];
- struct buf *buf, *next;
+ struct buf *buf;
unsigned int i = 0;
ssize_t n;
@@ -153,7 +153,7 @@ buf_write(struct msgbuf *msgbuf)
if (i >= IOV_MAX)
break;
iov[i].iov_base = buf->buf + buf->rpos;
- iov[i].iov_len = buf->size - buf->rpos;
+ iov[i].iov_len = buf->wpos - buf->rpos;
i++;
}
@@ -170,17 +170,7 @@ buf_write(struct msgbuf *msgbuf)
return (-2);
}
- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
- buf = next) {
- next = TAILQ_NEXT(buf, entry);
- if (buf->rpos + n >= buf->size) {
- n -= buf->size - buf->rpos;
- buf_dequeue(msgbuf, buf);
- } else {
- buf->rpos += n;
- n = 0;
- }
- }
+ msgbuf_drain(msgbuf, n);
return (0);
}
@@ -201,6 +191,24 @@ msgbuf_init(struct msgbuf *msgbuf)
}
void
+msgbuf_drain(struct msgbuf *msgbuf, size_t n)
+{
+ struct buf *buf, *next;
+
+ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
+ buf = next) {
+ next = TAILQ_NEXT(buf, entry);
+ if (buf->rpos + n >= buf->wpos) {
+ n -= buf->wpos - buf->rpos;
+ buf_dequeue(msgbuf, buf);
+ } else {
+ buf->rpos += n;
+ n = 0;
+ }
+ }
+}
+
+void
msgbuf_clear(struct msgbuf *msgbuf)
{
struct buf *buf;
@@ -213,7 +221,7 @@ int
msgbuf_write(struct msgbuf *msgbuf)
{
struct iovec iov[IOV_MAX];
- struct buf *buf, *next;
+ struct buf *buf;
unsigned int i = 0;
ssize_t n;
struct msghdr msg;
@@ -270,17 +278,7 @@ msgbuf_write(struct msgbuf *msgbuf)
buf->fd = -1;
}
- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
- buf = next) {
- next = TAILQ_NEXT(buf, entry);
- if (buf->rpos + n >= buf->wpos) {
- n -= buf->wpos - buf->rpos;
- buf_dequeue(msgbuf, buf);
- } else {
- buf->rpos += n;
- n = 0;
- }
- }
+ msgbuf_drain(msgbuf, n);
return (0);
}

View File

@ -0,0 +1,54 @@
Index: bgpd/carp.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/carp.c,v
retrieving revision 1.1.1.6
retrieving revision 1.4
diff -u -p -r1.1.1.6 -r1.4
--- bgpd/carp.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
+++ bgpd/carp.c 22 Oct 2009 15:10:02 -0000 1.4
@@ -93,9 +93,8 @@ carp_demote_shutdown(void)
while ((c = TAILQ_FIRST(&carpgroups)) != NULL) {
TAILQ_REMOVE(&carpgroups, c, entry);
- for (; c->changed_by > 0; c->changed_by--)
- if (c->do_demote)
- carp_demote_ioctl(c->group, -1);
+ if (c->do_demote && c->changed_by > 0)
+ carp_demote_ioctl(c->group, -c->changed_by);
free(c->group);
free(c);
@@ -105,6 +104,9 @@ carp_demote_shutdown(void)
int
carp_demote_get(char *group)
{
+#if defined(__FreeBSD__) /* FreeBSD does not have support for CARP */
+ return (-1);
+#else
int s;
struct ifgroupreq ifgr;
@@ -127,6 +129,7 @@ carp_demote_get(char *group)
close(s);
return ((int)ifgr.ifgr_attrib.ifg_carp_demoted);
+#endif /* defined(__FreeBSD__) */
}
int
@@ -159,6 +162,9 @@ carp_demote_set(char *group, int demote)
int
carp_demote_ioctl(char *group, int demote)
{
+#if defined(__FreeBSD__) /* FreeBSD does not have support for CARP */
+ return (-1);
+#else
int s, res;
struct ifgroupreq ifgr;
@@ -181,4 +187,5 @@ carp_demote_ioctl(char *group, int demot
close(s);
return (res);
+#endif /* defined(__FreeBSD__) */
}

View File

@ -0,0 +1,109 @@
Index: bgpd/config.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/config.c,v
retrieving revision 1.1.1.6
retrieving revision 1.3
diff -u -p -r1.1.1.6 -r1.3
--- bgpd/config.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
+++ bgpd/config.c 13 Oct 2012 18:36:00 -0000 1.3
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.51 2009/01/26 23:10:02 claudio Exp $ */
+/* $OpenBSD: config.c,v 1.55 2010/09/02 14:03:21 sobrado Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -20,6 +20,11 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */
+#include <netmpls/mpls.h>
+#endif
#include <errno.h>
#include <ifaddrs.h>
@@ -47,8 +52,6 @@ merge_config(struct bgpd_config *xconf,
/* preserve cmd line opts */
conf->opts = xconf->opts;
- conf->csock = xconf->csock;
- conf->rcsock = xconf->rcsock;
if (!conf->as) {
log_warnx("configuration error: AS not given");
@@ -64,6 +67,9 @@ merge_config(struct bgpd_config *xconf,
if ((conf->flags & BGPD_FLAG_REFLECTOR) && conf->clusterid == 0)
conf->clusterid = conf->bgpid;
+ free(xconf->csock);
+ free(xconf->rcsock);
+
conf->listen_addrs = xconf->listen_addrs;
memcpy(xconf, conf, sizeof(struct bgpd_config));
@@ -74,7 +80,7 @@ merge_config(struct bgpd_config *xconf,
nla->reconf = RECONF_REINIT;
} else {
- /*
+ /*
* merge new listeners:
* -flag all existing ones as to be deleted
* -those that are in both new and old: flag to keep
@@ -208,7 +214,7 @@ host_v4(const char *s, struct bgpd_addr
return (0);
}
- h->af = AF_INET;
+ h->aid = AID_INET;
h->v4.s_addr = ina.s_addr;
*len = bits;
@@ -225,13 +231,7 @@ host_v6(const char *s, struct bgpd_addr
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(s, "0", &hints, &res) == 0) {
- h->af = AF_INET6;
- memcpy(&h->v6,
- &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
- sizeof(h->v6));
- h->scope_id =
- ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
-
+ sa2addr(res->ai_addr, h);
freeaddrinfo(res);
return (1);
}
@@ -317,3 +317,30 @@ prepare_listeners(struct bgpd_config *co
}
}
}
+
+int
+get_mpe_label(struct rdomain *r)
+{
+#if !defined(__FreeBSD__) /* FreeBSD has no mpls support. */
+ struct ifreq ifr;
+ struct shim_hdr shim;
+ int s;
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s == -1)
+ return (-1);
+
+ bzero(&shim, sizeof(shim));
+ bzero(&ifr, sizeof(ifr));
+ strlcpy(ifr.ifr_name, r->ifmpe, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)&shim;
+
+ if (ioctl(s, SIOCGETLABEL, (caddr_t)&ifr) == -1) {
+ close(s);
+ return (-1);
+ }
+ close(s);
+ r->label = shim.shim_label;
+#endif
+ return (0);
+}

View File

@ -0,0 +1,171 @@
Index: bgpd/control.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/control.c,v
retrieving revision 1.1.1.7
retrieving revision 1.1.1.10
diff -u -p -r1.1.1.7 -r1.1.1.10
--- bgpd/control.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/control.c 13 Oct 2012 18:22:41 -0000 1.1.1.10
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.61 2009/05/05 20:09:19 sthen Exp $ */
+/* $OpenBSD: control.c,v 1.71 2012/04/12 17:26:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -53,7 +53,7 @@ control_init(int restricted, char *path)
if (unlink(path) == -1)
if (errno != ENOENT) {
- log_warn("unlink %s", path);
+ log_warn("control_init: unlink %s", path);
close(fd);
return (-1);
}
@@ -122,15 +122,18 @@ control_accept(int listenfd, int restric
len = sizeof(sun);
if ((connfd = accept(listenfd,
(struct sockaddr *)&sun, &len)) == -1) {
- if (errno != EWOULDBLOCK && errno != EINTR)
- log_warn("session_control_accept");
+ if (errno == ENFILE || errno == EMFILE) {
+ pauseaccept = getmonotime();
+ return (0);
+ } else if (errno != EWOULDBLOCK && errno != EINTR)
+ log_warn("control_accept: accept");
return (0);
}
session_socket_blockmode(connfd, BM_NONBLOCK);
- if ((ctl_conn = malloc(sizeof(struct ctl_conn))) == NULL) {
- log_warn("session_control_accept");
+ if ((ctl_conn = calloc(1, sizeof(struct ctl_conn))) == NULL) {
+ log_warn("control_accept");
close(connfd);
return (0);
}
@@ -182,7 +185,7 @@ control_close(int fd)
close(c->ibuf.fd);
free(c);
-
+ pauseaccept = 0;
return (1);
}
@@ -191,7 +194,8 @@ control_dispatch_msg(struct pollfd *pfd,
{
struct imsg imsg;
struct ctl_conn *c;
- int n;
+ ssize_t n;
+ int verbose;
struct peer *p;
struct ctl_neighbor *neighbor;
struct ctl_show_rib_request *ribreq;
@@ -305,7 +309,8 @@ control_dispatch_msg(struct pollfd *pfd,
break;
case IMSG_CTL_FIB_COUPLE:
case IMSG_CTL_FIB_DECOUPLE:
- imsg_compose_parent(imsg.hdr.type, 0, NULL, 0);
+ imsg_compose_parent(imsg.hdr.type, imsg.hdr.peerid,
+ 0, NULL, 0);
break;
case IMSG_CTL_NEIGHBOR_UP:
case IMSG_CTL_NEIGHBOR_DOWN:
@@ -328,13 +333,19 @@ control_dispatch_msg(struct pollfd *pfd,
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_DOWN:
- bgp_fsm(p, EVNT_STOP);
+ session_stop(p, ERR_CEASE_ADMIN_DOWN);
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_CLEAR:
- bgp_fsm(p, EVNT_STOP);
- timer_set(p, Timer_IdleHold,
- SESSION_CLEAR_DELAY);
+ if (!p->conf.down) {
+ session_stop(p,
+ ERR_CEASE_ADMIN_RESET);
+ timer_set(p, Timer_IdleHold,
+ SESSION_CLEAR_DELAY);
+ } else {
+ session_stop(p,
+ ERR_CEASE_ADMIN_DOWN);
+ }
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_RREFRESH:
@@ -352,13 +363,19 @@ control_dispatch_msg(struct pollfd *pfd,
"wrong length");
break;
case IMSG_CTL_RELOAD:
+ case IMSG_CTL_SHOW_INTERFACE:
+ case IMSG_CTL_SHOW_FIB_TABLES:
+ c->ibuf.pid = imsg.hdr.pid;
+ imsg_compose_parent(imsg.hdr.type, 0, imsg.hdr.pid,
+ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
+ break;
case IMSG_CTL_KROUTE:
case IMSG_CTL_KROUTE_ADDR:
case IMSG_CTL_SHOW_NEXTHOP:
- case IMSG_CTL_SHOW_INTERFACE:
c->ibuf.pid = imsg.hdr.pid;
- imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
+ imsg_compose_parent(imsg.hdr.type, imsg.hdr.peerid,
+ imsg.hdr.pid, imsg.data, imsg.hdr.len -
+ IMSG_HEADER_SIZE);
break;
case IMSG_CTL_SHOW_RIB:
case IMSG_CTL_SHOW_RIB_AS:
@@ -370,7 +387,7 @@ control_dispatch_msg(struct pollfd *pfd,
neighbor->descr[PEER_DESCR_LEN - 1] = 0;
ribreq->peerid = 0;
p = NULL;
- if (neighbor->addr.af) {
+ if (neighbor->addr.aid) {
p = getpeerbyaddr(&neighbor->addr);
if (p == NULL) {
control_result(c,
@@ -397,8 +414,7 @@ control_dispatch_msg(struct pollfd *pfd,
break;
}
if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX)
- && (ribreq->prefix.af != AF_INET)
- && (ribreq->prefix.af != AF_INET6)) {
+ && (ribreq->prefix.aid == AID_UNSPEC)) {
/* malformed request, must specify af */
control_result(c, CTL_RES_PARSE_ERROR);
break;
@@ -418,6 +434,8 @@ control_dispatch_msg(struct pollfd *pfd,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
break;
case IMSG_NETWORK_ADD:
+ case IMSG_NETWORK_ASPATH:
+ case IMSG_NETWORK_ATTR:
case IMSG_NETWORK_REMOVE:
case IMSG_NETWORK_FLUSH:
case IMSG_NETWORK_DONE:
@@ -425,6 +443,20 @@ control_dispatch_msg(struct pollfd *pfd,
imsg_compose_rde(imsg.hdr.type, 0,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
break;
+ case IMSG_CTL_LOG_VERBOSE:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(verbose))
+ break;
+
+ /* forward to other processes */
+ imsg_compose_parent(imsg.hdr.type, 0, imsg.hdr.pid,
+ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
+ imsg_compose_rde(imsg.hdr.type, 0,
+ imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
+
+ memcpy(&verbose, imsg.data, sizeof(verbose));
+ log_verbose(verbose);
+ break;
default:
break;
}

View File

@ -0,0 +1,275 @@
Index: bgpd/imsg.c
===================================================================
RCS file: bgpd/imsg.c
diff -N bgpd/imsg.c
--- bgpd/imsg.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,268 +0,0 @@
-/* $OpenBSD: imsg.c,v 1.47 2009/06/08 08:30:06 dlg Exp $ */
-
-/*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "imsg.h"
-
-int imsg_get_fd(struct imsgbuf *);
-
-void
-imsg_init(struct imsgbuf *ibuf, int fd)
-{
- msgbuf_init(&ibuf->w);
- bzero(&ibuf->r, sizeof(ibuf->r));
- ibuf->fd = fd;
- ibuf->w.fd = fd;
- ibuf->pid = getpid();
- TAILQ_INIT(&ibuf->fds);
-}
-
-ssize_t
-imsg_read(struct imsgbuf *ibuf)
-{
- struct msghdr msg;
- struct cmsghdr *cmsg;
- union {
- struct cmsghdr hdr;
- char buf[CMSG_SPACE(sizeof(int) * 16)];
- } cmsgbuf;
- struct iovec iov;
- ssize_t n;
- int fd;
- struct imsg_fd *ifd;
-
- bzero(&msg, sizeof(msg));
-
- iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
- iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = &cmsgbuf.buf;
- msg.msg_controllen = sizeof(cmsgbuf.buf);
-
- if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
- if (errno != EINTR && errno != EAGAIN) {
- return (-1);
- }
- return (-2);
- }
-
- ibuf->r.wpos += n;
-
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- fd = (*(int *)CMSG_DATA(cmsg));
- if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) {
- /* XXX: this return can leak */
- return (-1);
- }
- ifd->fd = fd;
- TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry);
- }
- /* we do not handle other ctl data level */
- }
-
- return (n);
-}
-
-ssize_t
-imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
-{
- size_t av, left, datalen;
-
- av = ibuf->r.wpos;
-
- if (IMSG_HEADER_SIZE > av)
- return (0);
-
- memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
- if (imsg->hdr.len < IMSG_HEADER_SIZE ||
- imsg->hdr.len > MAX_IMSGSIZE) {
- errno = ERANGE;
- return (-1);
- }
- if (imsg->hdr.len > av)
- return (0);
- datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
- ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
- if ((imsg->data = malloc(datalen)) == NULL)
- return (-1);
-
- if (imsg->hdr.flags & IMSGF_HASFD)
- imsg->fd = imsg_get_fd(ibuf);
- else
- imsg->fd = -1;
-
- memcpy(imsg->data, ibuf->r.rptr, datalen);
-
- if (imsg->hdr.len < av) {
- left = av - imsg->hdr.len;
- memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
- ibuf->r.wpos = left;
- } else
- ibuf->r.wpos = 0;
-
- return (datalen + IMSG_HEADER_SIZE);
-}
-
-int
-imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
- pid_t pid, int fd, void *data, u_int16_t datalen)
-{
- struct buf *wbuf;
-
- if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
- return (-1);
-
- if (imsg_add(wbuf, data, datalen) == -1)
- return (-1);
-
- wbuf->fd = fd;
-
- imsg_close(ibuf, wbuf);
-
- return (1);
-}
-
-int
-imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
- pid_t pid, int fd, const struct iovec *iov, int iovcnt)
-{
- struct buf *wbuf;
- int i, datalen = 0;
-
- for (i = 0; i < iovcnt; i++)
- datalen += iov[i].iov_len;
-
- if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
- return (-1);
-
- for (i = 0; i < iovcnt; i++)
- if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
- return (-1);
-
- wbuf->fd = fd;
-
- imsg_close(ibuf, wbuf);
-
- return (1);
-}
-
-/* ARGSUSED */
-struct buf *
-imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
- pid_t pid, u_int16_t datalen)
-{
- struct buf *wbuf;
- struct imsg_hdr hdr;
-
- datalen += IMSG_HEADER_SIZE;
- if (datalen > MAX_IMSGSIZE) {
- errno = ERANGE;
- return (NULL);
- }
-
- hdr.type = type;
- hdr.flags = 0;
- hdr.peerid = peerid;
- if ((hdr.pid = pid) == 0)
- hdr.pid = ibuf->pid;
- if ((wbuf = buf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
- return (NULL);
- }
- if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
- return (NULL);
-
- return (wbuf);
-}
-
-int
-imsg_add(struct buf *msg, void *data, u_int16_t datalen)
-{
- if (datalen)
- if (buf_add(msg, data, datalen) == -1) {
- buf_free(msg);
- return (-1);
- }
- return (datalen);
-}
-
-void
-imsg_close(struct imsgbuf *ibuf, struct buf *msg)
-{
- struct imsg_hdr *hdr;
-
- hdr = (struct imsg_hdr *)msg->buf;
-
- hdr->flags &= ~IMSGF_HASFD;
- if (msg->fd != -1)
- hdr->flags |= IMSGF_HASFD;
-
- hdr->len = (u_int16_t)msg->wpos;
-
- buf_close(&ibuf->w, msg);
-}
-
-void
-imsg_free(struct imsg *imsg)
-{
- free(imsg->data);
-}
-
-int
-imsg_get_fd(struct imsgbuf *ibuf)
-{
- int fd;
- struct imsg_fd *ifd;
-
- if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
- return (-1);
-
- fd = ifd->fd;
- TAILQ_REMOVE(&ibuf->fds, ifd, entry);
- free(ifd);
-
- return (fd);
-}
-
-int
-imsg_flush(struct imsgbuf *ibuf)
-{
- while (ibuf->w.queued)
- if (msgbuf_write(&ibuf->w) < 0)
- return (-1);
- return (0);
-}
-
-void
-imsg_clear(struct imsgbuf *ibuf)
-{
- while (ibuf->w.queued)
- msgbuf_clear(&ibuf->w);
-}

View File

@ -0,0 +1,115 @@
Index: bgpd/imsg.h
===================================================================
RCS file: bgpd/imsg.h
diff -N bgpd/imsg.h
--- bgpd/imsg.h 14 Feb 2010 20:19:57 -0000 1.1.1.5
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,108 +0,0 @@
-/* $OpenBSD: imsg.h,v 1.3 2009/06/07 05:56:24 eric Exp $ */
-
-/*
- * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
- * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/tree.h>
-
-#define READ_BUF_SIZE 65535
-#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
-#define MAX_IMSGSIZE 16384
-
-struct buf {
- TAILQ_ENTRY(buf) entry;
- u_char *buf;
- size_t size;
- size_t max;
- size_t wpos;
- size_t rpos;
- int fd;
-};
-
-struct msgbuf {
- TAILQ_HEAD(, buf) bufs;
- u_int32_t queued;
- int fd;
-};
-
-struct buf_read {
- u_char buf[READ_BUF_SIZE];
- u_char *rptr;
- size_t wpos;
-};
-
-struct imsg_fd {
- TAILQ_ENTRY(imsg_fd) entry;
- int fd;
-};
-
-struct imsgbuf {
- TAILQ_HEAD(, imsg_fd) fds;
- struct buf_read r;
- struct msgbuf w;
- int fd;
- pid_t pid;
-};
-
-#define IMSGF_HASFD 1
-
-struct imsg_hdr {
- u_int32_t type;
- u_int16_t len;
- u_int16_t flags;
- u_int32_t peerid;
- u_int32_t pid;
-};
-
-struct imsg {
- struct imsg_hdr hdr;
- int fd;
- void *data;
-};
-
-
-/* buffer.c */
-struct buf *buf_open(size_t);
-struct buf *buf_dynamic(size_t, size_t);
-int buf_add(struct buf *, const void *, size_t);
-void *buf_reserve(struct buf *, size_t);
-void *buf_seek(struct buf *, size_t, size_t);
-size_t buf_size(struct buf *);
-size_t buf_left(struct buf *);
-void buf_close(struct msgbuf *, struct buf *);
-int buf_write(struct msgbuf *);
-void buf_free(struct buf *);
-void msgbuf_init(struct msgbuf *);
-void msgbuf_clear(struct msgbuf *);
-int msgbuf_write(struct msgbuf *);
-
-/* imsg.c */
-void imsg_init(struct imsgbuf *, int);
-ssize_t imsg_read(struct imsgbuf *);
-ssize_t imsg_get(struct imsgbuf *, struct imsg *);
-int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
- int, void *, u_int16_t);
-int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
- int, const struct iovec *, int);
-struct buf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
- u_int16_t);
-int imsg_add(struct buf *, void *, u_int16_t);
-void imsg_close(struct imsgbuf *, struct buf *);
-void imsg_free(struct imsg *);
-int imsg_flush(struct imsgbuf *);
-void imsg_clear(struct imsgbuf *);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
Index: bgpd/log.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.c,v
retrieving revision 1.1.1.5
retrieving revision 1.1.1.8
diff -u -p -r1.1.1.5 -r1.1.1.8
--- bgpd/log.c 14 Feb 2010 20:19:57 -0000 1.1.1.5
+++ bgpd/log.c 13 Oct 2012 18:22:43 -0000 1.1.1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.50 2007/04/23 13:04:24 claudio Exp $ */
+/* $OpenBSD: log.c,v 1.55 2011/08/20 19:02:28 sthen Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -32,6 +32,7 @@
#include "log.h"
int debug;
+int verbose;
void logit(int, const char *, ...);
@@ -42,8 +43,9 @@ log_fmt_peer(const struct peer_config *p
char *pfmt, *p;
ip = log_addr(&peer->remote_addr);
- if ((peer->remote_addr.af == AF_INET && peer->remote_masklen != 32) ||
- (peer->remote_addr.af == AF_INET6 && peer->remote_masklen != 128)) {
+ if ((peer->remote_addr.aid == AID_INET && peer->remote_masklen != 32) ||
+ (peer->remote_addr.aid == AID_INET6 &&
+ peer->remote_masklen != 128)) {
if (asprintf(&p, "%s/%u", ip, peer->remote_masklen) == -1)
fatal(NULL);
} else {
@@ -77,6 +79,12 @@ log_init(int n_debug)
}
void
+log_verbose(int v)
+{
+ verbose = v;
+}
+
+void
logit(int pri, const char *fmt, ...)
{
va_list ap;
@@ -193,7 +201,7 @@ log_debug(const char *emsg, ...)
{
va_list ap;
- if (debug) {
+ if (verbose) {
va_start(ap, emsg);
vlog(LOG_DEBUG, emsg, ap);
va_end(ap);
@@ -250,7 +258,7 @@ log_statechange(struct peer *peer, enum
void
log_notification(const struct peer *peer, u_int8_t errcode, u_int8_t subcode,
- u_char *data, u_int16_t datalen)
+ u_char *data, u_int16_t datalen, const char *dir)
{
char *p;
const char *suberrname = NULL;
@@ -283,27 +291,31 @@ log_notification(const struct peer *peer
suberrname = suberr_cease_names[subcode];
break;
case ERR_HOLDTIMEREXPIRED:
- case ERR_FSM:
uk = 1;
break;
+ case ERR_FSM:
+ if (subcode >= sizeof(suberr_fsm_names)/sizeof(char *))
+ uk = 1;
+ else
+ suberrname = suberr_fsm_names[subcode];
+ break;
default:
- logit(LOG_CRIT, "%s: received notification, unknown errcode "
- "%u, subcode %u", p, errcode, subcode);
+ logit(LOG_CRIT, "%s: %s notification, unknown errcode "
+ "%u, subcode %u", p, dir, errcode, subcode);
free(p);
return;
}
if (uk)
- logit(LOG_CRIT,
- "%s: received notification: %s, unknown subcode %u",
- p, errnames[errcode], subcode);
+ logit(LOG_CRIT, "%s: %s notification: %s, unknown subcode %u",
+ p, dir, errnames[errcode], subcode);
else {
if (suberrname == NULL)
- logit(LOG_CRIT, "%s: received notification: %s",
- p, errnames[errcode]);
+ logit(LOG_CRIT, "%s: %s notification: %s", p,
+ dir, errnames[errcode]);
else
- logit(LOG_CRIT, "%s: received notification: %s, %s",
- p, errnames[errcode], suberrname);
+ logit(LOG_CRIT, "%s: %s notification: %s, %s",
+ p, dir, errnames[errcode], suberrname);
}
free(p);
}
@@ -318,6 +330,9 @@ log_conn_attempt(const struct peer *peer
b = log_sockaddr(sa);
logit(LOG_INFO, "connection from non-peer %s refused", b);
} else {
+ /* only log if there is a chance that the session may come up */
+ if (peer->conf.down && peer->state == STATE_IDLE)
+ return;
p = log_fmt_peer(&peer->conf);
logit(LOG_INFO, "Connection attempt from %s while session is "
"in state %s", p, statenames[peer->state]);

View File

@ -0,0 +1,39 @@
Index: bgpd/log.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/log.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.2 -r1.1.1.3
--- bgpd/log.h 9 Jul 2009 16:49:54 -0000 1.1.1.2
+++ bgpd/log.h 13 Oct 2012 18:22:43 -0000 1.1.1.3
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.h,v 1.11 2008/09/11 14:49:58 henning Exp $ */
+/* $OpenBSD: log.h,v 1.13 2012/06/10 11:16:08 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -71,6 +71,13 @@ static const char * const suberr_open_na
"unsupported capability"
};
+static const char * const suberr_fsm_names[] = {
+ "unspecified error",
+ "received unexpected message in OpenSent",
+ "received unexpected message in OpenConfirm",
+ "received unexpected message in Established"
+};
+
static const char * const suberr_update_names[] = {
"none",
"attribute list error",
@@ -109,7 +116,9 @@ static const char * const ctl_res_strerr
"no such neighbor",
"permission denied",
"neighbor does not have this capability",
- "config file has errors, reload failed"
+ "config file has errors, reload failed",
+ "previous reload still running",
+ "out of memory"
};
static const char * const timernames[] = {

View File

@ -0,0 +1,864 @@
Index: bgpd/mrt.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.c,v
retrieving revision 1.1.1.7
retrieving revision 1.1.1.11
diff -u -p -r1.1.1.7 -r1.1.1.11
--- bgpd/mrt.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/mrt.c 8 Dec 2012 10:37:09 -0000 1.1.1.11
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.c,v 1.63 2009/06/29 12:22:16 claudio Exp $ */
+/* $OpenBSD: mrt.c,v 1.72 2011/11/06 10:29:05 guenther Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -21,6 +21,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -32,20 +33,22 @@
#include "mrt.h"
-int mrt_attr_dump(struct buf *, 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_hdr_se(struct buf **, struct peer *, u_int16_t, u_int16_t,
+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 buf **, u_int16_t type, u_int16_t, u_int32_t);
+int mrt_dump_hdr_rde(struct ibuf **, u_int16_t type, u_int16_t, u_int32_t);
int mrt_open(struct mrt *, time_t);
#define DUMP_BYTE(x, b) \
do { \
u_char t = (b); \
- if (buf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump1: buf_add error"); \
+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \
+ log_warn("mrt_dump1: ibuf_add error"); \
goto fail; \
} \
} while (0)
@@ -54,8 +57,8 @@ int mrt_open(struct mrt *, time_t);
do { \
u_int16_t t; \
t = htons((s)); \
- if (buf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump2: buf_add error"); \
+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \
+ log_warn("mrt_dump2: ibuf_add error"); \
goto fail; \
} \
} while (0)
@@ -64,8 +67,8 @@ int mrt_open(struct mrt *, time_t);
do { \
u_int32_t t; \
t = htonl((l)); \
- if (buf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump3: buf_add error"); \
+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \
+ log_warn("mrt_dump3: ibuf_add error"); \
goto fail; \
} \
} while (0)
@@ -73,8 +76,8 @@ int mrt_open(struct mrt *, time_t);
#define DUMP_NLONG(x, l) \
do { \
u_int32_t t = (l); \
- if (buf_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump4: buf_add error"); \
+ if (ibuf_add((x), &t, sizeof(t)) == -1) { \
+ log_warn("mrt_dump4: ibuf_add error"); \
goto fail; \
} \
} while (0)
@@ -83,55 +86,64 @@ void
mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen,
struct peer *peer)
{
- struct buf *buf;
+ struct ibuf *buf;
int incoming = 0;
+ u_int16_t subtype = BGP4MP_MESSAGE;
+
+ if (peer->capa.neg.as4byte)
+ subtype = BGP4MP_MESSAGE_AS4;
/* 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 (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
+ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, subtype,
pkglen, incoming) == -1)
return;
- if (buf_add(buf, pkg, pkglen) == -1) {
- log_warnx("mrt_dump_bgp_msg: buf_add error");
- buf_free(buf);
+ if (ibuf_add(buf, pkg, pkglen) == -1) {
+ log_warn("mrt_dump_bgp_msg: ibuf_add error");
+ ibuf_free(buf);
return;
}
- buf_close(&mrt->wbuf, buf);
+ ibuf_close(&mrt->wbuf, buf);
}
void
mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state,
struct peer *peer)
{
- struct buf *buf;
+ struct ibuf *buf;
+ u_int16_t subtype = BGP4MP_STATE_CHANGE;
+
+ if (peer->capa.neg.as4byte)
+ subtype = BGP4MP_STATE_CHANGE_AS4;
- if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
+ if (mrt_dump_hdr_se(&buf, peer, MSG_PROTOCOL_BGP4MP, subtype,
2 * sizeof(short), 0) == -1)
return;
DUMP_SHORT(buf, old_state);
DUMP_SHORT(buf, new_state);
- buf_close(&mrt->wbuf, buf);
+ ibuf_close(&mrt->wbuf, buf);
return;
fail:
- buf_free(buf);
+ ibuf_free(buf);
}
int
-mrt_attr_dump(struct buf *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;
- u_int8_t l;
+ u_int16_t plen, afi;
+ u_int8_t l, safi;
/* origin */
if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ORIGIN,
@@ -140,12 +152,16 @@ mrt_attr_dump(struct buf *buf, struct rd
/* aspath */
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)
+ if (!v2)
+ pdata = aspath_deflate(pdata, &plen, &neednewpath);
+ if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_ASPATH, pdata,
+ plen) == -1) {
+ free(pdata);
return (-1);
+ }
free(pdata);
- if (nexthop) {
+ if (nexthop && nexthop->aid == AID_INET) {
/* nexthop, already network byte order */
if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_NEXTHOP,
&nexthop->v4.s_addr, 4) == -1)
@@ -159,7 +175,7 @@ mrt_attr_dump(struct buf *buf, struct rd
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);
@@ -173,12 +189,51 @@ mrt_attr_dump(struct buf *buf, struct rd
return (-1);
}
+ if (nexthop && nexthop->aid != AID_INET) {
+ struct ibuf *nhbuf;
+
+ if ((nhbuf = ibuf_dynamic(0, UCHAR_MAX)) == NULL)
+ return (-1);
+ 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,
+ nhbuf->buf, ibuf_size(nhbuf)) == -1) {
+fail:
+ ibuf_free(nhbuf);
+ return (-1);
+ }
+ ibuf_free(nhbuf);
+ }
+
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)
+ ATTR_AS4_PATH, pdata, plen) == -1) {
+ free(pdata);
return (-1);
+ }
free(pdata);
}
@@ -189,28 +244,26 @@ int
mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum,
struct rde_peer *peer)
{
- struct buf *buf, *hbuf = NULL, *h2buf = NULL;
- void *bptr;
+ struct ibuf *buf, *hbuf = NULL, *h2buf = NULL;
struct bgpd_addr addr, nexthop, *nh;
u_int16_t len;
- u_int8_t p_len;
- sa_family_t af;
+ u_int8_t aid;
- if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) {
- log_warn("mrt_dump_entry_mp: buf_dynamic");
+ if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
+ log_warn("mrt_dump_entry_mp: ibuf_dynamic");
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;
}
- len = buf_size(buf);
+ len = ibuf_size(buf);
- if ((h2buf = buf_dynamic(MRT_BGP4MP_IPv4_HEADER_SIZE +
+ if ((h2buf = ibuf_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");
+ log_warn("mrt_dump_entry_mp: ibuf_dynamic");
goto fail;
}
@@ -219,25 +272,26 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
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:
+ aid = peer->remote_addr.aid == AID_UNSPEC ? p->prefix->aid :
+ peer->remote_addr.aid;
+ switch (aid) {
+ case AID_INET:
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:
+ case AID_INET6:
DUMP_SHORT(h2buf, AFI_IPv6);
- if (buf_add(h2buf, &peer->local_v6_addr.v6,
+ if (ibuf_add(h2buf, &peer->local_v6_addr.v6,
sizeof(struct in6_addr)) == -1 ||
- buf_add(h2buf, &peer->remote_addr.v6,
+ 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: ibuf_add error");
goto fail;
}
break;
default:
- log_warnx("king bula found new AF %d in mrt_dump_entry_mp", af);
+ log_warnx("king bula found new AF in mrt_dump_entry_mp");
goto fail;
}
@@ -247,25 +301,25 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
if (p->aspath->nexthop == NULL) {
bzero(&nexthop, sizeof(struct bgpd_addr));
- nexthop.af = addr.af;
+ nexthop.aid = addr.aid;
nh = &nexthop;
} else
nh = &p->aspath->nexthop->exit_nexthop;
pt_getaddr(p->prefix, &addr);
- switch (addr.af) {
- case AF_INET:
+ switch (addr.aid) {
+ case AID_INET:
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:
+ case AID_INET6:
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");
+ if (ibuf_add(h2buf, &nh->v6, sizeof(struct in6_addr)) == -1) {
+ log_warn("mrt_dump_entry_mp: ibuf_add error");
goto fail;
}
break;
@@ -274,35 +328,30 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
goto fail;
}
- p_len = PREFIX_SIZE(p->prefix->prefixlen);
- if ((bptr = buf_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;
}
DUMP_SHORT(h2buf, len);
- len += buf_size(h2buf);
+ len += ibuf_size(h2buf);
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);
+ ibuf_close(&mrt->wbuf, hbuf);
+ ibuf_close(&mrt->wbuf, h2buf);
+ ibuf_close(&mrt->wbuf, buf);
return (len + MRT_HEADER_SIZE);
fail:
if (hbuf)
- buf_free(hbuf);
- if (h2buf);
- buf_free(h2buf);
- buf_free(buf);
+ ibuf_free(hbuf);
+ if (h2buf)
+ ibuf_free(h2buf);
+ ibuf_free(buf);
return (-1);
}
@@ -310,34 +359,37 @@ int
mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
struct rde_peer *peer)
{
- struct buf *buf, *hbuf;
+ struct ibuf *buf, *hbuf;
struct bgpd_addr addr, *nh;
size_t len;
+ u_int16_t subtype;
+ u_int8_t dummy;
- if (p->prefix->af != AF_INET && peer->remote_addr.af == AF_INET)
- /* only able to dump IPv4 */
+ if (p->prefix->aid != peer->remote_addr.aid &&
+ p->prefix->aid != AID_INET && p->prefix->aid != AID_INET6)
+ /* only able to dump pure IPv4/IPv6 */
return (0);
- if ((buf = buf_dynamic(0, MAX_PKTSIZE)) == NULL) {
- log_warnx("mrt_dump_entry: buf_dynamic");
+ if ((buf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
+ log_warn("mrt_dump_entry: ibuf_dynamic");
return (-1);
}
if (p->aspath->nexthop == NULL) {
bzero(&addr, sizeof(struct bgpd_addr));
- addr.af = AF_INET;
+ addr.aid = p->prefix->aid;
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");
- buf_free(buf);
+ ibuf_free(buf);
return (-1);
}
- len = buf_size(buf);
-
- if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, AFI_IPv4, len) == -1) {
- buf_free(buf);
+ len = ibuf_size(buf);
+ aid2afi(p->prefix->aid, &subtype, &dummy);
+ if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, subtype, len) == -1) {
+ ibuf_free(buf);
return (-1);
}
@@ -345,23 +397,241 @@ mrt_dump_entry(struct mrt *mrt, struct p
DUMP_SHORT(hbuf, snum);
pt_getaddr(p->prefix, &addr);
- DUMP_NLONG(hbuf, addr.v4.s_addr);
+ switch (p->prefix->aid) {
+ case AID_INET:
+ DUMP_NLONG(hbuf, addr.v4.s_addr);
+ break;
+ case AID_INET6:
+ if (ibuf_add(hbuf, &addr.v6, sizeof(struct in6_addr)) == -1) {
+ log_warn("mrt_dump_entry: ibuf_add error");
+ goto fail;
+ }
+ break;
+ }
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);
+ switch (p->prefix->aid) {
+ case AID_INET:
+ DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr);
+ break;
+ case AID_INET6:
+ if (ibuf_add(hbuf, &peer->remote_addr.v6,
+ sizeof(struct in6_addr)) == -1) {
+ log_warn("mrt_dump_entry: ibuf_add error");
+ goto fail;
+ }
+ break;
+ }
DUMP_SHORT(hbuf, peer->short_as);
DUMP_SHORT(hbuf, len);
- buf_close(&mrt->wbuf, hbuf);
- buf_close(&mrt->wbuf, buf);
+ ibuf_close(&mrt->wbuf, hbuf);
+ ibuf_close(&mrt->wbuf, buf);
return (len + MRT_HEADER_SIZE);
fail:
- buf_free(hbuf);
- buf_free(buf);
+ ibuf_free(hbuf);
+ ibuf_free(buf);
+ 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: ibuf_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: ibuf_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: ibuf_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: ibuf_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: ibuf_add error");
+ goto fail;
+ }
+
+ off = ibuf_size(buf);
+ if (ibuf_reserve(buf, sizeof(nump)) == NULL) {
+ log_warn("mrt_dump_v2_hdr: ibuf_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: ibuf_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);
}
@@ -371,6 +641,11 @@ mrt_dump_upcall(struct rib_entry *re, vo
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
@@ -387,7 +662,7 @@ mrt_dump_upcall(struct rib_entry *re, vo
}
void
-mrt_dump_done(void *ptr)
+mrt_done(void *ptr)
{
struct mrt *mrtbuf = ptr;
@@ -395,14 +670,14 @@ mrt_dump_done(void *ptr)
}
int
-mrt_dump_hdr_se(struct buf ** bp, struct peer *peer, u_int16_t type,
+mrt_dump_hdr_se(struct ibuf ** bp, struct peer *peer, u_int16_t type,
u_int16_t subtype, u_int32_t len, int swap)
{
time_t now;
- if ((*bp = buf_dynamic(MRT_HEADER_SIZE, MRT_HEADER_SIZE +
+ 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: ibuf_dynamic error");
return (-1);
}
@@ -468,23 +743,23 @@ mrt_dump_hdr_se(struct buf ** bp, struct
case AF_INET6:
DUMP_SHORT(*bp, AFI_IPv6);
if (!swap)
- if (buf_add(*bp, &((struct sockaddr_in6 *)
+ 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: ibuf_add error");
goto fail;
}
- if (buf_add(*bp,
+ 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: ibuf_add error");
goto fail;
}
if (swap)
- if (buf_add(*bp, &((struct sockaddr_in6 *)
+ 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: ibuf_add error");
goto fail;
}
break;
@@ -493,20 +768,20 @@ mrt_dump_hdr_se(struct buf ** bp, struct
return (0);
fail:
- buf_free(*bp);
+ ibuf_free(*bp);
return (-1);
}
int
-mrt_dump_hdr_rde(struct buf **bp, u_int16_t type, u_int16_t subtype,
+mrt_dump_hdr_rde(struct ibuf **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 +
+ 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: ibuf_dynamic error");
return (-1);
}
@@ -517,19 +792,28 @@ mrt_dump_hdr_rde(struct buf **bp, u_int1
switch (type) {
case MSG_TABLE_DUMP:
- DUMP_LONG(*bp, MRT_DUMP_HEADER_SIZE + len);
+ switch (subtype) {
+ case AFI_IPv4:
+ len += MRT_DUMP_HEADER_SIZE;
+ break;
+ case AFI_IPv6:
+ len += MRT_DUMP_HEADER_SIZE_V6;
+ break;
+ }
+ DUMP_LONG(*bp, len);
break;
case MSG_PROTOCOL_BGP4MP:
+ case MSG_TABLE_DUMP_V2:
DUMP_LONG(*bp, len);
break;
default:
log_warnx("mrt_dump_hdr_rde: unsupported type");
goto fail;
- }
+ }
return (0);
fail:
- buf_free(*bp);
+ ibuf_free(*bp);
return (-1);
}
@@ -538,21 +822,22 @@ mrt_write(struct mrt *mrt)
{
int r;
- if ((r = buf_write(&mrt->wbuf)) < 0) {
+ if ((r = ibuf_write(&mrt->wbuf)) < 0) {
log_warn("mrt dump aborted, mrt_write");
mrt_clean(mrt);
+ mrt_done(mrt);
}
}
void
mrt_clean(struct mrt *mrt)
{
- struct buf *b;
+ struct ibuf *b;
close(mrt->wbuf.fd);
while ((b = TAILQ_FIRST(&mrt->wbuf.bufs))) {
TAILQ_REMOVE(&mrt->wbuf.bufs, b, entry);
- buf_free(b);
+ ibuf_free(b);
}
mrt->wbuf.queued = 0;
}
@@ -590,7 +875,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,
@@ -659,7 +945,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 =

View File

@ -0,0 +1,287 @@
Index: bgpd/mrt.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/mrt.h,v
retrieving revision 1.1.1.6
retrieving revision 1.1.1.9
diff -u -p -r1.1.1.6 -r1.1.1.9
--- bgpd/mrt.h 14 Feb 2010 20:19:57 -0000 1.1.1.6
+++ bgpd/mrt.h 13 Oct 2012 18:22:43 -0000 1.1.1.9
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.h,v 1.23 2009/06/29 12:22:16 claudio Exp $ */
+/* $OpenBSD: mrt.h,v 1.30 2011/09/18 09:31:25 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -18,12 +18,10 @@
#ifndef __MRT_H__
#define __MRT_H__
-#include "bgpd.h"
-
/*
* MRT binary packet format
* For more info see:
- * draft-ietf-grow-mrt-04.txt, "MRT routing information export format"
+ * draft-ietf-grow-mrt-11.txt, "MRT routing information export format"
* http://www.quagga.net/docs/docs-multi/Packet-Binary-Dump-Format.html
*/
@@ -37,11 +35,18 @@
* | length | length of packet excluding this header
* +--------+--------+--------+--------+
*
- * ET types include an additional 32bit microsecond field comming after the
- * length field.
+ * ET types include an additional 32bit microsecond field coming after the
+ * length field. Which is accounted in the length field.
*/
#define MRT_HEADER_SIZE 12
+struct mrt_hdr {
+ u_int32_t timestamp;
+ u_int16_t type;
+ u_int16_t subtype;
+ u_int32_t length;
+} __packed;
+
enum MRT_MSG_TYPES {
MSG_NULL, /* 0 empty msg (deprecated) */
MSG_START, /* 1 sender is starting up */
@@ -70,13 +75,15 @@ enum MRT_MSG_TYPES {
* that are normaly saved as MSG_TABLE_DUMP.
* In most cases this is the format to choose to dump updates et al.
*/
-enum MRT_BGP4MP_TYPES {
+enum MRT_BGP4MP_SUBTYPES {
BGP4MP_STATE_CHANGE, /* state change */
BGP4MP_MESSAGE, /* bgp message */
BGP4MP_ENTRY, /* table dumps (deprecated) */
BGP4MP_SNAPSHOT, /* file name for dump (deprecated) */
+ BGP4MP_MESSAGE_AS4, /* same as BGP4MP_MESSAGE with 4byte AS */
BGP4MP_STATE_CHANGE_AS4,
- BGP4MP_MESSAGE_AS4 /* same as BGP4MP_MESSAGE with 4byte AS */
+ BGP4MP_MESSAGE_LOCAL, /* same as BGP4MP_MESSAGE but for self */
+ BGP4MP_MESSAGE_AS4_LOCAL /* originated updates. Not implemented */
};
/* size of the BGP4MP headers without payload */
@@ -104,6 +111,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 +163,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_SUBTYPES {
+ 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.
@@ -182,8 +282,14 @@ enum MRT_BGP4MP_TYPES {
* The status field is unused and should be set to 1.
*/
+enum MRT_DUMP_SUBTYPES {
+ MRT_DUMP_AFI_IP=1,
+ MRT_DUMP_AFI_IPv6=2
+};
+
/* size of the dump header until attr_len */
#define MRT_DUMP_HEADER_SIZE 22
+#define MRT_DUMP_HEADER_SIZE_V6 46
/*
* OLD MRT message headers. These structs are here for completion but
@@ -192,7 +298,7 @@ enum MRT_BGP4MP_TYPES {
* Only for bgp messages (type 5, 9 and 10)
* Nota bene for bgp dumps MSG_PROTOCOL_BGP4MP should be used.
*/
-enum MRT_BGP_TYPES {
+enum MRT_BGP_SUBTYPES {
MSG_BGP_NULL,
MSG_BGP_UPDATE, /* raw update packet (contains both withdraws
and announcements) */
@@ -221,10 +327,8 @@ enum MRT_BGP_TYPES {
*
* For IPv6 the type is MSG_PROTOCOL_BGP4PLUS and the subtype remains
* MSG_BGP_UPDATE. The source_ip and dest_ip are again extended to 16 bytes.
- */
-
-/*
- * 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.)
*
* +--------+--------+--------+--------+
@@ -235,7 +339,7 @@ enum MRT_BGP_TYPES {
* | new_state |
* +--------+--------+
*
- * State are defined in RFC 1771.
+ * States are defined in RFC 1771/4271.
*/
/*
@@ -251,66 +355,4 @@ enum MRT_BGP_TYPES {
* terminated ... | 0 |
* +--------+--------+--------+
*/
-
-#define MRT_FILE_LEN 512
-enum mrt_type {
- MRT_NONE,
- MRT_TABLE_DUMP,
- MRT_TABLE_DUMP_MP,
- MRT_ALL_IN,
- MRT_ALL_OUT,
- MRT_UPDATE_IN,
- MRT_UPDATE_OUT
-};
-
-enum mrt_state {
- MRT_STATE_RUNNING,
- MRT_STATE_OPEN,
- MRT_STATE_REOPEN,
- MRT_STATE_REMOVE
-};
-
-struct mrt {
- char rib[PEER_DESCR_LEN];
- struct msgbuf wbuf;
- LIST_ENTRY(mrt) entry;
- u_int32_t peer_id;
- u_int32_t group_id;
- enum mrt_type type;
- enum mrt_state state;
- u_int16_t seqnum;
-};
-
-struct mrt_config {
- struct mrt conf;
- char name[MRT_FILE_LEN]; /* base file name */
- char file[MRT_FILE_LEN]; /* actual file name */
- time_t ReopenTimer;
- time_t ReopenTimerInterval;
-};
-
-#define MRT2MC(x) ((struct mrt_config *)(x))
-#define MRT_MAX_TIMEOUT 7200
-
-struct peer;
-struct prefix;
-struct rib_entry;
-
-/* prototypes */
-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 rib_entry *, void *);
-void mrt_dump_done(void *);
-void mrt_write(struct mrt *);
-void mrt_clean(struct mrt *);
-void mrt_init(struct imsgbuf *, struct imsgbuf *);
-int mrt_timeout(struct mrt_head *);
-void mrt_reconfigure(struct mrt_head *);
-void mrt_handler(struct mrt_head *);
-struct mrt *mrt_get(struct mrt_head *, struct mrt *);
-int mrt_mergeconfig(struct mrt_head *, struct mrt_head *);
-
#endif

View File

@ -0,0 +1,14 @@
Index: bgpd/name2id.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/name2id.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.2 -r1.1.1.3
--- bgpd/name2id.c 9 Jul 2009 16:49:54 -0000 1.1.1.2
+++ bgpd/name2id.c 13 Oct 2012 18:22:43 -0000 1.1.1.3
@@ -1,4 +1,4 @@
-/* $OpenBSD: name2id.c,v 1.9 2009/06/04 04:46:42 claudio Exp $ */
+/* $OpenBSD: name2id.c,v 1.8 2009/05/17 12:25:15 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Henning Brauer <henning@openbsd.org>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,471 @@
diff -ur bgpd.orig/pfkey.c bgpd/pfkey.c
--- bgpd.orig/pfkey.c 2013-03-15 12:07:16.000000000 +0000
+++ bgpd/pfkey.c 2013-03-15 12:07:47.000000000 +0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.37 2009/04/21 15:25:52 henning Exp $ */
+/* $OpenBSD: pfkey.c,v 1.40 2009/12/14 17:38:18 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -21,7 +21,7 @@
#include <sys/socket.h>
#include <sys/uio.h>
#include <net/pfkeyv2.h>
-#include <netinet/ip_ipsp.h>
+//#include <netinet/ip_ipsp.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
@@ -65,15 +65,15 @@
{
struct sadb_msg smsg;
struct sadb_sa sa;
- struct sadb_address sa_src, sa_dst, sa_peer, sa_smask, sa_dmask;
+ struct sadb_address sa_src, sa_dst;
struct sadb_key sa_akey, sa_ekey;
struct sadb_spirange sa_spirange;
- struct sadb_protocol sa_flowtype, sa_protocol;
struct iovec iov[IOV_CNT];
ssize_t n;
int len = 0;
int iov_cnt;
- struct sockaddr_storage ssrc, sdst, speer, smask, dmask;
+ struct sockaddr_storage ssrc, sdst, smask, dmask;
+ struct sockaddr *saptr;
if (!pid)
pid = getpid();
@@ -81,22 +81,17 @@
/* we need clean sockaddr... no ports set */
bzero(&ssrc, sizeof(ssrc));
bzero(&smask, sizeof(smask));
- switch (src->af) {
- case AF_INET:
- ((struct sockaddr_in *)&ssrc)->sin_addr = src->v4;
- ssrc.ss_len = sizeof(struct sockaddr_in);
- ssrc.ss_family = AF_INET;
+ if ((saptr = addr2sa(src, 0)))
+ memcpy(&ssrc, saptr, sizeof(ssrc));
+ switch (src->aid) {
+ case AID_INET:
memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8);
break;
- case AF_INET6:
- memcpy(&((struct sockaddr_in6 *)&ssrc)->sin6_addr,
- &src->v6, sizeof(struct in6_addr));
- ssrc.ss_len = sizeof(struct sockaddr_in6);
- ssrc.ss_family = AF_INET6;
+ case AID_INET6:
memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff,
128/8);
break;
- case 0:
+ case AID_UNSPEC:
ssrc.ss_len = sizeof(struct sockaddr);
break;
default:
@@ -107,22 +102,17 @@
bzero(&sdst, sizeof(sdst));
bzero(&dmask, sizeof(dmask));
- switch (dst->af) {
- case AF_INET:
- ((struct sockaddr_in *)&sdst)->sin_addr = dst->v4;
- sdst.ss_len = sizeof(struct sockaddr_in);
- sdst.ss_family = AF_INET;
+ if ((saptr = addr2sa(dst, 0)))
+ memcpy(&sdst, saptr, sizeof(sdst));
+ switch (dst->aid) {
+ case AID_INET:
memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8);
break;
- case AF_INET6:
- memcpy(&((struct sockaddr_in6 *)&sdst)->sin6_addr,
- &dst->v6, sizeof(struct in6_addr));
- sdst.ss_len = sizeof(struct sockaddr_in6);
- sdst.ss_family = AF_INET6;
+ case AID_INET6:
memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff,
128/8);
break;
- case 0:
+ case AID_UNSPEC:
sdst.ss_len = sizeof(struct sockaddr);
break;
default:
@@ -135,7 +125,7 @@
smsg.sadb_msg_version = PF_KEY_V2;
smsg.sadb_msg_seq = ++sadb_msg_seq;
smsg.sadb_msg_pid = pid;
- smsg.sadb_msg_len = sizeof(smsg) / 8;
+ smsg.sadb_msg_len = PFKEY_UNIT64(sizeof(smsg));
smsg.sadb_msg_type = mtype;
smsg.sadb_msg_satype = satype;
@@ -143,7 +133,7 @@
case SADB_GETSPI:
bzero(&sa_spirange, sizeof(sa_spirange));
sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
- sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8;
+ sa_spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(sa_spirange));
sa_spirange.sadb_spirange_min = 0x100;
sa_spirange.sadb_spirange_max = 0xffffffff;
sa_spirange.sadb_spirange_reserved = 0;
@@ -153,11 +143,12 @@
case SADB_DELETE:
bzero(&sa, sizeof(sa));
sa.sadb_sa_exttype = SADB_EXT_SA;
- sa.sadb_sa_len = sizeof(sa) / 8;
+ sa.sadb_sa_len = PFKEY_UNIT64(sizeof(sa));
sa.sadb_sa_replay = 0;
sa.sadb_sa_spi = spi;
sa.sadb_sa_state = SADB_SASTATE_MATURE;
break;
+#if 0
case SADB_X_ADDFLOW:
case SADB_X_DELFLOW:
bzero(&sa_flowtype, sizeof(sa_flowtype));
@@ -172,35 +163,37 @@
sa_protocol.sadb_protocol_direction = 0;
sa_protocol.sadb_protocol_proto = 6;
break;
+#endif
}
bzero(&sa_src, sizeof(sa_src));
sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
- sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8;
+ sa_src.sadb_address_len = PFKEY_UNIT64(sizeof(sa_src) + ROUNDUP(ssrc.ss_len));
bzero(&sa_dst, sizeof(sa_dst));
sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
- sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8;
+ sa_dst.sadb_address_len = PFKEY_UNIT64(sizeof(sa_dst) + ROUNDUP(sdst.ss_len));
sa.sadb_sa_auth = aalg;
- sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */
+ sa.sadb_sa_encrypt = ealg; /* XXX */
switch (mtype) {
case SADB_ADD:
case SADB_UPDATE:
bzero(&sa_akey, sizeof(sa_akey));
sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH;
- sa_akey.sadb_key_len = (sizeof(sa_akey) +
- ((alen + 7) / 8) * 8) / 8;
+ sa_akey.sadb_key_len = PFKEY_UNIT64(sizeof(sa_akey) +
+ (PFKEY_ALIGN8(alen)));
sa_akey.sadb_key_bits = 8 * alen;
bzero(&sa_ekey, sizeof(sa_ekey));
sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
- sa_ekey.sadb_key_len = (sizeof(sa_ekey) +
- ((elen + 7) / 8) * 8) / 8;
+ sa_ekey.sadb_key_len = PFKEY_UNIT64(sizeof(sa_ekey) +
+ (PFKEY_ALIGN8(elen)));
sa_ekey.sadb_key_bits = 8 * elen;
break;
+#if 0
case SADB_X_ADDFLOW:
case SADB_X_DELFLOW:
/* sa_peer always points to the remote machine */
@@ -220,8 +213,8 @@
sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW;
bzero(&smask, sizeof(smask));
- switch (src->af) {
- case AF_INET:
+ switch (src->aid) {
+ case AID_INET:
smask.ss_len = sizeof(struct sockaddr_in);
smask.ss_family = AF_INET;
memset(&((struct sockaddr_in *)&smask)->sin_addr,
@@ -233,7 +226,7 @@
htons(0xffff);
}
break;
- case AF_INET6:
+ case AID_INET6:
smask.ss_len = sizeof(struct sockaddr_in6);
smask.ss_family = AF_INET6;
memset(&((struct sockaddr_in6 *)&smask)->sin6_addr,
@@ -247,8 +240,8 @@
break;
}
bzero(&dmask, sizeof(dmask));
- switch (dst->af) {
- case AF_INET:
+ switch (dst->aid) {
+ case AID_INET:
dmask.ss_len = sizeof(struct sockaddr_in);
dmask.ss_family = AF_INET;
memset(&((struct sockaddr_in *)&dmask)->sin_addr,
@@ -260,7 +253,7 @@
htons(0xffff);
}
break;
- case AF_INET6:
+ case AID_INET6:
dmask.ss_len = sizeof(struct sockaddr_in6);
dmask.ss_family = AF_INET6;
memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr,
@@ -284,6 +277,7 @@
sa_dmask.sadb_address_len =
(sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)) / 8;
break;
+#endif
}
iov_cnt = 0;
@@ -310,6 +304,7 @@
smsg.sadb_msg_len += sa_spirange.sadb_spirange_len;
iov_cnt++;
break;
+#if 0
case SADB_X_ADDFLOW:
/* sa_peer always points to the remote machine */
iov[iov_cnt].iov_base = &sa_peer;
@@ -351,6 +346,7 @@
smsg.sadb_msg_len += sa_dmask.sadb_address_len;
iov_cnt++;
break;
+#endif
}
/* dest addr */
@@ -380,7 +376,7 @@
iov[iov_cnt].iov_len = sizeof(sa_akey);
iov_cnt++;
iov[iov_cnt].iov_base = akey;
- iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8;
+ iov[iov_cnt].iov_len = PFKEY_ALIGN8(alen);
smsg.sadb_msg_len += sa_akey.sadb_key_len;
iov_cnt++;
}
@@ -390,14 +386,14 @@
iov[iov_cnt].iov_len = sizeof(sa_ekey);
iov_cnt++;
iov[iov_cnt].iov_base = ekey;
- iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8;
+ iov[iov_cnt].iov_len = PFKEY_ALIGN8(elen);
smsg.sadb_msg_len += sa_ekey.sadb_key_len;
iov_cnt++;
}
break;
}
- len = smsg.sadb_msg_len * 8;
+ len = PFKEY_UNUNIT64(smsg.sadb_msg_len);
do {
n = writev(sd, iov, iov_cnt);
} while (n == -1 && (errno == EAGAIN || errno == EINTR));
@@ -411,6 +407,33 @@
}
int
+pfkey_read(int sd, struct sadb_msg *h)
+{
+ struct sadb_msg hdr;
+
+ if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
+ log_warn("pfkey peek");
+ return (-1);
+ }
+
+ /* XXX: Only one message can be outstanding. */
+ if (hdr.sadb_msg_seq == sadb_msg_seq &&
+ hdr.sadb_msg_pid == pid) {
+ if (h)
+ bcopy(&hdr, h, sizeof(hdr));
+ return (0);
+ }
+
+ /* not ours, discard */
+ if (read(sd, &hdr, sizeof(hdr)) == -1) {
+ log_warn("pfkey read");
+ return (-1);
+ }
+
+ return (1);
+}
+
+int
pfkey_reply(int sd, u_int32_t *spip)
{
struct sadb_msg hdr, *msg;
@@ -418,27 +441,17 @@
struct sadb_sa *sa;
u_int8_t *data;
ssize_t len;
+ int rv;
- for (;;) {
- if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
- log_warn("pfkey peek");
- return (-1);
- }
-
- if (hdr.sadb_msg_seq == sadb_msg_seq &&
- hdr.sadb_msg_pid == pid)
- break;
-
- /* not ours, discard */
- if (read(sd, &hdr, sizeof(hdr)) == -1) {
- log_warn("pfkey read");
+ do {
+ rv = pfkey_read(sd, &hdr);
+ if (rv == -1)
return (-1);
- }
- }
+ } while (rv);
if (hdr.sadb_msg_errno != 0) {
errno = hdr.sadb_msg_errno;
- if (errno == ESRCH)
+ if (errno == ESRCH || errno == EEXIST)
return (0);
else {
log_warn("pfkey");
@@ -486,13 +499,8 @@
pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, u_int8_t keylen,
char *key, u_int32_t *spi)
{
- if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0,
- src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0)
- return (-1);
- if (pfkey_reply(fd, spi) < 0)
- return (-1);
- if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0,
- src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) < 0)
+ if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_ADD, 0,
+ src, dst, *spi, SADB_X_AALG_TCP_MD5, keylen, key, SADB_EALG_NONE, 0, NULL, 0, 0) < 0)
return (-1);
if (pfkey_reply(fd, NULL) < 0)
return (-1);
@@ -503,7 +511,7 @@
pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, u_int32_t *spi)
{
if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0,
- src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0)
+ src, dst, *spi, SADB_X_AALG_TCP_MD5, 0, NULL, 0, 0, NULL, 0, 0) < 0)
return (-1);
if (pfkey_reply(fd, NULL) < 0)
return (-1);
@@ -511,37 +519,37 @@
return (0);
}
+#define TCP_SIG_SPI 0x1000
int
pfkey_md5sig_establish(struct peer *p)
{
sleep(1);
- if (!p->auth.spi_out)
- if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr,
- p->conf.auth.md5key_len, p->conf.auth.md5key,
- &p->auth.spi_out) == -1)
- return (-1);
- if (!p->auth.spi_in)
- if (pfkey_sa_add(&p->conf.remote_addr, &p->auth.local_addr,
- p->conf.auth.md5key_len, p->conf.auth.md5key,
- &p->auth.spi_in) == -1)
- return (-1);
+ p->auth.spi_out = htonl(TCP_SIG_SPI);
+ if (pfkey_sa_add(&p->auth.local_addr, &p->conf.remote_addr,
+ p->conf.auth.md5key_len, p->conf.auth.md5key,
+ &p->auth.spi_out) == -1)
+ return (-1);
+ p->auth.spi_in = htonl(TCP_SIG_SPI);
+ if (pfkey_sa_add(&p->conf.remote_addr, &p->auth.local_addr,
+ p->conf.auth.md5key_len, p->conf.auth.md5key,
+ &p->auth.spi_out) == -1)
+ return (-1);
p->auth.established = 1;
return (0);
}
+#undef TCP_SIG_SPI
int
pfkey_md5sig_remove(struct peer *p)
{
- if (p->auth.spi_out)
- if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
- &p->auth.spi_out) == -1)
- return (-1);
- if (p->auth.spi_in)
- if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
- &p->auth.spi_in) == -1)
- return (-1);
+ if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
+ &p->auth.spi_out) == -1)
+ return (-1);
+ if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
+ &p->auth.spi_in) == -1)
+ return (-1);
p->auth.established = 0;
return (0);
@@ -550,6 +558,7 @@
int
pfkey_ipsec_establish(struct peer *p)
{
+#if 0
uint8_t satype = SADB_SATYPE_ESP;
switch (p->auth.method) {
@@ -621,6 +630,9 @@
p->auth.established = 1;
return (0);
+#else
+ return (-1);
+#endif
}
int
@@ -660,6 +672,7 @@
break;
}
+#if 0
if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
&p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) < 0)
return (-1);
@@ -681,6 +694,7 @@
if (pfkey_flow(fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
&p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) < 0)
return (-1);
+#endif
if (pfkey_reply(fd, NULL) < 0)
return (-1);
@@ -715,9 +729,7 @@
int
pfkey_remove(struct peer *p)
{
- if (!p->auth.established)
- return (0);
- else if (p->auth.method == AUTH_MD5SIG)
+ if (p->auth.method == AUTH_MD5SIG)
return (pfkey_md5sig_remove(p));
else
return (pfkey_ipsec_remove(p));
@@ -730,11 +742,9 @@
if (errno == EPROTONOSUPPORT) {
log_warnx("PF_KEY not available, disabling ipsec");
sysdep->no_pfkey = 1;
- return (0);
- } else {
- log_warn("PF_KEY socket");
return (-1);
- }
+ } else
+ fatal("pfkey setup failed");
}
- return (0);
+ return (fd);
}

View File

@ -0,0 +1,17 @@
Index: bgpd/pftable.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/pftable.c,v
retrieving revision 1.1.1.5
retrieving revision 1.1.1.7
diff -u -p -r1.1.1.5 -r1.1.1.7
--- bgpd/pftable.c 14 Feb 2010 20:19:57 -0000 1.1.1.5
+++ bgpd/pftable.c 13 Oct 2012 18:22:44 -0000 1.1.1.7
@@ -214,7 +214,7 @@ pftable_add_work(const char *table, stru
bzero(pfa, sizeof(*pfa));
memcpy(&pfa->pfra_u, &addr->ba, (len + 7U) / 8);
- pfa->pfra_af = addr->af;
+ pfa->pfra_af = aid2af(addr->aid);
pfa->pfra_net = len;
pft->naddrs++;

View File

@ -0,0 +1,439 @@
Index: bgpd/printconf.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/printconf.c,v
retrieving revision 1.1.1.7
retrieving revision 1.11
diff -u -p -r1.1.1.7 -r1.11
--- bgpd/printconf.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/printconf.c 16 May 2014 00:36:26 -0000 1.11
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.88 2012/09/23 09:39:18 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -16,9 +16,13 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#if defined(__FreeBSD__) /* limits.h */
+#include <limits.h>
+#endif
#include "bgpd.h"
#include "mrt.h"
@@ -27,14 +31,19 @@
void print_op(enum comp_ops);
void print_community(int, int);
+void print_extcommunity(struct filter_extcommunity *);
+void print_origin(u_int8_t);
void print_set(struct filter_set_head *);
void print_mainconf(struct bgpd_config *);
+void print_rdomain_targets(struct filter_set_head *, const char *);
+void print_rdomain(struct rdomain *);
+const char *print_af(u_int8_t);
void print_network(struct network_config *);
void print_peer(struct peer_config *, struct bgpd_config *,
const char *);
const char *print_auth_alg(u_int8_t);
const char *print_enc_alg(u_int8_t);
-const char *print_safi(u_int8_t);
+void print_announce(struct peer_config *, const char *);
void print_rule(struct peer *, struct filter_rule *);
const char * mrt_type(enum mrt_type);
void print_mrt(u_int32_t, u_int32_t, const char *, const char *);
@@ -94,6 +103,45 @@ print_community(int as, int type)
}
void
+print_extcommunity(struct filter_extcommunity *c)
+{
+ switch (c->type & EXT_COMMUNITY_VALUE) {
+ case EXT_COMMUNITY_TWO_AS:
+ printf("%s %i:%i ", log_ext_subtype(c->subtype),
+ c->data.ext_as.as, c->data.ext_as.val);
+ break;
+ case EXT_COMMUNITY_IPV4:
+ printf("%s %s:%i ", log_ext_subtype(c->subtype),
+ inet_ntoa(c->data.ext_ip.addr), c->data.ext_ip.val);
+ break;
+ case EXT_COMMUNITY_FOUR_AS:
+ printf("%s %s:%i ", log_ext_subtype(c->subtype),
+ log_as(c->data.ext_as4.as4), c->data.ext_as.val);
+ break;
+ case EXT_COMMUNITY_OPAQUE:
+ printf("%s 0x%llx ", log_ext_subtype(c->subtype),
+ (long long unsigned int)c->data.ext_opaq);
+ break;
+ default:
+ printf("0x%x 0x%llx ", c->type, (long long unsigned int)c->data.ext_opaq);
+ break;
+ }
+}
+
+void
+print_origin(u_int8_t o)
+{
+ if (o == ORIGIN_IGP)
+ printf("igp ");
+ else if (o == ORIGIN_EGP)
+ printf("egp ");
+ else if (o == ORIGIN_INCOMPLETE)
+ printf("incomplete ");
+ else
+ printf("%u ", o);
+}
+
+void
print_set(struct filter_set_head *set)
{
struct filter_set *s;
@@ -161,11 +209,23 @@ print_set(struct filter_set_head *set)
case ACTION_RTLABEL:
printf("rtlabel %s ", s->action.rtlabel);
break;
+ case ACTION_SET_ORIGIN:
+ printf("origin ");
+ print_origin(s->action.origin);
+ break;
case ACTION_RTLABEL_ID:
case ACTION_PFTABLE_ID:
/* not possible */
printf("king bula saiz: config broken");
break;
+ case ACTION_SET_EXT_COMMUNITY:
+ printf("ext-community ");
+ print_extcommunity(&s->action.ext_community);
+ break;
+ case ACTION_DEL_EXT_COMMUNITY:
+ printf("ext-community delete ");
+ print_extcommunity(&s->action.ext_community);
+ break;
}
}
printf("}");
@@ -182,6 +242,10 @@ print_mainconf(struct bgpd_config *conf)
printf(" %u", conf->short_as);
ina.s_addr = conf->bgpid;
printf("\nrouter-id %s\n", inet_ntoa(ina));
+
+ printf("socket \"%s\"\n", conf->csock);
+ if (conf->rcsock)
+ printf("socket \"%s\" restricted\n", conf->rcsock);
if (conf->holdtime)
printf("holdtime %u\n", conf->holdtime);
if (conf->min_holdtime)
@@ -189,11 +253,6 @@ print_mainconf(struct bgpd_config *conf)
if (conf->connectretry)
printf("connect-retry %u\n", conf->connectretry);
- if (conf->flags & BGPD_FLAG_NO_FIB_UPDATE)
- printf("fib-update no\n");
- else
- printf("fib-update yes\n");
-
if (conf->flags & BGPD_FLAG_NO_EVALUATE)
printf("route-collector yes\n");
@@ -214,43 +273,67 @@ print_mainconf(struct bgpd_config *conf)
printf("nexthop qualify via bgp\n");
if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT)
printf("nexthop qualify via default\n");
+}
- if (conf->flags & BGPD_FLAG_REDIST_CONNECTED) {
- printf("network inet connected");
- if (!TAILQ_EMPTY(&conf->connectset))
- printf(" ");
- print_set(&conf->connectset);
- printf("\n");
- }
- if (conf->flags & BGPD_FLAG_REDIST_STATIC) {
- printf("network inet static");
- if (!TAILQ_EMPTY(&conf->staticset))
- printf(" ");
- print_set(&conf->staticset);
- printf("\n");
- }
- if (conf->flags & BGPD_FLAG_REDIST6_CONNECTED) {
- printf("network inet6 connected");
- if (!TAILQ_EMPTY(&conf->connectset6))
- printf(" ");
- print_set(&conf->connectset6);
- printf("\n");
- }
- if (conf->flags & BGPD_FLAG_REDIST_STATIC) {
- printf("network inet6 static");
- if (!TAILQ_EMPTY(&conf->staticset6))
- printf(" ");
- print_set(&conf->staticset6);
+void
+print_rdomain_targets(struct filter_set_head *set, const char *tgt)
+{
+ struct filter_set *s;
+ TAILQ_FOREACH(s, set, entry) {
+ printf("\t%s ", tgt);
+ print_extcommunity(&s->action.ext_community);
printf("\n");
}
- if (conf->rtableid)
- printf("rtable %u\n", conf->rtableid);
+}
+
+void
+print_rdomain(struct rdomain *r)
+{
+ printf("rdomain %u {\n", r->rtableid);
+ printf("\tdescr \"%s\"\n", r->descr);
+ if (r->flags & F_RIB_NOFIBSYNC)
+ printf("\tfib-update no\n");
+ else
+ printf("\tfib-update yes\n");
+ printf("\tdepend on %s\n", r->ifmpe);
+
+ printf("\n\t%s\n", log_rd(r->rd));
+
+ print_rdomain_targets(&r->export, "export-target");
+ print_rdomain_targets(&r->import, "import-target");
+
+ printf("}\n");
+}
+
+const char *
+print_af(u_int8_t aid)
+{
+ /*
+ * Hack around the fact that aid2str() will return "IPv4 unicast"
+ * for AID_INET. AID_INET and AID_INET6 need special handling and
+ * the other AID should never end up here (at least for now).
+ */
+ if (aid == AID_INET)
+ return ("inet");
+ if (aid == AID_INET6)
+ return ("inet6");
+ return (aid2str(aid));
}
void
print_network(struct network_config *n)
{
- printf("network %s/%u", log_addr(&n->prefix), n->prefixlen);
+ switch (n->type) {
+ case NETWORK_STATIC:
+ printf("network %s static", print_af(n->prefix.aid));
+ break;
+ case NETWORK_CONNECTED:
+ printf("network %s connected", print_af(n->prefix.aid));
+ break;
+ default:
+ printf("network %s/%u", log_addr(&n->prefix), n->prefixlen);
+ break;
+ }
if (!TAILQ_EMPTY(&n->attrset))
printf(" ");
print_set(&n->attrset);
@@ -263,8 +346,8 @@ print_peer(struct peer_config *p, struct
char *method;
struct in_addr ina;
- if ((p->remote_addr.af == AF_INET && p->remote_masklen != 32) ||
- (p->remote_addr.af == AF_INET6 && p->remote_masklen != 128))
+ if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) ||
+ (p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128))
printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr),
p->remote_masklen);
else
@@ -281,7 +364,7 @@ print_peer(struct peer_config *p, struct
printf("%s\tmultihop %u\n", c, p->distance);
if (p->passive)
printf("%s\tpassive\n", c);
- if (p->local_addr.af)
+ if (p->local_addr.aid)
printf("%s\tlocal-address %s\n", c, log_addr(&p->local_addr));
if (p->max_prefix) {
printf("%s\tmax-prefix %u", c, p->max_prefix);
@@ -295,6 +378,12 @@ print_peer(struct peer_config *p, struct
printf("%s\tholdtime min %u\n", c, p->min_holdtime);
if (p->announce_capa == 0)
printf("%s\tannounce capabilities no\n", c);
+ if (p->capabilities.refresh == 0)
+ printf("%s\tannounce refresh no\n", c);
+ if (p->capabilities.grestart.restart == 0)
+ printf("%s\tannounce restart no\n", c);
+ if (p->capabilities.as4byte == 0)
+ printf("%s\tannounce as4byte no\n", c);
if (p->announce_type == ANNOUNCE_SELF)
printf("%s\tannounce self\n", c);
else if (p->announce_type == ANNOUNCE_NONE)
@@ -324,6 +413,10 @@ print_peer(struct peer_config *p, struct
printf("%s\tdepend on \"%s\"\n", c, p->if_depend);
if (p->flags & PEERFLAG_TRANS_AS)
printf("%s\ttransparent-as yes\n", c);
+#if defined(IPV6_LINKLOCAL_PEER)
+ if (p->lliface[0])
+ printf("%s\tinterface %s\n", c, p->lliface);
+#endif
if (p->auth.method == AUTH_MD5SIG)
printf("%s\ttcp md5sig\n", c);
@@ -354,8 +447,7 @@ print_peer(struct peer_config *p, struct
if (p->ttlsec)
printf("%s\tttl-security yes\n", c);
- printf("%s\tannounce IPv4 %s\n", c, print_safi(p->capabilities.mp_v4));
- printf("%s\tannounce IPv6 %s\n", c, print_safi(p->capabilities.mp_v6));
+ print_announce(p, c);
if (p->softreconfig_in == 1)
printf("%s\tsoftreconfig in yes\n", c);
@@ -399,17 +491,14 @@ print_enc_alg(u_int8_t alg)
}
}
-const char *
-print_safi(u_int8_t safi)
+void
+print_announce(struct peer_config *p, const char *c)
{
- switch (safi) {
- case SAFI_NONE:
- return ("none");
- case SAFI_UNICAST:
- return ("unicast");
- default:
- return ("?");
- }
+ u_int8_t aid;
+
+ for (aid = 0; aid < AID_MAX; aid++)
+ if (p->capabilities.mp[aid])
+ printf("%s\tannounce %s\n", c, aid2str(aid));
}
void
@@ -455,14 +544,14 @@ print_rule(struct peer *peer_l, struct f
} else
printf("any ");
- if (r->match.prefix.addr.af)
+ if (r->match.prefix.addr.aid)
printf("prefix %s/%u ", log_addr(&r->match.prefix.addr),
r->match.prefix.len);
- if (r->match.prefix.addr.af == 0 && r->match.prefixlen.af) {
- if (r->match.prefixlen.af == AF_INET)
+ if (r->match.prefix.addr.aid == 0 && r->match.prefixlen.aid) {
+ if (r->match.prefixlen.aid == AID_INET)
printf("inet ");
- if (r->match.prefixlen.af == AF_INET6)
+ if (r->match.prefixlen.aid == AID_INET6)
printf("inet6 ");
}
@@ -479,6 +568,13 @@ print_rule(struct peer *peer_l, struct f
}
}
+ if (r->match.nexthop.flags) {
+ if (r->match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR)
+ printf("nexthop neighbor ");
+ else
+ printf("nexthop %s ", log_addr(&r->match.nexthop.addr));
+ }
+
if (r->match.as.type) {
if (r->match.as.type == AS_ALL)
printf("AS %s ", log_as(r->match.as.as));
@@ -492,11 +588,20 @@ print_rule(struct peer *peer_l, struct f
printf("unfluffy-as %s ", log_as(r->match.as.as));
}
+ if (r->match.aslen.type) {
+ printf("%s %u ", r->match.aslen.type == ASLEN_MAX ?
+ "max-as-len" : "max-as-seq", r->match.aslen.aslen);
+ }
+
if (r->match.community.as != COMMUNITY_UNSET) {
printf("community ");
print_community(r->match.community.as,
r->match.community.type);
}
+ if (r->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID) {
+ printf("ext-community ");
+ print_extcommunity(&r->match.ext_community);
+ }
print_set(&r->set);
@@ -513,6 +618,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:
@@ -541,12 +648,12 @@ print_mrt(u_int32_t pid, u_int32_t gid,
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,
+ printf(" %ld\n",
MRT2MC(m)->ReopenTimerInterval);
}
}
@@ -612,26 +719,34 @@ peer_compare(const void *aa, const void
void
print_config(struct bgpd_config *conf, struct rib_names *rib_l,
struct network_head *net_l, struct peer *peer_l,
- struct filter_head *rules_l, struct mrt_head *mrt_l)
+ struct filter_head *rules_l, struct mrt_head *mrt_l,
+ struct rdomain_head *rdom_l)
{
struct filter_rule *r;
struct network *n;
struct rde_rib *rr;
+ struct rdomain *rd;
xmrt_l = mrt_l;
- printf("\n");
print_mainconf(conf);
printf("\n");
+ TAILQ_FOREACH(n, net_l, entry)
+ print_network(&n->net);
+ printf("\n");
+ SIMPLEQ_FOREACH(rd, rdom_l, entry)
+ print_rdomain(rd);
+ printf("\n");
SIMPLEQ_FOREACH(rr, rib_l, entry) {
if (rr->flags & F_RIB_NOEVALUATE)
printf("rde rib %s no evaluate\n", rr->name);
- else
+ else if (rr->flags & F_RIB_NOFIB)
printf("rde rib %s\n", rr->name);
+ else
+ printf("rde rib %s rtable %u fib-update %s\n", rr->name,
+ rr->rtableid, rr->flags & F_RIB_NOFIBSYNC ?
+ "no" : "yes");
}
printf("\n");
- TAILQ_FOREACH(n, net_l, entry)
- print_network(&n->net);
- printf("\n");
print_mrt(0, 0, "", "");
printf("\n");
print_groups(conf, peer_l);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,361 @@
Index: bgpd/rde.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde.h,v
retrieving revision 1.1.1.8
retrieving revision 1.1.1.13
diff -u -p -r1.1.1.8 -r1.1.1.13
--- bgpd/rde.h 14 Feb 2010 20:19:57 -0000 1.1.1.8
+++ bgpd/rde.h 8 Dec 2012 10:37:09 -0000 1.1.1.13
@@ -1,8 +1,8 @@
-/* $OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.144 2012/09/12 05:56:22 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
- * Andre Oppermann <oppermann@pipeline.ch>
+ * Andre Oppermann <oppermann@networx.ch>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -56,16 +56,16 @@ struct rde_peer {
struct bgpd_addr local_v6_addr;
struct uptree_prefix up_prefix;
struct uptree_attr up_attrs;
- struct uplist_attr updates;
- struct uplist_prefix withdraws;
- struct uplist_attr updates6;
- struct uplist_prefix withdraws6;
- struct capabilities capa_announced;
- struct capabilities capa_received;
+ struct uplist_attr updates[AID_MAX];
+ struct uplist_prefix withdraws[AID_MAX];
+ struct capabilities capa;
+ time_t staletime[AID_MAX];
u_int64_t prefix_rcvd_update;
u_int64_t prefix_rcvd_withdraw;
+ u_int64_t prefix_rcvd_eor;
u_int64_t prefix_sent_update;
u_int64_t prefix_sent_withdraw;
+ u_int64_t prefix_sent_eor;
u_int32_t prefix_cnt; /* # of prefixes */
u_int32_t remote_bgpid; /* host byte order! */
u_int32_t up_pcnt;
@@ -75,12 +75,16 @@ 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 */
};
#define AS_SET 1
#define AS_SEQUENCE 2
+#define AS_CONFED_SEQUENCE 3
+#define AS_CONFED_SET 4
#define ASPATH_HEADER_SIZE (sizeof(struct aspath) - sizeof(u_char))
LIST_HEAD(aspath_list, aspath);
@@ -117,6 +121,9 @@ enum attrtypes {
#define ATTR_PARTIAL 0x20
#define ATTR_TRANSITIVE 0x40
#define ATTR_OPTIONAL 0x80
+#define ATTR_RESERVED 0x0f
+/* by default mask the reserved bits and the ext len bit */
+#define ATTR_DEFMASK (ATTR_RESERVED | ATTR_EXTLEN)
/* default attribute flags for well known attributes */
#define ATTR_WELL_KNOWN ATTR_TRANSITIVE
@@ -163,6 +170,8 @@ LIST_HEAD(prefix_head, prefix);
#define F_NEXTHOP_REJECT 0x02000
#define F_NEXTHOP_BLACKHOLE 0x04000
#define F_NEXTHOP_NOMODIFY 0x08000
+#define F_NEXTHOP_MASK 0x0f000
+#define F_ATTR_PARSE_ERR 0x10000
#define F_ATTR_LINKED 0x20000
@@ -220,14 +229,14 @@ struct nexthop {
/* generic entry without address specific part */
struct pt_entry {
RB_ENTRY(pt_entry) pt_e;
- sa_family_t af;
+ u_int8_t aid;
u_int8_t prefixlen;
u_int16_t refcnt;
};
struct pt_entry4 {
RB_ENTRY(pt_entry) pt_e;
- sa_family_t af;
+ u_int8_t aid;
u_int8_t prefixlen;
u_int16_t refcnt;
struct in_addr prefix4;
@@ -235,12 +244,25 @@ struct pt_entry4 {
struct pt_entry6 {
RB_ENTRY(pt_entry) pt_e;
- sa_family_t af;
+ u_int8_t aid;
u_int8_t prefixlen;
u_int16_t refcnt;
struct in6_addr prefix6;
};
+struct pt_entry_vpn4 {
+ RB_ENTRY(pt_entry) pt_e;
+ u_int8_t aid;
+ u_int8_t prefixlen;
+ u_int16_t refcnt;
+ struct in_addr prefix4;
+ u_int64_t rd;
+ u_int8_t labelstack[21];
+ u_int8_t labellen;
+ u_int8_t pad1;
+ u_int8_t pad2;
+};
+
struct rib_context {
LIST_ENTRY(rib_context) entry;
struct rib_entry *ctx_re;
@@ -250,7 +272,7 @@ struct rib_context {
void (*ctx_wait)(void *);
void *ctx_arg;
unsigned int ctx_count;
- sa_family_t ctx_af;
+ u_int8_t ctx_aid;
};
struct rib_entry {
@@ -262,23 +284,15 @@ struct rib_entry {
u_int16_t flags;
};
-enum rib_state {
- RIB_NONE,
- RIB_ACTIVE,
- RIB_DELETE
-};
-
struct rib {
char name[PEER_DESCR_LEN];
struct rib_tree rib;
- enum rib_state state;
+ u_int rtableid;
u_int16_t flags;
u_int16_t id;
+ enum reconf_action state;
};
-#define F_RIB_ENTRYLOCK 0x0001
-#define F_RIB_NOEVALUATE 0x0002
-#define F_RIB_NOFIB 0x0004
#define RIB_FAILED 0xffff
struct prefix {
@@ -292,8 +306,14 @@ struct prefix {
extern struct rde_memstats rdemem;
/* prototypes */
+/* mrt.c */
+int mrt_dump_v2_hdr(struct mrt *, struct bgpd_config *,
+ struct rde_peer_head *);
+void mrt_dump_upcall(struct rib_entry *, void *);
+void mrt_done(void *);
+
/* rde.c */
-void rde_send_kroute(struct prefix *, struct prefix *);
+void rde_send_kroute(struct prefix *, struct prefix *, u_int16_t);
void rde_send_nexthop(struct bgpd_addr *, int);
void rde_send_pftable(u_int16_t, struct bgpd_addr *,
u_int8_t, int);
@@ -309,7 +329,7 @@ int rde_as4byte(struct rde_peer *);
/* rde_attr.c */
int attr_write(void *, u_int16_t, u_int8_t, u_int8_t, void *,
u_int16_t);
-int attr_writebuf(struct buf *, u_int8_t, u_int8_t, void *,
+int attr_writebuf(struct ibuf *, u_int8_t, u_int8_t, void *,
u_int16_t);
void attr_init(u_int32_t);
void attr_shutdown(void);
@@ -327,6 +347,7 @@ int aspath_verify(void *, u_int16_t, i
#define AS_ERR_LEN -1
#define AS_ERR_TYPE -2
#define AS_ERR_BAD -3
+#define AS_ERR_SOFT -4
void aspath_init(u_int32_t);
void aspath_shutdown(void);
struct aspath *aspath_get(void *, u_int16_t);
@@ -341,22 +362,66 @@ u_int32_t aspath_neighbor(struct aspath
int aspath_loopfree(struct aspath *, u_int32_t);
int aspath_compare(struct aspath *, struct aspath *);
u_char *aspath_prepend(struct aspath *, u_int32_t, int, u_int16_t *);
-int aspath_match(struct aspath *, enum as_spec, u_int32_t);
-int community_match(void *, u_int16_t, int, int);
+int aspath_lenmatch(struct aspath *, enum aslen_spec, u_int);
+int community_match(struct rde_aspath *, int, int);
int community_set(struct rde_aspath *, int, int);
void community_delete(struct rde_aspath *, int, int);
+int community_ext_match(struct rde_aspath *,
+ struct filter_extcommunity *, u_int16_t);
+int community_ext_set(struct rde_aspath *,
+ struct filter_extcommunity *, u_int16_t);
+void community_ext_delete(struct rde_aspath *,
+ struct filter_extcommunity *, u_int16_t);
+int community_ext_conv(struct filter_extcommunity *, u_int16_t,
+ u_int64_t *);
+
+/* rde_decide.c */
+void prefix_evaluate(struct prefix *, struct rib_entry *);
+
+/* rde_filter.c */
+enum filter_actions rde_filter(u_int16_t, struct rde_aspath **,
+ struct filter_head *, struct rde_peer *,
+ struct rde_aspath *, struct bgpd_addr *, u_int8_t,
+ struct rde_peer *, enum directions);
+void rde_apply_set(struct rde_aspath *, struct filter_set_head *,
+ u_int8_t, struct rde_peer *, struct rde_peer *);
+int rde_filter_equal(struct filter_head *, struct filter_head *,
+ struct rde_peer *, enum directions);
+
+/* rde_prefix.c */
+#define pt_empty(pt) ((pt)->refcnt == 0)
+#define pt_ref(pt) do { \
+ ++(pt)->refcnt; \
+ if ((pt)->refcnt == 0) \
+ fatalx("pt_ref: overflow"); \
+} while(0)
+#define pt_unref(pt) do { \
+ if ((pt)->refcnt == 0) \
+ fatalx("pt_unref: underflow"); \
+ --(pt)->refcnt; \
+} while(0)
+
+void pt_init(void);
+void pt_shutdown(void);
+void pt_getaddr(struct pt_entry *, struct bgpd_addr *);
+struct pt_entry *pt_fill(struct bgpd_addr *, int);
+struct pt_entry *pt_get(struct bgpd_addr *, int);
+struct pt_entry *pt_add(struct bgpd_addr *, int);
+void pt_remove(struct pt_entry *);
+struct pt_entry *pt_lookup(struct bgpd_addr *);
+int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *);
/* rde_rib.c */
extern u_int16_t rib_size;
extern struct rib *ribs;
-u_int16_t rib_new(int, char *, u_int16_t);
+u_int16_t rib_new(char *, u_int, u_int16_t);
u_int16_t rib_find(char *);
void rib_free(struct rib *);
struct rib_entry *rib_get(struct rib *, struct bgpd_addr *, int);
struct rib_entry *rib_lookup(struct rib *, struct bgpd_addr *);
void rib_dump(struct rib *, void (*)(struct rib_entry *, void *),
- void *, sa_family_t);
+ void *, u_int8_t);
void rib_dump_r(struct rib_context *);
void rib_dump_runner(void);
int rib_dump_pending(void);
@@ -368,6 +433,7 @@ int path_update(struct rib *, struct r
int path_compare(struct rde_aspath *, struct rde_aspath *);
struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *);
void path_remove(struct rde_aspath *);
+void path_remove_stale(struct rde_aspath *, u_int8_t);
void path_destroy(struct rde_aspath *);
int path_empty(struct rde_aspath *);
struct rde_aspath *path_copy(struct rde_aspath *);
@@ -375,8 +441,6 @@ 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 rib *, struct rde_peer *,
struct bgpd_addr *, int, u_int32_t);
int prefix_add(struct rib *, struct rde_aspath *,
@@ -385,6 +449,7 @@ void prefix_move(struct rde_aspath *,
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,
@@ -395,7 +460,7 @@ void prefix_network_clean(struct rde_p
void nexthop_init(u_int32_t);
void nexthop_shutdown(void);
void nexthop_modify(struct rde_aspath *, struct bgpd_addr *,
- enum action_types, sa_family_t);
+ enum action_types, u_int8_t);
void nexthop_link(struct rde_aspath *);
void nexthop_unlink(struct rde_aspath *);
int nexthop_delete(struct nexthop *);
@@ -403,9 +468,6 @@ void nexthop_update(struct kroute_next
struct nexthop *nexthop_get(struct bgpd_addr *);
int nexthop_compare(struct nexthop *, struct nexthop *);
-/* rde_decide.c */
-void prefix_evaluate(struct prefix *, struct rib_entry *);
-
/* rde_update.c */
void up_init(struct rde_peer *);
void up_down(struct rde_peer *);
@@ -415,49 +477,14 @@ int up_generate(struct rde_peer *, str
void up_generate_updates(struct filter_head *, struct rde_peer *,
struct prefix *, struct prefix *);
void up_generate_default(struct filter_head *, struct rde_peer *,
- sa_family_t);
+ u_int8_t);
+int up_generate_marker(struct rde_peer *, u_int8_t);
int up_dump_prefix(u_char *, int, struct uplist_prefix *,
struct rde_peer *);
int up_dump_attrnlri(u_char *, int, struct rde_peer *);
-u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *);
-u_char *up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *);
-
-/* rde_prefix.c */
-#define pt_empty(pt) ((pt)->refcnt == 0)
-#define pt_ref(pt) do { \
- ++(pt)->refcnt; \
- if ((pt)->refcnt == 0) \
- fatalx("pt_ref: overflow"); \
-} while(0)
-#define pt_unref(pt) do { \
- if ((pt)->refcnt == 0) \
- fatalx("pt_unref: underflow"); \
- --(pt)->refcnt; \
-} while(0)
-
-void pt_init(void);
-void pt_shutdown(void);
-void pt_getaddr(struct pt_entry *, struct bgpd_addr *);
-struct pt_entry *pt_fill(struct bgpd_addr *, int);
-struct pt_entry *pt_get(struct bgpd_addr *, int);
-struct pt_entry *pt_add(struct bgpd_addr *, int);
-void pt_remove(struct pt_entry *);
-struct pt_entry *pt_lookup(struct bgpd_addr *);
-int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *);
-
-
-/* rde_filter.c */
-enum filter_actions rde_filter(u_int16_t, struct rde_aspath **,
- struct filter_head *, struct rde_peer *,
- struct rde_aspath *, struct bgpd_addr *, u_int8_t,
- struct rde_peer *, enum directions);
-void rde_apply_set(struct rde_aspath *, struct filter_set_head *,
- sa_family_t, struct rde_peer *, struct rde_peer *);
-int rde_filter_community(struct rde_aspath *, int, int);
-int rde_filter_equal(struct filter_head *, struct filter_head *,
- struct rde_peer *, enum directions);
-
-/* util.c */
-u_int32_t aspath_extract(const void *, int);
+u_char *up_dump_mp_unreach(u_char *, u_int16_t *, struct rde_peer *,
+ u_int8_t);
+int up_dump_mp_reach(u_char *, u_int16_t *, struct rde_peer *,
+ u_int8_t);
#endif /* __RDE_H__ */

View File

@ -0,0 +1,562 @@
Index: bgpd/rde_attr.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_attr.c,v
retrieving revision 1.1.1.6
retrieving revision 1.7
diff -u -p -r1.1.1.6 -r1.7
--- bgpd/rde_attr.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
+++ bgpd/rde_attr.c 13 Oct 2012 18:36:00 -0000 1.7
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_attr.c,v 1.79 2009/03/19 06:52:59 claudio Exp $ */
+/* $OpenBSD: rde_attr.c,v 1.90 2012/04/12 17:27:20 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -17,14 +17,22 @@
*/
#include <sys/types.h>
+#if defined(__FreeBSD__) /* sys/hash.h */
+#include "hash.h"
+#else
#include <sys/hash.h>
+#endif /* defined(__FreeBSD__) */
#include <sys/queue.h>
#include <netinet/in.h>
+#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#if defined(__FreeBSD__) /* limits.h */
+#include <limits.h>
+#endif /* defined(__FreeBSD__) */
#include "bgpd.h"
#include "rde.h"
@@ -36,12 +44,12 @@ attr_write(void *p, u_int16_t p_len, u_i
u_char *b = p;
u_int16_t tmp, tot_len = 2; /* attribute header (without len) */
+ flags &= ~ATTR_DEFMASK;
if (data_len > 255) {
tot_len += 2 + data_len;
flags |= ATTR_EXTLEN;
} else {
tot_len += 1 + data_len;
- flags &= ~ATTR_EXTLEN;
}
if (tot_len > p_len)
@@ -63,26 +71,26 @@ attr_write(void *p, u_int16_t p_len, u_i
}
int
-attr_writebuf(struct buf *buf, u_int8_t flags, u_int8_t type, void *data,
+attr_writebuf(struct ibuf *buf, u_int8_t flags, u_int8_t type, void *data,
u_int16_t data_len)
{
u_char hdr[4];
+ flags &= ~ATTR_DEFMASK;
if (data_len > 255) {
flags |= ATTR_EXTLEN;
hdr[2] = (data_len >> 8) & 0xff;
hdr[3] = data_len & 0xff;
} else {
- flags &= ~ATTR_EXTLEN;
hdr[2] = data_len & 0xff;
}
hdr[0] = flags;
hdr[1] = type;
- if (buf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1)
+ if (ibuf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1)
return (-1);
- if (buf_add(buf, data, data_len) == -1)
+ if (ibuf_add(buf, data, data_len) == -1)
return (-1);
return (0);
}
@@ -146,8 +154,11 @@ attr_optadd(struct rde_aspath *asp, u_in
for (l = 0; l < asp->others_len; l++) {
if (asp->others[l] == NULL)
break;
- if (type == asp->others[l]->type)
+ if (type == asp->others[l]->type) {
+ if (a->refcnt == 0)
+ attr_put(a);
return (-1);
+ }
}
/* add attribute to the table but first bump refcnt */
@@ -318,6 +329,7 @@ attr_alloc(u_int8_t flags, u_int8_t type
fatal("attr_optadd");
rdemem.attr_cnt++;
+ flags &= ~ATTR_DEFMASK; /* normalize mask */
a->flags = flags;
a->hash = hash32_buf(&flags, sizeof(flags), HASHINIT);
a->type = type;
@@ -347,6 +359,7 @@ attr_lookup(u_int8_t flags, u_int8_t typ
struct attr *a;
u_int32_t hash;
+ flags &= ~ATTR_DEFMASK; /* normalize mask */
hash = hash32_buf(&flags, sizeof(flags), HASHINIT);
hash = hash32_buf(&type, sizeof(type), hash);
hash = hash32_buf(&len, sizeof(len), hash);
@@ -405,6 +418,7 @@ aspath_verify(void *data, u_int16_t len,
u_int8_t *seg = data;
u_int16_t seg_size, as_size = 2;
u_int8_t seg_len, seg_type;
+ int err = 0;
if (len & 1)
/* odd length aspath are invalid */
@@ -419,7 +433,15 @@ aspath_verify(void *data, u_int16_t len,
seg_type = seg[0];
seg_len = seg[1];
- if (seg_type != AS_SET && seg_type != AS_SEQUENCE)
+ /*
+ * BGP confederations should not show up but consider them
+ * as a soft error which invalidates the path but keeps the
+ * bgp session running.
+ */
+ if (seg_type == AS_CONFED_SEQUENCE || seg_type == AS_CONFED_SET)
+ err = AS_ERR_SOFT;
+ if (seg_type != AS_SET && seg_type != AS_SEQUENCE &&
+ seg_type != AS_CONFED_SEQUENCE && seg_type != AS_CONFED_SET)
return (AS_ERR_TYPE);
seg_size = 2 + as_size * seg_len;
@@ -431,7 +453,7 @@ aspath_verify(void *data, u_int16_t len,
/* empty aspath segments are not allowed */
return (AS_ERR_BAD);
}
- return (0); /* aspath is valid but probably not loop free */
+ return (err); /* aspath is valid but probably not loop free */
}
void
@@ -762,15 +784,9 @@ aspath_countcopy(struct aspath *aspath,
u_int32_t
aspath_neighbor(struct aspath *aspath)
{
- /*
- * Empty aspath is OK -- internal as route.
- * But what is the neighbor? For now let's return 0.
- * That should not break anything.
- */
-
+ /* Empty aspath is OK -- internal AS route. */
if (aspath->len == 0)
- return (0);
-
+ return (rde_local_as());
return (aspath_extract(aspath->data, 0));
}
@@ -910,76 +926,63 @@ aspath_prepend(struct aspath *asp, u_int
return (p);
}
-/* we need to be able to search more than one as */
int
-aspath_match(struct aspath *a, enum as_spec type, u_int32_t as)
+aspath_lenmatch(struct aspath *a, enum aslen_spec type, u_int aslen)
{
u_int8_t *seg;
- int final;
+ u_int32_t as, lastas = 0;
+ u_int count = 0;
u_int16_t len, seg_size;
u_int8_t i, seg_type, seg_len;
- if (type == AS_EMPTY) {
- if (a->len == 0)
+ if (type == ASLEN_MAX) {
+ if (aslen < aspath_count(a->data, a->len))
return (1);
else
return (0);
}
- final = 0;
+ /* type == ASLEN_SEQ */
seg = a->data;
for (len = a->len; len > 0; len -= seg_size, seg += seg_size) {
seg_type = seg[0];
seg_len = seg[1];
seg_size = 2 + sizeof(u_int32_t) * seg_len;
- final = (len == seg_size);
-
- /* just check the first (leftmost) AS */
- if (type == AS_PEER) {
- if (as == aspath_extract(seg, 0))
- return (1);
- else
- return (0);
- }
- /* just check the final (rightmost) AS */
- if (type == AS_SOURCE) {
- /* not yet in the final segment */
- if (!final)
- continue;
-
- if (as == aspath_extract(seg, seg_len - 1))
- return (1);
- else
- return (0);
- }
-
- /* AS_TRANSIT or AS_ALL */
for (i = 0; i < seg_len; i++) {
- if (as == aspath_extract(seg, i)) {
- /*
- * the source (rightmost) AS is excluded from
- * AS_TRANSIT matches.
- */
- if (final && i == seg_len - 1 &&
- type == AS_TRANSIT)
- return (0);
- return (1);
- }
+ /* what should we do with AS_SET? */
+ as = aspath_extract(seg, i);
+ if (as == lastas) {
+ if (aslen < ++count)
+ return (1);
+ } else
+ count = 1;
+ lastas = as;
}
}
return (0);
}
+/*
+ * Functions handling communities and extended communities.
+ */
+
+int community_ext_matchone(struct filter_extcommunity *, u_int16_t, u_int64_t);
+
int
-community_match(void *data, u_int16_t len, int as, int type)
+community_match(struct rde_aspath *asp, int as, int type)
{
- u_int8_t *p = data;
- u_int16_t eas, etype;
+ struct attr *a;
+ u_int8_t *p;
+ u_int16_t eas, etype, len;
- len >>= 2; /* divide by four */
+ a = attr_optget(asp, ATTR_COMMUNITIES);
+ if (a == NULL)
+ /* no communities, no match */
+ return (0);
- for (; len > 0; len--) {
+ p = a->data;
+ for (len = a->len / 4; len > 0; len--) {
eas = *p++;
eas <<= 8;
eas |= *p++;
@@ -1000,7 +1003,6 @@ community_set(struct rde_aspath *asp, in
u_int8_t *p = NULL;
unsigned int i, ncommunities = 0;
u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE;
- u_int8_t t = ATTR_COMMUNITIES;
attr = attr_optget(asp, ATTR_COMMUNITIES);
if (attr != NULL) {
@@ -1017,7 +1019,7 @@ community_set(struct rde_aspath *asp, in
p += 4;
}
- if (ncommunities++ >= 0x3fff)
+ if (ncommunities++ >= USHRT_MAX / 4)
/* overflow */
return (0);
@@ -1032,11 +1034,10 @@ community_set(struct rde_aspath *asp, in
if (attr != NULL) {
memcpy(p + 4, attr->data, attr->len);
f = attr->flags;
- t = attr->type;
attr_free(asp, attr);
}
- attr_optadd(asp, f, t, p, ncommunities << 2);
+ attr_optadd(asp, f, ATTR_COMMUNITIES, p, ncommunities << 2);
free(p);
return (1);
@@ -1049,7 +1050,7 @@ community_delete(struct rde_aspath *asp,
u_int8_t *p, *n;
u_int16_t l, len = 0;
u_int16_t eas, etype;
- u_int8_t f, t;
+ u_int8_t f;
attr = attr_optget(asp, ATTR_COMMUNITIES);
if (attr == NULL)
@@ -1100,10 +1101,250 @@ community_delete(struct rde_aspath *asp,
}
f = attr->flags;
- t = attr->type;
attr_free(asp, attr);
- attr_optadd(asp, f, t, n, len);
+ attr_optadd(asp, f, ATTR_COMMUNITIES, n, len);
free(n);
}
+int
+community_ext_match(struct rde_aspath *asp, struct filter_extcommunity *c,
+ u_int16_t neighas)
+{
+ struct attr *attr;
+ u_int8_t *p;
+ u_int64_t ec;
+ u_int16_t len;
+
+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES);
+ if (attr == NULL)
+ /* no communities, no match */
+ return (0);
+
+ p = attr->data;
+ for (len = attr->len / sizeof(ec); len > 0; len--) {
+ memcpy(&ec, p, sizeof(ec));
+ if (community_ext_matchone(c, neighas, ec))
+ return (1);
+ p += sizeof(ec);
+ }
+
+ return (0);
+}
+
+int
+community_ext_set(struct rde_aspath *asp, struct filter_extcommunity *c,
+ u_int16_t neighas)
+{
+ struct attr *attr;
+ u_int8_t *p = NULL;
+ u_int64_t community;
+ unsigned int i, ncommunities = 0;
+ u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE;
+
+ if (community_ext_conv(c, neighas, &community))
+ return (0);
+
+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES);
+ if (attr != NULL) {
+ p = attr->data;
+ ncommunities = attr->len / sizeof(community);
+ }
+
+ /* first check if the community is not already set */
+ for (i = 0; i < ncommunities; i++) {
+ if (memcmp(&community, p, sizeof(community)) == 0)
+ /* already present, nothing todo */
+ return (1);
+ p += sizeof(community);
+ }
+
+ if (ncommunities++ >= USHRT_MAX / sizeof(community))
+ /* overflow */
+ return (0);
+
+ if ((p = malloc(ncommunities * sizeof(community))) == NULL)
+ fatal("community_ext_set");
+
+ memcpy(p, &community, sizeof(community));
+ if (attr != NULL) {
+ memcpy(p + sizeof(community), attr->data, attr->len);
+ f = attr->flags;
+ attr_free(asp, attr);
+ }
+
+ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, p,
+ ncommunities * sizeof(community));
+
+ free(p);
+ return (1);
+}
+
+void
+community_ext_delete(struct rde_aspath *asp, struct filter_extcommunity *c,
+ u_int16_t neighas)
+{
+ struct attr *attr;
+ u_int8_t *p, *n;
+ u_int64_t community;
+ u_int16_t l, len = 0;
+ u_int8_t f;
+
+ if (community_ext_conv(c, neighas, &community))
+ return;
+
+ attr = attr_optget(asp, ATTR_EXT_COMMUNITIES);
+ if (attr == NULL)
+ /* no attr nothing to do */
+ return;
+
+ p = attr->data;
+ for (l = 0; l < attr->len; l += sizeof(community)) {
+ if (memcmp(&community, p + l, sizeof(community)) == 0)
+ /* match */
+ continue;
+ len += sizeof(community);
+ }
+
+ if (len == 0) {
+ attr_free(asp, attr);
+ return;
+ }
+
+ if ((n = malloc(len)) == NULL)
+ fatal("community_delete");
+
+ p = attr->data;
+ for (l = 0; l < len && p < attr->data + attr->len;
+ p += sizeof(community)) {
+ if (memcmp(&community, p, sizeof(community)) == 0)
+ /* match */
+ continue;
+ memcpy(n + l, p, sizeof(community));
+ l += sizeof(community);
+ }
+
+ f = attr->flags;
+
+ attr_free(asp, attr);
+ attr_optadd(asp, f, ATTR_EXT_COMMUNITIES, n, len);
+ free(n);
+}
+
+int
+community_ext_conv(struct filter_extcommunity *c, u_int16_t neighas,
+ u_int64_t *community)
+{
+ u_int64_t com;
+ u_int32_t ip;
+
+ com = (u_int64_t)c->type << 56;
+ switch (c->type & EXT_COMMUNITY_VALUE) {
+ case EXT_COMMUNITY_TWO_AS:
+ com |= (u_int64_t)c->subtype << 48;
+ com |= (u_int64_t)c->data.ext_as.as << 32;
+ com |= c->data.ext_as.val;
+ break;
+ case EXT_COMMUNITY_IPV4:
+ com |= (u_int64_t)c->subtype << 48;
+ ip = ntohl(c->data.ext_ip.addr.s_addr);
+ com |= (u_int64_t)ip << 16;
+ com |= c->data.ext_ip.val;
+ break;
+ case EXT_COMMUNITY_FOUR_AS:
+ com |= (u_int64_t)c->subtype << 48;
+ com |= (u_int64_t)c->data.ext_as4.as4 << 16;
+ com |= c->data.ext_as4.val;
+ break;
+ case EXT_COMMUNITY_OPAQUE:
+ com |= (u_int64_t)c->subtype << 48;
+ com |= c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX;
+ break;
+ default:
+ com |= c->data.ext_opaq & 0xffffffffffffffULL;
+ break;
+ }
+
+ *community = htobe64(com);
+
+ return (0);
+}
+
+int
+community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas,
+ u_int64_t community)
+{
+ u_int64_t com, mask;
+ u_int32_t ip;
+
+ community = betoh64(community);
+
+ com = (u_int64_t)c->type << 56;
+ mask = 0xffULL << 56;
+ if ((com & mask) != (community & mask))
+ return (0);
+
+ switch (c->type & EXT_COMMUNITY_VALUE) {
+ case EXT_COMMUNITY_TWO_AS:
+ case EXT_COMMUNITY_IPV4:
+ case EXT_COMMUNITY_FOUR_AS:
+ case EXT_COMMUNITY_OPAQUE:
+ com = (u_int64_t)c->subtype << 48;
+ mask = 0xffULL << 48;
+ if ((com & mask) != (community & mask))
+ return (0);
+ break;
+ default:
+ com = c->data.ext_opaq & 0xffffffffffffffULL;
+ mask = 0xffffffffffffffULL;
+ if ((com & mask) == (community & mask))
+ return (1);
+ return (0);
+ }
+
+
+ switch (c->type & EXT_COMMUNITY_VALUE) {
+ case EXT_COMMUNITY_TWO_AS:
+ com = (u_int64_t)c->data.ext_as.as << 32;
+ mask = 0xffffULL << 32;
+ if ((com & mask) != (community & mask))
+ return (0);
+
+ com = c->data.ext_as.val;
+ mask = 0xffffffffULL;
+ if ((com & mask) == (community & mask))
+ return (1);
+ break;
+ case EXT_COMMUNITY_IPV4:
+ ip = ntohl(c->data.ext_ip.addr.s_addr);
+ com = (u_int64_t)ip << 16;
+ mask = 0xffffffff0000ULL;
+ if ((com & mask) != (community & mask))
+ return (0);
+
+ com = c->data.ext_ip.val;
+ mask = 0xffff;
+ if ((com & mask) == (community & mask))
+ return (1);
+ break;
+ case EXT_COMMUNITY_FOUR_AS:
+ com = (u_int64_t)c->data.ext_as4.as4 << 16;
+ mask = 0xffffffffULL << 16;
+ if ((com & mask) != (community & mask))
+ return (0);
+
+ com = c->data.ext_as4.val;
+ mask = 0xffff;
+ if ((com & mask) == (community & mask))
+ return (1);
+ break;
+ case EXT_COMMUNITY_OPAQUE:
+ com = c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX;
+ mask = EXT_COMMUNITY_OPAQUE_MAX;
+ if ((com & mask) == (community & mask))
+ return (1);
+ break;
+ }
+
+ return (0);
+}

View File

@ -0,0 +1,133 @@
Index: bgpd/rde_decide.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_decide.c,v
retrieving revision 1.1.1.6
retrieving revision 1.4
diff -u -p -r1.1.1.6 -r1.4
--- bgpd/rde_decide.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
+++ bgpd/rde_decide.c 13 Oct 2012 18:36:00 -0000 1.4
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_decide.c,v 1.58 2009/06/29 14:10:13 claudio Exp $ */
+/* $OpenBSD: rde_decide.c,v 1.61 2012/04/12 17:31:05 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -109,6 +109,9 @@ int
prefix_cmp(struct prefix *p1, struct prefix *p2)
{
struct rde_aspath *asp1, *asp2;
+ struct attr *a;
+ u_int32_t p1id, p2id;
+ int p1cnt, p2cnt;
if (p1 == NULL)
return (-1);
@@ -118,6 +121,12 @@ prefix_cmp(struct prefix *p1, struct pre
asp1 = p1->aspath;
asp2 = p2->aspath;
+ /* pathes with errors are not eligible */
+ if (asp1->flags & F_ATTR_PARSE_ERR)
+ return (-1);
+ if (asp2->flags & F_ATTR_PARSE_ERR)
+ return (1);
+
/* only loop free pathes are eligible */
if (asp1->flags & F_ATTR_LOOP)
return (-1);
@@ -130,7 +139,7 @@ prefix_cmp(struct prefix *p1, struct pre
if (asp1->nexthop != NULL && asp1->nexthop->state != NEXTHOP_REACH)
return (-1);
- /* 2. preference of prefix, bigger is better */
+ /* 2. local preference of prefix, bigger is better */
if ((asp1->lpref - asp2->lpref) != 0)
return (asp1->lpref - asp2->lpref);
@@ -154,10 +163,10 @@ prefix_cmp(struct prefix *p1, struct pre
* It is absolutely important that the ebgp value in peer_config.ebgp
* is bigger than all other ones (IBGP, confederations)
*/
- if ((asp1->peer->conf.ebgp - asp2->peer->conf.ebgp) != 0) {
- if (asp1->peer->conf.ebgp == 1) /* p1 is EBGP other is lower */
+ if (asp1->peer->conf.ebgp != asp2->peer->conf.ebgp) {
+ if (asp1->peer->conf.ebgp) /* p1 is EBGP other is lower */
return 1;
- else if (asp2->peer->conf.ebgp == 1) /* p2 is EBGP */
+ else if (asp2->peer->conf.ebgp) /* p2 is EBGP */
return -1;
}
@@ -181,13 +190,30 @@ prefix_cmp(struct prefix *p1, struct pre
if ((p2->lastchange - p1->lastchange) != 0)
return (p2->lastchange - p1->lastchange);
- /* 10. lowest BGP Id wins */
- if ((p2->aspath->peer->remote_bgpid -
- p1->aspath->peer->remote_bgpid) != 0)
- return (p2->aspath->peer->remote_bgpid -
- p1->aspath->peer->remote_bgpid);
+ /* 10. lowest BGP Id wins, use ORIGINATOR_ID if present */
+ if ((a = attr_optget(asp1, ATTR_ORIGINATOR_ID)) != NULL) {
+ memcpy(&p1id, a->data, sizeof(p1id));
+ p1id = ntohl(p1id);
+ } else
+ p1id = asp1->peer->remote_bgpid;
+ if ((a = attr_optget(asp2, ATTR_ORIGINATOR_ID)) != NULL) {
+ memcpy(&p2id, a->data, sizeof(p2id));
+ p2id = ntohl(p2id);
+ } else
+ p2id = asp2->peer->remote_bgpid;
+ if ((p2id - p1id) != 0)
+ return (p2id - p1id);
+
+ /* 11. compare CLUSTER_LIST length, shorter is better */
+ p1cnt = p2cnt = 0;
+ if ((a = attr_optget(asp1, ATTR_CLUSTER_LIST)) != NULL)
+ p1cnt = a->len / sizeof(u_int32_t);
+ if ((a = attr_optget(asp2, ATTR_CLUSTER_LIST)) != NULL)
+ p2cnt = a->len / sizeof(u_int32_t);
+ if ((p2cnt - p1cnt) != 0)
+ return (p2cnt - p1cnt);
- /* 11. lowest peer address wins (IPv4 is better than IPv6) */
+ /* 12. lowest peer address wins (IPv4 is better than IPv6) */
if (memcmp(&p1->aspath->peer->remote_addr,
&p2->aspath->peer->remote_addr,
sizeof(p1->aspath->peer->remote_addr)) != 0)
@@ -195,7 +221,7 @@ prefix_cmp(struct prefix *p1, struct pre
&p2->aspath->peer->remote_addr,
sizeof(p1->aspath->peer->remote_addr)));
- /* 12. for announced prefixes prefer dynamic routes */
+ /* 13. for announced prefixes prefer dynamic routes */
if ((asp1->flags & F_ANN_DYNAMIC) != (asp2->flags & F_ANN_DYNAMIC)) {
if (asp1->flags & F_ANN_DYNAMIC)
return (1);
@@ -204,7 +230,7 @@ prefix_cmp(struct prefix *p1, struct pre
}
fatalx("Uh, oh a politician in the decision process");
- /* NOTREACHED */
+ return(0); /* NOTREACHED */
}
/*
@@ -245,7 +271,7 @@ prefix_evaluate(struct prefix *p, struct
}
xp = LIST_FIRST(&re->prefix_h);
- if (xp == NULL || xp->aspath->flags & F_ATTR_LOOP ||
+ if (xp == NULL || xp->aspath->flags & (F_ATTR_LOOP|F_ATTR_PARSE_ERR) ||
(xp->aspath->nexthop != NULL &&
xp->aspath->nexthop->state != NEXTHOP_REACH))
/* xp is ineligible */
@@ -263,7 +289,7 @@ prefix_evaluate(struct prefix *p, struct
*/
rde_generate_updates(re->ribid, xp, re->active);
if ((re->flags & F_RIB_NOFIB) == 0)
- rde_send_kroute(xp, re->active);
+ rde_send_kroute(xp, re->active, re->ribid);
re->active = xp;
if (xp != NULL)

View File

@ -0,0 +1,297 @@
Index: bgpd/rde_filter.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_filter.c,v
retrieving revision 1.1.1.7
retrieving revision 1.9
diff -u -p -r1.1.1.7 -r1.9
--- bgpd/rde_filter.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/rde_filter.c 8 Dec 2012 20:17:59 -0000 1.9
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_filter.c,v 1.56 2009/06/06 01:10:29 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.67 2011/09/20 21:19:06 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -26,7 +26,7 @@
#include "rde.h"
int rde_filter_match(struct filter_rule *, struct rde_aspath *,
- struct bgpd_addr *, u_int8_t, struct rde_peer *);
+ struct bgpd_addr *, u_int8_t, struct rde_peer *, struct rde_peer *);
int filterset_equal(struct filter_set_head *, struct filter_set_head *);
enum filter_actions
@@ -40,6 +40,13 @@ rde_filter(u_int16_t ribid, struct rde_a
if (new != NULL)
*new = NULL;
+ if (asp->flags & F_ATTR_PARSE_ERR)
+ /*
+ * don't try to filter bad updates just deny them
+ * so they act as implicit withdraws
+ */
+ return (ACTION_DENY);
+
TAILQ_FOREACH(f, rules, entry) {
if (dir != f->dir)
continue;
@@ -51,7 +58,7 @@ rde_filter(u_int16_t ribid, struct rde_a
if (f->peer.peerid != 0 &&
f->peer.peerid != peer->conf.id)
continue;
- if (rde_filter_match(f, asp, prefix, prefixlen, peer)) {
+ if (rde_filter_match(f, asp, prefix, prefixlen, peer, from)) {
if (asp != NULL && new != NULL) {
/* asp may get modified so create a copy */
if (*new == NULL) {
@@ -59,7 +66,7 @@ rde_filter(u_int16_t ribid, struct rde_a
/* ... and use the copy from now on */
asp = *new;
}
- rde_apply_set(asp, &f->set, prefix->af,
+ rde_apply_set(asp, &f->set, prefix->aid,
from, peer);
}
if (f->action != ACTION_NONE)
@@ -73,7 +80,7 @@ rde_filter(u_int16_t ribid, struct rde_a
void
rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh,
- sa_family_t af, struct rde_peer *from, struct rde_peer *peer)
+ u_int8_t aid, struct rde_peer *from, struct rde_peer *peer)
{
struct filter_set *set;
u_char *np;
@@ -167,7 +174,7 @@ rde_apply_set(struct rde_aspath *asp, st
case ACTION_SET_NEXTHOP_NOMODIFY:
case ACTION_SET_NEXTHOP_SELF:
nexthop_modify(asp, &set->action.nexthop, set->type,
- af);
+ aid);
break;
case ACTION_SET_COMMUNITY:
switch (set->action.community.as) {
@@ -243,19 +250,42 @@ rde_apply_set(struct rde_aspath *asp, st
asp->rtlabelid = set->action.id;
rtlabel_ref(asp->rtlabelid);
break;
+ case ACTION_SET_ORIGIN:
+ asp->origin = set->action.origin;
+ break;
+ case ACTION_SET_EXT_COMMUNITY:
+ community_ext_set(asp, &set->action.ext_community,
+ peer->conf.remote_as);
+ break;
+ case ACTION_DEL_EXT_COMMUNITY:
+ community_ext_delete(asp, &set->action.ext_community,
+ peer->conf.remote_as);
+ break;
}
}
}
int
rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
- struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer)
+ struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer,
+ struct rde_peer *from)
{
- int as, type;
+ u_int32_t pas;
+ int cas, type;
- if (asp != NULL && f->match.as.type != AS_NONE)
- if (aspath_match(asp->aspath, f->match.as.type,
- f->match.as.as) == 0)
+ if (asp != NULL && f->match.as.type != AS_NONE) {
+ if (f->match.as.flags & AS_FLAG_NEIGHBORAS)
+ pas = peer->conf.remote_as;
+ else
+ pas = f->match.as.as;
+ if (aspath_match(asp->aspath->data, asp->aspath->len,
+ f->match.as.type, pas) == 0)
+ return (0);
+ }
+
+ if (asp != NULL && f->match.aslen.type != ASLEN_NONE)
+ if (aspath_lenmatch(asp->aspath, f->match.aslen.type,
+ f->match.aslen.aslen) == 0)
return (0);
if (asp != NULL && f->match.community.as != COMMUNITY_UNSET) {
@@ -263,10 +293,10 @@ rde_filter_match(struct filter_rule *f,
case COMMUNITY_ERROR:
fatalx("rde_apply_set bad community string");
case COMMUNITY_NEIGHBOR_AS:
- as = peer->conf.remote_as;
+ cas = peer->conf.remote_as;
break;
default:
- as = f->match.community.as;
+ cas = f->match.community.as;
break;
}
@@ -281,12 +311,17 @@ rde_filter_match(struct filter_rule *f,
break;
}
- if (rde_filter_community(asp, as, type) == 0)
+ if (community_match(asp, cas, type) == 0)
return (0);
}
+ if (asp != NULL &&
+ (f->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID))
+ if (community_ext_match(asp, &f->match.ext_community,
+ peer->conf.remote_as) == 0)
+ return (0);
- if (f->match.prefix.addr.af != 0) {
- if (f->match.prefix.addr.af != prefix->af)
+ if (f->match.prefix.addr.aid != 0) {
+ if (f->match.prefix.addr.aid != prefix->aid)
/* don't use IPv4 rules for IPv6 and vice versa */
return (0);
@@ -322,7 +357,7 @@ rde_filter_match(struct filter_rule *f,
} else if (f->match.prefixlen.op != OP_NONE) {
/* only prefixlen without a prefix */
- if (f->match.prefixlen.af != prefix->af)
+ if (f->match.prefixlen.aid != prefix->aid)
/* don't use IPv4 rules for IPv6 and vice versa */
return (0);
@@ -350,25 +385,40 @@ rde_filter_match(struct filter_rule *f,
}
/* NOTREACHED */
}
+ if (f->match.nexthop.flags != 0) {
+ struct bgpd_addr *nexthop, *cmpaddr;
+ if (asp->nexthop == NULL)
+ /* no nexthop, skip */
+ return (0);
+ nexthop = &asp->nexthop->exit_nexthop;
+ if (f->match.nexthop.flags == FILTER_NEXTHOP_ADDR)
+ cmpaddr = &f->match.nexthop.addr;
+ else
+ cmpaddr = &from->remote_addr;
+ if (cmpaddr->aid != nexthop->aid)
+ /* don't use IPv4 rules for IPv6 and vice versa */
+ return (0);
+
+ switch (cmpaddr->aid) {
+ case AID_INET:
+ if (cmpaddr->v4.s_addr != nexthop->v4.s_addr)
+ return (0);
+ break;
+ case AID_INET6:
+ if (memcmp(&cmpaddr->v6, &nexthop->v6,
+ sizeof(struct in6_addr)))
+ return (0);
+ break;
+ default:
+ fatalx("King Bula lost in address space");
+ }
+ }
/* matched somewhen or is anymatch rule */
return (1);
}
int
-rde_filter_community(struct rde_aspath *asp, int as, int type)
-{
- struct attr *a;
-
- a = attr_optget(asp, ATTR_COMMUNITIES);
- if (a == NULL)
- /* no communities, no match */
- return (0);
-
- return (community_match(a->data, a->len, as, type));
-}
-
-int
rde_filter_equal(struct filter_head *a, struct filter_head *b,
struct rde_peer *peer, enum directions dir)
{
@@ -476,6 +526,12 @@ filterset_cmp(struct filter_set *a, stru
return (a->action.community.type - b->action.community.type);
}
+ if (a->type == ACTION_SET_EXT_COMMUNITY ||
+ a->type == ACTION_DEL_EXT_COMMUNITY) { /* a->type == b->type */
+ return (memcmp(&a->action.ext_community,
+ &b->action.ext_community, sizeof(a->action.ext_community)));
+ }
+
if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) {
/*
* This is the only interesting case, all others are considered
@@ -483,13 +539,29 @@ filterset_cmp(struct filter_set *a, stru
* reject it at the same time. Allow one IPv4 and one IPv6
* per filter set or only one of the other nexthop modifiers.
*/
- return (a->action.nexthop.af - b->action.nexthop.af);
+ return (a->action.nexthop.aid - b->action.nexthop.aid);
}
/* equal */
return (0);
}
+void
+filterset_move(struct filter_set_head *source, struct filter_set_head *dest)
+{
+ struct filter_set *s;
+
+ TAILQ_INIT(dest);
+
+ if (source == NULL)
+ return;
+
+ while ((s = TAILQ_FIRST(source)) != NULL) {
+ TAILQ_REMOVE(source, s, entry);
+ TAILQ_INSERT_TAIL(dest, s, entry);
+ }
+}
+
int
filterset_equal(struct filter_set_head *ah, struct filter_set_head *bh)
{
@@ -574,6 +646,19 @@ filterset_equal(struct filter_set_head *
if (strcmp(as, bs) == 0)
continue;
break;
+ case ACTION_SET_ORIGIN:
+ if (a->type == b->type &&
+ a->action.origin == b->action.origin)
+ continue;
+ break;
+ case ACTION_SET_EXT_COMMUNITY:
+ case ACTION_DEL_EXT_COMMUNITY:
+ if (a->type == b->type && memcmp(
+ &a->action.ext_community,
+ &b->action.ext_community,
+ sizeof(a->action.ext_community)) == 0)
+ continue;
+ break;
}
/* compare failed */
return (0);
@@ -616,7 +701,14 @@ filterset_name(enum action_types type)
case ACTION_RTLABEL:
case ACTION_RTLABEL_ID:
return ("rtlabel");
+ case ACTION_SET_ORIGIN:
+ return ("origin");
+ case ACTION_SET_EXT_COMMUNITY:
+ return ("ext-community");
+ case ACTION_DEL_EXT_COMMUNITY:
+ return ("ext-community delete");
}
fatalx("filterset_name: got lost");
+ return (NULL); /* NOT REACHED */
}

View File

@ -0,0 +1,301 @@
Index: bgpd/rde_prefix.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_prefix.c,v
retrieving revision 1.1.1.6
retrieving revision 1.6
diff -u -p -r1.1.1.6 -r1.6
--- bgpd/rde_prefix.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
+++ bgpd/rde_prefix.c 13 Oct 2012 18:36:00 -0000 1.6
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_prefix.c,v 1.29 2009/05/30 18:27:17 claudio Exp $ */
+/* $OpenBSD: rde_prefix.c,v 1.31 2010/01/13 06:02:37 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -38,15 +38,16 @@
* pt_lookup: lookup a IP in the prefix table. Mainly for "show ip bgp".
* pt_empty: returns true if there is no bgp prefix linked to the pt_entry.
* pt_init: initialize prefix table.
- * pt_alloc?: allocate a AF specific pt_entry. Internal function.
+ * pt_alloc: allocate a AF specific pt_entry. Internal function.
* pt_free: free a pt_entry. Internal function.
*/
/* internal prototypes */
-static struct pt_entry4 *pt_alloc4(void);
-static struct pt_entry6 *pt_alloc6(void);
+static struct pt_entry *pt_alloc(struct pt_entry *);
static void pt_free(struct pt_entry *);
+size_t pt_sizes[AID_MAX] = AID_PTSIZE;
+
RB_HEAD(pt_tree, pt_entry);
RB_PROTOTYPE(pt_tree, pt_entry, pt_e, pt_prefix_cmp);
RB_GENERATE(pt_tree, pt_entry, pt_e, pt_prefix_cmp);
@@ -70,17 +71,24 @@ void
pt_getaddr(struct pt_entry *pte, struct bgpd_addr *addr)
{
bzero(addr, sizeof(struct bgpd_addr));
- switch (pte->af) {
- case AF_INET:
- addr->af = pte->af;
+ addr->aid = pte->aid;
+ switch (addr->aid) {
+ case AID_INET:
addr->v4 = ((struct pt_entry4 *)pte)->prefix4;
break;
- case AF_INET6:
- addr->af = pte->af;
+ case AID_INET6:
memcpy(&addr->v6, &((struct pt_entry6 *)pte)->prefix6,
sizeof(addr->v6));
/* XXX scope_id ??? */
break;
+ case AID_VPN_IPv4:
+ addr->vpn4.addr = ((struct pt_entry_vpn4 *)pte)->prefix4;
+ addr->vpn4.rd = ((struct pt_entry_vpn4 *)pte)->rd;
+ addr->vpn4.labellen = ((struct pt_entry_vpn4 *)pte)->labellen;
+ memcpy(addr->vpn4.labelstack,
+ ((struct pt_entry_vpn4 *)pte)->labelstack,
+ addr->vpn4.labellen);
+ break;
default:
fatalx("pt_getaddr: unknown af");
}
@@ -89,33 +97,49 @@ pt_getaddr(struct pt_entry *pte, struct
struct pt_entry *
pt_fill(struct bgpd_addr *prefix, int prefixlen)
{
- static struct pt_entry4 pte4;
- static struct pt_entry6 pte6;
- in_addr_t addr_hbo;
+ static struct pt_entry4 pte4;
+ static struct pt_entry6 pte6;
+ static struct pt_entry_vpn4 pte_vpn4;
+ in_addr_t addr_hbo;
- switch (prefix->af) {
- case AF_INET:
+ switch (prefix->aid) {
+ case AID_INET:
bzero(&pte4, sizeof(pte4));
+ pte4.aid = prefix->aid;
if (prefixlen > 32)
- fatalx("pt_get: bad IPv4 prefixlen");
- pte4.af = AF_INET;
+ fatalx("pt_fill: bad IPv4 prefixlen");
addr_hbo = ntohl(prefix->v4.s_addr);
pte4.prefix4.s_addr = htonl(addr_hbo &
prefixlen2mask(prefixlen));
pte4.prefixlen = prefixlen;
return ((struct pt_entry *)&pte4);
- case AF_INET6:
+ case AID_INET6:
bzero(&pte6, sizeof(pte6));
+ pte6.aid = prefix->aid;
if (prefixlen > 128)
fatalx("pt_get: bad IPv6 prefixlen");
- pte6.af = AF_INET6;
pte6.prefixlen = prefixlen;
inet6applymask(&pte6.prefix6, &prefix->v6, prefixlen);
return ((struct pt_entry *)&pte6);
+ case AID_VPN_IPv4:
+ bzero(&pte_vpn4, sizeof(pte_vpn4));
+ pte_vpn4.aid = prefix->aid;
+ if (prefixlen > 32)
+ fatalx("pt_fill: bad IPv4 prefixlen");
+ addr_hbo = ntohl(prefix->vpn4.addr.s_addr);
+ pte_vpn4.prefix4.s_addr = htonl(addr_hbo &
+ prefixlen2mask(prefixlen));
+ pte_vpn4.prefixlen = prefixlen;
+ pte_vpn4.rd = prefix->vpn4.rd;
+ pte_vpn4.labellen = prefix->vpn4.labellen;
+ memcpy(pte_vpn4.labelstack, prefix->vpn4.labelstack,
+ prefix->vpn4.labellen);
+ return ((struct pt_entry *)&pte_vpn4);
default:
- log_warnx("pt_get: unknown af");
- return (NULL);
+ fatalx("pt_fill: unknown af");
}
+ /* NOT REACHED */
+ return (NULL);
}
struct pt_entry *
@@ -131,39 +155,12 @@ struct pt_entry *
pt_add(struct bgpd_addr *prefix, int prefixlen)
{
struct pt_entry *p = NULL;
- struct pt_entry4 *p4;
- struct pt_entry6 *p6;
- in_addr_t addr_hbo;
-
- switch (prefix->af) {
- case AF_INET:
- p4 = pt_alloc4();
- if (prefixlen > 32)
- fatalx("pt_add: bad IPv4 prefixlen");
- p4->af = AF_INET;
- p4->prefixlen = prefixlen;
- addr_hbo = ntohl(prefix->v4.s_addr);
- p4->prefix4.s_addr = htonl(addr_hbo &
- prefixlen2mask(prefixlen));
- p = (struct pt_entry *)p4;
- break;
- case AF_INET6:
- p6 = pt_alloc6();
- if (prefixlen > 128)
- fatalx("pt_add: bad IPv6 prefixlen");
- p6->af = AF_INET6;
- p6->prefixlen = prefixlen;
- inet6applymask(&p6->prefix6, &prefix->v6, prefixlen);
- p = (struct pt_entry *)p6;
- break;
- default:
- fatalx("pt_add: unknown af");
- }
- if (RB_INSERT(pt_tree, &pttable, p) != NULL) {
- log_warnx("pt_add: insert failed");
- return (NULL);
- }
+ p = pt_fill(prefix, prefixlen);
+ p = pt_alloc(p);
+
+ if (RB_INSERT(pt_tree, &pttable, p) != NULL)
+ fatalx("pt_add: insert failed");
return (p);
}
@@ -183,13 +180,14 @@ struct pt_entry *
pt_lookup(struct bgpd_addr *addr)
{
struct pt_entry *p;
- int i;
+ int i = 0;
- switch (addr->af) {
- case AF_INET:
+ switch (addr->aid) {
+ case AID_INET:
+ case AID_VPN_IPv4:
i = 32;
break;
- case AF_INET6:
+ case AID_INET6:
i = 128;
break;
default:
@@ -206,17 +204,18 @@ pt_lookup(struct bgpd_addr *addr)
int
pt_prefix_cmp(const struct pt_entry *a, const struct pt_entry *b)
{
- const struct pt_entry4 *a4, *b4;
- const struct pt_entry6 *a6, *b6;
- int i;
+ const struct pt_entry4 *a4, *b4;
+ const struct pt_entry6 *a6, *b6;
+ const struct pt_entry_vpn4 *va4, *vb4;
+ int i;
- if (a->af > b->af)
+ if (a->aid > b->aid)
return (1);
- if (a->af < b->af)
+ if (a->aid < b->aid)
return (-1);
- switch (a->af) {
- case AF_INET:
+ switch (a->aid) {
+ case AID_INET:
a4 = (const struct pt_entry4 *)a;
b4 = (const struct pt_entry4 *)b;
if (ntohl(a4->prefix4.s_addr) > ntohl(b4->prefix4.s_addr))
@@ -228,7 +227,7 @@ pt_prefix_cmp(const struct pt_entry *a,
if (a4->prefixlen < b4->prefixlen)
return (-1);
return (0);
- case AF_INET6:
+ case AID_INET6:
a6 = (const struct pt_entry6 *)a;
b6 = (const struct pt_entry6 *)b;
@@ -242,49 +241,49 @@ pt_prefix_cmp(const struct pt_entry *a,
if (a6->prefixlen > b6->prefixlen)
return (1);
return (0);
+ case AID_VPN_IPv4:
+ va4 = (const struct pt_entry_vpn4 *)a;
+ vb4 = (const struct pt_entry_vpn4 *)b;
+ if (ntohl(va4->prefix4.s_addr) > ntohl(vb4->prefix4.s_addr))
+ return (1);
+ if (ntohl(va4->prefix4.s_addr) < ntohl(vb4->prefix4.s_addr))
+ return (-1);
+ if (va4->prefixlen > vb4->prefixlen)
+ return (1);
+ if (va4->prefixlen < vb4->prefixlen)
+ return (-1);
+ if (betoh64(va4->rd) > betoh64(vb4->rd))
+ return (1);
+ if (betoh64(va4->rd) < betoh64(vb4->rd))
+ return (-1);
+ return (0);
default:
fatalx("pt_prefix_cmp: unknown af");
}
return (-1);
}
-/* returns a zeroed pt_entry function may not return on fail */
-static struct pt_entry4 *
-pt_alloc4(void)
+/*
+ * Returns a pt_entry cloned from the one passed in.
+ * Function may not return on failure.
+ */
+static struct pt_entry *
+pt_alloc(struct pt_entry *op)
{
- struct pt_entry4 *p;
+ struct pt_entry *p;
- p = calloc(1, sizeof(*p));
+ p = malloc(pt_sizes[op->aid]);
if (p == NULL)
fatal("pt_alloc");
- rdemem.pt4_cnt++;
- return (p);
-}
+ rdemem.pt_cnt[op->aid]++;
+ memcpy(p, op, pt_sizes[op->aid]);
-static struct pt_entry6 *
-pt_alloc6(void)
-{
- struct pt_entry6 *p;
-
- p = calloc(1, sizeof(*p));
- if (p == NULL)
- fatal("pt_alloc");
- rdemem.pt6_cnt++;
return (p);
}
static void
pt_free(struct pt_entry *pte)
{
- switch (pte->af) {
- case AF_INET:
- rdemem.pt4_cnt--;
- break;
- case AF_INET6:
- rdemem.pt6_cnt--;
- break;
- default:
- break;
- }
+ rdemem.pt_cnt[pte->aid]--;
free(pte);
}

View File

@ -0,0 +1,513 @@
Index: bgpd/rde_rib.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_rib.c,v
retrieving revision 1.1.1.7
retrieving revision 1.8
diff -u -p -r1.1.1.7 -r1.8
--- bgpd/rde_rib.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/rde_rib.c 13 Oct 2012 18:36:00 -0000 1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.116 2009/06/29 14:13:48 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.133 2012/07/01 11:55:13 sthen Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -18,7 +18,11 @@
#include <sys/types.h>
#include <sys/queue.h>
+#if defined(__FreeBSD__) /* sys/hash.h */
+#include "hash.h"
+#else
#include <sys/hash.h>
+#endif /* defined(__FreeBSD__) */
#include <stdlib.h>
#include <string.h>
@@ -50,16 +54,15 @@ RB_GENERATE(rib_tree, rib_entry, rib_e,
/* RIB specific functions */
u_int16_t
-rib_new(int id, char *name, u_int16_t flags)
+rib_new(char *name, u_int rtableid, u_int16_t flags)
{
struct rib *xribs;
size_t newsize;
+ u_int16_t id;
- if (id < 0) {
- for (id = 0; id < rib_size; id++) {
- if (*ribs[id].name == '\0')
- break;
- }
+ for (id = 0; id < rib_size; id++) {
+ if (*ribs[id].name == '\0')
+ break;
}
if (id == RIB_FAILED)
@@ -78,9 +81,10 @@ rib_new(int id, char *name, u_int16_t fl
bzero(&ribs[id], sizeof(struct rib));
strlcpy(ribs[id].name, name, sizeof(ribs[id].name));
RB_INIT(&ribs[id].rib);
- ribs[id].state = RIB_ACTIVE;
+ ribs[id].state = RECONF_REINIT;
ribs[id].id = id;
ribs[id].flags = flags;
+ ribs[id].rtableid = rtableid;
return (id);
}
@@ -173,15 +177,16 @@ rib_lookup(struct rib *rib, struct bgpd_
struct rib_entry *re;
int i;
- switch (addr->af) {
- case AF_INET:
+ switch (addr->aid) {
+ case AID_INET:
+ case AID_VPN_IPv4:
for (i = 32; i >= 0; i--) {
re = rib_get(rib, addr, i);
if (re != NULL)
return (re);
}
break;
- case AF_INET6:
+ case AID_INET6:
for (i = 128; i >= 0; i--) {
re = rib_get(rib, addr, i);
if (re != NULL)
@@ -215,6 +220,7 @@ rib_add(struct rib *rib, struct bgpd_add
if (RB_INSERT(rib_tree, &rib->rib, re) != NULL) {
log_warnx("rib_add: insert failed");
+ free(re);
return (NULL);
}
@@ -254,7 +260,7 @@ rib_empty(struct rib_entry *re)
void
rib_dump(struct rib *rib, void (*upcall)(struct rib_entry *, void *),
- void *arg, sa_family_t af)
+ void *arg, u_int8_t aid)
{
struct rib_context *ctx;
@@ -263,7 +269,7 @@ rib_dump(struct rib *rib, void (*upcall)
ctx->ctx_rib = rib;
ctx->ctx_upcall = upcall;
ctx->ctx_arg = arg;
- ctx->ctx_af = af;
+ ctx->ctx_aid = aid;
rib_dump_r(ctx);
}
@@ -280,7 +286,8 @@ rib_dump_r(struct rib_context *ctx)
re = rib_restart(ctx);
for (i = 0; re != NULL; re = RB_NEXT(rib_tree, unused, re)) {
- if (ctx->ctx_af != AF_UNSPEC && ctx->ctx_af != re->prefix->af)
+ if (ctx->ctx_aid != AID_UNSPEC &&
+ ctx->ctx_aid != re->prefix->aid)
continue;
if (ctx->ctx_count && i++ >= ctx->ctx_count &&
(re->flags & F_RIB_ENTRYLOCK) == 0) {
@@ -308,7 +315,7 @@ rib_restart(struct rib_context *ctx)
re->flags &= ~F_RIB_ENTRYLOCK;
/* find first non empty element */
- while (rib_empty(re))
+ while (re && rib_empty(re))
re = RB_NEXT(rib_tree, unused, re);
/* free the previously locked rib element if empty */
@@ -502,6 +509,36 @@ path_remove(struct rde_aspath *asp)
}
}
+/* remove all stale routes or if staletime is 0 remove all routes for
+ a specified AID. */
+void
+path_remove_stale(struct rde_aspath *asp, u_int8_t aid)
+{
+ struct prefix *p, *np;
+ time_t staletime;
+
+ staletime = asp->peer->staletime[aid];
+ for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = np) {
+ np = LIST_NEXT(p, path_l);
+ if (p->prefix->aid != aid)
+ continue;
+
+ if (staletime && p->lastchange > staletime)
+ continue;
+
+ if (asp->pftableid) {
+ struct bgpd_addr addr;
+
+ pt_getaddr(p->prefix, &addr);
+ /* Commit is done in peer_flush() */
+ rde_send_pftable(p->aspath->pftableid, &addr,
+ p->prefix->prefixlen, 1);
+ }
+ prefix_destroy(p);
+ }
+}
+
+
/* this function is only called by prefix_remove and path_remove */
void
path_destroy(struct rde_aspath *asp)
@@ -624,48 +661,6 @@ static void prefix_link(struct prefix
struct rde_aspath *);
static void prefix_unlink(struct prefix *);
-int
-prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b,
- int prefixlen)
-{
- in_addr_t mask, aa, ba;
- int i;
- u_int8_t m;
-
- if (a->af != b->af)
- return (a->af - b->af);
-
- switch (a->af) {
- case AF_INET:
- if (prefixlen > 32)
- fatalx("prefix_cmp: bad IPv4 prefixlen");
- mask = htonl(prefixlen2mask(prefixlen));
- aa = ntohl(a->v4.s_addr & mask);
- ba = ntohl(b->v4.s_addr & mask);
- if (aa != ba)
- return (aa - ba);
- return (0);
- case AF_INET6:
- if (prefixlen > 128)
- fatalx("prefix_cmp: bad IPv6 prefixlen");
- for (i = 0; i < prefixlen / 8; i++)
- if (a->v6.s6_addr[i] != b->v6.s6_addr[i])
- return (a->v6.s6_addr[i] - b->v6.s6_addr[i]);
- i = prefixlen % 8;
- if (i) {
- m = 0xff00 >> i;
- if ((a->v6.s6_addr[prefixlen / 8] & m) !=
- (b->v6.s6_addr[prefixlen / 8] & m))
- return ((a->v6.s6_addr[prefixlen / 8] & m) -
- (b->v6.s6_addr[prefixlen / 8] & m));
- }
- return (0);
- default:
- fatalx("prefix_cmp: unknown af");
- }
- return (-1);
-}
-
/*
* search for specified prefix of a peer. Returns NULL if not found.
*/
@@ -806,16 +801,58 @@ prefix_write(u_char *buf, int len, struc
{
int totlen;
- if (prefix->af != AF_INET && prefix->af != AF_INET6)
+ switch (prefix->aid) {
+ case AID_INET:
+ case AID_INET6:
+ totlen = PREFIX_SIZE(plen);
+
+ if (totlen > len)
+ return (-1);
+ *buf++ = plen;
+ memcpy(buf, &prefix->ba, totlen - 1);
+ return (totlen);
+ case AID_VPN_IPv4:
+ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) +
+ prefix->vpn4.labellen;
+ plen += (sizeof(prefix->vpn4.rd) + prefix->vpn4.labellen) * 8;
+
+ if (totlen > len)
+ return (-1);
+ *buf++ = plen;
+ memcpy(buf, &prefix->vpn4.labelstack, prefix->vpn4.labellen);
+ buf += prefix->vpn4.labellen;
+ memcpy(buf, &prefix->vpn4.rd, sizeof(prefix->vpn4.rd));
+ buf += sizeof(prefix->vpn4.rd);
+ memcpy(buf, &prefix->vpn4.addr, PREFIX_SIZE(plen) - 1);
+ return (totlen);
+ default:
return (-1);
+ }
+}
- totlen = PREFIX_SIZE(plen);
+int
+prefix_writebuf(struct ibuf *buf, struct bgpd_addr *prefix, u_int8_t plen)
+{
+ int totlen;
+ void *bptr;
- if (totlen > len)
+ 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);
- *buf++ = plen;
- memcpy(buf, &prefix->ba, totlen - 1);
- return (totlen);
+ }
+
+ if ((bptr = ibuf_reserve(buf, totlen)) == NULL)
+ return (-1);
+ if (prefix_write(bptr, totlen, prefix, plen) == -1)
+ return (-1);
+ return (0);
}
/*
@@ -861,7 +898,7 @@ prefix_updateall(struct rde_aspath *asp,
*/
if ((p->rib->flags & F_RIB_NOFIB) == 0 &&
p == p->rib->active)
- rde_send_kroute(p, NULL);
+ rde_send_kroute(p, NULL, p->rib->ribid);
continue;
}
@@ -871,7 +908,7 @@ prefix_updateall(struct rde_aspath *asp,
* If the prefix is the active one remove it first,
* this has to be done because we can not detect when
* the active prefix changes its state. In this case
- * we know that this is a withdrawl and so the second
+ * we know that this is a withdrawal and so the second
* prefix_evaluate() will generate no update because
* the nexthop is unreachable or ineligible.
*/
@@ -885,16 +922,12 @@ prefix_updateall(struct rde_aspath *asp,
void
prefix_destroy(struct prefix *p)
{
- struct rib_entry *re;
struct rde_aspath *asp;
- re = p->rib;
asp = p->aspath;
prefix_unlink(p);
prefix_free(p);
- if (rib_empty(re))
- rib_remove(re);
if (path_empty(asp))
path_destroy(asp);
}
@@ -907,21 +940,16 @@ prefix_network_clean(struct rde_peer *pe
{
struct rde_aspath *asp, *xasp;
struct prefix *p, *xp;
- struct pt_entry *pte;
for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = xasp) {
xasp = LIST_NEXT(asp, peer_l);
- if ((asp->flags & F_ANN_DYNAMIC) == flags)
+ if ((asp->flags & F_ANN_DYNAMIC) != flags)
continue;
for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = xp) {
xp = LIST_NEXT(p, path_l);
if (reloadtime > p->lastchange) {
- pte = p->prefix;
prefix_unlink(p);
prefix_free(p);
-
- if (pt_empty(pte))
- pt_remove(pte);
}
}
if (path_empty(asp))
@@ -954,11 +982,11 @@ prefix_link(struct prefix *pref, struct
static void
prefix_unlink(struct prefix *pref)
{
- if (pref->rib) {
- /* make route decision */
- LIST_REMOVE(pref, rib_l);
- prefix_evaluate(NULL, pref->rib);
- }
+ struct rib_entry *re = pref->rib;
+
+ /* make route decision */
+ LIST_REMOVE(pref, rib_l);
+ prefix_evaluate(NULL, re);
LIST_REMOVE(pref, path_l);
PREFIX_COUNT(pref->aspath, -1);
@@ -966,6 +994,8 @@ prefix_unlink(struct prefix *pref)
pt_unref(pref->prefix);
if (pt_empty(pref->prefix))
pt_remove(pref->prefix);
+ if (rib_empty(re))
+ rib_remove(re);
/* destroy all references to other objects */
pref->aspath = NULL;
@@ -973,8 +1003,8 @@ prefix_unlink(struct prefix *pref)
pref->rib = NULL;
/*
- * It's the caller's duty to remove empty aspath respectively pt_entry
- * structures. Also freeing the unlinked prefix is the caller's duty.
+ * It's the caller's duty to remove empty aspath structures.
+ * Also freeing the unlinked prefix is the caller's duty.
*/
}
@@ -1070,10 +1100,6 @@ nexthop_update(struct kroute_nexthop *ms
return;
}
- if (nexthop_delete(nh))
- /* nexthop no longer used */
- return;
-
oldstate = nh->state;
if (msg->valid)
nh->state = NEXTHOP_REACH;
@@ -1088,21 +1114,13 @@ nexthop_update(struct kroute_nexthop *ms
memcpy(&nh->true_nexthop, &msg->gateway,
sizeof(nh->true_nexthop));
- switch (msg->nexthop.af) {
- case AF_INET:
- nh->nexthop_netlen = msg->kr.kr4.prefixlen;
- nh->nexthop_net.af = AF_INET;
- nh->nexthop_net.v4.s_addr = msg->kr.kr4.prefix.s_addr;
- break;
- case AF_INET6:
- nh->nexthop_netlen = msg->kr.kr6.prefixlen;
- nh->nexthop_net.af = AF_INET6;
- memcpy(&nh->nexthop_net.v6, &msg->kr.kr6.prefix,
- sizeof(struct in6_addr));
- break;
- default:
- fatalx("nexthop_update: unknown af");
- }
+ memcpy(&nh->nexthop_net, &msg->net,
+ sizeof(nh->nexthop_net));
+ nh->nexthop_netlen = msg->netlen;
+
+ if (nexthop_delete(nh))
+ /* nexthop no longer used */
+ return;
if (rde_noevaluate())
/*
@@ -1118,35 +1136,38 @@ nexthop_update(struct kroute_nexthop *ms
void
nexthop_modify(struct rde_aspath *asp, struct bgpd_addr *nexthop,
- enum action_types type, sa_family_t af)
+ enum action_types type, u_int8_t aid)
{
struct nexthop *nh;
- if (type == ACTION_SET_NEXTHOP_REJECT) {
- asp->flags |= F_NEXTHOP_REJECT;
+ if (type == ACTION_SET_NEXTHOP && aid != nexthop->aid)
return;
- }
- if (type == ACTION_SET_NEXTHOP_BLACKHOLE) {
+
+ asp->flags &= ~F_NEXTHOP_MASK;
+ switch (type) {
+ case ACTION_SET_NEXTHOP_REJECT:
+ asp->flags |= F_NEXTHOP_REJECT;
+ break;
+ case ACTION_SET_NEXTHOP_BLACKHOLE:
asp->flags |= F_NEXTHOP_BLACKHOLE;
- return;
- }
- if (type == ACTION_SET_NEXTHOP_NOMODIFY) {
+ break;
+ case ACTION_SET_NEXTHOP_NOMODIFY:
asp->flags |= F_NEXTHOP_NOMODIFY;
- return;
- }
- if (type == ACTION_SET_NEXTHOP_SELF) {
+ break;
+ case ACTION_SET_NEXTHOP_SELF:
asp->flags |= F_NEXTHOP_SELF;
- return;
+ break;
+ case ACTION_SET_NEXTHOP:
+ nh = nexthop_get(nexthop);
+ if (asp->flags & F_ATTR_LINKED)
+ nexthop_unlink(asp);
+ asp->nexthop = nh;
+ if (asp->flags & F_ATTR_LINKED)
+ nexthop_link(asp);
+ break;
+ default:
+ break;
}
- if (af != nexthop->af)
- return;
-
- nh = nexthop_get(nexthop);
- if (asp->flags & F_ATTR_LINKED)
- nexthop_unlink(asp);
- asp->nexthop = nh;
- if (asp->flags & F_ATTR_LINKED)
- nexthop_link(asp);
}
void
@@ -1233,17 +1254,17 @@ nexthop_compare(struct nexthop *na, stru
a = &na->exit_nexthop;
b = &nb->exit_nexthop;
- if (a->af != b->af)
- return (a->af - b->af);
+ if (a->aid != b->aid)
+ return (a->aid - b->aid);
- switch (a->af) {
- case AF_INET:
+ switch (a->aid) {
+ case AID_INET:
if (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr))
return (1);
if (ntohl(a->v4.s_addr) < ntohl(b->v4.s_addr))
return (-1);
return (0);
- case AF_INET6:
+ case AID_INET6:
return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr)));
default:
fatalx("nexthop_cmp: unknown af");
@@ -1269,14 +1290,14 @@ nexthop_hash(struct bgpd_addr *nexthop)
{
u_int32_t h = 0;
- switch (nexthop->af) {
- case AF_INET:
+ switch (nexthop->aid) {
+ case AID_INET:
h = (AF_INET ^ ntohl(nexthop->v4.s_addr) ^
ntohl(nexthop->v4.s_addr) >> 13) &
nexthoptable.nexthop_hashmask;
break;
- case AF_INET6:
- h = hash32_buf(nexthop->v6.s6_addr, sizeof(struct in6_addr),
+ case AID_INET6:
+ h = hash32_buf(&nexthop->v6, sizeof(struct in6_addr),
HASHINIT) & nexthoptable.nexthop_hashmask;
break;
default:

View File

@ -0,0 +1,644 @@
Index: bgpd/rde_update.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_update.c,v
retrieving revision 1.1.1.7
retrieving revision 1.8
diff -u -p -r1.1.1.7 -r1.8
--- bgpd/rde_update.c 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/rde_update.c 13 Oct 2012 18:36:00 -0000 1.8
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_update.c,v 1.68 2009/06/06 01:10:29 claudio Exp $ */
+/* $OpenBSD: rde_update.c,v 1.77 2010/01/13 06:02:37 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -17,19 +17,27 @@
*/
#include <sys/types.h>
#include <sys/queue.h>
+#if defined(__FreeBSD__) /* sys/hash.h */
+#include "hash.h"
+#else
#include <sys/hash.h>
+#endif /* defined(__FreeBSD__) */
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#if defined(__FreeBSD__) /* limits.h */
+#include <limits.h>
+#endif /* defined(__FreeBSD__) */
#include "bgpd.h"
#include "rde.h"
in_addr_t up_get_nexthop(struct rde_peer *, struct rde_aspath *);
int up_generate_mp_reach(struct rde_peer *, struct update_attr *,
- struct rde_aspath *, sa_family_t);
+ struct rde_aspath *, u_int8_t);
int up_generate_attr(struct rde_peer *, struct update_attr *,
- struct rde_aspath *, sa_family_t);
+ struct rde_aspath *, u_int8_t);
/* update stuff. */
struct update_prefix {
@@ -65,10 +73,12 @@ RB_GENERATE(uptree_attr, update_attr, en
void
up_init(struct rde_peer *peer)
{
- TAILQ_INIT(&peer->updates);
- TAILQ_INIT(&peer->withdraws);
- TAILQ_INIT(&peer->updates6);
- TAILQ_INIT(&peer->withdraws6);
+ u_int8_t i;
+
+ for (i = 0; i < AID_MAX; i++) {
+ TAILQ_INIT(&peer->updates[i]);
+ TAILQ_INIT(&peer->withdraws[i]);
+ }
RB_INIT(&peer->up_prefix);
RB_INIT(&peer->up_attrs);
peer->up_pcnt = 0;
@@ -103,8 +113,10 @@ up_clear(struct uplist_attr *updates, st
void
up_down(struct rde_peer *peer)
{
- up_clear(&peer->updates, &peer->withdraws);
- up_clear(&peer->updates6, &peer->withdraws6);
+ u_int8_t i;
+
+ for (i = 0; i < AID_MAX; i++)
+ up_clear(&peer->updates[i], &peer->withdraws[i]);
RB_INIT(&peer->up_prefix);
RB_INIT(&peer->up_attrs);
@@ -120,19 +132,19 @@ up_prefix_cmp(struct update_prefix *a, s
{
int i;
- if (a->prefix.af < b->prefix.af)
+ if (a->prefix.aid < b->prefix.aid)
return (-1);
- if (a->prefix.af > b->prefix.af)
+ if (a->prefix.aid > b->prefix.aid)
return (1);
- switch (a->prefix.af) {
- case AF_INET:
+ switch (a->prefix.aid) {
+ case AID_INET:
if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr))
return (-1);
if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr))
return (1);
break;
- case AF_INET6:
+ case AID_INET6:
i = memcmp(&a->prefix.v6, &b->prefix.v6,
sizeof(struct in6_addr));
if (i > 0)
@@ -140,6 +152,25 @@ up_prefix_cmp(struct update_prefix *a, s
if (i < 0)
return (-1);
break;
+ case AID_VPN_IPv4:
+ if (betoh64(a->prefix.vpn4.rd) < betoh64(b->prefix.vpn4.rd))
+ return (-1);
+ if (betoh64(a->prefix.vpn4.rd) > betoh64(b->prefix.vpn4.rd))
+ return (1);
+ if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr))
+ return (-1);
+ if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr))
+ return (1);
+ if (a->prefixlen < b->prefixlen)
+ return (-1);
+ if (a->prefixlen > b->prefixlen)
+ return (1);
+ if (a->prefix.vpn4.labellen < b->prefix.vpn4.labellen)
+ return (-1);
+ if (a->prefix.vpn4.labellen > b->prefix.vpn4.labellen)
+ return (1);
+ return (memcmp(a->prefix.vpn4.labelstack,
+ b->prefix.vpn4.labelstack, a->prefix.vpn4.labellen));
default:
fatalx("pt_prefix_cmp: unknown af");
}
@@ -174,18 +205,8 @@ up_add(struct rde_peer *peer, struct upd
struct uplist_attr *upl = NULL;
struct uplist_prefix *wdl = NULL;
- switch (p->prefix.af) {
- case AF_INET:
- upl = &peer->updates;
- wdl = &peer->withdraws;
- break;
- case AF_INET6:
- upl = &peer->updates6;
- wdl = &peer->withdraws6;
- break;
- default:
- fatalx("up_add: unknown AF");
- }
+ upl = &peer->updates[p->prefix.aid];
+ wdl = &peer->withdraws[p->prefix.aid];
/* 1. search for attr */
if (a != NULL && (na = RB_FIND(uptree_attr, &peer->up_attrs, a)) ==
@@ -270,23 +291,16 @@ up_test_update(struct rde_peer *peer, st
/* Do not send routes back to sender */
return (0);
+ if (p->aspath->flags & F_ATTR_PARSE_ERR)
+ fatalx("try to send out a botched path");
if (p->aspath->flags & F_ATTR_LOOP)
fatalx("try to send out a looped path");
pt_getaddr(p->prefix, &addr);
- switch (addr.af) {
- case AF_INET:
- if (peer->capa_announced.mp_v4 == SAFI_NONE &&
- peer->capa_received.mp_v6 != SAFI_NONE)
- return (-1);
- break;
- case AF_INET6:
- if (peer->capa_announced.mp_v6 == SAFI_NONE)
- return (-1);
- break;
- }
+ if (peer->capa.mp[addr.aid] == 0)
+ return (-1);
- if (p->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) {
+ if (!p->aspath->peer->conf.ebgp && !peer->conf.ebgp) {
/*
* route reflector redistribution rules:
* 1. if announce is set -> announce
@@ -325,13 +339,13 @@ up_test_update(struct rde_peer *peer, st
}
/* well known communities */
- if (rde_filter_community(p->aspath,
+ if (community_match(p->aspath,
COMMUNITY_WELLKNOWN, COMMUNITY_NO_ADVERTISE))
return (0);
- if (peer->conf.ebgp && rde_filter_community(p->aspath,
+ if (peer->conf.ebgp && community_match(p->aspath,
COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPORT))
return (0);
- if (peer->conf.ebgp && rde_filter_community(p->aspath,
+ if (peer->conf.ebgp && community_match(p->aspath,
COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPSUBCONFED))
return (0);
@@ -362,7 +376,7 @@ up_generate(struct rde_peer *peer, struc
if (ua == NULL)
fatal("up_generate");
- if (up_generate_attr(peer, ua, asp, addr->af) == -1) {
+ if (up_generate_attr(peer, ua, asp, addr->aid) == -1) {
log_warnx("generation of bgp path attributes failed");
free(ua);
return (-1);
@@ -444,18 +458,12 @@ up_generate_updates(struct filter_head *
/* send a default route to the specified peer */
void
up_generate_default(struct filter_head *rules, struct rde_peer *peer,
- sa_family_t af)
+ u_int8_t aid)
{
struct rde_aspath *asp, *fasp;
struct bgpd_addr addr;
- if (peer->capa_received.mp_v4 == SAFI_NONE &&
- peer->capa_received.mp_v6 != SAFI_NONE &&
- af == AF_INET)
- return;
-
- if (peer->capa_received.mp_v6 == SAFI_NONE &&
- af == AF_INET6)
+ if (peer->capa.mp[aid] == 0)
return;
asp = path_get();
@@ -471,7 +479,7 @@ up_generate_default(struct filter_head *
/* filter as usual */
bzero(&addr, sizeof(addr));
- addr.af = af;
+ addr.aid = aid;
if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL,
DIR_OUT) == ACTION_DENY) {
@@ -491,6 +499,43 @@ up_generate_default(struct filter_head *
path_put(asp);
}
+/* generate a EoR marker in the update list. This is a horrible hack. */
+int
+up_generate_marker(struct rde_peer *peer, u_int8_t aid)
+{
+ struct update_attr *ua;
+ struct update_attr *na = NULL;
+ struct uplist_attr *upl = NULL;
+
+ ua = calloc(1, sizeof(struct update_attr));
+ if (ua == NULL)
+ fatal("up_generate_marker");
+
+ upl = &peer->updates[aid];
+
+ /* 1. search for attr */
+ if ((na = RB_FIND(uptree_attr, &peer->up_attrs, ua)) == NULL) {
+ /* 1.1 if not found -> add */
+ TAILQ_INIT(&ua->prefix_h);
+ if (RB_INSERT(uptree_attr, &peer->up_attrs, ua) != NULL) {
+ log_warnx("uptree_attr insert failed");
+ /* cleanup */
+ free(ua);
+ return (-1);
+ }
+ TAILQ_INSERT_TAIL(upl, ua, attr_l);
+ peer->up_acnt++;
+ } else {
+ /* 1.2 if found -> use that, free ua */
+ free(ua);
+ ua = na;
+ /* move to end of update queue */
+ TAILQ_REMOVE(upl, ua, attr_l);
+ TAILQ_INSERT_TAIL(upl, ua, attr_l);
+ }
+ return (0);
+}
+
u_char up_attr_buf[4096];
/* only for IPv4 */
@@ -551,28 +596,41 @@ up_get_nexthop(struct rde_peer *peer, st
int
up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa,
- struct rde_aspath *a, sa_family_t af)
+ struct rde_aspath *a, u_int8_t aid)
{
u_int16_t tmp;
- switch (af) {
- case AF_INET6:
+ switch (aid) {
+ case AID_INET6:
upa->mpattr_len = 21; /* AFI + SAFI + NH LEN + NH + Reserved */
upa->mpattr = malloc(upa->mpattr_len);
if (upa->mpattr == NULL)
fatal("up_generate_mp_reach");
- tmp = htons(AFI_IPv6);
+ if (aid2afi(aid, &tmp, &upa->mpattr[2]))
+ fatalx("up_generate_mp_reachi: bad AID");
+ tmp = htons(tmp);
memcpy(upa->mpattr, &tmp, sizeof(tmp));
- upa->mpattr[2] = SAFI_UNICAST;
upa->mpattr[3] = sizeof(struct in6_addr);
upa->mpattr[20] = 0; /* Reserved must be 0 */
/* nexthop dance see also up_get_nexthop() */
- if (peer->conf.ebgp == 0) {
+ if (a->flags & F_NEXTHOP_NOMODIFY) {
+ /* no modify flag set */
+ if (a->nexthop == NULL)
+ memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6,
+ sizeof(struct in6_addr));
+ else
+ memcpy(&upa->mpattr[4],
+ &a->nexthop->exit_nexthop.v6,
+ sizeof(struct in6_addr));
+ } else if (a->flags & F_NEXTHOP_SELF)
+ memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6,
+ sizeof(struct in6_addr));
+ else if (!peer->conf.ebgp) {
/* ibgp */
if (a->nexthop == NULL ||
- (a->nexthop->exit_nexthop.af == AF_INET6 &&
- memcmp(&a->nexthop->exit_nexthop.v6,
+ (a->nexthop->exit_nexthop.aid == AID_INET6 &&
+ !memcmp(&a->nexthop->exit_nexthop.v6,
&peer->remote_addr.v6, sizeof(struct in6_addr))))
memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6,
sizeof(struct in6_addr));
@@ -603,6 +661,68 @@ up_generate_mp_reach(struct rde_peer *pe
memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6,
sizeof(struct in6_addr));
return (0);
+ case AID_VPN_IPv4:
+ upa->mpattr_len = 17; /* AFI + SAFI + NH LEN + NH + Reserved */
+ upa->mpattr = calloc(upa->mpattr_len, 1);
+ if (upa->mpattr == NULL)
+ fatal("up_generate_mp_reach");
+ if (aid2afi(aid, &tmp, &upa->mpattr[2]))
+ fatalx("up_generate_mp_reachi: bad AID");
+ tmp = htons(tmp);
+ memcpy(upa->mpattr, &tmp, sizeof(tmp));
+ upa->mpattr[3] = sizeof(u_int64_t) + sizeof(struct in_addr);
+
+ /* nexthop dance see also up_get_nexthop() */
+ if (a->flags & F_NEXTHOP_NOMODIFY) {
+ /* no modify flag set */
+ if (a->nexthop == NULL)
+ memcpy(&upa->mpattr[12],
+ &peer->local_v4_addr.v4,
+ sizeof(struct in_addr));
+ else
+ /* nexthops are stored as IPv4 addrs */
+ memcpy(&upa->mpattr[12],
+ &a->nexthop->exit_nexthop.v4,
+ sizeof(struct in_addr));
+ } else if (a->flags & F_NEXTHOP_SELF)
+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4,
+ sizeof(struct in_addr));
+ else if (!peer->conf.ebgp) {
+ /* ibgp */
+ if (a->nexthop == NULL ||
+ (a->nexthop->exit_nexthop.aid == AID_INET &&
+ !memcmp(&a->nexthop->exit_nexthop.v4,
+ &peer->remote_addr.v4, sizeof(struct in_addr))))
+ memcpy(&upa->mpattr[12],
+ &peer->local_v4_addr.v4,
+ sizeof(struct in_addr));
+ else
+ memcpy(&upa->mpattr[12],
+ &a->nexthop->exit_nexthop.v4,
+ sizeof(struct in_addr));
+ } else if (peer->conf.distance == 1) {
+ /* ebgp directly connected */
+ if (a->nexthop != NULL &&
+ a->nexthop->flags & NEXTHOP_CONNECTED)
+ if (prefix_compare(&peer->remote_addr,
+ &a->nexthop->nexthop_net,
+ a->nexthop->nexthop_netlen) == 0) {
+ /*
+ * nexthop and peer are in the same
+ * subnet
+ */
+ memcpy(&upa->mpattr[12],
+ &a->nexthop->exit_nexthop.v4,
+ sizeof(struct in_addr));
+ return (0);
+ }
+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4,
+ sizeof(struct in_addr));
+ } else
+ /* ebgp multihop */
+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4,
+ sizeof(struct in_addr));
+ return (0);
default:
break;
}
@@ -611,7 +731,7 @@ up_generate_mp_reach(struct rde_peer *pe
int
up_generate_attr(struct rde_peer *peer, struct update_attr *upa,
- struct rde_aspath *a, sa_family_t af)
+ struct rde_aspath *a, u_int8_t aid)
{
struct attr *oa, *newaggr = NULL;
u_char *pdata;
@@ -643,8 +763,8 @@ up_generate_attr(struct rde_peer *peer,
wlen += r; len -= r;
free(pdata);
- switch (af) {
- case AF_INET:
+ switch (aid) {
+ case AID_INET:
nexthop = up_get_nexthop(peer, a);
if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN,
ATTR_NEXTHOP, &nexthop, 4)) == -1)
@@ -659,9 +779,11 @@ up_generate_attr(struct rde_peer *peer,
/*
* The old MED from other peers MUST not be announced to others
* unless the MED is originating from us or the peer is an IBGP one.
+ * Only exception are routers with "transparent-as yes" set.
*/
- if (a->flags & F_ATTR_MED && (peer->conf.ebgp == 0 ||
- a->flags & F_ATTR_MED_ANNOUNCE)) {
+ if (a->flags & F_ATTR_MED && (!peer->conf.ebgp ||
+ a->flags & F_ATTR_MED_ANNOUNCE ||
+ peer->conf.flags & PEERFLAG_TRANS_AS)) {
tmp32 = htonl(a->med);
if ((r = attr_write(up_attr_buf + wlen, len, ATTR_OPTIONAL,
ATTR_MED, &tmp32, 4)) == -1)
@@ -669,7 +791,7 @@ up_generate_attr(struct rde_peer *peer,
wlen += r; len -= r;
}
- if (peer->conf.ebgp == 0) {
+ if (!peer->conf.ebgp) {
/* local preference, only valid for ibgp */
tmp32 = htonl(a->lpref);
if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN,
@@ -704,7 +826,7 @@ up_generate_attr(struct rde_peer *peer,
u_int16_t tas;
if ((!(oa->flags & ATTR_TRANSITIVE)) &&
- peer->conf.ebgp != 0) {
+ peer->conf.ebgp) {
r = 0;
break;
}
@@ -730,7 +852,7 @@ up_generate_attr(struct rde_peer *peer,
case ATTR_ORIGINATOR_ID:
case ATTR_CLUSTER_LIST:
if ((!(oa->flags & ATTR_TRANSITIVE)) &&
- peer->conf.ebgp != 0) {
+ peer->conf.ebgp) {
r = 0;
break;
}
@@ -791,7 +913,7 @@ up_generate_attr(struct rde_peer *peer,
/* write mp attribute to different buffer */
if (ismp)
- if (up_generate_mp_reach(peer, upa, a, AF_INET6) == -1)
+ if (up_generate_mp_reach(peer, upa, a, aid) == -1)
return (-1);
/* the bgp path attributes are now stored in the global buf */
@@ -810,6 +932,7 @@ up_dump_prefix(u_char *buf, int len, str
{
struct update_prefix *upp;
int r, wpos = 0;
+ u_int8_t i;
while ((upp = TAILQ_FIRST(prefix_head)) != NULL) {
if ((r = prefix_write(buf + wpos, len - wpos,
@@ -820,13 +943,14 @@ up_dump_prefix(u_char *buf, int len, str
log_warnx("dequeuing update failed.");
TAILQ_REMOVE(upp->prefix_h, upp, prefix_l);
peer->up_pcnt--;
- if (upp->prefix_h == &peer->withdraws ||
- upp->prefix_h == &peer->withdraws6) {
- peer->up_wcnt--;
- peer->prefix_sent_withdraw++;
- } else {
- peer->up_nlricnt--;
- peer->prefix_sent_update++;
+ for (i = 0; i < AID_MAX; i++) {
+ if (upp->prefix_h == &peer->withdraws[i]) {
+ peer->up_wcnt--;
+ peer->prefix_sent_withdraw++;
+ } else {
+ peer->up_nlricnt--;
+ peer->prefix_sent_update++;
+ }
}
free(upp);
}
@@ -844,16 +968,21 @@ up_dump_attrnlri(u_char *buf, int len, s
* It is possible that a queued path attribute has no nlri prefix.
* Ignore and remove those path attributes.
*/
- while ((upa = TAILQ_FIRST(&peer->updates)) != NULL)
+ while ((upa = TAILQ_FIRST(&peer->updates[AID_INET])) != NULL)
if (TAILQ_EMPTY(&upa->prefix_h)) {
+ attr_len = upa->attr_len;
if (RB_REMOVE(uptree_attr, &peer->up_attrs,
upa) == NULL)
log_warnx("dequeuing update failed.");
- TAILQ_REMOVE(&peer->updates, upa, attr_l);
+ TAILQ_REMOVE(&peer->updates[AID_INET], upa, attr_l);
free(upa->attr);
free(upa->mpattr);
free(upa);
peer->up_acnt--;
+ /* XXX horrible hack,
+ * if attr_len is 0, it is a EoR marker */
+ if (attr_len == 0)
+ return (-1);
} else
break;
@@ -884,7 +1013,7 @@ up_dump_attrnlri(u_char *buf, int len, s
if (TAILQ_EMPTY(&upa->prefix_h)) {
if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL)
log_warnx("dequeuing update failed.");
- TAILQ_REMOVE(&peer->updates, upa, attr_l);
+ TAILQ_REMOVE(&peer->updates[AID_INET], upa, attr_l);
free(upa->attr);
free(upa->mpattr);
free(upa);
@@ -895,12 +1024,13 @@ up_dump_attrnlri(u_char *buf, int len, s
}
u_char *
-up_dump_mp_unreach(u_char *buf, u_int16_t *len, struct rde_peer *peer)
+up_dump_mp_unreach(u_char *buf, u_int16_t *len, struct rde_peer *peer,
+ u_int8_t aid)
{
int wpos;
u_int16_t datalen, tmp;
u_int16_t attrlen = 2; /* attribute header (without len) */
- u_int8_t flags = ATTR_OPTIONAL;
+ u_int8_t flags = ATTR_OPTIONAL, safi;
/*
* reserve space for withdraw len, attr len, the attribute header
@@ -912,7 +1042,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_
return (NULL);
datalen = up_dump_prefix(buf + wpos, *len - wpos,
- &peer->withdraws6, peer);
+ &peer->withdraws[aid], peer);
if (datalen == 0)
return (NULL);
@@ -920,9 +1050,11 @@ up_dump_mp_unreach(u_char *buf, u_int16_
/* prepend header, need to do it reverse */
/* safi & afi */
- buf[--wpos] = SAFI_UNICAST;
+ if (aid2afi(aid, &tmp, &safi))
+ fatalx("up_dump_mp_unreach: bad AID");
+ buf[--wpos] = safi;
wpos -= sizeof(u_int16_t);
- tmp = htons(AFI_IPv6);
+ tmp = htons(tmp);
memcpy(buf + wpos, &tmp, sizeof(u_int16_t));
/* attribute length */
@@ -959,33 +1091,39 @@ up_dump_mp_unreach(u_char *buf, u_int16_
return (buf + wpos);
}
-u_char *
-up_dump_mp_reach(u_char *buf, u_int16_t *len, struct rde_peer *peer)
+int
+up_dump_mp_reach(u_char *buf, u_int16_t *len, struct rde_peer *peer,
+ u_int8_t aid)
{
struct update_attr *upa;
int wpos;
- u_int16_t datalen, tmp;
+ u_int16_t attr_len, datalen, tmp;
u_int8_t flags = ATTR_OPTIONAL;
/*
* It is possible that a queued path attribute has no nlri prefix.
* Ignore and remove those path attributes.
*/
- while ((upa = TAILQ_FIRST(&peer->updates6)) != NULL)
+ while ((upa = TAILQ_FIRST(&peer->updates[aid])) != NULL)
if (TAILQ_EMPTY(&upa->prefix_h)) {
+ attr_len = upa->attr_len;
if (RB_REMOVE(uptree_attr, &peer->up_attrs,
upa) == NULL)
log_warnx("dequeuing update failed.");
- TAILQ_REMOVE(&peer->updates6, upa, attr_l);
+ TAILQ_REMOVE(&peer->updates[aid], upa, attr_l);
free(upa->attr);
free(upa->mpattr);
free(upa);
peer->up_acnt--;
+ /* XXX horrible hack,
+ * if attr_len is 0, it is a EoR marker */
+ if (attr_len == 0)
+ return (-1);
} else
break;
if (upa == NULL)
- return (NULL);
+ return (-2);
/*
* reserve space for attr len, the attributes, the
@@ -993,12 +1131,12 @@ up_dump_mp_reach(u_char *buf, u_int16_t
*/
wpos = 2 + 2 + upa->attr_len + 4 + upa->mpattr_len;
if (*len < wpos)
- return (NULL);
+ return (-2);
datalen = up_dump_prefix(buf + wpos, *len - wpos,
&upa->prefix_h, peer);
if (datalen == 0)
- return (NULL);
+ return (-2);
if (upa->mpattr_len == 0 || upa->mpattr == NULL)
fatalx("mulitprotocol update without MP attrs");
@@ -1038,7 +1176,7 @@ up_dump_mp_reach(u_char *buf, u_int16_t
if (TAILQ_EMPTY(&upa->prefix_h)) {
if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL)
log_warnx("dequeuing update failed.");
- TAILQ_REMOVE(&peer->updates6, upa, attr_l);
+ TAILQ_REMOVE(&peer->updates[aid], upa, attr_l);
free(upa->attr);
free(upa->mpattr);
free(upa);
@@ -1046,6 +1184,5 @@ up_dump_mp_reach(u_char *buf, u_int16_t
}
*len = datalen + 4;
- return (buf + wpos);
+ return (wpos);
}
-

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
Index: bgpd/session.h
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/session.h,v
retrieving revision 1.1.1.7
retrieving revision 1.1.1.10
diff -u -p -r1.1.1.7 -r1.1.1.10
--- bgpd/session.h 14 Feb 2010 20:19:57 -0000 1.1.1.7
+++ bgpd/session.h 13 Oct 2012 18:22:50 -0000 1.1.1.10
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.101 2009/06/05 20:26:38 claudio Exp $ */
+/* $OpenBSD: session.h,v 1.113 2012/04/12 17:26:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -94,6 +94,13 @@ enum suberr_open {
ERR_OPEN_CAPA
};
+enum suberr_fsm {
+ ERR_FSM_UNSPECIFIC = 0,
+ ERR_FSM_UNEX_OPENSENT,
+ ERR_FSM_UNEX_OPENCONFIRM,
+ ERR_FSM_UNEX_ESTABLISHED
+};
+
enum opt_params {
OPT_PARAM_NONE,
OPT_PARAM_AUTH,
@@ -109,7 +116,7 @@ enum capa_codes {
};
struct bgp_msg {
- struct buf *buf;
+ struct ibuf *buf;
enum msg_type type;
u_int16_t len;
};
@@ -155,8 +162,10 @@ struct peer_stats {
u_int64_t msg_sent_rrefresh;
u_int64_t prefix_rcvd_update;
u_int64_t prefix_rcvd_withdraw;
+ u_int64_t prefix_rcvd_eor;
u_int64_t prefix_sent_update;
u_int64_t prefix_sent_withdraw;
+ u_int64_t prefix_sent_eor;
time_t last_updown;
time_t last_read;
u_int32_t prefix_cnt;
@@ -172,6 +181,7 @@ enum Timer {
Timer_IdleHold,
Timer_IdleHoldReset,
Timer_CarpUndemote,
+ Timer_RestartTimeout,
Timer_Max
};
@@ -189,6 +199,7 @@ struct peer {
struct {
struct capabilities ann;
struct capabilities peer;
+ struct capabilities neg;
} capa;
struct {
struct bgpd_addr local_addr;
@@ -201,7 +212,7 @@ struct peer {
struct sockaddr_storage sa_remote;
struct peer_timer_head timers;
struct msgbuf wbuf;
- struct buf_read *rbuf;
+ struct ibuf_read *rbuf;
struct peer *next;
int fd;
int lasterr;
@@ -217,47 +228,25 @@ struct peer {
u_int8_t passive;
};
-struct peer *peers;
+extern struct peer *peers;
+extern time_t pauseaccept;
struct ctl_timer {
enum Timer type;
time_t val;
};
-/* session.c */
-void session_socket_blockmode(int, enum blockmodes);
-pid_t session_main(struct bgpd_config *, struct peer *,
- struct network_head *, struct filter_head *,
- struct mrt_head *, struct rib_names *,
- int[2], int[2], int[2], int[2]);
-void bgp_fsm(struct peer *, enum session_events);
-int session_neighbor_rrefresh(struct peer *p);
-struct peer *getpeerbyaddr(struct bgpd_addr *);
-struct peer *getpeerbydesc(const char *);
-int imsg_compose_parent(int, pid_t, void *, u_int16_t);
-int imsg_compose_rde(int, pid_t, void *, u_int16_t);
-
-/* log.c */
-char *log_fmt_peer(const struct peer_config *);
-void log_statechange(struct peer *, enum session_state,
- enum session_events);
-void log_notification(const struct peer *, u_int8_t, u_int8_t,
- u_char *, u_int16_t);
-void log_conn_attempt(const struct peer *, struct sockaddr *);
-
-/* parse.y */
-int parse_config(char *, struct bgpd_config *, struct mrt_head *,
- struct peer **, struct network_head *, struct filter_head *);
+/* carp.c */
+int carp_demote_init(char *, int);
+void carp_demote_shutdown(void);
+int carp_demote_get(char *);
+int carp_demote_set(char *, int);
/* config.c */
int merge_config(struct bgpd_config *, struct bgpd_config *,
struct peer *, struct listen_addrs *);
void prepare_listeners(struct bgpd_config *);
-
-/* rde.c */
-pid_t rde_main(struct bgpd_config *, struct peer *, struct network_head *,
- struct filter_head *, struct mrt_head *, struct rib_names *,
- int[2], int[2], int[2], int[2], int);
+int get_mpe_label(struct rdomain *);
/* control.c */
int control_init(int, char *);
@@ -266,7 +255,27 @@ void control_shutdown(int);
int control_dispatch_msg(struct pollfd *, u_int *);
unsigned int control_accept(int, int);
+/* log.c */
+char *log_fmt_peer(const struct peer_config *);
+void log_statechange(struct peer *, enum session_state,
+ enum session_events);
+void log_notification(const struct peer *, u_int8_t, u_int8_t,
+ u_char *, u_int16_t, const char *);
+void log_conn_attempt(const struct peer *, struct sockaddr *);
+
+/* mrt.c */
+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 *);
+
+/* parse.y */
+int parse_config(char *, struct bgpd_config *, struct mrt_head *,
+ struct peer **, struct network_head *, struct filter_head *,
+ struct rdomain_head *);
+
/* pfkey.c */
+int pfkey_read(int, struct sadb_msg *);
int pfkey_establish(struct peer *);
int pfkey_remove(struct peer *);
int pfkey_init(struct bgpd_sysdep *);
@@ -274,15 +283,24 @@ int pfkey_init(struct bgpd_sysdep *);
/* printconf.c */
void print_config(struct bgpd_config *, struct rib_names *,
struct network_head *, struct peer *, struct filter_head *,
- struct mrt_head *);
+ struct mrt_head *, struct rdomain_head *);
-/* carp.c */
-int carp_demote_init(char *, int);
-void carp_demote_shutdown(void);
-int carp_demote_get(char *);
-int carp_demote_set(char *, int);
+/* rde.c */
+pid_t rde_main(int[2], int[2], int[2], int[2], int);
+
+/* session.c */
+void session_socket_blockmode(int, enum blockmodes);
+pid_t session_main(int[2], int[2], int[2], int[2]);
+void bgp_fsm(struct peer *, enum session_events);
+int session_neighbor_rrefresh(struct peer *p);
+struct peer *getpeerbyaddr(struct bgpd_addr *);
+struct peer *getpeerbydesc(const char *);
+int imsg_compose_parent(int, u_int32_t, pid_t, void *, u_int16_t);
+int imsg_compose_rde(int, pid_t, void *, u_int16_t);
+void session_stop(struct peer *, u_int8_t);
/* timer.c */
+time_t getmonotime(void);
struct peer_timer *timer_get(struct peer *, enum Timer);
struct peer_timer *timer_nextisdue(struct peer *);
time_t timer_nextduein(struct peer *);

View File

@ -0,0 +1,32 @@
Index: bgpd/timer.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/timer.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.4
diff -u -p -r1.1.1.2 -r1.1.1.4
--- bgpd/timer.c 9 Jul 2009 16:49:54 -0000 1.1.1.2
+++ bgpd/timer.c 13 Oct 2012 18:22:50 -0000 1.1.1.4
@@ -1,4 +1,4 @@
-/* $OpenBSD: timer.c,v 1.13 2009/01/21 20:32:53 henning Exp $ */
+/* $OpenBSD: timer.c,v 1.14 2010/10/24 17:20:08 deraadt Exp $ */
/*
* Copyright (c) 2003-2007 Henning Brauer <henning@openbsd.org>
@@ -23,8 +23,6 @@
#include "bgpd.h"
#include "session.h"
-time_t getmonotime(void);
-
time_t
getmonotime(void)
{
@@ -43,7 +41,7 @@ timer_get(struct peer *p, enum Timer tim
TAILQ_FOREACH(pt, &p->timers, entry)
if (pt->type == timer)
- break;
+ break;
return (pt);
}

View File

@ -0,0 +1,440 @@
Index: bgpd/util.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpd/util.c,v
retrieving revision 1.1.1.6
retrieving revision 1.7
diff -u -p -r1.1.1.6 -r1.7
--- bgpd/util.c 14 Feb 2010 20:19:57 -0000 1.1.1.6
+++ bgpd/util.c 13 Oct 2012 18:36:00 -0000 1.7
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.6 2009/06/12 16:42:53 claudio Exp $ */
+/* $OpenBSD: util.c,v 1.11 2010/03/29 09:04:43 claudio Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -18,6 +18,9 @@
*/
#include <sys/types.h>
#include <sys/socket.h>
+#if defined(__FreeBSD__) /* sys/limits.h */
+#include <sys/limits.h>
+#endif /* defined(__FreeBSD__) */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -28,15 +31,30 @@
#include "bgpd.h"
#include "rde.h"
+const char *aspath_delim(u_int8_t, int);
+
const char *
log_addr(const struct bgpd_addr *addr)
{
static char buf[48];
+ char tbuf[16];
- if (inet_ntop(addr->af, &addr->ba, buf, sizeof(buf)) == NULL)
- return ("?");
- else
+ switch (addr->aid) {
+ case AID_INET:
+ case AID_INET6:
+ if (inet_ntop(aid2af(addr->aid), &addr->ba, buf,
+ sizeof(buf)) == NULL)
+ return ("?");
return (buf);
+ case AID_VPN_IPv4:
+ if (inet_ntop(AF_INET, &addr->vpn4.addr, tbuf,
+ sizeof(tbuf)) == NULL)
+ return ("?");
+ snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->vpn4.rd),
+ tbuf);
+ return (buf);
+ }
+ return ("???");
}
const char *
@@ -90,6 +108,96 @@ log_as(u_int32_t as)
return (buf);
}
+const char *
+log_rd(u_int64_t rd)
+{
+ static char buf[32];
+ struct in_addr addr;
+ u_int32_t u32;
+ u_int16_t u16;
+
+ rd = betoh64(rd);
+ switch (rd >> 48) {
+ case EXT_COMMUNITY_TWO_AS:
+ u32 = rd & 0xffffffff;
+ u16 = (rd >> 32) & 0xffff;
+ snprintf(buf, sizeof(buf), "rd %i:%i", u16, u32);
+ break;
+ case EXT_COMMUNITY_FOUR_AS:
+ u32 = (rd >> 16) & 0xffffffff;
+ u16 = rd & 0xffff;
+ snprintf(buf, sizeof(buf), "rd %s:%i", log_as(u32), u16);
+ break;
+ case EXT_COMMUNITY_IPV4:
+ u32 = (rd >> 16) & 0xffffffff;
+ u16 = rd & 0xffff;
+ addr.s_addr = htonl(u32);
+ snprintf(buf, sizeof(buf), "rd %s:%i", inet_ntoa(addr), u16);
+ break;
+ default:
+ return ("rd ?");
+ }
+ return (buf);
+}
+
+/* NOTE: this function does not check if the type/subtype combo is
+ * actually valid. */
+const char *
+log_ext_subtype(u_int8_t subtype)
+{
+ static char etype[6];
+
+ switch (subtype) {
+ case EXT_COMMUNITY_ROUTE_TGT:
+ return ("rt"); /* route target */
+ case EXT_CUMMUNITY_ROUTE_ORIG:
+ return ("soo"); /* source of origin */
+ case EXT_COMMUNITY_OSPF_DOM_ID:
+ return ("odi"); /* ospf domain id */
+ case EXT_COMMUNITY_OSPF_RTR_TYPE:
+ return ("ort"); /* ospf route type */
+ case EXT_COMMUNITY_OSPF_RTR_ID:
+ return ("ori"); /* ospf router id */
+ case EXT_COMMUNITY_BGP_COLLECT:
+ return ("bdc"); /* bgp data collection */
+ default:
+ snprintf(etype, sizeof(etype), "[%u]", subtype);
+ return (etype);
+ }
+}
+
+const char *
+aspath_delim(u_int8_t seg_type, int closing)
+{
+ static char db[8];
+
+ switch (seg_type) {
+ case AS_SET:
+ if (!closing)
+ return ("{ ");
+ else
+ return (" }");
+ case AS_SEQUENCE:
+ return ("");
+ case AS_CONFED_SEQUENCE:
+ if (!closing)
+ return ("( ");
+ else
+ return (" )");
+ case AS_CONFED_SET:
+ if (!closing)
+ return ("[ ");
+ else
+ return (" ]");
+ default:
+ if (!closing)
+ snprintf(db, sizeof(db), "!%u ", seg_type);
+ else
+ snprintf(db, sizeof(db), " !%u", seg_type);
+ return (db);
+ }
+}
+
int
aspath_snprint(char *buf, size_t size, void *data, u_int16_t len)
{
@@ -118,16 +226,10 @@ aspath_snprint(char *buf, size_t size, v
seg_len = seg[1];
seg_size = 2 + sizeof(u_int32_t) * seg_len;
- if (seg_type == AS_SET) {
- if (total_size != 0)
- r = snprintf(buf, size, " { ");
- else
- r = snprintf(buf, size, "{ ");
- UPDATE();
- } else if (total_size != 0) {
- r = snprintf(buf, size, " ");
- UPDATE();
- }
+ r = snprintf(buf, size, "%s%s",
+ total_size != 0 ? " " : "",
+ aspath_delim(seg_type, 0));
+ UPDATE();
for (i = 0; i < seg_len; i++) {
r = snprintf(buf, size, "%s",
@@ -138,10 +240,8 @@ aspath_snprint(char *buf, size_t size, v
UPDATE();
}
}
- if (seg_type == AS_SET) {
- r = snprintf(buf, size, " }");
- UPDATE();
- }
+ r = snprintf(buf, size, "%s", aspath_delim(seg_type, 1));
+ UPDATE();
}
/* ensure that we have a valid C-string especially for empty as path */
if (size > 0)
@@ -235,6 +335,67 @@ aspath_strlen(void *data, u_int16_t len)
return (total_size);
}
+/* we need to be able to search more than one as */
+int
+aspath_match(void *data, u_int16_t len, enum as_spec type, u_int32_t as)
+{
+ u_int8_t *seg;
+ int final;
+ u_int16_t seg_size;
+ u_int8_t i, seg_type, seg_len;
+
+ if (type == AS_EMPTY) {
+ if (len == 0)
+ return (1);
+ else
+ return (0);
+ }
+
+ final = 0;
+ seg = data;
+ for (; len > 0; len -= seg_size, seg += seg_size) {
+ seg_type = seg[0];
+ seg_len = seg[1];
+ seg_size = 2 + sizeof(u_int32_t) * seg_len;
+
+ final = (len == seg_size);
+
+ /* just check the first (leftmost) AS */
+ if (type == AS_PEER) {
+ if (as == aspath_extract(seg, 0))
+ return (1);
+ else
+ return (0);
+ }
+ /* just check the final (rightmost) AS */
+ if (type == AS_SOURCE) {
+ /* not yet in the final segment */
+ if (!final)
+ continue;
+
+ if (as == aspath_extract(seg, seg_len - 1))
+ return (1);
+ else
+ return (0);
+ }
+
+ /* AS_TRANSIT or AS_ALL */
+ for (i = 0; i < seg_len; i++) {
+ if (as == aspath_extract(seg, i)) {
+ /*
+ * the source (rightmost) AS is excluded from
+ * AS_TRANSIT matches.
+ */
+ if (final && i == seg_len - 1 &&
+ type == AS_TRANSIT)
+ return (0);
+ return (1);
+ }
+ }
+ }
+ return (0);
+}
+
/*
* Extract the asnum out of the as segment at the specified position.
* Direct access is not possible because of non-aligned reads.
@@ -251,6 +412,66 @@ aspath_extract(const void *seg, int pos)
return (ntohl(as));
}
+int
+prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b,
+ int prefixlen)
+{
+ in_addr_t mask, aa, ba;
+ int i;
+ u_int8_t m;
+
+ if (a->aid != b->aid)
+ return (a->aid - b->aid);
+
+ switch (a->aid) {
+ case AID_INET:
+ if (prefixlen > 32)
+ fatalx("prefix_cmp: bad IPv4 prefixlen");
+ mask = htonl(prefixlen2mask(prefixlen));
+ aa = ntohl(a->v4.s_addr & mask);
+ ba = ntohl(b->v4.s_addr & mask);
+ if (aa != ba)
+ return (aa - ba);
+ return (0);
+ case AID_INET6:
+ if (prefixlen > 128)
+ fatalx("prefix_cmp: bad IPv6 prefixlen");
+ for (i = 0; i < prefixlen / 8; i++)
+ if (a->v6.s6_addr[i] != b->v6.s6_addr[i])
+ return (a->v6.s6_addr[i] - b->v6.s6_addr[i]);
+ i = prefixlen % 8;
+ if (i) {
+ m = 0xff00 >> i;
+ if ((a->v6.s6_addr[prefixlen / 8] & m) !=
+ (b->v6.s6_addr[prefixlen / 8] & m))
+ return ((a->v6.s6_addr[prefixlen / 8] & m) -
+ (b->v6.s6_addr[prefixlen / 8] & m));
+ }
+ return (0);
+ case AID_VPN_IPv4:
+ if (prefixlen > 32)
+ fatalx("prefix_cmp: bad IPv4 VPN prefixlen");
+ if (betoh64(a->vpn4.rd) > betoh64(b->vpn4.rd))
+ return (1);
+ if (betoh64(a->vpn4.rd) < betoh64(b->vpn4.rd))
+ return (-1);
+ mask = htonl(prefixlen2mask(prefixlen));
+ aa = ntohl(a->vpn4.addr.s_addr & mask);
+ ba = ntohl(b->vpn4.addr.s_addr & mask);
+ if (aa != ba)
+ return (aa - ba);
+ if (a->vpn4.labellen > b->vpn4.labellen)
+ return (1);
+ if (a->vpn4.labellen < b->vpn4.labellen)
+ return (-1);
+ return (memcmp(a->vpn4.labelstack, b->vpn4.labelstack,
+ a->vpn4.labellen));
+ default:
+ fatalx("prefix_cmp: unknown af");
+ }
+ return (-1);
+}
+
in_addr_t
prefixlen2mask(u_int8_t prefixlen)
{
@@ -276,3 +497,115 @@ inet6applymask(struct in6_addr *dest, co
for (i = 0; i < 16; i++)
dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i];
}
+
+/* address family translation functions */
+const struct aid aid_vals[AID_MAX] = AID_VALS;
+
+const char *
+aid2str(u_int8_t aid)
+{
+ if (aid < AID_MAX)
+ return (aid_vals[aid].name);
+ return ("unknown AID");
+}
+
+int
+aid2afi(u_int8_t aid, u_int16_t *afi, u_int8_t *safi)
+{
+ if (aid < AID_MAX) {
+ *afi = aid_vals[aid].afi;
+ *safi = aid_vals[aid].safi;
+ return (0);
+ }
+ return (-1);
+}
+
+int
+afi2aid(u_int16_t afi, u_int8_t safi, u_int8_t *aid)
+{
+ u_int8_t i;
+
+ for (i = 0; i < AID_MAX; i++)
+ if (aid_vals[i].afi == afi && aid_vals[i].safi == safi) {
+ *aid = i;
+ return (0);
+ }
+
+ return (-1);
+}
+
+sa_family_t
+aid2af(u_int8_t aid)
+{
+ if (aid < AID_MAX)
+ return (aid_vals[aid].af);
+ return (AF_UNSPEC);
+}
+
+int
+af2aid(sa_family_t af, u_int8_t safi, u_int8_t *aid)
+{
+ u_int8_t i;
+
+ if (safi == 0) /* default to unicast subclass */
+ safi = SAFI_UNICAST;
+
+ for (i = 0; i < AID_MAX; i++)
+ if (aid_vals[i].af == af && aid_vals[i].safi == safi) {
+ *aid = i;
+ return (0);
+ }
+
+ return (-1);
+}
+
+struct sockaddr *
+addr2sa(struct bgpd_addr *addr, u_int16_t port)
+{
+ static struct sockaddr_storage ss;
+ struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss;
+ struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss;
+
+ if (addr->aid == AID_UNSPEC)
+ return (NULL);
+
+ bzero(&ss, sizeof(ss));
+ switch (addr->aid) {
+ case AID_INET:
+ sa_in->sin_family = AF_INET;
+ sa_in->sin_len = sizeof(struct sockaddr_in);
+ sa_in->sin_addr.s_addr = addr->v4.s_addr;
+ sa_in->sin_port = htons(port);
+ break;
+ case AID_INET6:
+ sa_in6->sin6_family = AF_INET6;
+ sa_in6->sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&sa_in6->sin6_addr, &addr->v6,
+ sizeof(sa_in6->sin6_addr));
+ sa_in6->sin6_port = htons(port);
+ sa_in6->sin6_scope_id = addr->scope_id;
+ break;
+ }
+
+ return ((struct sockaddr *)&ss);
+}
+
+void
+sa2addr(struct sockaddr *sa, struct bgpd_addr *addr)
+{
+ struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
+ struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
+
+ bzero(addr, sizeof(*addr));
+ switch (sa->sa_family) {
+ case AF_INET:
+ addr->aid = AID_INET;
+ memcpy(&addr->v4, &sa_in->sin_addr, sizeof(addr->v4));
+ break;
+ case AF_INET6:
+ addr->aid = AID_INET6;
+ memcpy(&addr->v6, &sa_in6->sin6_addr, sizeof(addr->v6));
+ addr->scope_id = sa_in6->sin6_scope_id; /* I hate v6 */
+ break;
+ }
+}

View File

@ -0,0 +1,275 @@
Index: openbsd-compat/fmt_scaled.c
===================================================================
RCS file: openbsd-compat/fmt_scaled.c
diff -N openbsd-compat/fmt_scaled.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/fmt_scaled.c 30 Jun 2009 06:40:07 -0000 1.1
@@ -0,0 +1,268 @@
+/* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */
+
+/*
+ * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * fmt_scaled: Format numbers scaled for human comprehension
+ * scan_scaled: Scan numbers in this format.
+ *
+ * "Human-readable" output uses 4 digits max, and puts a unit suffix at
+ * the end. Makes output compact and easy-to-read esp. on huge disks.
+ * Formatting code was originally in OpenBSD "df", converted to library routine.
+ * Scanning code written for OpenBSD libutil.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "util.h"
+
+typedef enum {
+ NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6
+} unit_type;
+
+/* These three arrays MUST be in sync! XXX make a struct */
+static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA };
+static char scale_chars[] = "BKMGTPE";
+static long long scale_factors[] = {
+ 1LL,
+ 1024LL,
+ 1024LL*1024,
+ 1024LL*1024*1024,
+ 1024LL*1024*1024*1024,
+ 1024LL*1024*1024*1024*1024,
+ 1024LL*1024*1024*1024*1024*1024,
+};
+#define SCALE_LENGTH (sizeof(units)/sizeof(units[0]))
+
+#define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */
+
+/** Convert the given input string "scaled" into numeric in "result".
+ * Return 0 on success, -1 and errno set on error.
+ */
+int
+scan_scaled(char *scaled, long long *result)
+{
+ char *p = scaled;
+ int sign = 0;
+ unsigned int i, ndigits = 0, fract_digits = 0;
+ long long scale_fact = 1, whole = 0, fpart = 0;
+
+ /* Skip leading whitespace */
+ while (isascii(*p) && isspace(*p))
+ ++p;
+
+ /* Then at most one leading + or - */
+ while (*p == '-' || *p == '+') {
+ if (*p == '-') {
+ if (sign) {
+ errno = EINVAL;
+ return -1;
+ }
+ sign = -1;
+ ++p;
+ } else if (*p == '+') {
+ if (sign) {
+ errno = EINVAL;
+ return -1;
+ }
+ sign = +1;
+ ++p;
+ }
+ }
+
+ /* Main loop: Scan digits, find decimal point, if present.
+ * We don't allow exponentials, so no scientific notation
+ * (but note that E for Exa might look like e to some!).
+ * Advance 'p' to end, to get scale factor.
+ */
+ for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) {
+ if (*p == '.') {
+ if (fract_digits > 0) { /* oops, more than one '.' */
+ errno = EINVAL;
+ return -1;
+ }
+ fract_digits = 1;
+ continue;
+ }
+
+ i = (*p) - '0'; /* whew! finally a digit we can use */
+ if (fract_digits > 0) {
+ if (fract_digits >= MAX_DIGITS-1)
+ /* ignore extra fractional digits */
+ continue;
+ fract_digits++; /* for later scaling */
+ fpart *= 10;
+ fpart += i;
+ } else { /* normal digit */
+ if (++ndigits >= MAX_DIGITS) {
+ errno = ERANGE;
+ return -1;
+ }
+ whole *= 10;
+ whole += i;
+ }
+ }
+
+ if (sign) {
+ whole *= sign;
+ fpart *= sign;
+ }
+
+ /* If no scale factor given, we're done. fraction is discarded. */
+ if (!*p) {
+ *result = whole;
+ return 0;
+ }
+
+ /* Validate scale factor, and scale whole and fraction by it. */
+ for (i = 0; i < SCALE_LENGTH; i++) {
+
+ /** Are we there yet? */
+ if (*p == scale_chars[i] ||
+ *p == tolower(scale_chars[i])) {
+
+ /* If it ends with alphanumerics after the scale char, bad. */
+ if (isalnum(*(p+1))) {
+ errno = EINVAL;
+ return -1;
+ }
+ scale_fact = scale_factors[i];
+
+ /* scale whole part */
+ whole *= scale_fact;
+
+ /* truncate fpart so it does't overflow.
+ * then scale fractional part.
+ */
+ while (fpart >= LLONG_MAX / scale_fact) {
+ fpart /= 10;
+ fract_digits--;
+ }
+ fpart *= scale_fact;
+ if (fract_digits > 0) {
+ for (i = 0; i < fract_digits -1; i++)
+ fpart /= 10;
+ }
+ whole += fpart;
+ *result = whole;
+ return 0;
+ }
+ }
+ errno = ERANGE;
+ return -1;
+}
+
+/* Format the given "number" into human-readable form in "result".
+ * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE.
+ * Return 0 on success, -1 and errno set if error.
+ */
+int
+fmt_scaled(long long number, char *result)
+{
+ long long abval, fract = 0;
+ unsigned int i;
+ unit_type unit = NONE;
+
+ abval = (number < 0LL) ? -number : number; /* no long long_abs yet */
+
+ /* Not every negative long long has a positive representation.
+ * Also check for numbers that are just too darned big to format
+ */
+ if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) {
+ errno = ERANGE;
+ return -1;
+ }
+
+ /* scale whole part; get unscaled fraction */
+ for (i = 0; i < SCALE_LENGTH; i++) {
+ if (abval/1024 < scale_factors[i]) {
+ unit = units[i];
+ fract = (i == 0) ? 0 : abval % scale_factors[i];
+ number /= scale_factors[i];
+ if (i > 0)
+ fract /= scale_factors[i - 1];
+ break;
+ }
+ }
+
+ fract = (10 * fract + 512) / 1024;
+ /* if the result would be >= 10, round main number */
+ if (fract == 10) {
+ if (number >= 0)
+ number++;
+ else
+ number--;
+ fract = 0;
+ }
+
+ if (number == 0)
+ strlcpy(result, "0B", FMT_SCALED_STRSIZE);
+ else if (unit == NONE || number >= 100 || number <= -100) {
+ if (fract >= 5) {
+ if (number >= 0)
+ number++;
+ else
+ number--;
+ }
+ (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c",
+ number, scale_chars[unit]);
+ } else
+ (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c",
+ number, fract, scale_chars[unit]);
+
+ return 0;
+}
+
+#ifdef MAIN
+/*
+ * This is the original version of the program in the man page.
+ * Copy-and-paste whatever you need from it.
+ */
+int
+main(int argc, char **argv)
+{
+ char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE];
+ long long ninput = 10483892, result;
+
+ if (scan_scaled(cinput, &result) == 0)
+ printf("\"%s\" -> %lld\n", cinput, result);
+ else
+ perror(cinput);
+
+ if (fmt_scaled(ninput, buf) == 0)
+ printf("%lld -> \"%s\"\n", ninput, buf);
+ else
+ fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno));
+
+ return 0;
+}
+#endif

View File

@ -0,0 +1,134 @@
Index: openbsd-compat/hash.h
===================================================================
RCS file: openbsd-compat/hash.h
diff -N openbsd-compat/hash.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/hash.h 30 Jun 2009 05:48:11 -0000 1.1
@@ -0,0 +1,127 @@
+/* $OpenBSD: hash.h,v 1.4 2004/05/25 18:37:23 jmc Exp $ */
+
+/*
+ * Copyright (c) 2001 Tobias Weingartner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_HASH_H_
+#define _SYS_HASH_H_
+#include <sys/types.h>
+
+/*
+ * Note: SMALL_KERNEL might be used to shrink these, right now I
+ * do not see the point, as my kernel did not grow appreciably when
+ * I switched to these from other inline code. This may have to be
+ * revisited when/if these functions become more prevalent in the
+ * kernel.
+ */
+
+/* Convenience */
+#ifndef HASHINIT
+#define HASHINIT 5381
+#define HASHSTEP(x,c) (((x << 5) + x) + (c))
+#endif
+
+/*
+ * Return a 32-bit hash of the given buffer. The init
+ * value should be 0, or the previous hash value to extend
+ * the previous hash.
+ */
+static __inline uint32_t
+hash32_buf(const void *buf, size_t len, uint32_t hash)
+{
+ const unsigned char *p = buf;
+
+ while (len--)
+ hash = HASHSTEP(hash, *p++);
+
+ return hash;
+}
+
+/*
+ * Return a 32-bit hash of the given string.
+ */
+static __inline uint32_t
+hash32_str(const void *buf, uint32_t hash)
+{
+ const unsigned char *p = buf;
+
+ while (*p)
+ hash = HASHSTEP(hash, *p++);
+
+ return hash;
+}
+
+/*
+ * Return a 32-bit hash of the given string, limited by N.
+ */
+static __inline uint32_t
+hash32_strn(const void *buf, size_t len, uint32_t hash)
+{
+ const unsigned char *p = buf;
+
+ while (*p && len--)
+ hash = HASHSTEP(hash, *p++);
+
+ return hash;
+}
+
+/*
+ * Return a 32-bit hash of the given string terminated by C,
+ * (as well as 0). This is mainly here as a helper for the
+ * namei() hashing of path name parts.
+ */
+static __inline uint32_t
+hash32_stre(const void *buf, int end, char **ep, uint32_t hash)
+{
+ const unsigned char *p = buf;
+
+ while (*p && (*p != end))
+ hash = HASHSTEP(hash, *p++);
+
+ if (ep)
+ *ep = (char *)p;
+
+ return hash;
+}
+
+/*
+ * Return a 32-bit hash of the given string, limited by N,
+ * and terminated by C (as well as 0). This is mainly here
+ * as a helper for the namei() hashing of path name parts.
+ */
+static __inline uint32_t
+hash32_strne(const void *buf, size_t len, int end, char **ep, uint32_t hash)
+{
+ const unsigned char *p = buf;
+
+ while (*p && (*p != end) && len--)
+ hash = HASHSTEP(hash, *p++);
+
+ if (ep)
+ *ep = (char *)p;
+
+ return hash;
+}
+#endif /* !_SYS_HASH_H_ */

View File

@ -0,0 +1,619 @@
Index: openbsd-compat/if_media.h
===================================================================
RCS file: openbsd-compat/if_media.h
diff -N openbsd-compat/if_media.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/if_media.h 30 Jun 2009 05:48:11 -0000 1.1
@@ -0,0 +1,612 @@
+/* $OpenBSD: if_media.h,v 1.17 2004/11/02 02:12:16 reyk Exp $ */
+/* $NetBSD: if_media.h,v 1.22 2000/02/17 21:53:16 sommerfeld Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1997
+ * Jonathan Stone and Jason R. Thorpe. All rights reserved.
+ *
+ * This software is derived from information provided by Matt Thomas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jonathan Stone
+ * and Jason R. Thorpe for the NetBSD Project.
+ * 4. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NET_IF_MEDIA_H_
+#define _NET_IF_MEDIA_H_
+
+/*
+ * Prototypes and definitions for BSD/OS-compatible network interface
+ * media selection.
+ *
+ * Where it is safe to do so, this code strays slightly from the BSD/OS
+ * design. Software which uses the API (device drivers, basically)
+ * shouldn't notice any difference.
+ *
+ * Many thanks to Matt Thomas for providing the information necessary
+ * to implement this interface.
+ */
+
+#ifdef _KERNEL
+
+#include <sys/queue.h>
+
+/*
+ * Driver callbacks for media status and change requests.
+ */
+typedef int (*ifm_change_cb_t)(struct ifnet *ifp);
+typedef void (*ifm_stat_cb_t)(struct ifnet *ifp, struct ifmediareq *req);
+
+/*
+ * In-kernel representation of a single supported media type.
+ */
+struct ifmedia_entry {
+ TAILQ_ENTRY(ifmedia_entry) ifm_list;
+ int ifm_media; /* description of this media attachment */
+ int ifm_data; /* for driver-specific use */
+ void *ifm_aux; /* for driver-specific use */
+};
+
+/*
+ * One of these goes into a network interface's softc structure.
+ * It is used to keep general media state.
+ */
+struct ifmedia {
+ int ifm_mask; /* mask of changes we don't care about */
+ int ifm_media; /* current user-set media word */
+ struct ifmedia_entry *ifm_cur; /* currently selected media */
+ TAILQ_HEAD(, ifmedia_entry) ifm_list; /* list of all supported media */
+ ifm_change_cb_t ifm_change; /* media change driver callback */
+ ifm_stat_cb_t ifm_status; /* media status driver callback */
+};
+
+/* Initialize an interface's struct if_media field. */
+void ifmedia_init(struct ifmedia *ifm, int dontcare_mask,
+ ifm_change_cb_t change_callback, ifm_stat_cb_t status_callback);
+
+/* Add one supported medium to a struct ifmedia. */
+void ifmedia_add(struct ifmedia *ifm, int mword, int data, void *aux);
+
+/* Add an array (of ifmedia_entry) media to a struct ifmedia. */
+void ifmedia_list_add(struct ifmedia *mp, struct ifmedia_entry *lp,
+ int count);
+
+/* Set default media type on initialization. */
+void ifmedia_set(struct ifmedia *ifm, int mword);
+
+/* Common ioctl function for getting/setting media, called by driver. */
+int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr,
+ struct ifmedia *ifm, u_long cmd);
+
+/* Locate a media entry */
+struct ifmedia_entry *ifmedia_match(struct ifmedia *ifm,
+ int flags, int mask);
+
+/* Delete all media for a given media instance */
+void ifmedia_delete_instance(struct ifmedia *, int);
+
+/* Compute baudrate for a given media. */
+int ifmedia_baudrate(int);
+#endif /*_KERNEL */
+
+/*
+ * if_media Options word:
+ * Bits Use
+ * ---- -------
+ * 0-4 Media subtype MAX SUBTYPE == 31!
+ * 5-7 Media type
+ * 8-15 Type specific options
+ * 16-19 RFU
+ * 20-27 Shared (global) options
+ * 28-31 Instance
+ */
+
+/*
+ * Ethernet
+ */
+#define IFM_ETHER 0x00000020
+#define IFM_10_T 3 /* 10BaseT - RJ45 */
+#define IFM_10_2 4 /* 10Base2 - Thinnet */
+#define IFM_10_5 5 /* 10Base5 - AUI */
+#define IFM_100_TX 6 /* 100BaseTX - RJ45 */
+#define IFM_100_FX 7 /* 100BaseFX - Fiber */
+#define IFM_100_T4 8 /* 100BaseT4 - 4 pair cat 3 */
+#define IFM_100_VG 9 /* 100VG-AnyLAN */
+#define IFM_100_T2 10 /* 100BaseT2 */
+#define IFM_1000_SX 11 /* 1000BaseSX - multi-mode fiber */
+#define IFM_10_STP 12 /* 10BaseT over shielded TP */
+#define IFM_10_FL 13 /* 10BaseFL - Fiber */
+#define IFM_1000_LX 14 /* 1000baseLX - single-mode fiber */
+#define IFM_1000_CX 15 /* 1000baseCX - 150ohm STP */
+#define IFM_1000_T 16 /* 1000baseT - 4 pair cat 5 */
+#define IFM_1000_TX IFM_1000_T /* for backwards compatibility */
+#define IFM_HPNA_1 17 /* HomePNA 1.0 (1Mb/s) */
+
+#define IFM_ETH_MASTER 0x00000100 /* master mode (1000baseT) */
+
+/*
+ * Token ring
+ */
+#define IFM_TOKEN 0x00000040
+#define IFM_TOK_STP4 3 /* Shielded twisted pair 4m - DB9 */
+#define IFM_TOK_STP16 4 /* Shielded twisted pair 16m - DB9 */
+#define IFM_TOK_UTP4 5 /* Unshielded twisted pair 4m - RJ45 */
+#define IFM_TOK_UTP16 6 /* Unshielded twisted pair 16m - RJ45 */
+#define IFM_TOK_ETR 0x00000200 /* Early token release */
+#define IFM_TOK_SRCRT 0x00000400 /* Enable source routing features */
+#define IFM_TOK_ALLR 0x00000800 /* All routes / Single route bcast */
+
+/*
+ * FDDI
+ */
+#define IFM_FDDI 0x00000060
+#define IFM_FDDI_SMF 3 /* Single-mode fiber */
+#define IFM_FDDI_MMF 4 /* Multi-mode fiber */
+#define IFM_FDDI_UTP 5 /* CDDI / UTP */
+#define IFM_FDDI_DA 0x00000100 /* Dual attach / single attach */
+
+/*
+ * IEEE 802.11 Wireless
+ */
+#define IFM_IEEE80211 0x00000080
+#define IFM_IEEE80211_FH1 3 /* Frequency Hopping 1Mbps */
+#define IFM_IEEE80211_FH2 4 /* Frequency Hopping 2Mbps */
+#define IFM_IEEE80211_DS2 5 /* Direct Sequence 2Mbps */
+#define IFM_IEEE80211_DS5 6 /* Direct Sequence 5Mbps*/
+#define IFM_IEEE80211_DS11 7 /* Direct Sequence 11Mbps*/
+#define IFM_IEEE80211_DS1 8 /* Direct Sequence 1Mbps*/
+#define IFM_IEEE80211_DS22 9 /* Direct Sequence 22Mbps */
+#define IFM_IEEE80211_OFDM6 10 /* OFDM 6Mbps */
+#define IFM_IEEE80211_OFDM9 11 /* OFDM 9Mbps */
+#define IFM_IEEE80211_OFDM12 12 /* OFDM 12Mbps */
+#define IFM_IEEE80211_OFDM18 13 /* OFDM 18Mbps */
+#define IFM_IEEE80211_OFDM24 14 /* OFDM 24Mbps */
+#define IFM_IEEE80211_OFDM36 15 /* OFDM 36Mbps */
+#define IFM_IEEE80211_OFDM48 16 /* OFDM 48Mbps */
+#define IFM_IEEE80211_OFDM54 17 /* OFDM 54Mbps */
+#define IFM_IEEE80211_OFDM72 18 /* OFDM 72Mbps */
+
+#define IFM_IEEE80211_ADHOC 0x100 /* Operate in Adhoc mode */
+#define IFM_IEEE80211_HOSTAP 0x200 /* Operate in Host AP mode */
+#define IFM_IEEE80211_IBSS 0x400 /* Operate in IBSS mode */
+#define IFM_IEEE80211_IBSSMASTER 0x800 /* Operate as an IBSS master */
+#define IFM_IEEE80211_MONITOR 0x1000 /* Operate in Monitor mode */
+#define IFM_IEEE80211_TURBO 0x2000 /* Operate in Turbo mode */
+
+/* operating mode for multi-mode devices */
+#define IFM_IEEE80211_11A 0x00010000 /* 5Ghz, OFDM mode */
+#define IFM_IEEE80211_11B 0x00020000 /* Direct Sequence mode */
+#define IFM_IEEE80211_11G 0x00030000 /* 2Ghz, CCK mode */
+#define IFM_IEEE80211_FH 0x00040000 /* 2Ghz, GFSK mode */
+
+/*
+ * Digitally multiplexed "Carrier" Serial Interfaces
+ */
+#define IFM_TDM 0x000000a0
+#define IFM_TDM_T1 3 /* T1 B8ZS+ESF 24 ts */
+#define IFM_TDM_T1_AMI 4 /* T1 AMI+SF 24 ts */
+#define IFM_TDM_E1 5 /* E1 HDB3+G.703 clearchannel 32 ts */
+#define IFM_TDM_E1_G704 6 /* E1 HDB3+G.703+G.704 channelized 31 ts */
+#define IFM_TDM_E1_AMI 7 /* E1 AMI+G.703 32 ts */
+#define IFM_TDM_E1_AMI_G704 8 /* E1 AMI+G.703+G.704 31 ts */
+#define IFM_TDM_T3 9 /* T3 B3ZS+C-bit 672 ts */
+#define IFM_TDM_T3_M13 10 /* T3 B3ZS+M13 672 ts */
+#define IFM_TDM_E3 11 /* E3 HDB3+G.751 512? ts */
+#define IFM_TDM_E3_G751 12 /* E3 G.751 512 ts */
+#define IFM_TDM_E3_G832 13 /* E3 G.832 512 ts */
+/*
+ * 6 major ways that networks talk: Drivers enforce independent selection,
+ * meaning, a driver will ensure that only one of these is set at a time.
+ */
+#define IFM_TDM_HDLC_CRC16 0x0100 /* Use 16-bit CRC for HDLC instead */
+#define IFM_TDM_PPP 0x0200 /* SPPP (dumb) */
+#define IFM_TDM_FR_ANSI 0x0400 /* Frame Relay + LMI ANSI "Annex D" */
+#define IFM_TDM_FR_CISCO 0x0800 /* Frame Relay + LMI Cisco */
+#define IFM_TDM_FR_ITU 0x1000 /* Frame Relay + LMI ITU "Q933A" */
+
+/*
+ * Common Access Redundancy Protocol
+ */
+#define IFM_CARP 0x000000c0
+
+/*
+ * Shared media sub-types
+ */
+#define IFM_AUTO 0 /* Autoselect best media */
+#define IFM_MANUAL 1 /* Jumper/dipswitch selects media */
+#define IFM_NONE 2 /* Deselect all media */
+
+/*
+ * Shared options
+ */
+#define IFM_FDX 0x00100000 /* Force full duplex */
+#define IFM_HDX 0x00200000 /* Force half duplex */
+#define IFM_FLOW 0x00400000 /* enable hardware flow control */
+#define IFM_FLAG0 0x01000000 /* Driver defined flag */
+#define IFM_FLAG1 0x02000000 /* Driver defined flag */
+#define IFM_FLAG2 0x04000000 /* Driver defined flag */
+#define IFM_LOOP 0x08000000 /* Put hardware in loopback */
+
+/*
+ * Masks
+ */
+#define IFM_NMASK 0x000000e0 /* Network type */
+#define IFM_TMASK 0x0000001f /* Media sub-type */
+#define IFM_IMASK 0xf0000000 /* Instance */
+#define IFM_ISHIFT 28 /* Instance shift */
+#define IFM_OMASK 0x0000ff00 /* Type specific options */
+#define IFM_MMASK 0x00070000 /* Mode */
+#define IFM_MSHIFT 16 /* Mode shift */
+#define IFM_GMASK 0x0ff00000 /* Global options */
+
+#define IFM_NMIN IFM_ETHER /* lowest Network type */
+#define IFM_NMAX IFM_NMASK /* highest Network type */
+
+/*
+ * Status bits
+ */
+#define IFM_AVALID 0x00000001 /* Active bit valid */
+#define IFM_ACTIVE 0x00000002 /* Interface attached to working net */
+
+/* Mask of "status valid" bits, for ifconfig(8). */
+#define IFM_STATUS_VALID IFM_AVALID
+
+/* List of "status valid" bits, for ifconfig(8). */
+#define IFM_STATUS_VALID_LIST { \
+ IFM_AVALID, \
+ 0 \
+}
+
+/*
+ * Macros to extract various bits of information from the media word.
+ */
+#define IFM_TYPE(x) ((x) & IFM_NMASK)
+#define IFM_SUBTYPE(x) ((x) & IFM_TMASK)
+#define IFM_INST(x) (((x) & IFM_IMASK) >> IFM_ISHIFT)
+#define IFM_OPTIONS(x) ((x) & (IFM_OMASK|IFM_GMASK))
+#define IFM_MODE(x) ((x) & IFM_MMASK)
+
+#define IFM_INST_MAX IFM_INST(IFM_IMASK)
+#define IFM_INST_ANY (-1)
+
+/*
+ * Macro to create a media word.
+ */
+#define IFM_MAKEWORD(type, subtype, options, instance) \
+ ((type) | (subtype) | (options) | ((instance) << IFM_ISHIFT))
+#define IFM_MAKEMODE(mode) \
+ (((mode) << IFM_MSHIFT) & IFM_MMASK)
+/*
+ * NetBSD extension not defined in the BSDI API. This is used in various
+ * places to get the canonical description for a given type/subtype.
+ *
+ * In the subtype and mediaopt descriptions, the valid TYPE bits are OR'd
+ * in to indicate which TYPE the subtype/option corresponds to. If no
+ * TYPE is present, it is a shared media/mediaopt.
+ *
+ * Note that these are parsed case-insensitive.
+ *
+ * Order is important. The first matching entry is the canonical name
+ * for a media type; subsequent matches are aliases.
+ */
+struct ifmedia_description {
+ int ifmt_word; /* word value; may be masked */
+ const char *ifmt_string; /* description */
+};
+
+#define IFM_TYPE_DESCRIPTIONS { \
+ { IFM_ETHER, "Ethernet" }, \
+ { IFM_ETHER, "ether" }, \
+ { IFM_TOKEN, "TokenRing" }, \
+ { IFM_TOKEN, "token" }, \
+ { IFM_FDDI, "FDDI" }, \
+ { IFM_IEEE80211, "IEEE802.11" }, \
+ { IFM_TDM, "TDM" }, \
+ { IFM_CARP, "CARP" }, \
+ { 0, NULL }, \
+}
+
+#define IFM_TYPE_MATCH(dt, t) \
+ (IFM_TYPE((dt)) == 0 || IFM_TYPE((dt)) == IFM_TYPE((t)))
+
+#define IFM_SUBTYPE_DESCRIPTIONS { \
+ { IFM_AUTO, "autoselect" }, \
+ { IFM_AUTO, "auto" }, \
+ { IFM_MANUAL, "manual" }, \
+ { IFM_NONE, "none" }, \
+ \
+ { IFM_ETHER|IFM_10_T, "10baseT" }, \
+ { IFM_ETHER|IFM_10_T, "10baseT/UTP" }, \
+ { IFM_ETHER|IFM_10_T, "UTP" }, \
+ { IFM_ETHER|IFM_10_T, "10UTP" }, \
+ { IFM_ETHER|IFM_10_2, "10base2" }, \
+ { IFM_ETHER|IFM_10_2, "10base2/BNC" }, \
+ { IFM_ETHER|IFM_10_2, "BNC" }, \
+ { IFM_ETHER|IFM_10_2, "10BNC" }, \
+ { IFM_ETHER|IFM_10_5, "10base5" }, \
+ { IFM_ETHER|IFM_10_5, "10base5/AUI" }, \
+ { IFM_ETHER|IFM_10_5, "AUI" }, \
+ { IFM_ETHER|IFM_10_5, "10AUI" }, \
+ { IFM_ETHER|IFM_100_TX, "100baseTX" }, \
+ { IFM_ETHER|IFM_100_TX, "100TX" }, \
+ { IFM_ETHER|IFM_100_FX, "100baseFX" }, \
+ { IFM_ETHER|IFM_100_FX, "100FX" }, \
+ { IFM_ETHER|IFM_100_T4, "100baseT4" }, \
+ { IFM_ETHER|IFM_100_T4, "100T4" }, \
+ { IFM_ETHER|IFM_100_VG, "100baseVG" }, \
+ { IFM_ETHER|IFM_100_VG, "100VG" }, \
+ { IFM_ETHER|IFM_100_T2, "100baseT2" }, \
+ { IFM_ETHER|IFM_100_T2, "100T2" }, \
+ { IFM_ETHER|IFM_1000_SX, "1000baseSX" }, \
+ { IFM_ETHER|IFM_1000_SX, "1000SX" }, \
+ { IFM_ETHER|IFM_10_STP, "10baseSTP" }, \
+ { IFM_ETHER|IFM_10_STP, "STP" }, \
+ { IFM_ETHER|IFM_10_STP, "10STP" }, \
+ { IFM_ETHER|IFM_10_FL, "10baseFL" }, \
+ { IFM_ETHER|IFM_10_FL, "FL" }, \
+ { IFM_ETHER|IFM_10_FL, "10FL" }, \
+ { IFM_ETHER|IFM_1000_LX, "1000baseLX" }, \
+ { IFM_ETHER|IFM_1000_LX, "1000LX" }, \
+ { IFM_ETHER|IFM_1000_CX, "1000baseCX" }, \
+ { IFM_ETHER|IFM_1000_CX, "1000CX" }, \
+ { IFM_ETHER|IFM_1000_T, "1000baseT" }, \
+ { IFM_ETHER|IFM_1000_T, "1000T" }, \
+ { IFM_ETHER|IFM_1000_T, "1000baseTX" }, \
+ { IFM_ETHER|IFM_1000_T, "1000TX" }, \
+ { IFM_ETHER|IFM_HPNA_1, "HomePNA1" }, \
+ { IFM_ETHER|IFM_HPNA_1, "HPNA1" }, \
+ \
+ { IFM_TOKEN|IFM_TOK_STP4, "DB9/4Mbit" }, \
+ { IFM_TOKEN|IFM_TOK_STP4, "4STP" }, \
+ { IFM_TOKEN|IFM_TOK_STP16, "DB9/16Mbit" }, \
+ { IFM_TOKEN|IFM_TOK_STP16, "16STP" }, \
+ { IFM_TOKEN|IFM_TOK_UTP4, "UTP/4Mbit" }, \
+ { IFM_TOKEN|IFM_TOK_UTP4, "4UTP" }, \
+ { IFM_TOKEN|IFM_TOK_UTP16, "UTP/16Mbit" }, \
+ { IFM_TOKEN|IFM_TOK_UTP16, "16UTP" }, \
+ \
+ { IFM_FDDI|IFM_FDDI_SMF, "Single-mode" }, \
+ { IFM_FDDI|IFM_FDDI_SMF, "SMF" }, \
+ { IFM_FDDI|IFM_FDDI_MMF, "Multi-mode" }, \
+ { IFM_FDDI|IFM_FDDI_MMF, "MMF" }, \
+ { IFM_FDDI|IFM_FDDI_UTP, "UTP" }, \
+ { IFM_FDDI|IFM_FDDI_UTP, "CDDI" }, \
+ \
+ { IFM_IEEE80211|IFM_IEEE80211_FH1, "FH1" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_FH2, "FH2" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS2, "DS2" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS5, "DS5" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS11, "DS11" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS1, "DS1" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS22, "DS22" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM6, "OFDM6" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM9, "OFDM9" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM12, "OFDM12" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM18, "OFDM18" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM24, "OFDM24" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM36, "OFDM36" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM48, "OFDM48" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM54, "OFDM54" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM72, "OFDM72" }, \
+ \
+ { IFM_TDM|IFM_TDM_T1, "t1" }, \
+ { IFM_TDM|IFM_TDM_T1_AMI, "t1-ami" }, \
+ { IFM_TDM|IFM_TDM_E1, "e1" }, \
+ { IFM_TDM|IFM_TDM_E1_G704, "e1-g.704" }, \
+ { IFM_TDM|IFM_TDM_E1_AMI, "e1-ami" }, \
+ { IFM_TDM|IFM_TDM_E1_AMI_G704, "e1-ami-g.704" }, \
+ { IFM_TDM|IFM_TDM_T3, "t3" }, \
+ { IFM_TDM|IFM_TDM_T3_M13, "t3-m13" }, \
+ { IFM_TDM|IFM_TDM_E3, "e3" }, \
+ { IFM_TDM|IFM_TDM_E3_G751, "e3-g.751" }, \
+ { IFM_TDM|IFM_TDM_E3_G832, "e3-g.832" }, \
+ \
+ { 0, NULL }, \
+}
+
+#define IFM_MODE_DESCRIPTIONS { \
+ { IFM_AUTO, "autoselect" }, \
+ { IFM_AUTO, "auto" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_11A, "11a" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_11B, "11b" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_11G, "11g" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_FH, "fh" }, \
+ { 0, NULL }, \
+}
+
+#define IFM_OPTION_DESCRIPTIONS { \
+ { IFM_FDX, "full-duplex" }, \
+ { IFM_FDX, "fdx" }, \
+ { IFM_HDX, "half-duplex" }, \
+ { IFM_HDX, "hdx" }, \
+ { IFM_FLAG0, "flag0" }, \
+ { IFM_FLAG1, "flag1" }, \
+ { IFM_FLAG2, "flag2" }, \
+ { IFM_LOOP, "loopback" }, \
+ { IFM_LOOP, "hw-loopback"}, \
+ { IFM_LOOP, "loop" }, \
+ \
+ { IFM_ETHER|IFM_ETH_MASTER, "master" }, \
+ \
+ { IFM_TOKEN|IFM_TOK_ETR, "EarlyTokenRelease" }, \
+ { IFM_TOKEN|IFM_TOK_ETR, "ETR" }, \
+ { IFM_TOKEN|IFM_TOK_SRCRT, "SourceRouting" }, \
+ { IFM_TOKEN|IFM_TOK_SRCRT, "SRCRT" }, \
+ { IFM_TOKEN|IFM_TOK_ALLR, "AllRoutes" }, \
+ { IFM_TOKEN|IFM_TOK_ALLR, "ALLR" }, \
+ \
+ { IFM_FDDI|IFM_FDDI_DA, "dual-attach" }, \
+ { IFM_FDDI|IFM_FDDI_DA, "das" }, \
+ \
+ { IFM_IEEE80211|IFM_IEEE80211_ADHOC, "adhoc" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_HOSTAP, "hostap" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_IBSS, "ibss" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_IBSSMASTER, "ibss-master" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_MONITOR, "monitor" }, \
+ { IFM_IEEE80211|IFM_IEEE80211_TURBO, "turbo" }, \
+ \
+ { IFM_TDM|IFM_TDM_HDLC_CRC16, "hdlc-crc16" }, \
+ { IFM_TDM|IFM_TDM_PPP, "ppp" }, \
+ { IFM_TDM|IFM_TDM_FR_ANSI, "framerelay-ansi" }, \
+ { IFM_TDM|IFM_TDM_FR_CISCO, "framerelay-cisco" }, \
+ { IFM_TDM|IFM_TDM_FR_ANSI, "framerelay-itu" }, \
+ \
+ { 0, NULL }, \
+}
+
+/*
+ * Baudrate descriptions for the various media types.
+ */
+struct ifmedia_baudrate {
+ int ifmb_word; /* media word */
+ int ifmb_baudrate; /* corresponding baudrate */
+};
+
+#define IFM_BAUDRATE_DESCRIPTIONS { \
+ { IFM_ETHER|IFM_10_T, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_10_2, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_10_5, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_100_TX, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_100_FX, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_100_T4, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_100_VG, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_100_T2, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_1000_SX, IF_Mbps(1000) }, \
+ { IFM_ETHER|IFM_10_STP, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_10_FL, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_1000_LX, IF_Mbps(1000) }, \
+ { IFM_ETHER|IFM_1000_CX, IF_Mbps(1000) }, \
+ { IFM_ETHER|IFM_1000_T, IF_Mbps(1000) }, \
+ { IFM_ETHER|IFM_HPNA_1, IF_Mbps(1) }, \
+ \
+ { IFM_TOKEN|IFM_TOK_STP4, IF_Mbps(4) }, \
+ { IFM_TOKEN|IFM_TOK_STP16, IF_Mbps(16) }, \
+ { IFM_TOKEN|IFM_TOK_UTP4, IF_Mbps(4) }, \
+ { IFM_TOKEN|IFM_TOK_UTP16, IF_Mbps(16) }, \
+ \
+ { IFM_FDDI|IFM_FDDI_SMF, IF_Mbps(100) }, \
+ { IFM_FDDI|IFM_FDDI_MMF, IF_Mbps(100) }, \
+ { IFM_FDDI|IFM_FDDI_UTP, IF_Mbps(100) }, \
+ \
+ { IFM_IEEE80211|IFM_IEEE80211_FH1, IF_Mbps(1) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_FH2, IF_Mbps(2) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS1, IF_Mbps(1) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS2, IF_Mbps(2) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS5, IF_Mbps(5) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS11, IF_Mbps(11) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS22, IF_Mbps(22) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM6, IF_Mbps(6) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM9, IF_Mbps(9) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM12, IF_Mbps(12) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM18, IF_Mbps(18) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM24, IF_Mbps(24) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM36, IF_Mbps(36) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM48, IF_Mbps(48) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM54, IF_Mbps(54) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_OFDM72, IF_Mbps(72) }, \
+ \
+ { IFM_TDM|IFM_TDM_T1, IF_Kbps(1536) }, \
+ { IFM_TDM|IFM_TDM_T1_AMI, IF_Kbps(1536) }, \
+ { IFM_TDM|IFM_TDM_E1, IF_Kbps(2048) }, \
+ { IFM_TDM|IFM_TDM_E1_G704, IF_Kbps(2048) }, \
+ { IFM_TDM|IFM_TDM_E1_AMI, IF_Kbps(2048) }, \
+ { IFM_TDM|IFM_TDM_E1_AMI_G704, IF_Kbps(2048) }, \
+ { IFM_TDM|IFM_TDM_T3, IF_Kbps(44736) }, \
+ { IFM_TDM|IFM_TDM_T3_M13, IF_Kbps(44736) }, \
+ { IFM_TDM|IFM_TDM_E3, IF_Kbps(34368) }, \
+ { IFM_TDM|IFM_TDM_E3_G751, IF_Kbps(34368) }, \
+ { IFM_TDM|IFM_TDM_E3_G832, IF_Kbps(34368) }, \
+ \
+ { 0, 0 }, \
+}
+
+/*
+ * Status bit descriptions for the various media types.
+ */
+struct ifmedia_status_description {
+ int ifms_type;
+ int ifms_valid;
+ int ifms_bit;
+ const char *ifms_string[2];
+};
+
+#define IFM_STATUS_DESC(ifms, bit) \
+ (ifms)->ifms_string[((ifms)->ifms_bit & (bit)) ? 1 : 0]
+
+#define IFM_STATUS_DESCRIPTIONS { \
+ { IFM_ETHER, IFM_AVALID, IFM_ACTIVE, \
+ { "no carrier", "active" } }, \
+ { IFM_FDDI, IFM_AVALID, IFM_ACTIVE, \
+ { "no ring", "inserted" } }, \
+ { IFM_TOKEN, IFM_AVALID, IFM_ACTIVE, \
+ { "no ring", "inserted" } }, \
+ { IFM_IEEE80211, IFM_AVALID, IFM_ACTIVE, \
+ { "no network", "active" } }, \
+ { IFM_TDM, IFM_AVALID, IFM_ACTIVE, \
+ { "no carrier", "active" } }, \
+ { IFM_CARP, IFM_AVALID, IFM_ACTIVE, \
+ { "backup", "master" } }, \
+ { 0, 0, 0, \
+ { NULL, NULL } } \
+}
+#endif /* _NET_IF_MEDIA_H_ */

View File

@ -0,0 +1,312 @@
Index: openbsd-compat/imsg-buffer.c
===================================================================
RCS file: openbsd-compat/imsg-buffer.c
diff -N openbsd-compat/imsg-buffer.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/imsg-buffer.c 8 Dec 2012 20:17:59 -0000 1.2
@@ -0,0 +1,305 @@
+/* $OpenBSD: imsg-buffer.c,v 1.1 2010/05/26 16:44:32 nicm Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "imsg.h"
+
+int ibuf_realloc(struct ibuf *, size_t);
+void ibuf_enqueue(struct msgbuf *, struct ibuf *);
+void ibuf_dequeue(struct msgbuf *, struct ibuf *);
+
+struct ibuf *
+ibuf_open(size_t len)
+{
+ struct ibuf *buf;
+
+ if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
+ return (NULL);
+ if ((buf->buf = malloc(len)) == NULL) {
+ free(buf);
+ return (NULL);
+ }
+ buf->size = buf->max = len;
+ buf->fd = -1;
+
+ return (buf);
+}
+
+struct ibuf *
+ibuf_dynamic(size_t len, size_t max)
+{
+ struct ibuf *buf;
+
+ if (max < len)
+ return (NULL);
+
+ if ((buf = ibuf_open(len)) == NULL)
+ return (NULL);
+
+ if (max > 0)
+ buf->max = max;
+
+ return (buf);
+}
+
+int
+ibuf_realloc(struct ibuf *buf, size_t len)
+{
+ u_char *b;
+
+ /* on static buffers max is eq size and so the following fails */
+ if (buf->wpos + len > buf->max) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ b = realloc(buf->buf, buf->wpos + len);
+ if (b == NULL)
+ return (-1);
+ buf->buf = b;
+ buf->size = buf->wpos + len;
+
+ return (0);
+}
+
+int
+ibuf_add(struct ibuf *buf, const void *data, size_t len)
+{
+ if (buf->wpos + len > buf->size)
+ if (ibuf_realloc(buf, len) == -1)
+ return (-1);
+
+ memcpy(buf->buf + buf->wpos, data, len);
+ buf->wpos += len;
+ return (0);
+}
+
+void *
+ibuf_reserve(struct ibuf *buf, size_t len)
+{
+ void *b;
+
+ if (buf->wpos + len > buf->size)
+ if (ibuf_realloc(buf, len) == -1)
+ return (NULL);
+
+ b = buf->buf + buf->wpos;
+ buf->wpos += len;
+ return (b);
+}
+
+void *
+ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
+{
+ /* only allowed to seek in already written parts */
+ if (pos + len > buf->wpos)
+ return (NULL);
+
+ return (buf->buf + pos);
+}
+
+size_t
+ibuf_size(struct ibuf *buf)
+{
+ return (buf->wpos);
+}
+
+size_t
+ibuf_left(struct ibuf *buf)
+{
+ return (buf->max - buf->wpos);
+}
+
+void
+ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+ ibuf_enqueue(msgbuf, buf);
+}
+
+int
+ibuf_write(struct msgbuf *msgbuf)
+{
+ struct iovec iov[IOV_MAX];
+ struct ibuf *buf;
+ unsigned int i = 0;
+ ssize_t n;
+
+ bzero(&iov, sizeof(iov));
+ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
+ if (i >= IOV_MAX)
+ break;
+ iov[i].iov_base = buf->buf + buf->rpos;
+ iov[i].iov_len = buf->wpos - buf->rpos;
+ i++;
+ }
+
+again:
+ if ((n = writev(msgbuf->fd, iov, i)) == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto again;
+ if (errno == ENOBUFS)
+ errno = EAGAIN;
+ return (-1);
+ }
+
+ if (n == 0) { /* connection closed */
+ errno = 0;
+ return (0);
+ }
+
+ msgbuf_drain(msgbuf, n);
+
+ return (1);
+}
+
+void
+ibuf_free(struct ibuf *buf)
+{
+ free(buf->buf);
+ free(buf);
+}
+
+void
+msgbuf_init(struct msgbuf *msgbuf)
+{
+ msgbuf->queued = 0;
+ msgbuf->fd = -1;
+ TAILQ_INIT(&msgbuf->bufs);
+}
+
+void
+msgbuf_drain(struct msgbuf *msgbuf, size_t n)
+{
+ struct ibuf *buf, *next;
+
+ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
+ buf = next) {
+ next = TAILQ_NEXT(buf, entry);
+ if (buf->rpos + n >= buf->wpos) {
+ n -= buf->wpos - buf->rpos;
+ ibuf_dequeue(msgbuf, buf);
+ } else {
+ buf->rpos += n;
+ n = 0;
+ }
+ }
+}
+
+void
+msgbuf_clear(struct msgbuf *msgbuf)
+{
+ struct ibuf *buf;
+
+ while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
+ ibuf_dequeue(msgbuf, buf);
+}
+
+int
+msgbuf_write(struct msgbuf *msgbuf)
+{
+ struct iovec iov[IOV_MAX];
+ struct ibuf *buf;
+ unsigned int i = 0;
+ ssize_t n;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr hdr;
+ char buf[CMSG_SPACE(sizeof(int))];
+ } cmsgbuf;
+
+ bzero(&iov, sizeof(iov));
+ bzero(&msg, sizeof(msg));
+ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
+ if (i >= IOV_MAX)
+ break;
+ iov[i].iov_base = buf->buf + buf->rpos;
+ iov[i].iov_len = buf->wpos - buf->rpos;
+ i++;
+ if (buf->fd != -1)
+ break;
+ }
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = i;
+
+ if (buf != NULL && buf->fd != -1) {
+ msg.msg_control = (caddr_t)&cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ *(int *)CMSG_DATA(cmsg) = buf->fd;
+ }
+
+again:
+ if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto again;
+ if (errno == ENOBUFS)
+ errno = EAGAIN;
+ return (-1);
+ }
+
+ if (n == 0) { /* connection closed */
+ errno = 0;
+ return (0);
+ }
+
+ /*
+ * assumption: fd got sent if sendmsg sent anything
+ * this works because fds are passed one at a time
+ */
+ if (buf != NULL && buf->fd != -1) {
+ close(buf->fd);
+ buf->fd = -1;
+ }
+
+ msgbuf_drain(msgbuf, n);
+
+ return (1);
+}
+
+void
+ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+ TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
+ msgbuf->queued++;
+}
+
+void
+ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+ TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
+
+ if (buf->fd != -1)
+ close(buf->fd);
+
+ msgbuf->queued--;
+ ibuf_free(buf);
+}

View File

@ -0,0 +1,312 @@
Index: openbsd-compat/imsg.c
===================================================================
RCS file: openbsd-compat/imsg.c
diff -N openbsd-compat/imsg.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/imsg.c 8 Dec 2012 20:17:59 -0000 1.2
@@ -0,0 +1,305 @@
+/* $OpenBSD: imsg.c,v 1.1 2010/05/26 16:44:32 nicm Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "imsg.h"
+
+int imsg_fd_overhead = 0;
+
+int imsg_get_fd(struct imsgbuf *);
+
+void
+imsg_init(struct imsgbuf *ibuf, int fd)
+{
+ msgbuf_init(&ibuf->w);
+ bzero(&ibuf->r, sizeof(ibuf->r));
+ ibuf->fd = fd;
+ ibuf->w.fd = fd;
+ ibuf->pid = getpid();
+ TAILQ_INIT(&ibuf->fds);
+}
+
+ssize_t
+imsg_read(struct imsgbuf *ibuf)
+{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr hdr;
+ char buf[CMSG_SPACE(sizeof(int) * 1)];
+ } cmsgbuf;
+ struct iovec iov;
+ ssize_t n = -1;
+ int fd;
+ struct imsg_fd *ifd;
+
+ bzero(&msg, sizeof(msg));
+
+ iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
+ iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
+
+ if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
+ return (-1);
+
+again:
+#if defined(__FreeBSD__)
+ if (imsg_fd_overhead +
+#else
+ if (getdtablecount() + imsg_fd_overhead +
+#endif
+ (CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int)
+ >= getdtablesize()) {
+ errno = EAGAIN;
+ return (-1);
+ }
+
+ if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
+ if (errno == EMSGSIZE)
+ goto fail;
+ if (errno != EINTR && errno != EAGAIN)
+ goto fail;
+ goto again;
+ }
+
+ ibuf->r.wpos += n;
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_RIGHTS) {
+ int i;
+ int j;
+
+ /*
+ * We only accept one file descriptor. Due to C
+ * padding rules, our control buffer might contain
+ * more than one fd, and we must close them.
+ */
+ j = ((char *)cmsg + cmsg->cmsg_len -
+ (char *)CMSG_DATA(cmsg)) / sizeof(int);
+ for (i = 0; i < j; i++) {
+ fd = ((int *)CMSG_DATA(cmsg))[i];
+ if (i == 0) {
+ ifd->fd = fd;
+ TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
+ entry);
+ ifd = NULL;
+ } else
+ close(fd);
+ }
+ }
+ /* we do not handle other ctl data level */
+ }
+
+fail:
+ if (ifd)
+ free(ifd);
+ return (n);
+}
+
+ssize_t
+imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
+{
+ size_t av, left, datalen;
+
+ av = ibuf->r.wpos;
+
+ if (IMSG_HEADER_SIZE > av)
+ return (0);
+
+ memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
+ if (imsg->hdr.len < IMSG_HEADER_SIZE ||
+ imsg->hdr.len > MAX_IMSGSIZE) {
+ errno = ERANGE;
+ return (-1);
+ }
+ if (imsg->hdr.len > av)
+ return (0);
+ datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+ ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
+ if ((imsg->data = malloc(datalen)) == NULL)
+ return (-1);
+
+ if (imsg->hdr.flags & IMSGF_HASFD)
+ imsg->fd = imsg_get_fd(ibuf);
+ else
+ imsg->fd = -1;
+
+ memcpy(imsg->data, ibuf->r.rptr, datalen);
+
+ if (imsg->hdr.len < av) {
+ left = av - imsg->hdr.len;
+ memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
+ ibuf->r.wpos = left;
+ } else
+ ibuf->r.wpos = 0;
+
+ return (datalen + IMSG_HEADER_SIZE);
+}
+
+int
+imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
+ pid_t pid, int fd, void *data, u_int16_t datalen)
+{
+ struct ibuf *wbuf;
+
+ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
+ return (-1);
+
+ if (imsg_add(wbuf, data, datalen) == -1)
+ return (-1);
+
+ wbuf->fd = fd;
+
+ imsg_close(ibuf, wbuf);
+
+ return (1);
+}
+
+int
+imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
+ pid_t pid, int fd, const struct iovec *iov, int iovcnt)
+{
+ struct ibuf *wbuf;
+ int i, datalen = 0;
+
+ for (i = 0; i < iovcnt; i++)
+ datalen += iov[i].iov_len;
+
+ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
+ return (-1);
+
+ for (i = 0; i < iovcnt; i++)
+ if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
+ return (-1);
+
+ wbuf->fd = fd;
+
+ imsg_close(ibuf, wbuf);
+
+ return (1);
+}
+
+/* ARGSUSED */
+struct ibuf *
+imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
+ pid_t pid, u_int16_t datalen)
+{
+ struct ibuf *wbuf;
+ struct imsg_hdr hdr;
+
+ datalen += IMSG_HEADER_SIZE;
+ if (datalen > MAX_IMSGSIZE) {
+ errno = ERANGE;
+ return (NULL);
+ }
+
+ hdr.type = type;
+ hdr.flags = 0;
+ hdr.peerid = peerid;
+ if ((hdr.pid = pid) == 0)
+ hdr.pid = ibuf->pid;
+ if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
+ return (NULL);
+ }
+ if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
+ return (NULL);
+
+ return (wbuf);
+}
+
+int
+imsg_add(struct ibuf *msg, void *data, u_int16_t datalen)
+{
+ if (datalen)
+ if (ibuf_add(msg, data, datalen) == -1) {
+ ibuf_free(msg);
+ return (-1);
+ }
+ return (datalen);
+}
+
+void
+imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
+{
+ struct imsg_hdr *hdr;
+
+ hdr = (struct imsg_hdr *)msg->buf;
+
+ hdr->flags &= ~IMSGF_HASFD;
+ if (msg->fd != -1)
+ hdr->flags |= IMSGF_HASFD;
+
+ hdr->len = (u_int16_t)msg->wpos;
+
+ ibuf_close(&ibuf->w, msg);
+}
+
+void
+imsg_free(struct imsg *imsg)
+{
+ free(imsg->data);
+}
+
+int
+imsg_get_fd(struct imsgbuf *ibuf)
+{
+ int fd;
+ struct imsg_fd *ifd;
+
+ if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
+ return (-1);
+
+ fd = ifd->fd;
+ TAILQ_REMOVE(&ibuf->fds, ifd, entry);
+ free(ifd);
+
+ return (fd);
+}
+
+int
+imsg_flush(struct imsgbuf *ibuf)
+{
+ while (ibuf->w.queued)
+ if (msgbuf_write(&ibuf->w) < 0)
+ return (-1);
+ return (0);
+}
+
+void
+imsg_clear(struct imsgbuf *ibuf)
+{
+ int fd;
+
+ msgbuf_clear(&ibuf->w);
+ while ((fd = imsg_get_fd(ibuf)) != -1)
+ close(fd);
+}

View File

@ -0,0 +1,119 @@
Index: openbsd-compat/imsg.h
===================================================================
RCS file: openbsd-compat/imsg.h
diff -N openbsd-compat/imsg.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/imsg.h 8 Dec 2012 20:17:59 -0000 1.2
@@ -0,0 +1,112 @@
+/* $OpenBSD: imsg.h,v 1.1 2010/05/26 16:44:32 nicm Exp $ */
+
+/*
+ * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
+ * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _IMSG_H_
+#define _IMSG_H_
+
+#define IBUF_READ_SIZE 65535
+#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
+#define MAX_IMSGSIZE 16384
+
+struct ibuf {
+ TAILQ_ENTRY(ibuf) entry;
+ u_char *buf;
+ size_t size;
+ size_t max;
+ size_t wpos;
+ size_t rpos;
+ int fd;
+};
+
+struct msgbuf {
+ TAILQ_HEAD(, ibuf) bufs;
+ u_int32_t queued;
+ int fd;
+};
+
+struct ibuf_read {
+ u_char buf[IBUF_READ_SIZE];
+ u_char *rptr;
+ size_t wpos;
+};
+
+struct imsg_fd {
+ TAILQ_ENTRY(imsg_fd) entry;
+ int fd;
+};
+
+struct imsgbuf {
+ TAILQ_HEAD(, imsg_fd) fds;
+ struct ibuf_read r;
+ struct msgbuf w;
+ int fd;
+ pid_t pid;
+};
+
+#define IMSGF_HASFD 1
+
+struct imsg_hdr {
+ u_int32_t type;
+ u_int16_t len;
+ u_int16_t flags;
+ u_int32_t peerid;
+ u_int32_t pid;
+};
+
+struct imsg {
+ struct imsg_hdr hdr;
+ int fd;
+ void *data;
+};
+
+
+/* buffer.c */
+struct ibuf *ibuf_open(size_t);
+struct ibuf *ibuf_dynamic(size_t, size_t);
+int ibuf_add(struct ibuf *, const void *, size_t);
+void *ibuf_reserve(struct ibuf *, size_t);
+void *ibuf_seek(struct ibuf *, size_t, size_t);
+size_t ibuf_size(struct ibuf *);
+size_t ibuf_left(struct ibuf *);
+void ibuf_close(struct msgbuf *, struct ibuf *);
+int ibuf_write(struct msgbuf *);
+void ibuf_free(struct ibuf *);
+void msgbuf_init(struct msgbuf *);
+void msgbuf_clear(struct msgbuf *);
+int msgbuf_write(struct msgbuf *);
+void msgbuf_drain(struct msgbuf *, size_t);
+
+/* imsg.c */
+void imsg_init(struct imsgbuf *, int);
+ssize_t imsg_read(struct imsgbuf *);
+ssize_t imsg_get(struct imsgbuf *, struct imsg *);
+int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+ int, void *, u_int16_t);
+int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+ int, const struct iovec *, int);
+struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+ u_int16_t);
+int imsg_add(struct ibuf *, void *, u_int16_t);
+void imsg_close(struct imsgbuf *, struct ibuf *);
+void imsg_free(struct imsg *);
+int imsg_flush(struct imsgbuf *);
+void imsg_clear(struct imsgbuf *);
+
+#endif

View File

@ -0,0 +1,98 @@
Index: openbsd-compat/openbsd-compat.h
===================================================================
RCS file: openbsd-compat/openbsd-compat.h
diff -N openbsd-compat/openbsd-compat.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/openbsd-compat.h 13 Oct 2012 18:50:10 -0000 1.8
@@ -0,0 +1,91 @@
+/*
+ * $hrs: openbgpd/openbsd-compat/openbsd-compat.h,v 1.8 2012/10/13 18:50:10 hrs Exp $
+ */
+
+#ifndef _OPENBSD_COMPAT_H
+#define _OPENBSD_COMPAT_H
+
+#define __dead
+
+/* bgpctl/bgpctl.c */
+#include <sys/endian.h>
+#include <inttypes.h>
+#define betoh64(x) (be64toh(x))
+#ifndef IFT_CARP
+#define IFT_CARP 0xf8
+#endif
+
+/* bgpd/irrfilter.c */
+typedef unsigned long ulong;
+
+/* bgpd/bgpd.c */
+#ifndef RTLABEL_LEN /* defined in net/pfvar.h */
+#define RTLABEL_LEN 32
+#endif
+#define RTA_LABEL 0
+
+#define SIMPLEQ_FOREACH STAILQ_FOREACH
+#define SIMPLEQ_FIRST STAILQ_FIRST
+#define SIMPLEQ_REMOVE_HEAD STAILQ_REMOVE_HEAD
+#define SIMPLEQ_INSERT_TAIL STAILQ_INSERT_TAIL
+#define SIMPLEQ_ENTRY STAILQ_ENTRY
+#define SIMPLEQ_HEAD STAILQ_HEAD
+#define SIMPLEQ_INIT STAILQ_INIT
+#define SIMPLEQ_HEAD_INITIALIZER STAILQ_HEAD_INITIALIZER
+
+/* Routing priorities used by the different routing protocols */
+#define RTP_NONE 0 /* unset priority use sane default */
+#define RTP_CONNECTED 4 /* directly connected routes */
+#define RTP_STATIC 8 /* static routes base priority */
+#define RTP_OSPF 32 /* OSPF routes */
+#define RTP_ISIS 36 /* IS-IS routes */
+#define RTP_RIP 40 /* RIP routes */
+#define RTP_BGP 48 /* BGP routes */
+#define RTP_DEFAULT 56 /* routes that have nothing set */
+#define RTP_MAX 63 /* maximum priority */
+#define RTP_ANY 64 /* any of the above */
+#define RTP_MASK 0x7f
+#define RTP_DOWN 0x80 /* route/link is down */
+
+/* missing LINK_STATE_* macros in net/if.h */
+#define LINK_STATE_INVALID LINK_STATE_UNKNOWN /* link invalid */
+#define LINK_STATE_KALIVE_DOWN 7 /* keepalive reports down */
+#define LINK_STATE_HALF_DUPLEX 5 /* link is up and half duplex */
+#define LINK_STATE_FULL_DUPLEX 6 /* link is up and full duplex */
+
+/*
+ * Status bit descriptions for the various interface types.
+ */
+struct if_status_description {
+ unsigned char ifs_type;
+ unsigned char ifs_state;
+ const char *ifs_string;
+};
+
+#define LINK_STATE_DESC_MATCH(_ifs, _t, _s) \
+ (((_ifs)->ifs_type == (_t) || (_ifs)->ifs_type == 0) && \
+ (_ifs)->ifs_state == (_s))
+
+#define LINK_STATE_DESCRIPTIONS { \
+ { IFT_ETHER, LINK_STATE_DOWN, "no carrier" }, \
+ \
+ { IFT_IEEE80211, LINK_STATE_DOWN, "no network" }, \
+ \
+ { IFT_PPP, LINK_STATE_DOWN, "no carrier" }, \
+ \
+ { IFT_CARP, LINK_STATE_DOWN, "backup" }, \
+ { IFT_CARP, LINK_STATE_UP, "master" }, \
+ { IFT_CARP, LINK_STATE_HALF_DUPLEX, "master" }, \
+ { IFT_CARP, LINK_STATE_FULL_DUPLEX, "master" }, \
+ \
+ { 0, LINK_STATE_UP, "active" }, \
+ { 0, LINK_STATE_HALF_DUPLEX, "active" }, \
+ { 0, LINK_STATE_FULL_DUPLEX, "active" }, \
+ \
+/* { 0, LINK_STATE_UNKNOWN, "unknown" }, */ \
+ { 0, LINK_STATE_INVALID, "invalid" }, \
+ { 0, LINK_STATE_DOWN, "down" }, \
+ { 0, LINK_STATE_KALIVE_DOWN, "keepalive down" }, \
+ { 0, 0, NULL } \
+}
+#endif /* _OPENBSD_COMPAT_H */

View File

@ -0,0 +1,126 @@
Index: openbsd-compat/util.h
===================================================================
RCS file: openbsd-compat/util.h
diff -N openbsd-compat/util.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/util.h 30 Jun 2009 06:40:07 -0000 1.1
@@ -0,0 +1,119 @@
+/* $OpenBSD: util.h,v 1.27 2006/06/14 02:14:25 krw Exp $ */
+/* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1995
+ * The Regents of the University of California. All rights reserved.
+ * Portions Copyright (c) 1996, Jason Downs. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/*
+ * fparseln() specific operation flags.
+ */
+#define FPARSELN_UNESCESC 0x01
+#define FPARSELN_UNESCCONT 0x02
+#define FPARSELN_UNESCCOMM 0x04
+#define FPARSELN_UNESCREST 0x08
+#define FPARSELN_UNESCALL 0x0f
+
+/*
+ * opendev() specific operation flags.
+ */
+#define OPENDEV_PART 0x01 /* Try to open the raw partition. */
+#define OPENDEV_BLCK 0x04 /* Open block, not character device. */
+
+/*
+ * uucplock(3) specific flags.
+ */
+#define UU_LOCK_INUSE (1)
+#define UU_LOCK_OK (0)
+#define UU_LOCK_OPEN_ERR (-1)
+#define UU_LOCK_READ_ERR (-2)
+#define UU_LOCK_CREAT_ERR (-3)
+#define UU_LOCK_WRITE_ERR (-4)
+#define UU_LOCK_LINK_ERR (-5)
+#define UU_LOCK_TRY_ERR (-6)
+#define UU_LOCK_OWNER_ERR (-7)
+
+/*
+ * fmt_scaled(3) specific flags.
+ */
+#define FMT_SCALED_STRSIZE 7 /* minus sign, 4 digits, suffix, null byte */
+
+/*
+ * stub struct definitions.
+ */
+struct __sFILE;
+struct login_cap;
+struct passwd;
+struct termios;
+struct utmp;
+struct winsize;
+
+__BEGIN_DECLS
+char *fparseln(struct __sFILE *, size_t *, size_t *, const char[3], int);
+void login(struct utmp *);
+int login_tty(int);
+int logout(const char *);
+void logwtmp(const char *, const char *, const char *);
+int opendev(char *, int, int, char **);
+int pidfile(const char *);
+void pw_setdir(const char *);
+char *pw_file(const char *);
+int pw_lock(int retries);
+int pw_mkdb(char *, int);
+int pw_abort(void);
+void pw_init(void);
+void pw_edit(int, const char *);
+void pw_prompt(void);
+void pw_copy(int, int, const struct passwd *, const struct passwd *);
+int pw_scan(char *, struct passwd *, int *);
+void pw_error(const char *, int, int);
+int openpty(int *, int *, char *, struct termios *, struct winsize *);
+int opendisk(const char *path, int flags, char *buf, size_t buflen,
+ int iscooked);
+pid_t forkpty(int *, char *, struct termios *, struct winsize *);
+int getmaxpartitions(void);
+int getrawpartition(void);
+void login_fbtab(const char *, uid_t, gid_t);
+int login_check_expire(struct __sFILE *, struct passwd *, char *, int);
+char *readlabelfs(char *, int);
+const char *uu_lockerr(int _uu_lockresult);
+int uu_lock(const char *_ttyname);
+int uu_lock_txfr(const char *_ttyname, pid_t _pid);
+int uu_unlock(const char *_ttyname);
+int fmt_scaled(long long number, char *result);
+int scan_scaled(char *scaled, long long *result);
+__END_DECLS
+
+#endif /* !_UTIL_H_ */

View File

@ -1,6 +0,0 @@
sbin/bgpctl
sbin/bgpd
man/man5/bgpd.conf.5.gz
man/man8/bgpctl.8.gz
man/man8/bgpd.8.gz
@sample etc/bgpd.conf.sample